我想使用类型化的memoryview优化函数,但是我不是参数类型。它可以是一个numpy数组,甚至是一个标量。那我该如何使用键入的memoryview?
最佳答案
这种问题的问题在于Python是动态类型的,因此在选择采用哪种代码路径时,您总是会失去速度。但是,原则上您可以使各个代码路径变得非常快。一种可能会为您带来良好结果的方法是:
快速实施如下。这假定您要对输入数组的每个元素应用一个函数(并希望输出数组的大小相同)。我选择的说明性函数只是将1加上每个值。我认为这在合理的地方也使用了numpy(而不只是键入的memoryviews):
cimport cython
import numpy as np
import numbers
@cython.boundscheck(False)
cdef double[:] _plus_one_impl(double[:] x):
cdef int n
cdef double[:] output
output = x.copy()
for n in range(x.shape[0]):
output[n] = x[n]+1
return output
def plus_one(x):
if isinstance(x,numbers.Real): # check if it's a number
return _plus_one_impl(np.array([x]))[0]
else:
try:
return _plus_one_impl(x)
except ValueError: # this gets thrown if conversion fails
if len(x.shape)<2:
raise ValueError('x could not be converted to double [:]')
output = np.empty_like(x) # output is all numpy, whatever the input is
for n in range(x.shape[0]): # this loop isn't typed, so is likely to be pretty slow
output[n,...] = plus_one(x[n,...])
return output
在某些情况下(例如二维尺寸较短的2D数组),此代码可能最终会变慢。
但是,我的真正建议是研究numpy ufuncs,它们为有效地实现这种事情提供了一个接口。 (请参阅http://docs.scipy.org/doc/numpy-dev/user/c-info.ufunc-tutorial.html)。不幸的是,它们比Cython还复杂。