Python 为什么在Cython中写入C数组会这么慢?

Python 为什么在Cython中写入C数组会这么慢?,python,optimization,cython,Python,Optimization,Cython,我有一个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 =

我有一个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)


消除了一些强制转换操作的需要,并将代码的速度提高了约2倍

我发现了一个可能解释速度缓慢的问题,请注意,您可以将
x
dx
创建为
double
以接收
float
值,方法是更改为:

cdef float x
cdef float dx
我得到了2X的加速,因为它避免了在
x=self.x[v]
中将浮点值转换为双精度,然后在
self.SX[k]=dx
中将浮点值转换为双精度


在你的方法中,我使用一个数组来存储
self.X
self.SX
的值,方法是通过
2*I+0
2*I+1
0
用于
self.X
1
用于
self.SX
)来控制访问时间也一样。

发布Cython生成的C代码(相关部分)会很有用;如果没有这条线,双循环中使用的唯一内存区域就是self.X,因此它很可能会一直保留在缓存中。当您添加self.SX行时,使用的堆数量会加倍,这可能会将其从缓存中推出?取决于nmax isI的值稍后将尝试这样做。问题是,我的实际代码要复杂得多,所以剥离它有点困难。“我目前的理论也是,它是缓存,”蓝辣椒说。谢谢你的意见。接得好。我接受了这个答案。感谢您的测试!
cdef float x
cdef float dx
cdef float x
cdef float dx