我有一个Cython类,如下面的一些人为例子:
cdef class Differential:
cdef int *SX
cdef int *X
cdef int nmax
def __init__(self, int nmax):
self.nmax = nmax ## usually around 10*1000
return
def __cinit__(self, int nmax, *arg, **args):
self.SX = <float *>malloc(nmax*cython.sizeof(float))
## assume self.X has some content.
self.X = <float *>malloc(nmax*cython.sizeof(float))
return
def __dealloc__(self):
free(self.SX)
free(self.X)
return
@cython.wraparound(False)
@cython.boundscheck(False)
@cython.nonecheck(False)
@cython.cdivision(True)
cdef void __reject(self, float step) nogil:
cdef unsigned int v
cdef unsigned int k
cdef double x
cdef double dx
float_array_init(self.SX,1000,0.) ## writes 0. to the 100000 first elements
for v in range(1000):
x = self.X[v]
for k in range(v+1,1000):
dx = x-self.X[k]
# the following line is the "problem":
self.SX[k] -= dx
## some more code
# manipulate SX some more. this section has less performance impact because it
# is not a double for-loop, so i have not included it in the example
# update X
for v in range(1000):
self.X[v] += self.SX[v]
def reject(self, float step):
self.__reject(step)
代码涉及的范围要大得多,但我试图将其删除到仍能说明代码流量的最小数量。
在我的主脚本中,我只创建一个Differential实例,然后我重复调用Differential.reject()(以及其他一些实际更改X值的内容。)
我知道我可以使用cpdef
来避免额外的包装调用(__reject()和reject()),但我的测试表明这没有区别。
我的问题如下:
当我注释掉self.SX[k] -= dx
行时,代码似乎加速了大约10倍。这是预期的吗?
我知道访问内存有成本,但我没想到代码会减慢那么多。
更新
如下所示,更改行
cdef double x
cdef double dx
到
cdef float x
cdef float dx
删除了对某些转换操作的需要,并将代码加速了大约2倍。
答案 0 :(得分:2)
我发现了一个可以解释缓慢的问题,请注意您创建x
和dx
作为double
来接收float
值,方法是更改为:< / p>
cdef float x
cdef float dx
我获得了2倍的加速,因为它避免了在x = self.X[v]
中将浮点值的转换加倍,然后在self.SX[k] -= dx
中再次从double转换为float。
您的方法中似乎不丢失缓存,我使用单个数组测试通过控制self.X
和self.SX
的值来存储2*i+0
和2*i+1
的值{1}}或0
(self.X
为1
,self.SX
为{{1}},时间安排相同。