Комментарии 55
Я ссылаюсь на The Computer Language Benchmarks Game уже больше десяти лет.
Больше десяти лет ссылаться на такой бесполезный источник. Этим можно гордится?
Как вы решаете проблемы невысокой производительности Python?
Для особой задачи существуют особый инструмент. Проблема производительности не должна волновать, если выбран Python. Если же этот вопрос стоит, то вы ошиблись в первоначальном выборе инструмента для решения задачи. В общем случае в сравнении C, C++ и JAVA, программный код на языке Python проще писать, отлаживать и сопровождать.
А так пробовать CPython, Jython, IronPython.
В общем случае в сравнении C, C++ и JAVA, программный код на языке Python проще писать, отлаживать и сопровождать
Я бы добавил "в определенных задачах". С и плюсы, как компилируемые, конечно, имеют вынужденные сложности с разработкой, но java и прочие интерпретируемые строго типизированные языки при определеном размере кода могут быть проще в написании (IDE, как правило, проще работать с языками "построже"), и в сопровождении (проверки на уровне компиляции это хорошо — в слишком гибких языках regression можно отслеживать только тестами. Не, TDD это неплохо, но когда тест надо писать на любой чих, чтобы ничего не свалилось, то это сомнительное свойство языка)
Не надо кидаться в Java и равнть к другим. Легаси код понятие растяжимое: ему 1 год, 3 или 10 лет?
Тем более не забываем об анализаторах, которые умеют подсказывать (если уж не сам писал проект), где, что и как поменялось и что более не юзается в выбранной версии языка для проекта.
Далее, если речь идет о чистой Java (конечно с внешними либами, но без совсем уж жирных, которые именуют себя фреймворками), то там все просто и понятно, под свою задачу, есессно.
Но, например, если бы мне нужно было бы обсчитать массив чисел, и производительности бы не хватало, сегодня я попробовал бы связку Python+Numpy+Ctypes и поробовал бы написать работу с массивом чисел на Си и дергать ее из питона.
Ну или Cython, но не факт, что получиться написать быстрее, чем на Python+C. Я имею в виду скорость разработки.
Насколько я понимаю, описанная в статье проблема имеет влияние только когда есть много потоков, конкурирующих за процессор.
Во многих реальных задачах потоки ждут i/o операции большую часть времени, так что это может быть незаметно. На 100%cpu нечасто приходится работать. А в devops или нехитрой оптимизации (где питон часто используется и, на мой взгляд, особенно хорош) вообще ни о чем
Ну да — в этом сама суть.
Питон "человеческий" язык со своей областью применения.
Натягивание совы на глобус, чтобы быть "лучшим" языком… возможно, а оно надо?
Хайп вокруг питона последнее время меня смущает: никто не говорит, что скрипты на bash для автоматизации чего-то сложнее ls|grep|wc выглядят, как порождение марсиан, но, как только в питоне изменился синтакс print или ввели новые операторы — все дружно обсуждают кризис языка
Пример деградации проекта, из за непродуманных действий — это ситуация с perl. Сколько лет уже пилят 6 версию, но стандартом она так и не стала. Сам язык есть, но это все еще 5 версия, которая осталась в своей нише, но это совсем не то, что было во времена рассвета.
в геймдеве, например, только для скриптинга…
Маленькая инди-игра EVE Online всё ещё на Stackless Python в клиенте и серверах, производительность затыкалась вставками C/C++.
Причиной невысокой производительности Python является его динамическая природа и универсальность.
Что-то статья как-то резко оборвалась. В начале рассматривалось сравнение с Javascript — там же почти все тоже самое, нет? Неужели при обращении к переменной ее тип не проверяется, в чем принципиальная разница?
Информация из разряда «когда-то мимо пробегало», потому что JS не зашёл: пишу на Python и C/C++. Если ошибаюсь, буду рад узнать более точные сведения.
Написал некий подбор параметров для вычисления. сначала сделал это на Rust, заняло довольно много времени, так как это был первый подход к расту, без каких-то особенных оптимизаций получилось вполне примлемо: ~4млн данных подбирало 7 параметров (где-то 12млн комбинаций) на домашнем i5-7500 около 5 часов.
Потом захотелось добавить ML, естественным выбором для этого был питон. ML подсчитал всё что надо, но я подумал, что питон такой модный и молодёжный, что почему бы не попробовать его применить глубже.
сначала с pandas — скорость была такая, что он и 1k данным считал больше минуты — это ни в какие ворота. Переписал всё исключтельно на numpy — скорость стала вполне приличной.
Но всё не верторизируешь, и одним numpy сыт не будешь — добавил перебор параметров как было раньше — и с каждым лишним if программа проседала на порядки, в итоге ETA подсчёта того что я описал в первом обзаце, показал что оно будет считаться несколько месяцев, что очень резко охладило желание использовать питон где-то за пределами ML.
сначала с pandas — скорость была такая, что он и 1k данным считал больше минуты — это ни в какие ворота. Переписал всё исключтельно на numpy — скорость стала вполне приличной.
Но ведь у pandas под капотом как раз numpy крутится, не может у них быть какого-то значимого различия в скорости. Возможно, вы в первом случае просто что-то сделали не так.
In [38]: arr = np.random.rand(1000, 10000)
In [39]: df = pd.DataFrame(arr)
In [40]: %timeit arr.mean(axis=1)
4.62 ms ± 114 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [41]: %timeit df.apply(np.mean, axis=1)
109 ms ± 1.43 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [42]: np.all(arr.mean(axis=1) == df.apply(np.mean, axis=1))
Out[42]: True
Удивительно, что в статье не упомянули numba. На мой взгляд, это самый простой, но при этом очень мощный способ увеличения производительности при минимальных изменениях в исходном коде.
Все это уже давно известно, ничего нового, никакого углубления в суть. Вот если бы автор, например, взял пример какой-нибудь функции на python и проанализировал ее байт-код, замерил бы скорость его компиляции и интерпретации и по регистрам проанализировал получившийся в итоге нативный код, сравнив его с аналогичным результатом на c# или c++, тогда я б поклонился. Была бы видна незаурядная работа, а так просто перечень общеизвестных истин. Кстати, что cpython делает с байт-кодом в pyc файлах? Он его просто интерпретирует, не компилируя в нативный, или каждый раз перекомпилирует? — из статьи так это и не ясно
Кстати, что cpython делает с байт-кодом в pyc файлах? Он его просто интерпретирует, не компилируя в нативный, или каждый раз перекомпилирует?
Именно интерпретирует. Перекомпиляцию производит, если изменяется исходный код. Как определяет, я не в курсе, просто не было интересно. По сути, сохранение этих файлов несколько ускоряет запуск программы.
Стоит добавить про numba — в некоторых случаях очень хорошо ускоряет код
Если мне нужна числодробилка, я напишу программу на С (может даже с OpenCL). Если мне нужна программа, которая вычитывает из последовательного порта данные, пакует их в XML и пуляет на удаленный сервер по HTTPS с авторизацией по сертификатам — я напишу ее на Python. Потому что так проще, удобнее и быстрее.
Как вы решаете проблемы невысокой производительности Python?
Поскольку Python все более и более популярен в научной среде, эта проблема решается использованием библиотек с высокой производительностью. Для многих вычислительных задач и обработки данных хватает производительности numpy, scipy, numba, pandas. Для чего-то более хитрого можно написать основную часть на C/C++/Cython, а Python использовать как высокоуровневую обертку. Еще есть Dask, который для определенных задач обещает довольно простой параллелизм, масштабируемый до суперкомпьютеров, но я им пока не пробовал пользоваться.
PS: PyQt отлично помогает избавиться от проблем производительности в GUI.
и используемые потоки будут интенсивно использовать подсистему ввода-вывода (например, если они будут работать с сетью или с диском), тогда можно будет наблюдать последствия того, как GIL управляет потоками. Вот как это выглядит в случае использования двух потоков, интенсивно нагружающих процессов.«Смешались люди-кони», как раз IO работа параллелится замечательно, а вот для CPU нагрузки* потоки не помогут.
Но это опять же зависит от задачи, если вы будете делать задачу сжатия данных (архиватор), то решение по скорости будет сопоставимо с С/С++.
Питон надо рассматривать как «мастер»-язык (код который управляет другим кодом), поэтому хорошо знать не просто питон а связку Python-C++ или Python-Cython, тогда вопросы скорости отпадут.
Но если все же надо его то numpy (при правильном применении) или какая-нибудь другая domain-specific библиотека дает прекрасную однопоточную производительность сочетая скорость C с удобством Python.
Чисто питоновские решения следует запускать на PyPy — это дает ускорение на порядок а то и на два.
А я все же рекомендую использовать старый добрый и надежный tcl.
Уважаемые читатели! Как вы решаете проблемы невысокой производительности Python?
Переходом на Julia.
.NET CIL (это то же самое, что .NET Common-Language-Runtime, CLR)
CIL далеко не то же самое что и CLR!!!
Да, в Python приходится думать что, как и почему. Но вариантов ускорить работу кода — море.
- Самый хороший способ — векторизация. Если есть возможность работать не с отдельными числами, а с массивами, а ещё лучше с матрицами, то надо так и делать — передавать массивы/матрицы и работать с ними прямо целиком. Тогда и Numpy, да и Pandas тоже, вполне себе летают.
- Если векторизировать нельзя и нужно обрабатывать отдельные числа внутри длинных циклов, то можно попробовать Numba, она с такими случаями хорошо справляется.
- Если есть предположение, что при обработке могут повторяться одинаковые данные, с которыми производятся "тяжёлые" вычисления, то хорошо работает кэширующий декоратор @functools.lru_cache
- Если простаивают ядра процессора, то можно использовать в каких-то случаях Dask (хотя у меня с ним всё время глюки вылазили, может просто я его не умею готовить), а в каких-то простейший Pool по парадигме map -> reduce. При грамотном подходе (достаточном размере порций и равномерности разбиения данных) это даст реальное ускорение, близкое к числу ядер процессора. Главное, не вылезать за память при этом. Как показывает практика, крэша при этом не будет (что меня удивило), но активная работа со свопом гасит весь эффект от ускорения.
Python — это медленно. Почему?