Pull to refresh

Comments 28

Пришло время открыть для себя самый старый и эффективный способ компиляции питонячего кода в бинарники — Cython.
Cython — хороший инструмент, но он не умеет «компилировать питонячий код». Cython это отдельный язык, местами похожий на python, и только.
Всмысле? Делаете с помощью cython сишный код, ну а потом его уж и компилить можно… чем угодно)
В том смысле, что не получится просто взять и скомпилировать, приведенную выше, функцию bubble_sort с помощью Сython. Ее нужно сначала переписать на Сython, а потом можно будет скомпилировать в С. А с помощью mypyc можно скомпилировать прямо python код. Т.е. один и тот же исходник может работать как обычный python модуль, так и в форме бинарника (CPython Extension).
Пробовали? Я к тому, что достаточно две строки в терминале, одна заставляет cython создать вам .c исходник (не все ли равно, что внутри), ну а после — уже какой-нибудь gcc. И вуаля, ну всего лишь лишняя строчка, не более
Да вы правы. Cython уже умеет компилировать python на прямую! А я похоже это проспал. Это здорово — больше python-компиляторов богу python-компиляторов. Добавлю в статью.
Функция bubble_sort без проблем компилируется при помощи Cython.
Непосредственно в ее оригинальном виде, без каких-либо аннотаций.

Я это сделал вот так:
from setuptools import setup
from Cython.Build import cythonize
setup(
	ext_modules = cythonize('lib.py'),
	script_args = ['build_ext', '--inplace'],
)

Получил файл вида «lib.<python version and platform>.pyd», который является dll/so-файлом (по соседству с ним и .c), аналогично имеет приоритет при импорте.
Ускорение дает примерно такое же, на моей машине 2.320 сек против 5.337 сек.

Аннотации (вот они уже специфичны для Cython, cdef там всякие) не пробовал добавлять.
Спасибо обновил статью!

В Cython работают над поддержкой аннотаций типов. Не знаю, как там прогресс, но обещали, что можно будет писать на Python, без всяких cdef и подобного.

Да, я слышал об этом, но это пока в планах. Но мне казалось, что они хотят просто сделать cython более похожим на python, но не компилировать сам python. В любом случае сейчас это не работает.
Запоздалый ответ, но Pyrex — это надмножество Python, соответственно Cython может транслировать любой валидный питонячий код. Расширения языка нужны только для трансляции в более эффективный сишный код.
Да, но пока он не учитывает аннотацию типов, работать эффективно скомпилированный код не может.
В смысле? Чисто питонячий код работает в среднем на 30% быстрее после компиляции Cython'ом, а если использовать pyrex'овые расширения, то типы переменных можно объявлять и тогда прирост будет уже сравнимый с чисто сишным кодом.
то типы переменных можно объявлять

т.е. переписть код на Cython? Hо если код уже содержит аннотации типов, то не разумно ли их использовать? mypyc как раз опирается на стандартную аннотацию типов, а mypy гарантирует соответствие объявленных типов их использованию в коде.

Такие идеи возникают уже лет 15 если не больше. Проблема в том, что в общем случае относительно типов python доказать что-либо практически невозможно. Слишком много динамических конструкций и магии. В рамках отдельного проекта ещё можно договориться об использовании какого-то подмножества языка (см. например rpython) и получить желанную возможность компилировать код статически, но в масштабе всей экосистемы это не реализуемо.

Интересно, мне в основном попадались проекты по внедрению JIT-а: psyco, Unladen Swallow, Pystone, Nimba, PyPy. Но не про AOT компиляцию. Про RPython читал, но на сколько я понимаю, он не совместим с обычным python, т.е. не получится использовать сторонние python пакеты, из-за чего применение его в реальности, практически невозможно. С mypyc же можно компилировать модули импортирующие обычные пакеты (при их использовании расширение будет возвращать управление интерпретатору). Поэтому мне этот путь видится наиболее перспективным.
Что касается динамических конструкцию, то mypy уже вносит достаточно ограничений, осталось исключить monkey patching.
мда, написать код на питоне, чтобы его потом подравить для генерации в С код, чтобы потом получить хз какое ускорение… Может нужно было вручную сразу переписать (необходимый) код на С?
Код на С тут присутствует как промежуточная стадия компиляции, и не более того, читать его практически невозможно и не нужно (если вы не занимаетесь оптимизацией самого компилятора). Это не отменяет сам факт, компиляции. По аналогичной схеме работают компиляторы Nim, Vala.
Может нужно было вручную сразу переписать (необходимый) код на С

Может сразу на ассемблер, чего уж?

Пришлось специально прочитать всю статью, чтобы убедиться — имеется ввиду "как скомпилировать программу на python".
А в компиляции самого питона ничего нового не появилось — согласно документации:


./configure
make
make install
По моему, из введения, должно стать понятно, что речь про компиляцию python-кода, а не CPython интерпретатора. В любом случае, надеюсь, что время потрачено не зря.
Раз уж пошло перечисление компиляторов, то грех не вспомнить GraalVM, ahead-of-time там тоже есть в виде native images, судя по документации, это даже дефолтный способ запуска python.
структуры CPyTagged. Это все еще не int

ну да…
typedef size_t CPyTagged;

41
Даже так! Думаю меня «говорящее» название типа смутило
>> Компиляция python кода в код С
Наверное всё-таки трансляция
UFO just landed and posted this here
С холодного старта? В любом случае впечатляет (если это не какая-то оптимизация). Но все таки JIT это совсем другая технология. И у PyPy есть свои недостатки, из-за чего его еще сложно встретить в реальной жизни.
И обращаю ваше внимание на статью Jukka Lehtosalo, там он говорит, что перевод на PyPy существенно ситуацию (скорость работы mypy) не улучшил, это и сподвигло его к созданию mypy.

Кстати расширения компилируемые mypyc могут работать и с PyPy, для этого генерируются отдельные варианты функций.
UFO just landed and posted this here
А у меня такой вопрос, может кто-то подскажет. Когда писал на python 3.5, то частенько собирал модули в Extension и компилировал с помощью build_ext. Все работало прекрасно. Потом обновился на последнюю версию python 3.9, начал использовать dataclass. Но столкнулся с тем, что мой способ компиляции перестал работать. Точнее модуль конечно компилируется, но во время работы скрипт падает при вызове инициализации dataclass. Разного рода ошибки с аргументами __init__.
Данную проблему можно как-то решить или это из общих ограничений?
Или надо выбирать либо dataclass, либо обычный класс и компиляция.
Sign up to leave a comment.