Автор: Антон Броиловский Редактура: Александр Наздрюхин, Андрей Шадриков
Python — (ну очень) высокоуровневый язык программирования. При работе с ним не нужно задумываться о том, как управлять памятью. Не нужно заботиться о том, чтобы имя переменной вдруг не начало указывать на объект другого типа. Не нужно даже думать о race condition’ах. Можно даже начать исполнять код, не написав его целиком: строчка за строчкой, как мы это делаем в Jupyter.
Одновременно с удобствами, в предыдущем абзаце мы на самом деле перечислили и причины, из-за которых Python медленный: фрагментация памяти, динамическая типизация, GIL, отсутствие компилируемости — это его зоны роста. Кажется, сейчас так принято говорить, чтоб не обидеть 😉.
Python любят за его выразительность и простоту. sum(x ** 2 for x in arr if x % 2 == 0)
. Сейчас мы всего одной строчкой выразили намерение посчитать сумму квадратов всех четных элементов списка.
А не любят его за медлительность и большое потребление памяти. Хорошая новость в том, что с этим можно бороться. Есть способы попроще: например, использование numpy при работе с большими матрицами ускорит нас благодаря векторизации и нивелированию фрагментации памяти. А есть способы посложнее: например, написать свои биндинги на C/C++.
Сегодня мы рассмотрим Numba как один из относительно простых способов ускорить python-код. Благодаря ней мне удавалось ускорить расчеты иногда в десятки, а иногда и в сотни раз.
Вам достаточно просто установить библиотеку при помощи pip (pip install numba
). Затем импортировать декоратор @njit
или @jit
(from numba import njit
), обернуть вашу функцию и, если повезет, получить из коробки ускорение в несколько раз!
Всего есть два режима работы numba, ****с помощью которых можно сократить время исполнения вашего кода на питоне:
Numba всегда пытается скомпилировать любую функцию, обернутую декоратором @jit
в режиме nopython, а если не получится — обратится за помощью к object mode. Для гарантии работы режима nopython используется либо декоратор @njit
, либо аргумент nopython=True
у декоратора @jit
, тогда если функцию скомпилировать не удастся — numba выдаст ошибку.
Если в коде есть много математических расчетов и циклов, с огромной вероятностью numba — ваш спаситель.
Конечно, было бы здорово всегда использовать режим nopython — все работает хорошо и быстро.
Но у этого режима ****есть проблема: для компиляции кода numba должна знать все методы, используемые в функции, которую вы хотите оптимизировать. Вариантов не так много — это могут быть функции из стандартной библиотеки питона, либо из numpy.