我一直在玩用python编写cffi模块,它们的速度让我想知道我是否正确使用标准python。这让我想完全切换到C!说实话,有一些伟大的python库,我永远无法在C中重新实现自己,所以这比任何事情都更加假设。

此示例显示了python中的sum函数与numpy数组一起使用,以及与c函数相比它的速度有多慢。是否有更快的pythonic方法来计算numpy数组的总和?

def cast_matrix(matrix, ffi):
    ap = ffi.new("double* [%d]" % (matrix.shape[0]))
    ptr = ffi.cast("double *", matrix.ctypes.data)
    for i in range(matrix.shape[0]):
        ap[i] = ptr + i*matrix.shape[1]                                                                
    return ap 

ffi = FFI()
ffi.cdef("""
double sum(double**, int, int);
""")
C = ffi.verify("""
double sum(double** matrix,int x, int y){
    int i, j; 
    double sum = 0.0;
    for (i=0; i<x; i++){
        for (j=0; j<y; j++){
            sum = sum + matrix[i][j];
        }
    }
    return(sum);
}
""")
m = np.ones(shape=(10,10))
print 'numpy says', m.sum()

m_p = cast_matrix(m, ffi)

sm = C.sum(m_p, m.shape[0], m.shape[1])
print 'cffi says', sm

只是为了显示功能的工作原理:

numpy says 100.0
cffi says 100.0

现在,如果我计时这个简单的功能,我发现numpy真的很慢!我是否以正确的方式使用numpy?有没有更快的方法来计算python中的总和?

import time
n = 1000000

t0 = time.time()
for i in range(n): C.sum(m_p, m.shape[0], m.shape[1])
t1 = time.time()

print 'cffi', t1-t0

t0 = time.time()
for i in range(n): m.sum()
t1 = time.time()

print 'numpy', t1-t0

时代:

cffi 0.818415880203
numpy 5.61657714844
有帮助吗?

解决方案

Numpy比C慢有两个原因:的Python开销(可能类似于cffi)和一般性。Numpy旨在处理任意维度的数组,在一堆不同的数据类型中。您使用cffi的示例是为2d浮动数组制作的。成本是编写几行代码vs .sum(), ,6个字符保存不到5微秒。(但当然,你已经知道这一点)。我只想强调CPU时间便宜,比开发人员时间便宜得多。

现在,如果你想坚持Numpy,并且你想获得更好的性能,你最好的选择是使用 瓶颈.它们提供了一些针对float和double的一维和二维数组优化的函数,并且它们非常快。在你的情况下,快16倍,这将使执行时间在0.35,或大约是cffi的两倍。

对于瓶颈没有的其他功能,您可以使用Cython。它可以帮助您使用更pythonic语法编写C代码。或者,如果您愿意,请将python逐步转换为C,直到您对速度感到满意。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top