为什么Cython一直在制作python对象而不是c

  • 本文关键字:对象 python Cython numpy cython
  • 更新时间 :
  • 英文 :


我正在尝试学习cython,在那里我使用annotate=True进行编译。

在基本手册中说:
如果一行是白色的,这意味着生成的代码不会与Python交互,因此运行速度将与普通C代码一样快。黄色越深,那一行中的Python交互就越多

然后,我在cython的基本手册说明中写下了以下代码(正如我所理解的(numpy:

+14: cdef entropy(counts):
15:     '''
16:     INPUT: pandas table with counts as obsN
17:     OUTPUT: general entropy
18:     '''
+19:     cdef int l = counts.shape[0]
+20:     cdef np.ndarray probs = np.zeros(l, dtype=np.float)
+21:     cdef int totals = np.sum(counts)
+22:     probs = counts/totals
+23:     cdef np.ndarray plogp = np.zeros(l, dtype=np.float)
+24:     plogp = ( probs.T * (np.log(probs)) ).T
+25:     cdef float d = np.exp(-1 * np.sum(plogp))
+26:     cdef float relative_d = d / probs.shape[0]
27: 
+28:     return {'d':d,
+29:             'relative_d':relative_d
30:             }

其中所有的">+"为黄色。

我做错了什么?如何使该函数的至少一部分以c速度运行?该函数返回一个python字典,因此我认为我不能返回任何c数据类型。我可能错了。

谢谢你的帮助!

首先,Cython不重写Numpy函数,它只是像CPython那样调用它们。这是例如np.zerosnp.sumnp.log的情况。使用Cython,这样的呼叫不会更快。如果你想要一个更快的代码,你可以使用简单的循环来在你的代码中重新实现它们。然而,这可能不会更快:一方面,如果您使用小数组,并且每个函数都生成读取/写入速度通常很慢的巨大临时数组,Numpy调用会引入一定的开销(由于Cython、内部函数调用、包装器等仍然启用了类型检查AFAIK(;另一方面,一些Numpy函数使用高度优化的代码(如BLAS或低级SIMD内部函数(。此外,Python中的除法行为与C不同。这就是为什么Cython提供了可以设置为True的标志cython.cdivision(默认为False(。如果使用Python分区,Cython会生成一个较慢的包装代码。最后,np.ndarray是一个CPython类型,因此,您可以使用memoryviews来处理Numpy对象。

如果您想获得快速代码,您当然需要使用内存视图循环,避免创建临时数组以及使用多个线程。此外,在您的情况下,您可以使用np.empty而不是np.zeros。除此之外,Numpy转置不是很有效,并且Numpy不能解决这个问题。您可以实现平铺换位来加快它的速度,但这对于有效地实现它来说并不是微不足道的。这里有一个Numba实现,它当然可以很容易地转换为Cython代码。在PythonNumpy代码中放入一些cdef通常不会使其更快。

相关内容

  • 没有找到相关文章

最新更新