Python 添加cython比numpy慢的阵列?

Python 添加cython比numpy慢的阵列?,python,arrays,numpy,cython,Python,Arrays,Numpy,Cython,我才刚开始学cython,请原谅我的无知。cython是否可以通过简单地将两个数组添加到一起来改进numpy?我在添加两个数组a+b以生成新的数组c时做了一次非常糟糕的尝试: import numpy as np cimport numpy as np DTYPE = np.int ctypedef np.int_t DTYPE_t def add_arrays(np.ndarray[DTYPE_t, ndim=2] a, np.ndarray[DTYPE_t, ndim=2] b, np.

我才刚开始学cython,请原谅我的无知。cython是否可以通过简单地将两个数组添加到一起来改进numpy?我在添加两个数组a+b以生成新的数组c时做了一次非常糟糕的尝试:

import numpy as np
cimport numpy as np

DTYPE = np.int
ctypedef np.int_t DTYPE_t

def add_arrays(np.ndarray[DTYPE_t, ndim=2] a, np.ndarray[DTYPE_t, ndim=2] b, np.ndarray[DTYPE_t, ndim=2] c):
    cdef int x = a.shape[0]
    cdef int y = a.shape[1]
    cdef int val_a
    cdef int val_b
    for j in range(x):
        for k in range(y):
            val_a = a[j][k]
            val_b = b[j][k]
            c[j][k] = val_a + val_b    
    return c
但是,当传递这些数组时,此版本的速度是numpy的700倍(*edit:than):

n = 1000 
a = np.ones((n, n), dtype=np.int)
b = np.ones((n, n), dtype=np.int)
c = np.zeros((n, n), dtype=np.int)
我显然错过了一些非常重要的事情

以下是两个示例:

“numpy方式”

循环方式

%%timeit
def add_arrays(ar1, ar2):
    for j in range(len(ar1)):
        for k in range(len(ar2)):
            val_a = ar1[j][k]
            val_b = ar2[j][k]
            result[j][k] = val_a + val_b    
    return result

add_arrays(table1, table2)

1000 loops, best of 3: 307 µs per loop
同样的事情,快20倍

尽管如此,我知道我还没有完全回答你的问题,但也许这能给你提供一个更好的视角来进行比较

[编辑]对于1000x1000个表格,时间差更明显;我想这是由于建造桌子的间接费用的摊销

former code: 100 loops, best of 3: 13.1 ms per loop
latter code: 1 loops, best of 3: 2.78 s per loop

这是一个200倍

我想你失踪了

cdef int j
cdef int k

因此,您的变量循环是python对象而不是c对象。问题是,当您实际上应该执行
c[j,k]
时,您正在像
c[j][k]
那样索引二维数组,否则Cython正在使用一个中间缓冲区来执行
buf=c[j]
,它将从中获取
buf[k]
,从而导致速度减慢。您应该使用适当的索引以及@XavierCombelle指定的
cdef
声明

您可以通过执行以下操作来检查此中间缓冲区是否导致减速:

np.ndarray[DTYPE_t, ndim=1] buf
然后,在循环内部:

buf = c[j]
buf[k] = val_a + val_b
此声明的缓冲区的速度(或关闭)应与以下速度相同:


您是否尝试过简单地添加两个numpy阵列?表1+表2代替了所有这些索引?
nditer
是迭代
cython
中一个或多个数组元素的更好工具。但是numpy
a+b
可能已经在它的
\uuuu add\uuuu
的C实现中使用了它。你是说纯python的速度比numpy慢20倍吗?他谈到了cython实现好的问题,我应该更清楚:我的意思是比较按预期使用numpy和在带有索引的numpy数组上循环。基于OP怀疑他遗漏了什么,我想在冒险进入cython领域之前帮助他校准真正的表现。是的,原则上是。。。。。。。。然而,这是另一个复杂的层面,只有在其他更容易的途径已经用尽时,才应该考虑IMHO;正确使用numpy是一个很好的性能来源,它通常是足够的并且易于访问。同意numpy很好,我只是在用cython做实验!是的,这是伟大的实验,我鼓励你做更多的。修修补补有很多东西需要学习:)我很想知道,对于这个简单的加法,cython的正确实现将在多大程度上击败numpy。(我对cython没有经验)。其他你可以尝试的东西是Numba和Jit,它们比我听说的cython更简单。太棒了!仅仅改变[j][k]对[j,k]的引用就会导致极大的加速;现在代码只比numpy慢3倍左右
buf = c[j]
buf[k] = val_a + val_b
c[j,k] = val_a + val_b