В данном пункте приведем пример простой функции на языке python. В качестве функции рассматривалась функция, которая суммирует числа от 0 до N. В эксперименте сравнивается скорость работы данной функции в следующих случаях:
PythonFunc(N)
--- функция реализована на python без предварительной компиляции;NumbaFunc(N)
--- функция реализована на python с использованием Numba;PyPyFunc(N)
--- функция реализована на pypy;CythonFunc(N)
--- функция реализована на python но предварительно скомпилирована;CythonTypedFunc(N)
--- функция реализована на cython с типизацией объектов;CythonOpenMPFunc(N)
--- функция реализована на cython с типизацией объектов а также распаралеливанием на OpenMP;NuitkaFunc(N)
--- функция которая компилируется с помощью Nuitka
Для сравнения рассматривается N = 100000000 для всех моделей, а также каждая функция вызывается 200 раз для усреднения результата.
В данном простом примере получили следующие оценки времени работы функций:
Функция | Время |
---|---|
PythonFunc | 4421±42 ms |
PyPyFunc | 127±3 ms |
NumbaFunc | 0.002±0.001 ms |
CythonFunc | 3191±69 ms |
CythonTypedFunc | 31±1 ms |
CythonOpenMPFunc | 10±3 ms |
NuitkaFunc | 4161±79 ms |
Весь код доступен по ссылке и ссылке.
В данном пункте сравним скорости работы простого векторного представления предложений. В качестве базового решения выбран CountVectorizer
из пакета sklearn
.
На основе CountVectorizer
был написан сообвественый класс Vectorizer
на python. Данный класс повторяет базовые возможности класса CountVectorizer
, такие как fit
и transform
. Код доступен по ссылке и ссылке.
Сревнение производительности проводится для класса Vectorizer
который работает в следующих случаях:
Vectorizer
--- простая реалзиция на python без компиляции;PyPyVectorizer
--- компииляция функции на pypy3;CythonVectorizer
--- простая компиляция класса при помощи cython без использования типизации;CythonTypedVectorizer
--- простая компиляция класса при помощи cython c использованием типизации;NuitkaVectorizer
--- простая компиляцияя функции при помощи nuitka.
В эксперименте сравнивается время метода fit
, а также метода transform
для всех моделей. Для оценки времени производится усреднение по нескольким независимым вызовам данных методов. Каждый раз вызов метода fit
производится на новом объекте рассматриваемого класса. Метод transform
вызывается также каждый раз на новом объекте рассматриваемого класса после вызова метода fit
.
Оценка времени выполнялась для выборки, которая состояла из 79582 строк (16.8mb текста). Всего в данном тексте содержится 76777 различных токенов, которые были найдены всемы моделями и добавлены в словарь.
Для чистоты эксперимента время представленное в таблице является устредненным по 200 вызовам функции fit
и 200 вызовам функции transform
.
Функция | Время fit |
Время transform |
---|---|---|
Vectorizer | 487±12 ms | 1606±12 ms |
PyPyVectorizer | 382±24 ms | 3405±80 ms |
CythonVectorizer | 465±11 ms | 1500±12 ms |
CythonTypedVectorizer | 409±8 ms | 1465±12 ms |
NuitkaVectorizer | 554±23 ms | 1553±42 ms |
После проведенных экспериментов данный компилятор показал себя очень хорошо. Он легкий в использовании легко использовать даже в jupyter-notebook
при помощи команды %%cython
.
Как видно из синтетического примера данный компилятор работает очень хорошо когда типы в функциях являются строго фиксируемыми. Как видно из результатов в базовом примере, jit компилятор pypy выполняет детский пример намного быстрее, чем после компиляции при помощи cython. Но после добавления типизации cython версия все равно оказалась намного быстрее.
Также весь исходный код доступен по ссылке, ссылке. Данный код легко собирается выполнив команду:
python setup.py build_ext --inplace
Данный функционал является очень полезным. Простой вызов prange
вместо range
и код уже паралелится на чистом OpenMP без дополнительных затрат на pickle
для сериалиции.
Правда для нас как для иследователей и людей которые занимаются анализом данныз и не видят python без numpy
и всех его плюсов с умножением матриц и других полезных операций данная функция недоступна. Один из важнейших минусов работы OpenMP в cython является то, что он позволяет паралелить только куски кода которые написаны на C++. А весь код который в себе содержит python объекты нужно оборачивать в GIL блокировку. Одним словом вещь хорошая если ваш код написан в большинстве на C++, или же вы не используете python объекты.
Данный транслятор языка python показал себя намного лучше чем обычный python и даже лучше чем простые компиляции python кода при помощи cython и nuitka. Причем его скорость была сопоставима со скоростью уже скомпилированого кода в котором была задана типизация, а в некоторых случаях даже быстрее.
Достаточно неплохой компилятор для компиляции python кода. Позволяет как получать исходный код на C++, получать исполняемые модули .so для дальнейшего подключения в python например.
К сожалению на практике показал самый плохой результат из всех представленых выше. Его скорость была лишь немного выше чем в просто python транслятора, который выполняется на лету, не говоря уже про pypy транслятор.
Также весь исходный код доступен по ссылке, ссылке. Данный код легко собирается выполнив команду:
python -m nuitka\
--module FileName.py\
--include-package=FileName\
--follow-import-to=FileName\
--show-modules\
--remove-output\
--output-dir=FileNamePack
Очень классная штука, единственный минус что не компилирует исходник, а является jit компиляцией. Так же как и cython имеет свои особености что код под нее нужно переписывать. Имеет встроенную автоматическую процедуру распаралеливания кода.
Базовый пример показал, что данный транслятор намного быстрее всех других.
Тесты проводились на операционной системе Ubuntu 18.04.3 LTS
Версия | |
---|---|
Python | 3.6.9 |
PyPy | 7.3.0 |
Cython | 0.29.15 |
Nuitka | 0.6.7 |
Numba | 0.48.0 |
Версия | |
---|---|
g++ | 7.5.0 |
gcc | 7.5.0 |
- Kurt W. Smith. Cython: A Guide for Python Programmers. Sebastopol: O’Reilly, 2015.
- Gorelick M., Ozsvald I. Hight Performance Python. Sebastopol: O’Reilly, 2014.