26 февраля 2010 г.

Ускоряем Python код.

fun python icon

Для людей программирующих на Python не секрет что его интерпритатор скоростью не блещет. И программы написаные на Python, по сравнению с большинством компилируемых языков, выполняются на порядки медленее.

Так как можно увеличить скорость исполнения программы не ухудшая простоту и ясность кода? Есть несколько способов.

Оговорюсь сразу что описанные способы не являются панацеей, и могут не подойти для применения во многих случаях. Если вам кажется что программа интерпретируется недостаточно быстро, то до применения любого из описаных способов необходимо выяснить узкие места с помощью профайлера. Благо в Python (>2.4) уже есть встроенные средства профилирования (cProfile, profile, hotshot).


Первым и очевидным способом увеличить быстродействие без изменений в коде программы является ускорение работы самого интерпритатора. Этим занялась Google, запустив проект Unladen Swallow. Цель - с помощью создания быстрой виртуальной машины на основе LLVM и JIT компиляции ускорить работу программ на Python в 5 раз по сравнению с CPython.

Можно использовать модули JIT компиляции и в самом CPython. Самым известным является Psyco. Теоретически с ним программы могут сравниться по скорости с аналогичными, написанными на Си. На практике он дает прирост скорости от 5 до 100 раз, но чаще - не более 10. Чтобы использовать Psyco нужно добавить в начале файла две строки:

import psyco
psyco.full()

Недостатками Psyco является то, что он реализован только для 32-разрядных версий CPython, и проект больше не развивается, хотя довольно широко используется.

Для быстрой работы с многомерными массивами есть замечательный модуль NumPy. Он написан на Си и содержит функции по работе с массивами, преобразований Фурье, случайными числами. Вместе с модулями SciPy и matplotlib могут служить заменой для MathLab. Работа с массивами NumPy гораздо быстрее, чем со списками или кортежами Python. А в сочетании с компиляторами, описанными ниже, дают скорость сопоставимую со скоростью программ на С/С++.

Jython iconЕще одним возможным выходом будет использовать не CPython, а другие реализации Пайтона, например Jython или IronPython. Они позволяют проводить бесшовную интеграцию кода написаного на Java и .NET соответственно. Хотя они и медленее CPython, использование JIT компиляции позволяет ускорить работу с массивами и сократить издержки на вызов функций.

Python предоставляет С - API для написания расширений и библиотек на других языках. Но писать критичные по производительности куски кода непосредственно на C/C++ (или другом языке) мягко говоря утомительно, поскольку большая часть кода будет содержать не логику работы программы, а конвертацию типов и жонглирование указателями.

Boost iconВ библиотеке Boost, знакомой C++ программистам, содержится фрэймворк boost.python, с помощью которого можно как писать расширения для Python на C++, так и вызывать Python код из С++ кода.

Этот способ как и способ с использованием Jython/IronPython плохи тем, что для увеличения скорости выполнения приходится приносить в жертву удобочитаемость и простоту кода. Было бы хорошо автоматически переводить код написанный на Python на какой нибудь компилируемый яык (C++/C#/Java).

Cython iconДля этого есть несколько инструментов: ShedSkin - оптимизирующий компилятор, переводящий исходный код Python на C++, и модуль Cython, позволяющий переводить Python-код на язык C или C++. И хотя оба делают практически одно и тоже, различий у них довольно много. Так ShedSkin - это экспериментальный компилятор на основе gcc, который может компилировать только типизированое подмножество Пайтона. Cython же по сути является надмножеством языка, в которое ввели информацию о типах. То есть практически любая корректная программа на Python c помощью Cython может быть переведена на язык C (это основной язык, хотя есть возможность использовать и C++), что не является верным для ShedSkin. Cython позволяет работать как с высокоуровневым абстракциями Python, так и с низкоуровневым типами и С-функциями. Притом конвертация типов происходит прозрачно для программиста. При использовании таких библиотек как NumPy, скорость работы, при обработке большого числа данных, вплотную приближается к скорости чистого C и часто выше аналогичной программы на C++.

Главное во время (а лучше и до) начала оптимизации помнить, что проще сделать правильную программу быстрой, чем быструю правильной.

Комментариев нет:

Отправить комментарий