我一直在玩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
答案 0 :(得分:13)
Numpy比C慢,原因有两个:Python开销(可能类似于cffi)和普遍性。 Numpy旨在以一堆不同的数据类型处理任意维度的数组。您的cffi示例是针对2D浮点数组生成的。成本是编写几行代码与.sum()
,6个字符以节省不到5微秒。 (但当然,你已经知道了这一点)。我只想强调CPU时间便宜,比开发时间便宜得多。
现在,如果您想坚持使用Numpy,并希望获得更好的性能,那么最好的选择是使用Bottleneck。它们提供了一些针对浮动和双打的1和2D阵列进行了优化的功能,并且它们非常快速。在你的情况下,快16倍,这将使执行时间为0.35,或大约是cffi的两倍。
对于瓶颈所没有的其他功能,您可以使用Cython。它可以帮助您使用更加pythonic语法编写C代码。或者,如果愿意,可以逐步将Python转换为C,直到您对速度感到满意为止。