Каковы относительные преимущества расширения 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 без повышения и с лучшими сообщениями об ошибках)