与 Boost.Python 相比,在 Cython 中扩展 NumPy 的相对优势是什么?
What are the relative advantages of extending NumPy in Cython vs Boost.Python?
我需要加快一些处理 NumPy 数组的算法。他们将使用 std::vector
和一些更高级的 STL 数据结构。
我已经将我的选择范围缩小到 Cython(它现在包装了大多数 STL 容器)和 Boost.Python(它现在内置了对 NumPy 的支持)。
根据我作为一名程序员的经验,我知道有时需要 个月 来使用一个框架来发现它隐藏的问题(因为它们很少被它的门徒用作谈话要点),所以你的帮助可能会为我节省很多时间。
与 Boost.Python 相比,在 Cython 中扩展 NumPy 的相对优势和劣势是什么?
对于小的一次性问题,我倾向于使用 cython,对于与 c++ 代码库的更大集成,更喜欢 boost Python。
部分取决于您的代码的受众。如果您正在与一个在 python 方面拥有丰富经验但使用 C++ 的经验很少的团队合作,那么 Cython 很有意义。如果你有一个固定的代码库,其中有复杂的类型可以互操作,boost python 最终可能会更便宜一些 运行.
Cython 鼓励您增量编写,根据需要逐渐添加类型以获得额外的性能并解决许多硬包装问题。 boost Python 需要付出大量努力来获得构建设置,并且很难生成在 PyPI
上有意义的包
Cython 有很好的内置错误 messages/diagnostics,但据我所知,boost 产生的错误可能很难解释 - 善待自己并使用 new-ish c++ 编译器,最好是一种以生成可读错误消息而闻名的编译器。
不要打折替代工具,如 numba(与 cython 的性能相似,代码为 Python,而不仅仅是看起来相似的东西)和 pybind11(提升 Python 没有提升并且错误更好消息)
这是一个非常不完整的答案,只涵盖了它的一小部分(如果我想到更多,我会编辑它):
提升doesn't look to implement operator[]
specifically for numpy arrays。这意味着 operator[]
将来自基础 object
class(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++ class 会默认构造在那里,然后在稍后分配 to/manipulated (这可能有点低效).对于超出简单用途的任何事情,您不想在 Cython 中操作 C++ 类型(相反,最好用 C++ 编写代码然后从 Cython 调用它)。
第二个限制是它与 non-class 模板斗争。一个常见的示例是 std::array
,它以数字为模板。根据您计划的代码,这可能是也可能不是问题。
我需要加快一些处理 NumPy 数组的算法。他们将使用 std::vector
和一些更高级的 STL 数据结构。
我已经将我的选择范围缩小到 Cython(它现在包装了大多数 STL 容器)和 Boost.Python(它现在内置了对 NumPy 的支持)。
根据我作为一名程序员的经验,我知道有时需要 个月 来使用一个框架来发现它隐藏的问题(因为它们很少被它的门徒用作谈话要点),所以你的帮助可能会为我节省很多时间。
与 Boost.Python 相比,在 Cython 中扩展 NumPy 的相对优势和劣势是什么?
对于小的一次性问题,我倾向于使用 cython,对于与 c++ 代码库的更大集成,更喜欢 boost Python。
部分取决于您的代码的受众。如果您正在与一个在 python 方面拥有丰富经验但使用 C++ 的经验很少的团队合作,那么 Cython 很有意义。如果你有一个固定的代码库,其中有复杂的类型可以互操作,boost python 最终可能会更便宜一些 运行.
Cython 鼓励您增量编写,根据需要逐渐添加类型以获得额外的性能并解决许多硬包装问题。 boost Python 需要付出大量努力来获得构建设置,并且很难生成在 PyPI
上有意义的包Cython 有很好的内置错误 messages/diagnostics,但据我所知,boost 产生的错误可能很难解释 - 善待自己并使用 new-ish c++ 编译器,最好是一种以生成可读错误消息而闻名的编译器。
不要打折替代工具,如 numba(与 cython 的性能相似,代码为 Python,而不仅仅是看起来相似的东西)和 pybind11(提升 Python 没有提升并且错误更好消息)
这是一个非常不完整的答案,只涵盖了它的一小部分(如果我想到更多,我会编辑它):
提升doesn't look to implement operator[]
specifically for numpy arrays。这意味着 operator[]
将来自基础 object
class(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++ class 会默认构造在那里,然后在稍后分配 to/manipulated (这可能有点低效).对于超出简单用途的任何事情,您不想在 Cython 中操作 C++ 类型(相反,最好用 C++ 编写代码然后从 Cython 调用它)。
第二个限制是它与 non-class 模板斗争。一个常见的示例是 std::array
,它以数字为模板。根据您计划的代码,这可能是也可能不是问题。