0

由于有多种方法可以为 python 编写二进制模块,如果我希望尽可能提高某些代码段的性能,我希望那些有经验的人可以就最佳方法提出建议。

据我了解,可以使用 python/numpy C-api 编写扩展,或者包装一些已经编写好的纯 C/C++/Fortran 函数,以便从 python 代码中调用。

当然,像 Cython 这样的工具是最简单的方法,但我认为手动编写代码可以提供更好的控制并提供更好的性能。

问题,可能是一般性的,是使用哪种方法。编写 C 或 C++ 扩展?包装外部 C/C++ 函数或对 python 函数使用回调?

我在阅读了 Langtangen 的“用于计算科学的 Python 脚本”的第 10 章后写了这个问题,其中比较了 python 和 C 之间的几种接口方法。

4

2 回答 2

3

我想说这取决于你的技能/经验和你的项目。如果这是非常恰当的并且您精通 C/C++ 并且您已经编写了 python 包装器,那么请编写您自己的扩展并对其进行接口。

如果您打算在其他项目上使用 Numpy,那么请使用 Numpy C-API,它内容广泛且文档齐全,但也需要处理大量文档。至少我在处理它时遇到了很多困难,但我又一次在 C 上很烂。

如果您不确定使用 Cython,则耗时少得多,并且在大多数情况下性能非常好。(我的选择)从我的角度来看,你需要成为一个优秀的 C 编码器才能在之前的 2 个实现中比 Cython 做得更好,这将更加复杂和耗时。那么你是一个出色的 C 编码器吗?

此外,如果您正在寻找性能,可能值得您花时间研究 pycuda 或其他一些 GPGPU 的东西,当然这取决于您的硬件。

于 2012-04-27T14:17:00.397 回答
1

可以在这里找到几种不同方法的良好比较。我已经尝试了 cython,并使用 f2py 包装了我自己的 fortran 代码。我发现 f2py 对于我的目的来说是更好的方法。这部分是受我理解 fortran 的事实影响,但老实说,像 fortran 90 这样的现代方言看起来与使用 numpy 的 python 代码相当相似,并且不应该那么难学。

使用 cython,你从缓慢的纯 python 代码开始,然后你必须经历一个繁琐的过程来检测你的代码,找出所有对 python API 的调用在哪里,并在正确的位置输入相关的 cython 关键字。将其转换为更快的 C 代码。使用 fortran,您只需编写普通代码,就已经获得了完整的编译速度,而无需进行混乱的迭代过程。

此外,cython 中的某些数组操作仍然会导致对 Python API 的调用缓慢,尤其是那些涉及切片操作的操作。相反,fortran 中的数组是编译器可以理解和优化的原生类型。话虽如此,cython 的发展速度非常快,因此未来可能会发生变化。

我发现 f2py 的最大缺点是它不支持派生类型的数组(类似于 numpy 的 recarray)。有人希望fwrap可以替代 f2py 来解决这个问题,但目前它似乎处于次要地位。顺便说一句,它是基于 cython 的。

于 2012-05-02T08:01:21.730 回答