Python лишается экспериментального JIT-компилятора: авторы PEP 836 отозвали предложение
Python's experimental JIT to be removed
Экспериментальный JIT-компилятор, добавленный в CPython в 2024 году для версии 3.13, будет удалён из основной ветки. Steering council потребовал стандартизировать проект через PEP с чёткими гарантиями и метриками, но после месяцев обсуждений авторы PEP 836 отозвали его, сославшись на нехватку ресурсов. Работа остановится в основном репозитории; продолжат ли её где-то ещё — решит сообщество.
Steering council справедливо устанавливает высокую планку для предложения такого масштаба, и мы не чувствуем, что у нас есть личные ресурсы, чтобы продвигать текущую версию дальше.
- adrian17
Досадно. Я время от времени следил за работой над этим.
С одной стороны, казалось, что работа над JIT шла полным ходом, пока SC не запросил новый PEP. Ещё досаднее, потому что частью надежды на JIT было то, что он компенсирует падение производительности из-за free threading.
С другой стороны, мне казалось, что при всех навороченных (и определённо крутых) оптимизациях, которые он получил (автоматическое удаление операций с refcount, новые специализации на основе типов, inplace-математические операции), выигрыш на макробенчмарках был не _таким уж_ впечатляющим для JIT. Потенциал для большего определённо есть, возможно, с ещё более навороченными оптимизациями вроде распаковки int'ов, но сложность только растёт.
> Там говорилось, что PEP был «чрезмерно оптимистичен» насчёт видимых пользователю различий при включённом JIT.
Технически JIT генерируется из того же исходника, что и сам цикл интерпретатора, так что изначально различия были крайне маловероятны, но, полагаю, риск только рос по мере появления новых путей и оптимизаций, специфичных только для JIT.
А политически, мне кажется, рассуждение SC было просто «этот побочный проект попал в основную ветку почти случайно и с тех пор варился без надзора, без признаков стабилизации»; и последний PEP, вероятно, всё ещё был слишком расплывчатым, с кучей «вот ещё вещи, которые мы можем добавить в варево» — так что я могу понять, если SC остался недоволен.
- rich_sasha
Вот вместо этого идея (может, она уже существует). Разрешить декоратор для написания inline-кода на Cython. Думаю, это решает 90% проблемы. При первом запуске или сразу компилировать декорированные функции. По сути, Cython и есть JIT, и пользователь включает его явно.
Так я могу легко писать встроенные функции с настоящей скоростью C на языке, похожем на Python.
Причины, по которым я редко использую Cython без этого:
- неизменённый Python-код, работающий в Cython, часто быстрее, но не настолько. Около 50% — это моё эмпирическое правило.
- но стиль разработки в Cython и Python очень разный, что добавляет много неудобств. Например, перезагрузка не совсем работает, профилирование другое, нужен каталог сборки и шаг сборки при развёртывании и т.д.
- сам Cython достаточно отличается и, я бы сказал, достаточно неинтуитивен, что если мне приходится иметь всё это, я лучше оберну свою функцию в Rust.
Такой декоратор дал бы вам способ с низким трением ускорять вещи, когда это нужно, с возможностью сделать их намного быстрее через все забавные возможности Cython, сохраняя при этом семантику в духе Python, в частности «семантику разработки».
Думаю, это потребовало бы некоторой модификации языка, поскольку Cython определённо был надмножеством Python; кажется, часть этого синтаксиса была упрощена, но, возможно, всё ещё строгое надмножество.
- PathOfEclipse
Сколько экспериментов с JIT для Python провалилось? Мне интересно, потому что Ruby, вероятно, сложнее оптимизировать, чем Python, но в Ruby JIT есть уже давно. Может, базовый Python более оптимизирован, чем базовый Ruby, поэтому JIT постепенно мало что меняет? Ещё я бы ожидал, что JavaScript сложнее оптимизировать, но у него есть JIT'ы. Хотя это может быть просто вопрос финансирования. Вероятно, на оптимизацию JavaScript есть гораздо больше денег и стимулов.
- graemep
Если посмотреть на причины, это кажется хорошим решением: https://discuss.python.org/t/pep-836-jit-go-brrr-the-path-to...
Уже есть много способов решить проблему производительности Python (оставляя в стороне вопрос, хороший ли Python выбор, если производительность важна), такие как Cython, Numba, Pypy и C-расширения.
- xx_ns
Досадно, что технически захватывающая новая функция убивается отчасти из-за того, что по сути является бюрократией (и нехватки личного времени у разработчика). С другой стороны, можно с уверенностью сказать, что строгое соблюдение политики PEP и вся связанная с этим бюрократия — это то, что делает Python отличным языком, к лучшему или к худшему.
Не сказать, что технические возражения были безосновательны, скорее всего, они очень даже были, и поддержка отладчика и инструментирования, а также работа по сопровождению звучат довольно болезненно сами по себе.
- mike_hearn
Печальный день для CPython, но он не обязан быть печальным днём для Python. Есть полностью поддерживаемая реализация Python 3.13 с продвинутым JIT-компилятором. Как только ваш Python прогреется, он может быть в 4 раза быстрее или больше (в зависимости от того, что делает ваша программа). Эта реализация называется GraalPy и строится на JVM:
Немного как Chrome: есть полностью открытая версия и проприетарная с несколькими дополнительными наворотами, но последняя полностью бесплатна как для открытого, так и для коммерческого использования (вы не можете распространять её за плату). Так что можете смело использовать её.
У неё есть другие интересные возможности
• Масштабируемый GC без пауз
• Распространение Python-программ одним бинарником (как в Go)
• Навороченное и оптимизированное взаимодействие с другими языками, включая Java, JavaScript, Kotlin, Ruby и любой другой язык Truffle.
• Поддержка нативных расширений. Протестировано и работает с распространёнными библиотеками, такими как SciPy, NumPy, PyTorch, Pandas и т.д.: https://graalpy.org/python-developers/compatibility/
• Они работают над режимом без GIL
В последние недели вышел новый веб-фреймворк для Python, который работает только на GraalPy, под названием Pyronaut (https://pyronaut.io/). Он использует преимущества взаимодействия с JVM, чтобы предоставить фреймворк Micronaut, который похож на Spring для тех, кто знает. Благодаря JIT и хорошо оптимизированным базовым библиотекам он работает чрезвычайно быстро, примерно в 3 раза быстрее, чем FastAPI+Granian, или в 7 раз быстрее, чем Flask+Gunicorn, и имеет гораздо больше возможностей.
- pansa2
> мы не чувствуем, что у нас есть личные ресурсы, чтобы продвигать текущую версию вперёд
Разработчики JIT — это те же люди, которые работали над Faster CPython в Microsoft? Неудивительно, что у них нет того же количества энергии, чтобы посвящать её JIT, теперь, когда он превратился из работы на полную ставку в хобби-проект.
- kannanvijayan
Выскажу здесь техническое горячее мнение.
Python — зрелый производственный язык с множеством пользователей. Ещё до того, как он стал огромным — лет 20 назад, когда я учился в колледже — чтобы внести небольшое обратно совместимое изменение API в расширение Python (в моём случае gnu readline), требовалось лично убедить GvR, что изменение API необходимо.
Каждая попытка JIT для Python, которую я видел, просто пытается копнуть слишком глубоко с первого захода и задаёт себе слишком большой масштаб.
Я считаю, что любая успешная попытка оптимизировать производительность Python с помощью JIT должна СНАЧАЛА начаться со 100% семантически совместимой скрытой модели типов для оптимизации доступа к свойствам объектов и диспетчеризации методов.
Самая большая разница в производительности в большинстве JIT для динамических языков происходит именно от этого, а не от оптимизации проверок в байткод-операциях или от компиляции в машинный код. Она от преобразования поиска в хеш-таблице в проверку + смещение за постоянное время.
Скрытую модель типов тоже непросто взломать. Она должна сохранять семантику dict, которые имеют очень динамичное поведение через различные методы `__*__`, и обрабатывать экзотические объекты области видимости, поскольку поиск по области видимости — самый распространённый, и у него своё экзотическое поведение (помню, Python предоставлял некоторую возможность кадрам вызываемого объекта инспектировать области видимости вызывающего в некоторых ограниченных случаях).