Каковы относительные преимущества расширения NumPy в Cython против Boost.Python?

Мне нужно ускорить некоторые алгоритмы, работающие с массивами NumPy. Они будут использовать std::vector и некоторые из более продвинутых структур данных STL.

Я сузил свой выбор до Cython (который теперь охватывает большинство контейнеров STL) и Boost.Python (который теперь имеет встроенную поддержку NumPy).

По своему опыту программиста я знаю, что иногда требуются месяцы работы со структурой, чтобы раскрыть ее скрытые проблемы (потому что они редко используются учениками в качестве предмета разговора), поэтому ваша помощь потенциально может сэкономить мне много времени.

Каковы относительные преимущества и недостатки расширения NumPy в Cython против Boost.Python?

2 ответа

Решение

Это очень неполный ответ, который на самом деле охватывает только пару его небольших частей (я отредактирую его, если подумаю еще о чем-нибудь):


Boost не выглядит для реализации operator[] специально для NumPy массивов. Это означает, что operator[] придет с базы object класс (это ndarray наследует), что будет означать, что вызов будет проходить через механизмы Python для __getitem__ и поэтому индексирование будет медленным (близко к скорости Python). Если вы хотите выполнять индексацию на скорости, вам придется самостоятельно выполнять арифметику с указателями:

// rough gist - untested:

// i,j,k are your indices

double* data = reinterpret_cast<double*>(array.get_data());
// in reality you'd check the dtype - the data may not be a double...

double data_element = array.strides(0)*i + array.strides(1)*j +array.strides(2)*k;

В отличие от Cython имеет эффективную индексацию NumPy массивов, встроенных автоматически.


Cython не очень хорош в таких вещах, как std::vector (хотя это не совсем ужасно - обычно вы можете обмануть его, делая то, что вы хотите). Одним заметным ограничением является то, что все cdef Они должны идти в начале функции, чтобы классы C++ были сконструированы там по умолчанию, а затем назначены / обработаны позже (что может быть несколько неэффективно). Для чего-то кроме простого использования вы не хотите манипулировать типами C++ в Cython (вместо этого лучше написать код на C++, а затем вызывать его из Cython).

Второе ограничение заключается в том, что он борется с неклассными шаблонами. Один общий пример std::array, который определяется с помощью числа. В зависимости от вашего запланированного кода это может или не может быть проблемой.

Для небольших одноразовых задач я предпочитаю Cython, для большей интеграции с базами кода C++ предпочитаю Boost Python.

Частично это зависит от аудитории вашего кода. Если вы работаете с командой со значительным опытом работы с Python, но с небольшим опытом использования C++, Cython имеет смысл. Если у вас есть фиксированная кодовая база со сложными типами, с которыми можно взаимодействовать, то ускоренный питон может оказаться немного дешевле в запуске.

Cython призывает вас писать постепенно, постепенно добавляя типы по мере необходимости, чтобы получить дополнительную производительность, и решает многие проблемы с жесткой упаковкой. Для форсирования Python требуются значительные усилия по настройке сборки, и может быть сложно создавать пакеты, имеющие смысл для PyPI.

В Cython есть хорошие встроенные сообщения об ошибках / диагностике, но из того, что я видел, ошибки, возникающие из-за буста, очень трудно интерпретировать - будьте добры к себе и используйте новый компилятор C++, предпочтительно тот, который известен как производящий читаемые сообщения об ошибках.

Не сбрасывайте со счетов альтернативные инструменты, такие как Numba (производительность, аналогичная Cython с кодом на Python, а не просто чем-то похожим) и Pybind11 (улучшите Python без повышения и с лучшими сообщениями об ошибках)

Другие вопросы по тегам