В Python, почему модуль реализован на C быстрее, чем чистый модуль Python, и как мне написать один? - PullRequest
9 голосов
/ 06 января 2011

Документация Python гласит, что причина, по которой cPickle быстрее, чем Pickle, заключается в том, что первый реализован на C. Что это означает точно?

Я делаю модуль для продвинутой математики на Python, инекоторые расчеты занимают значительное количество времени.Означает ли это, что если моя программа реализована на C, то она может быть сделана намного быстрее?

Я хочу импортировать этот модуль из других программ Python, так же, как я могу импортировать cPickle.

МожетВы объясняете, как реализовать модуль Python в C?

Ответы [ 4 ]

15 голосов
/ 06 января 2011

вы можете написать быстрый C-код и затем использовать его в ваших скриптах Python, чтобы ваша программа работала быстрее. [1] http://docs.python.org/extending/index.html#extending-index

Примером является Numpy, написанный на C (http://numpy.scipy.org/)

типичное использование - реализовать узкое место в C (или использовать библиотеку, написанную на C, конечно;)), из-за его скорости, и использовать python для оставшегося кода

[1] кстати, именно поэтому cPickle быстрее, чем pickle

редактирование:

взгляните на Pyrex: http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/version/Doc/About.html

'Pyrex - это язык специально предназначен для написания расширения Python модули. Он предназначен для преодоления разрыв между красивым, высоким уровнем, простой в использовании мир Python и грязный, низкоуровневый мир C. '

это не 'официальный' способ, но он может быть полезен

8 голосов
/ 06 января 2011

Как уже упоминалось, Numpy отлично подходит для векторных вычислений.(Может быть, еще лучше, но комментарий о том, что это лучше, чем что-либо, что вы могли бы написать без фактического выполнения работы, определенно верен.)

Однако не все может быть легко векторизовано, так что если у вас действительно есть тесные внутренниемного вызовов функций (скажем, сильно рекурсивный алгоритм), у вас все еще есть несколько вариантов: вероятно, наиболее популярным является Cython , который позволяет вам писать модули и функции в виде аннотированного Python и получать C-как скорость, когда вам это нужно.

Или, может быть, все ваше время находится во власти библиотечных вызовов для вычисления собственных значений или инвертирования матриц, вычисления специальных функций или деления действительно больших целых чисел - многие из которых проект Sage очень хорошо обрабатывает,Кстати, если то, что вы делаете, является более математическим, чем чисто сложное - в этом случае время, проведенное в Python, может даже не иметь значения.Все зависит от того, какие цифры вы используете.

7 голосов
/ 08 января 2011

Когда вы пишете функцию в python, создается новый объект функции, код функции анализируется и байт-компилируется [и сохраняется в атрибуте «func_code»], поэтому при вызове этой функции интерпретатор читает свой байт-код и выполняет его .

Если вы напишите ту же функцию в C, следуя API C / Python, чтобы сделать ее доступной в Python, интерпретатор создаст объект функции, но эта функция не будет иметь байт-кода. Когда интерпретатор находит вызов этой функции, он вызывает реальную функцию C, поэтому он выполняется со скоростью «машина», а не со скоростью «python-machine».

Вы можете проверить эту функцию проверки, написанную на C:

>>> map.func_code
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'builtin_function_or_method' object has no attribute 'func_code'
>>> def mymap():pass
... 
>>> mymap.func_code
<code object mymap at 0xcfb5b0, file "<stdin>", line 1>

Чтобы понять, как вы можете написать C-код для использования на Python, следуйте инструкциям на официальном сайте.

В любом случае, если вы просто выполняете вычисления в N-мерном массиве, numpy должно быть достаточно.

5 голосов
/ 06 января 2011

Помимо уже упомянутого Pyrex / Cython, у вас есть другие альтернативы:

Shed Skin : переводит (ограниченное подмножество) Python в C ++. Может автоматически сгенерировать расширение для вас. Для этого вы создадите расширение (при условии, что Linux):

wget http://shedskin.googlecode.com/files/shedskin-0.7.tgz
tar -xzf shedskin-0.7.tgz
# On your code folder:
PYTHONPATH=/path/to/shedskin-0.7 python shedskin -e yourmodule.py
# The above generates a Makefile and a yourmodule.h/.cpp pair
make
# Now you can "import yourmodule" from Python and check it's from the .so by "print yourmodule.__file__

PyPy : более быстрый Python с JIT-компилятором. Вы можете просто запустить свой код на нем вместо CPython. Поддерживает только Python 2.5 сейчас, 2.7 скоро. Может дать огромные ускорения по математике кода. Чтобы установить и запустить его (при условии, что Linux 32-битный):

wget http://pypy.org/download/pypy-1.4.1-linux.tar.bz2
tar -xjf pypy-1.4.1-linux.tar.bz2
sudo ln -s /path/to/pypy-1.4.1-linux/bin/pypy /usr/local/bin
# Then, instead of "python yourprogram.py" you'll just run "pypy yourprogram.py"

Плетение : Позволяет писать C inline , компилировать его.

Изменить: Если вы хотите, чтобы мы запускали эти инструменты для вас и тестировали, просто опубликуйте ваш код;)

...