Итак, что такое Cython?
Cython – это язык, который очень-очень похож на Python с добавлением синтаксических изюминок. Для того, чтобы убедиться в этом давайте взглянем на пример функции, реализованной на Python:
def is_prime_python(n):
for i in range(2, n):
if n % i == 0:
return False
return True
%%time
_ = is_prime_python(6_700_417)
Output:
CPU times: user 577 ms, sys: 4.35 ms, total: 582 ms
Wall time: 584 ms
Приведен простейший пример реализации проверки числа – простое число или нет. В качестве аргумента было взято большое число и видно, что Python проверяет это число примерно за полсекунды.
Теперь рассмотрим визави – Cython и реализацию его функции проверки числа:
%%cython
def is_prime_cython(int n):
cdef int i
for i in range(2, n):
if n % i == 0:
return False
return True
%%time
_ = is_prime_cython(6_700_417)
Output:
CPU times: user 23.1 ms, sys: 0 ns, total: 23.1 ms
Wall time: 26.8 ms
На первый взгляд отличий в коде практически нет, однако по результатам производительности видно превосходство Cython почти в 25 раз.
Давайте разберемся в чем же дело.
Разница состоит в том, что Cython в отличие от Python статически компилируемый и в нем есть, скажем, синтаксический сахар, который позволяет добавить статическую информацию о типах. В примере реализации функции на Python (напомню, что данный язык динамически типизируемый) в качестве аргумента подается какое-то n, а это n может оказаться чем угодно. И из-за, казалось бы, такой мелочи Python очень медленный. Интерпретатор Python совершает очень много действий для того, чтобы выяснить что же находится в этой переменной n.
В Cython, как и в таких языках как Java, C++, явно указывается то, что переменная n имеет тип int и переменная в цикле i также имеет тип int. Из-за этих явных указаний типов в переменной и происходит ускорение кода, так как больше нужно думать о том, какой это объект, какой у него тип данных и т.д.
На краткой схеме пайплайна Cython видно, что Cython код транслируется в C/C++ код, а далее компилируется в питоновское расширение .pyd, которое потом уже может использоваться с помощью Python. Это тоже одна из причин почему Cython супербыстрый.
Возникает хороший вопрос: «как компилировать Cython?». А на самом деле компилировать его очень даже просто. В примере реализации функции на Cython вызывается команда %%Cython, которая в свою очередь компилирует Cython код в ячейке.
Как мы знаем в С/С++ необходимо использовать Visual Studio, писать, запускать, компилировать, поэтому всё это бывает довольно сложно и вопрос, который возникает в случае с компилируемым языком «насколько сложно его компилировать?». В случае с Cython – супер просто. Условно в Jupyter ноутбуке написали код, вызвали команду %%Cython и код скомпилирован – его можно использовать. Если же имеется какой-то Cython код в файле, то необходимо просто импортировать install(), вызвать его. Соответственно, когда импортируются какие-то функции из файла, то Cython автоматически скомпилирует этот код.
Код, написанный в редакторе:
def is_prime_cython(int n):
cdef int i
for i in range(2, n):
if n % i == 0:
return False
return True
Теперь импортируем его следующей командой:
from pyximport import install
install()
from prime_check import is_prime_cython
Промежуточные итоги:
Cython - компилируемый язык;
Его синтаксис очень похож на Python, но с некоторыми дополнениями для статической типизации;
Статическая типизация + компиляция = скорость;
Писать только Python код, в случае Cython, совершенно нормально;
Нет никаких проблем с компиляцией.
Знатоки Numba скажут: зачем смотреть в сторону Cython, если можно просто использовать декоратор из Numba и код существенно прибавит в быстродействии.
Поговорим немного о разнице.
Напишем то же самый код для проверки числа только теперь сравним все полученные результаты:
Python | Cython | Numba |
|
|
|
|
|
|
CPU times: user 753 ms, sys: 3.75 ms, total: 756 ms Wall time: 783 ms | CPU times: user 21.3 ms, sys: 139 µs, total: 21.5 ms Wall time: 21.5 ms | CPU times: user 113 ms, sys: 1.18 ms, total: 114 ms Wall time: 115 ms |
Видно, что добавив декоратор @numba.njit, код ускорился почти в 5 раз и нет необходимости добавлять что-то лишнего, как в случае Cython. И зачем тогда изучать Cython, если везде можно обходиться одними декораторами от Numba?
У Cython есть одно большое преимущество перед Numba. Поскольку Cython язык, в нем есть всякие вещи по типу классов, в то время как Numba просто компилятор (не язык). Поэтому Cython может быть объектно-ориентированным, а Numba не может работать с классами нормально.
И другие плюсы Cython:
Cython поддерживает многомерные массивы (включая Numpy), следовательно более быстрый доступ к данным;
Cython выполняет множество проверок за вас: проверка границ массива, деление на ноль, переполнение;
Cython не ограничивается численными вычислениями.
Однако можно задаться вопросом: «зачем нам такой Python, если Cython это по сути тот же Python только быстрее и вообще он идеальный». Тем не менее и в Cython есть свои проблемы. Порой Cython код сложно отлаживать: когда допускается одна ошибка, синтаксический анализатор Cython проходит по всему коду, как лавина, и после одной ошибки возникает миллион других ошибок. Поэтому совет – смотрите самый верх (первые строчки) в сообщении об ошибке.
Документация не самая лучшая, так как это своего рода набор туториалов, то есть азы изучить можно, но если необходимо углубится в какой-то функционал, то трудно найти или практически невозможно найти описание.
Когда пишется оптимизированный код на Cython, он начинает походить на C, а C без соответствующей культуры начинает превращаться в какую-то кашу.
Просуммируем полученные знания:
Cython быстрый как C;
Поскольку это язык, то он очень гибкий;
Легко оборачивать C/C++ код;
Отладка Cython кода может быть проблемой;
Не лучшая документация.
Проекты, использующие Cython
Существующие проекты, которые используют Cython подтверждают тот тезис, что Cython создан не только для каких-то математических задач. Так Quora – веб-сайт, на котором отвечают на всякие вопросы, имеет очень загруженный трафик. Чтобы избавиться от проблем, которые преследуют в Python, этот сайт решили написать на Cython. К тому же уже знакомые библиотеки Pandas, а также Scikit-Learn используют язык Cython для улучшения своего функционала.
Финальные итоги:
Cython – это Python с некоторыми статическими вещами для скорости;
Cython отлично подходит для ускорения приложений Python;
Упакован множеством замечательных функций: оборачивание C/C++ кода, параллельные вычисления;
Не ограничивается численными вычислениями.