假设我想将numpy数组传递给cdef
函数:
cdef double mysum(double[:] arr):
cdef int n = len(arr)
cdef double result = 0
for i in range(n):
result = result + arr[i]
return result
这是处理输入numpy数组的现代方法吗?与这个问题比较:cython / numpy type of an array
如果我想做以下事情呢:
cdef double[:] mydifference(int a, int b):
cdef double[:] arr_a = np.arange(a)
cdef double[:] arr_b = np.arange(b)
return arr_a - arr_b
这将返回一个错误,因为没有为memoryview定义-
。那么,这个案子应该按以下方式处理吗?
cdef double[:] mydifference(int a, int b):
arr_a = np.arange(a)
arr_b = np.arange(b)
return arr_a - arr_b
我将引用文档the docs
这表明Cython的开发人员认为内存视图是现代的方式。
与
np.ndarray
符号相比,内存视图主要在优雅性和互操作性方面提供了一些很大的优势,但是它们在性能上并不优越。性能:
首先,应该注意boundscheck有时无法处理内存视图,从而导致boundscheck=True的内存视图的人为快速图形(即,您获得快速、不安全的索引),如果您依赖boundscheck来捕获错误,这可能是一个令人讨厌的意外。
在大多数情况下,一旦应用了编译器优化,内存视图和numpy数组表示法在性能上是相等的,通常是这样的。当存在差异时,通常不超过10-30%。
绩效基准
数字是以秒为单位执行100000000个操作的时间。越小越快。
基准代码(仅显示用于访问+分配)
这些基准表明,总体而言,业绩没有太大差别。有时np.ndarray符号要快一点,有时vice verca。
基准测试需要注意的一件事是,当代码变得更复杂或更“真实”时,差异会突然消失,就像编译器对应用一些非常聪明的优化失去信心一样。这可以从float的性能中看出,这里没有任何差别,可能是因为一些奇特的整数优化无法使用。
易用性
内存视图提供了显著的优势,例如,您可以在numpy数组、CPython数组、cython数组、c数组等上使用内存视图,无论是现在还是将来。还有一种简单的并行语法,可以将任何内容强制转换为内存视图:
在这方面,内存视图是很好的,因为如果您键入一个函数作为一个内存视图,那么它可以接受这些内容中的任何一个。这意味着您可以编写一个不依赖于numpy的模块,但它仍然可以使用numpy数组。
另一方面,
np.ndarray
符号产生的结果仍然是一个numpy数组,您可以调用它上的所有numpy数组方法。不过,同时拥有numpy数组和数组视图并不重要:在实践中,同时使用array和array视图可以很好地工作,我非常喜欢这种风格,因为它清楚地区分了python级方法和c级方法。
结论
表现是非常接近平等的,当然没有足够的差异,这是一个决定因素。
numpy数组表示法更接近于加速python代码而不做太多更改的理想,因为您可以继续使用相同的变量,同时获得全速数组索引。
另一方面,内存视图符号可能是未来的趋势。如果您喜欢它的优雅,并且使用不同类型的数据容器而不仅仅是numpy数组,那么出于一致性的考虑,使用内存视图是非常有理由的。
相关问题 更多 >
编程相关推荐