Выбрать главу

········i = 0

········while i < k and n % p[i]!= 0:

············i = i + 1

········if i == k:

············p[k] = n

············k = k + 1

············result.append(n)

········n = n + 1

····return result

Эта реализация алгоритма поиска простых чисел содержит дополнительные ключевые слова. Следующий пример написан на чистом Python:

def primes(kmax):

""" Расчет простых чисел с помощью стандартного синтаксиса Python """

····p= range(1000)

····result = []

····if kmax > 1000:

········kmax = 1000

····k = 0

····n = 2

····while k < kmax:

········i = 0

········while i < k and n % p[i]!= 0:

············i = i + 1

········if i == k:

············p[k] = n

············k = k + 1

············result.append(n)

········n = n + 1

····return result

Обратите внимание: в версии Cython вы объявляете, что целые числа и массивы целых чисел будут скомпилированы в типы C, в то же время будет создан список Python:

Тип объявляется как целое число.

Переменные n, k и i объявляются как целые числа.

Мы заранее выделяем память для массива целых чисел p размером в 1000 элементов.

В чем же разница? В версии Cython вы можете увидеть объявление типов переменных и массива целых чисел, которые выглядят так же, как и в обычном С. Например, дополнительное объявление типа (целочисленного) в выражении cdef int n,k,i позволяет компилятору Cython генерировать более эффективный код С. Поскольку синтаксис несовместим со стандартным Python, он сохраняется в файлах с расширением *.pyx, а не с расширением *.py.

Каковы различия в скорости? Давайте проверим!

Модуль pyximport позволяет импортировать файлы с расширением *.pyx (например, primesCy.pyx) с помощью скомпилированной в Cython версии функции primes.

Команда pyximport.install() позволяет интерпретатору Python непосредственно запустить компилятор Cython для генерации кода C, который автоматически компилируется в библиотеку с расширением *.so. Далее Cython может легко и эффективно импортировать эту библиотеку в ваш код Python.

С помощью функции time.time() вы можете сравнить время выполнения этих двух вызовов, которые определяют 500 простых чисел. На стандартном ноутбуке (dual-core AMD E-450 1.6 GHz) мы получили следующие значения:

Cython time: 0.0054 seconds

Python time: 0.0566 seconds

А здесь результат работы встроенной машины ARM BeagleBone (http://beagleboard.org/Products/BeagleBone):

Cython time: 0.0196 seconds

Python time: 0.3302 seconds

Numba

Numba (http://numba.pydata.org/) — это компилятор для Python, поддерживающий NumPy (он является динамическим — just-in-time (JIT)). Компилирует аннотированный код Python (и NumPy) для LLVM (Low-Level Virtual Machine) (http://llvm.org/) с помощью особых декораторов. Вкратце, Numba использует LLVM для компилирования кода Python в машинный код, который может быть нативно выполнен во время работы программы.

Если вы используете Anaconda, установите Numba с помощью команды conda install numba. Если нет, установите его вручную. Вы должны заранее установить NumPy и LLVM (перед Numba).

Проверьте, какая версия LLVM вам нужна (на странице PyPI для llvmlite по адресу https://pypi.python.org/pypi/llvmlite), и загрузите ее для вашей ОС:

• сборки LLVM для Windows (http://llvm.org/builds/);

• сборки LLVM для Debian/Ubuntu (http://llvm.org/apt/);

• сборки LLVM для Fedora (https://apps.fedoraproject.org/packages/llvm);

• вы можете найти информацию о том, как устанавливать LLVM на основе исходного кода для других систем Unix, в разделе «Сборка компиляторов Clang + LLVM» (http://ftp.math.utah.edu/pub/llvm/);

• для OS X используйте команду brew install homebrew/versions/llvm37 (или выберите текущую версию).

Как только вы установите LLVM и NumPy, инсталлируйте Numba с помощью pip. Вам может понадобиться помочь установщику найти файл llvm-config, предоставив переменной среды LLVM_CONFIG соответствующий путь, например:

$ LLVM_CONFIG=/path/to/llvm-config-3.7 pip install numba

Чтобы использовать его в своем коде, декорируйте свои функции:

Без аргументов декоратор @jit выполняет ленивую компиляцию — сам решает, оптимизировать ли функцию и как это сделать.