Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Shed Skin — экспериментальный транслятор из Python в C

Anna | 16.06.2014 | нет комментариев

Вступление

Shed Skin — это экспериментальный транслятор из Python в C , разработанный для возрастания скорости выполнения программ на Python с насыщенными вычислениями. Он преобразует программы, написанные на ограниченном подмножестве языка Python, в C . Код C дозволено скомпилировать в исполняемый код, тот, что может быть как отдельной программой, так и модулем растяжения, легко импортируемым и используемым в обыкновенной программе на Python.

Shed Skin использует способы сравнения типов, используемых в программе на Python, Дабы сгенерировать очевидные декларации типов, нужные для версии на C . От того что C — язык со статической типизацией, Shed Skin требует, Дабы код на Python был написан так, Дабы все переменные имели определенный тип.

Помимо ограничений на типизацию и подмножество языка, поддерживаемые программы не могут вольно применять стандартную библиотеку Python, правда поддерживается около 25 общеупотребительных модулей, такие как random и re (см. Ограничения Библиотеки).

Вдобавок, спецтехнология определения типов, применяемая Shed Skin, в данный момент не дюже отлично масштабируется для программ, размер которых превышает несколько тысяч строк кода (наивысший размер транслируемой программы — около 6,000 строк (sloccount)). В целом, это обозначает, что Shed Skin на данный момент огромнее подходит для трансляции маленьких программ и модулей растяжения, которые не применяют насыщенно особенности динамической типизации Python либо стандартную и внешние библиотеки. Смотри ниже альманах из 75 нетривиальных программ-примеров.

От того что Shed Skin находится всё еще в ранней стадии разработки, он может серьёзно улучшиться. В подлинный момент, Вы, допустимо, столкнётесь с какими-либо ошибками в процессе его применения. Пожалуйста, отправьте нам отчет о них, Дабы мы сумели их поправить!

В реальное время Shed Skin совместим с версиями Python с 2.4 по 2.7, ведёт себя как 2.6, и работает на Windows и большинстве UNIX-платформ, таких как GNU/Linux и OSX.

Ограничения на типизацию

Shed Skin транслирует обыкновенные, но статически типизированные программы, на C . Лимитация на статическую типизацию обозначает, что переменные могут иметь только один, непоколебимый тип. Так, скажем, код

a = 1
a = '1' # оплошность

недопустим. Впрочем, как в C , типы могут быть абстрактными, так, скажем, код

a = A()
a = B() # верно

где A и B имеют всеобщий базовый класс, возможен.

Лимитация на типизацию также обозначает, что элементы одной коллекции (list, set, и т.д.) не могут иметь различные типы (потому что типы их членов также обязаны быть статическими). Таким образом, код:

a = ['apple', 'b', 'c'] # верно
b = (1, 2, 3) # верно
c = [[10.3, -2.0], [1.5, 2.3], []] # верно

возможен, но код

d = [1, 2.5, 'abc'] # оплошность
e = [3, [1, 2]] # оплошность
f = (0, 'abc', [1, 2, 3]) # оплошность

недопустим. Ключи и значения словарей могут иметь различные типы:

g = {'a': 1, 'b': 2, 'c': 3} # верно
h = {'a': 1, 'b': 'hello', 'c': [1, 2, 3]} # оплошность

В нынешней версии Shed Skin смешанные типы также разрешены в кортежах длины два:

a = (1, [1]) # верно

В грядущем, допустимо, будут разрешены смешанные типы в кортежах большей длины.

Тип None дозволено смешивать только с нескалярными типами (то есть, не с int, float, bool либо complex):

l = [1]
l = None # верно
m = 1
m = None # оплошность
def fun(x = None): # оплошность: используйте определенное значение для x, скажем, x = -1
    pass
fun(1)

Целые числа и числа с плавающей точкой (integers и floats) обыкновенно дозволено смешивать (целые числа становятся числами с плавающей точкой). Если это немыслимо, Shed Skin выдаст сообщение об ошибке.

Ограничения на подмножество языка Python

Shed Skin неизменно будет поддерживать только подмножество всех особенностей языка Python. В данный момент следующие особенности не поддерживаются:

  • eval, getattr, hasattr, isinstance, всё динамическое
  • арифметика с произвольной точностью (целые числа — int — становятся 32-битными (знаковыми) по умолчанию на большинстве архитектур, см. Опции командной строки)
  • паковка-распаковка доводов (*args и **kwargs)
  • множественное наследование
  • вложенные функции и классы
  • unicode
  • наследование от встроенных типов (исключая Exception и object)
  • перегрузка функций __iter__, __call__, __del__
  • замыкания

Некоторые другие особенности поддерживаются только Отчасти:

  • к признакам класса дозволено обращаться только через имя класса:
            self.class_attr # оплошность
            SomeClass.class_attr # верно
            SomeClass.some_static_method() # верно
    
  • ссылки на функции дозволено передавать, но не на способы классов и не на классы, и они не могут содержаться в каком-либо контейнере:
    
            var = lambda x, y: x y # верно
            var = some_func # верно
            var = self.some_method # оплошность, ссылка на способ
            var = SomeClass # оплошность
            [var] # оплошность, находится в контейнере
    

Ограничения на библиотеки

На данный момент, в огромный степени поддерживаются следующие 25 модулей. Некоторые из них, такие как os.path, были транслированы на C с поддержкой Shed Skin.

  • array
  • binascii
  • bisect
  • collections (defaultdict, deque)
  • colorsys
  • ConfigParser (без SafeConfigParser)
  • copy
  • csv (без Dialect, Sniffer)
  • datetime
  • fnmatch
  • getopt
  • glob
  • heapq
  • itertools (без starmap)
  • math
  • mmap
  • os (под Windows отсутствует определенный функционал)
  • os.path
  • random
  • re
  • select (только функция select, под UNIX)
  • socket
  • string
  • struct (без Struct, pack_into, unpack_from)
  • sys
  • time

Подметим, что всякий иной модуль, такой, как pygame, pyqt либо pickle, дозволено применять в общности с модулем растяжения, сгенерированным с поддержкой Shed Skin. Примеры такого применения см. среди примеров к Shed Skin.

Установка

Имеется два вида установщиков: сапораспаковывающийся инсталятор Windows и архив UNIX. Но, безусловно, отменнее, если Shed Skin установлек с поддержкой администратора пакетов вашей инсталяции GNU/Linux (Shed Skin доступен по крайней мере на Debian, Ubuntu, Fedora и Arch).

Windows

Дабы установить Windows-версию, легко загрузите и запустите инсталятор. Если вы используете ActivePython либо иной нестандартный дистрибутив Python, либо MingW, вначале удалите его. Также имейте в виду, что, видимо, в 64-битной версии Python недостаёт какого-то файла, так что сборка модулей растяжения немыслима. Взамен 64-битной используйте 32-битную версию Python.

UNIX
Инсталяция через администратор пакетов

Пример команды для Ubuntu:

sudo apt-get install shedskin
Ручная инсталяция

Дабы установить дистрибутив из архива UNIX вручную, сделайте следующее:

  • загрузите и распакуйте архив
  • запустите команду run sudo python setup.py install
Зависимости

Дабы скомпилировать и запустить программы, сгенерированные shedskin, нужны следующие библиотеки:

  • g , компилятор C (версия 4.2 либо выше).
  • отладочные файлы pcre
  • отладочные файлы Python
  • сборщик мусора Boehm

Дабы установить эти библиотеки под Ubuntu, введите:

sudo apt-get install g   libpcre  dev python-all-dev libgc-dev

Если сборщик мусора Boehm недостижим через ваш администратор пакетов, используйте такой метод. Загрузите с вебсайта, скажем, версию 7.2alpha6, распакуйте её, и установите дальнейшим образом:

./configure --prefix=/usr/local --enable-threads=posix --enable-cplusplus --enable-thread-local-alloc --enable-large-config
make
make check
sudo make install

Если библиотека PCRE недостижима через ваш администратор пакетов, воспользуйтесь следущим методом. Загрузите с вебсайта, скажем, версию 8.12, распакуйте её и установите дальнейшим образом:

./configure --prefix=/usr/local
make
sudo make install
OSX
Ручная установка

Дабы установить Shed Skin из архива UNIX на систему OSX, сделайте следущее:

  • загрузите и распакуйте архив
  • запустите команду run sudo python setup.py install
Зависимости

Дабы cкомпилировать и запустить программы, сгенерированные shedskin, нужны следующие библиотеки:

  • g , компилятор C (версия 4.2 либо выше; поставляется со средой разработки Apple XCode?).
  • отладочные файлы pcre
  • отладочные файлы Python
  • сборщик мусора Boehm

Если сборщик мусора Boehm недостижим через ваш администратор пакетов, используйте такой метод. Загрузите с вебсайта, скажем, версию 7.2alpha6, распакуйте её, и установите дальнейшим образом:

./configure --prefix=/usr/local --enable-threads=posix --enable-cplusplus --enable-thread-local-alloc --enable-large-config
make
make check
sudo make install

Если библиотека PCRE недостижима через ваш администратор пакетов, воспользуйтесь следущим методом. Загрузите с вебсайта, скажем, версию 8.12, распакуйте её и установите дальнейшим образом:

./configure --prefix=/usr/local
make
sudo make install

Трансляция традиционной программы

На Windows вначале исполните (двойным щелчком) файл init.bat в директории, куда Вы установили Shed Skin.

Дабы скомпилировать следующую примитивную тестовую программу с именем test.py:
print 'hello, world!' 

введите:
shedskin test 

Создадутся два файла C с именами test.cpp и test.hpp, а также Makefile.

Дабы сделать исполняемый файл с именем test (либо test.exe), введите:

make

Создание модуля растяжения

Дабы скомпилировать следующую программу с именем simple_module.py как модуль растяжения:

# simple_module.py

def func1(x):
    return x 1

def func2(n):
    d = dict([(i, i*i)  for i in range(n)])
    return d

if __name__ == '__main__':
    print func1(5)
    print func2(10)

введите:

shedskin -e simple_module
make

Дабы команда ‘make’ выполнилась удачно на не-Windows системе, удостоверитесь, что у Вас установлены отладочные файлы Python (на Debian установите python-dev; на Fedora установите python-devel).

Подметьте, что Дабы было допустимо определение типов, ваш модуль должен вызывать только свои собственные функции. Такой результат достигается в примере за счет того, что вызовы размещены вовнутрь данные if __name__==’__main__’, так что они не вызываются, если модуль импортируют. Функции могут вызываться только неявно, то есть, если func2 вызывает func1, вызов func1 может быть опущен.

Модуль растяжения сейчас дозволено легко проимпортировать и применять как обыкновенно:

>>> from simple_module import func1, func2
>>> func1(5)
6
>>> func2(10)
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
Ограничения

Имеются значительные различия между применением компилированного модуля растяжения и оригиналом.

Дозволено передавать и возвращать только встроенные скалярные типы и контейнеры (int, float, complex, bool, str, list, tuple, dict, set), а также None и экземпляры классов, определённых пользователем. Так, скажем, неизвестные функции и итераторы в реальное время не поддерживаются.
Встроенные объекты а также их содержимое всецело преобразуются на всякий вызов/возврат функции из типов Shed Skin в CPython и напротив. Это обозначает, что невозможно менять встроенные объекты CPython со стороны Shed Skin и напротив, и реформирование может быть неторопливым Экземпляры классов, определённых пользователем дозволено передавать/возвращать без каких-либо реформирований и менять с всякий стороны.
Всеобщии переменные преобразуются только один раз, во время инициализации, из Shed Skin в CPython. Это обозначает, что значения версии CPython и версии Shed Skin могут меняться самостоятельно друг от друга. Этой задачи дозволено избежать, применяя только константные глабольные переменные, либо добавляя функции-геттеры и сеттеры.
Множественные (взаимодействующие) модули растяжения в подлинный момент не поддерживаются. Также, импорт и одновременное применение питоновской и транслированной версии может не трудиться.

Интеграция с Numpy

Shed Skin в реальное время не имеет прямой поддержки Numpy. Впрочем, допустимо передавть массив Numpy array в транслированный модуль растяжения Shed Skin как список (list), применяя его способ tolist. Подметьте, что это крайне неэффективно (см. выше), так что это дозволено применять, если огромное число времени расходуется внутри модуля растяжения. Разглядим дальнейший пример:

# simple_module2.py

def my_sum(a):
    """ compute sum of elements in list of lists (matrix) """
    h = len(a) # number of rows in matrix
    w = len(a[0]) # number of columns
    s = 0.0
    for i in range(h):
        for j in range(w):
            s  = a[i][j]
    return s

if __name__ == '__main__':
    print my_sum([[1.0, 2.0], [3.0, 4.0]]) 

Позже трансляции этого модуля как модуля растяжения с поддержкой Shed Skin, мы можем передать массив Numpy дальнейшим образом:

>>> import numpy
>>> import simple_module2
>>> a = numpy.array(([1.0, 2.0], [3.0, 4.0]))
>>> simple_module2.my_sum(a.tolist())
10.0

Распространение бинарных кодов

Windows

Дабы применять сгенерированный бинарный код Windows на иной системе либо запустить его без запуска init.bat, разместите следующие файлы в директорию совместно с бинарным файлом:

shedskin-0.9shedskingc.dll
shedskin-0.9shedskin-libpcre-0.dll
shedskin-0.9binlibgcc_s_dw-1.dll
shedskin-0.9binlibstdc .dll

UNIX

Дабы применять сгенерированный бинарный файл на иной системе, удостоверитесь, что там установлены libgc и libpcre3. Если это не так, и Вы не можете установить их глобально на систему, Вы можете разместить копии этих библиотек в ту же директорию, где лежит бинарь, с поддержкой следующих команд:

$ ldd test
libgc.so.1 => /usr/lib/libgc.so.1
libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3
$ cp /usr/lib/libgc.so.1 .
$ cp /lib/x86_64-linux-gnu/libpcre.so.3 .
$ LD_LIBRARY_PATH=. ./test

Подметьте, что обе системы обязаны быть 32- либо 64-битными. Если это не так, Shed Skin нужно установить на иной системе, Дабы пересобрать бинарник.

Multiprocessing

Представим, мы определили следующую функцию в файле под наименованием meuk.py:

def part_sum(start, end):
    """ calculate partial sum """
    sum = 0
    for x in xrange(start, end):
        if x % 2 == 0:
            sum -= 1.0 / x
        else:
            sum  = 1.0 / x
    return sum

if __name__ == ’__main__’:
    part_sum(1, 10)

Дабы транслировать данный файл в модуль растяжения, введите:

    shedskin -e meuk
    make

Дабы применять получившийся модуль растяжения с модулем стандартной библиотеки multiprocessing, легко добавьте wrapper на Python:

from multiprocessing import Pool

def part_sum((start, end)):
    import meuk
    return meuk.part_sum(start, end)

pool = Pool(processes=2)
print sum(pool.map(part_sum, [(1,10000000), (10000001, 20000000)]))

Вызов кода на C/C

Дабы вызвать код на C/C , сделайте следующее:

Дайте Shed Skin информацию о типизации с поддержкой модели типов кода C/C . Представим, нам необходимо вызвать примитивную функцию, которая возвращает список n наименьших примитивных чисел, крупных, чем заданное число. Дальнейшая модель типов, содержащаяся в файле stuff.py, довольна, Дабы Shed Skin произвел сравнение типов:

#stuff.py

def more_primes(n, nr=10):
    return [1]

Дабы произвести фактическое сравнение типов, напишите тестовую программу с наименованием test.py, которая использует эту модель типов, а после этого транслируйте её:

#test.py

import stuff
print stuff.more_primes(100)

shedskin test

Помимо test.py, данный код также транслирует stuff.py на C . Сейчас вы можете писать вручную код C/C в файле stuff.cpp. Дабы избежать его перезаписи во время дальнейшей трансляции файла test.py, переместите stuff.* в директорию lib/ Shed Skin.

Стандартная библиотека

Переместив stuff.* в lib/, мы реально добавили поддержку произвольного библиотечного модуля к Shed Skin. Другие программы, транслированные Shed Skin, сейчас могут импортировать нашу библиотеку и применять more_primes. Реально, в директории lib/ находятся модели типов и имплементации всех поддерживаемых модулей. Как Вы можете подметить, некоторые были Отчасти преобразованы в C в поддержкой Shed Skin.

Типы Shed Skin

Shed Skin снова реализует Python встроенные типы с поддержкой комплекта своих классов на C . Они имеют такой же интерфейс, как их Python-овские сотрудники, так что их легко применять (при условии, что у вас есть базовые познания C ). Подробности об определениях классов см. в файле lib/builtin.hpp. Если у вас есть сомнения, преобразуйте подобный код на Python в C и посмотрите на итог!

Опции командной строки

Команда shedskin поддерживает следующие опции:

  • -a –ann Вывести комментированный начальный код (.ss.py)
  • -b –nobounds Отключить проверку диапазонов
  • -e –extmod Сгенерировать модуль растяжения
  • -f –flags Задать флаги для Makefile
  • -g –nogcwarns Отключить предупреждения GC времени выполнения
  • -l –long Применять целые long long («64-бит»)
  • -m –makefile Указать другое имя Makefile
  • -n –silent Безмолвный режим, показывать только предупреждения
  • -o –noassert Отключить операторы assert
  • -r –random Применять стремительный генератор случайных чисел (rand())
  • -s –strhash Применять стремительный алгорифм хеширования строк (murmur)
  • -w –nowrap Отключить проверку wrap-around
  • -x –traceback Печатать traceback для непойманных исключений
  • -L –lib Добавить директорию с библиотеками

Скажем, Дабы транслировать файл test.py как модуль растяжения, введите shedskin –e test либо shedskin ––extmod test.

Опция -b либо –nobounds дюже Зачастую применяется, потому что она отключает исключения выхода за диапазон (IndexError), что может в огромный степени влиять на продуктивность.

    a = [1, 2, 3]
    print a[5] # invalid index: out of bounds

Советы и приёмы по совершенствованию продуктивности

Советы

Небольшиеаллокации памяти (скажем, создание нового кортежа, списка либо экземпляра класса) обыкновенно крепко не замедляют программу на Python. Впрочем, позже трансляции в C , Зачастую они становятся тесным местом. Это происходит потому что на всякую аллокацию памяти, память запрашивается у системы, она должна быть очищена сборщиком мусора, и огромное число последующих аллокаций памяти скорее каждого вызовет неимение в кэше. Ключевой подход к высокой продуктивности — Зачастую уменьшение числа мелких аллокаций, скажем, заменой небольшого генераторного выражения на цикл либо устранение промежуточных кортежей в некоторых вычислениях.

Впрочем, подметьте, что для идиоматических for a, b in enumerate(..), for a, b in enumerate(..) и for a, b in somedict.iteritems(), промежуточные маленькие объекты выкидываются оптимизатором, и строки длины 1 кешируются.

Некоторые особенности Python (которые могут замедлить сгенерированный код) не неизменно нужны, и их дозволено отключить. См. раздел «Опции командной строки» для подробностей. Выключение проверки диапазонов обыкновенно является дюже неопасной оптимизацией и могут значительно подмогнуть в случае кода, где Зачастую применяется операция взятия по индексу.

Доступ через признак в сгенерированном коде стремительней, чем взятие по индексу. Скажем, v.x * v.y * v.z стремительней, чем v[0] * v[1] * v[2].

Shed Skin берет флаги для компилятора C из файлов FLAGS* в директории, куда установлен Shed Skin. Эти флаги дозволено изменить, либо модифицировать с поддержкой локального файла с именем FLAGS.

При большом числе вычислений с плавающей точкой, не неизменно непременно следовать спецификациям IEEE о плавающей точке. Добавление флага -ffast-math может значительно повысить эффективность.

За счет профилирования дозволено выжать еще огромную эффективность. В последних версиях GCC вначале скомпилируйте и исполните сгенерированный код с поддержкой -fprofile-generate, а после этого с поддержкой fprofile-use.

Для лучших итогов, сконфигурируйте последнюю версию Boehm GC с поддержкой CPPFLAGS=”-O3 -march=native” ./configure –enable-cplusplus –enable-threads=pthreads –enable-thread-local-alloc –enable-large-config –enable-parallel-mark. Последняя опция разрешает GC применять несколько ядер процессора.

При оптимизации дюже пригодно знать, сколько времени тратится в всякой части вашей программы. Программу Gprof2Dot дозволено применять для создания прекрасных трафиков как для отдельной программы, так и для подлинного кода на Python. Программу OProfile дозволено применять для профилирования модуля растяжения.

Дабы применять Gprof2dot, загрузите файл gprof2dot.py с вебсайта и проинсталируйте Graphviz. После этого:

shedskin program
make program_prof
./program_prof
gprof program_prof | gprof2dot.py | dot -Tpng -ooutput.png

Дабы применять OProfile, установите его и используйте дальнейшим образом.

shedskin -e extmod
make
sudo opcontrol --start
python main_program_that_imports_extmod
sudo opcontrol --shutdown
opreport -l extmod.so
Приёмы

Следующие два фрагмента кода работают идентично, но поддерживается только 2-й:

statistics = {'nodes': 28, 'solutions': set()}

class statistics: pass
s = statistics(); s.nodes = 28; s.solutions = set()

Порядок вычисления доводов функции либо оператора print меняется при трансляции в C , так что отменнее каждого не рассчитывать на него:

print 'hoei', raw_input() # raw_input вызывается до итога 'hoei'!

Кортежи с различным типом элементов и длиной > 2 в реальное время не поддерживаются. Впрочем, их дозволено эмулировать:

class mytuple:
    def __init__(self, a, b, c):
        self.a, self.b, self.c = a, b, c

Блочные комментарии, окружённые #{ и #}, Shed Skin игнорирует. Эту специфика дозволено применять для комментирования кода, тот, что не может быть скомпилирован. Скажем, дальнейший фрагмент выведет точку только при запуске под CPython:

print "x =", x
print "y =", y
#{
import pylab as pl
pl.plot(x, y)
pl.show()
#}

Версия 0.9.4, 16 июня 2013, Mark Dufour и James Coughlan

 

Источник: programmingmaster.ru

Оставить комментарий
БАЗА ЗНАНИЙ
СЛУЧАЙНАЯ СТАТЬЯ
СЛУЧАЙНЫЙ БЛОГ
СЛУЧАЙНЫЙ МОД
СЛУЧАЙНЫЙ СКИН
НОВЫЕ МОДЫ
НОВЫЕ СКИНЫ
НАКОПЛЕННЫЙ ОПЫТ
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB