使用Python / C接口而不是Cython有优势吗?
我想用C或C ++编写一些模块,使用BLAS和LAPACK扩展python和numpy。 我也希望能够将代码作为独立的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有一些优势。 未来,我肯定会开发一些不涉及数值计算的东西,所以这个问题不仅仅是关于数值计算的问题。 我喜欢关于Python / C API的事情之一是我学习了一些关于Python解释器是如何工作的。
谢谢。
首先,你的问题中有一点我没有得到:
也希望能够将代码作为独立的C / C ++库进行分发。 […]一些函数需要从C / C ++代码中调用一个Python函数。
这应该如何工作?
接下来,就您的实际问题而言,直接使用Python / C API有一定的优势:
-
最有可能的是,编写C代码比编写Cython代码更有用。
-
用C写你的代码给你最大限度的控制。 为了从Cython代码获得与C代码相同的性能,您必须非常小心。 您不仅需要确保声明所有variables的types,还必须充分设置一些标志 – 只是一个例子是边界检查 。 您需要知道Cython如何获得最佳性能。
-
Cython代码依赖于Python。 编写也应该在Cython中作为独立C库分发的代码似乎不是一个好主意
目前的“顶级答案”听起来有点像FUD在我耳边。 首先,平均开发人员用C语言编写速度比NumPy + Cython无论如何都要快。 恰恰相反,在Python环境中获得必要的C代码正确工作所花费的时间通常比在Cython中编写一个快速原型要好得多,需要对其进行基准testing,优化,以更快的速度对其进行基准testing然后再决定是否有任何内容确实需要通过重写手工调整的C代码中的2%并从Cython代码中调用它来获得5-10%的性能。
我正在用Cython编写一个库,目前有大约18000行Cython代码,这些代码可以转换成几乎200K行的C代码。 我曾经通过在正确的地方注入了大约20行手动调整的C代码,使得几个非常重要的内部基本级别函数得到了几乎25%的提速。 我花了几个小时来重写和优化这个小部分。 这与我在第一时间用简单的C书写(而不得不保持)图书馆的大量时间相比毫无意义。
即使你知道C比Cython好得多,如果你知道Python 和 C,那么你将会学习Cython,以至于在任何情况下都值得投资,特别是当你使用数值的时候。 您编写的代码中80-95%将会从使用高级语言编写中受益匪浅,您可以安全地放下并投入一半时间,以便像编写代码一样快速地保存代码在低级语言中。
也就是说,您希望“能够将代码作为独立C / C ++库进行分发”的评论是坚持使用普通C / C ++的有效理由。 Cython总是依赖于CPython,这是相当依赖的。 但是,使用纯C / C ++(Python接口除外)将不允许您利用NumPy,因为这也取决于CPython。 所以,像往常一样用C语言编写某些东西时,在实际function之前,你必须做大量的基础工作。 在开始这项工作之前,你应该认真思考这个问题。
Python / C API的主要缺点是如果它在内部循环中使用,它可能会非常慢。 我看到调用一个Python函数需要80-160倍的命中时间来调用一个等效的C ++函数。
如果不妨碍你的代码,那么你能从Python中编写一些代码块,获得Python库,支持直接用Python编写的callback。 这也意味着您可以在不重新编译的情况下进行一些更改,使原型更容易。