Скорость
В этом разделе перечислены наиболее популярные способы оптимизации скорости, используемые сообществом Python. В табл. 8.1 показаны варианты оптимизации, которые вы можете применить после того, как попробуете простые методы вроде запуска профайлера (https://docs.python.org/3.5/library/profile.html) и сравнения параметров для сниппетов кода (https://docs.python.org/3.5/library/timeit.html).
Вы, возможно, уже слышали о глобальной блокировке интерпретатора (global interpreter lock, GIL) (http://wiki.python.org/moin/GlobalInterpreterLock). Это способ, с помощью которого реализация C для Python позволяет нескольким потокам работать одновременно.
Управление памятью в Python не полностью потокобезопасно, поэтому GIL нужен для того, чтобы помешать нескольким потокам запускать одновременно один и тот же код.
GIL зачастую называют ограничением Python, но он не является такой уж большой проблемой — мешает лишь тогда, когда процессы связаны с ЦП (в этом случае, как и для NumPy или криптографических библиотек, которые мы рассмотрим далее, код переписан на C со связыванием с Python). Для всего прочего (для ввода/вывода в сетях или файлах) узким местом является код, блокирующий один поток, ожидающий завершения операции ввода/вывода. Вы можете решить проблему с блокировкой с помощью потоков или событийно-ориентированного программирования.
Отметим, что в Python 2 имеются медленная и быстрая версии библиотек — StringIO и cStringIO, ElementTree и cElementTree. Реализации на C работают быстрее, но их нужно явно импортировать. Начиная с версии Python 3.3 обычные версии импортируют быструю реализацию там, где это возможно, а библиотеки, чье имя начинается с C, считаются устаревшими.
| Способ | Лицензия | Причины использовать |
|---|---|---|
| Многопоточность | PSFL | Позволяет создавать несколько потоков выполнения. Многопоточность (при использовании CPython из-за наличия GIL) не задействует собственные процессы; разные потоки переключаются, когда один из них заблокирован (это полезно, когда узким местом является какая-нибудь блокирующая задача вроде ожидания окончания операции ввода/вывода). GIL отсутствует в некоторых других реализациях Python вроде Jython и IronPython |
| Multiprocessing/subprocess | PSFL | Инструменты библиотеки multiprocessing позволяют создавать другие процессы Python, минуя GIL. Subprocess позволяет запускать несколько процессов командной строки |
| PyPy | Лицензия MIT | Этот интерпретатор Python (в данный момент для версии Python 2.7.10 или 3.2.5) предоставляет возможность динамической компиляции в код на языке С там, где это возможно. |
| Не требует усилий: вам не нужно писать код, при этом он дает значительный прирост скорости. Полноценная замена для CPython, которая обычно работает (любые библиотеки, написанные на С, должны использовать CFFI или находиться в списке совместимости PyPy (http://pypy.org/compat.html)) | ||
| Cython | Лицензия Apache | Предоставляет два способа статически скомпилировать код Python: использование языка аннотаций Cython (*.pxd); статистическое компилирование кода на чистом Python и применение декораторов Cython для указания типа объекта |
| Numba | Лицензия BSD | Предоставляет статический (благодаря инструменту pycc) и динамический компиляторы, компилирующие код в машинный код. Использует массивы NumPy. Требуется версия Python 2.7 или 3.4, библиотека llvmlite (http://llvmlite.pydata.org/en/latest/install/index.html) и ее зависимость, инфраструктура LLVM (Low-Level Virtual Machine) |
| Weave | Лицензия BSD | Предоставляет способ «сплести» несколько строк кода на C в код на Python (применяйте его только в том случае, если вы уже используете Weave). В противном случае используйте Cython — Weave считается устаревшим |
| PyCUDA/gnumpy/ TensorFlow/ Theano/PyOpenCL | MIT/модифицированная лицензия BSD/BSD/BSD/MIT | Эти библиотеки предоставляют разные способы использования NVIDIA GPU, если он у вас установлен, и могут установить набор инструментов для CUDA (http://docs.nvidia.com/cuda/). PyOpenCL может использовать процессоры не только от NVIDIA. Для каждого из них существует собственное приложение, например gnumpy предполагается как полноценная замена для NumPy |
| Непосредственное использование библиотек C/C++ | — | Повышение скорости стоит того, чтобы потратить дополнительное время на написание кода на C/C++ |