python - 为什么在 Cython 中写入 C 数组这么慢?

标签 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 = <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 倍。

最佳答案

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

cdef float x
cdef float dx

我的速度提高了 2 倍,因为它避免了在 x = self.X[v] 中将浮点值转换为 double,然后在 self 中再次从 double 转换为 float .SX[k] -= dx.

看来您的方法没有丢失缓存,我测试了使用单个数组来存储 self.Xself.SX 的值 通过 2*i+02*i+1 控制访问(0 for self.X 1 对于 self.SX),时间是相同的。

关于python - 为什么在 Cython 中写入 C 数组这么慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25643313/

相关文章:

c++ - 组装的 C++ 似乎包含多余的指令

arrays - 在 Matlab 中查找反转次数

python - 忽略 Cython、Python 和 KeyboardInterrupt

python - 优化 Python 中 numpy 数组中元素的索引和检索?

python - 创建共享内存的 pythonic 对象

python - Pymongo 按降序对评论进行排序

python - 在 Pandas 中聚合到当前行而不使用循环

python - 如何在测试中伪造Popen?

c++ - Cython、C++ 和 gsl

performance - WebSockets 在什么时候比轮询效率低?