使用Python/C接口相较于Cython有哪些优势?

50 投票
3 回答
10523 浏览
提问于 2025-04-16 16:03

我想通过用C或C++编写一些模块来扩展Python和numpy,并且希望使用BLAS和LAPACK库。我还想把这些代码打包成独立的C/C++库,能够使用单精度和双精度浮点数。我计划编写的一些函数包括用于解决线性方程组的共轭梯度法或加速的一阶方法。有些函数需要从C/C++代码中调用Python函数。

在尝试了一下Python/C API和Numpy/C API后,我发现很多人推荐使用Cython(比如可以参考这个问题这个问题)。我对Cython不是很了解,但似乎在某些情况下,你仍然需要使用Numpy/C API,并且要了解它是如何工作的。考虑到我已经对Python/C API有一些了解,但对Cython一无所知,我在想继续使用Python/C API是否有意义,以及使用这个API是否比Cython有一些优势。将来我肯定会开发一些不涉及数值计算的东西,所以这个问题不仅仅是关于numpy的。我喜欢Python/C API的一点是,它让我了解了一些关于Python解释器是如何工作的知识。

谢谢。

3 个回答

0

使用Python/C API的主要缺点是,如果在一个内层循环中使用,它可能会非常慢。我发现调用一个Python函数的速度比调用一个相同的C++函数慢80到160倍。

如果这个问题对你的代码没有影响,那么你就可以享受到用Python写一些代码块的好处,还可以使用Python的库,支持直接用Python编写的回调函数。这也意味着你可以进行一些修改而不需要重新编译,这样原型开发会更简单。

93

目前的“最佳答案”听起来有点像是在制造恐慌。首先,普通开发者在C语言中写的代码不一定比用NumPy和Cython写的代码快。实际上,要让C代码在Python环境中正常工作,所花的时间通常更适合用来快速写一个Cython的原型,测试性能,优化,再重新写得更快,最后再决定是否真的需要用手动调优的C代码来提高5-10%的性能,而这可能只涉及到2%的代码。

我正在用Cython写一个库,目前大约有18000行Cython代码,这些代码转换成几乎20万行的C代码。我曾经通过在合适的地方插入大约20行手动调优的C代码,让一些非常重要的基础函数的速度提升了近25%。我花了几个小时来重写和优化这小部分代码。与我省下的时间相比,这真是微不足道,因为我本来要花很多时间去写(并维护)纯C的库。

即使你对C的了解比Cython多,如果你同时懂Python和C,你会发现学习Cython非常快,值得投资,特别是当你在做数值计算的时候。你写的80-95%的代码在高级语言中写会受益匪浅,这样你可以轻松地把省下来的时间用来让你的代码和用低级语言写的一样快。

不过,你提到想“能够将代码作为独立的C/C++库分发”,这是坚持使用纯C/C++的一个合理理由。Cython总是依赖于CPython,这个依赖关系还是挺大的。不过,使用纯C/C++(除了Python接口)也无法利用NumPy,因为NumPy同样依赖于CPython。所以,当你用C写东西的时候,通常需要做很多基础工作,才能实现实际功能。在开始这项工作之前,你应该认真考虑一下。

11

首先,我有一点不太明白你的问题:

[...] 你还想把代码作为独立的C/C++库来分发。[...] 有些函数需要从C/C++代码中调用Python函数。

这到底是怎么回事呢?

接下来,关于你的实际问题,直接使用Python/C API确实有一些好处:

  • 你可能对写C代码更熟悉,而不是写Cython代码。

  • 用C语言写代码能让你有更大的控制权。要让Cython代码的性能和相应的C代码一样好,你需要非常小心。你不仅要确保声明所有变量的类型,还需要适当地设置一些标志——比如说,边界检查就是一个例子。你需要对Cython的工作原理有深入的了解,才能获得最佳性能。

  • Cython代码依赖于Python。如果你想把代码作为独立的C库分发,使用Cython似乎不是个好主意。

撰写回答