Python 为什么cffi比numpy快得多?
我一直在用python编写cffi模块,它们的速度让我怀疑我是否正确使用了标准python。这让我想完全切换到C!老实说,有一些很棒的python库我自己永远无法用C重新实现,所以这更像是一种假设 这个例子展示了python中与numpy数组一起使用的sum函数,以及它与c函数相比有多慢。有没有一种更快的pythonic方法来计算numpy数组的和Python 为什么cffi比numpy快得多?,python,c,numpy,pypy,python-cffi,Python,C,Numpy,Pypy,Python Cffi,我一直在用python编写cffi模块,它们的速度让我怀疑我是否正确使用了标准python。这让我想完全切换到C!老实说,有一些很棒的python库我自己永远无法用C重新实现,所以这更像是一种假设 这个例子展示了python中与numpy数组一起使用的sum函数,以及它与c函数相比有多慢。有没有一种更快的pythonic方法来计算numpy数组的和 def cast_matrix(matrix, ffi): ap = ffi.new("double* [%d]" % (matrix.sh
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真的很慢!
我使用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示例是针对二维浮点数阵列制作的。成本是编写几行代码vs
.sum()
,6个字符以节省不到5微秒的时间。(当然,你已经知道了这一点)。我只想强调,CPU时间很便宜,比开发人员的时间便宜得多
现在,如果您想坚持使用Numpy,并且希望获得更好的性能,那么最好的选择就是使用。它们提供了一些功能,针对浮点和双精度的1和2D阵列进行了优化,而且速度非常快。在您的情况下,速度提高了16倍,这将使执行时间提高到0.35,大约是cffi的两倍
对于瓶颈没有的其他功能,可以使用Cython。它可以帮助您使用更pythonic的语法编写C代码。或者,如果愿意,可以逐步将Python转换为C,直到您对速度感到满意。使用该模块进行基准测试。如果您安装了ipython,请尝试
%timeit np.sum(np.sum(m))
和`%timeit np.matrix.sum(x)`可能主要来自python开销,使用较大的数组(如1E3x1E3
尝试此操作,并减少循环次数将看到更多的可比时间。请注意,如果您直接使用瓶颈的专用函数,相对于Numpy,速度提高了约25倍。您的cffi现在在哪里?:)除了nan的运算外,这似乎比numpy的总和快不了多少。这里的关键似乎是通过预选底层的C函数来避免python开销。Numpy是否公开了专门的功能?您总是可以从C API调用它们,但是您需要通过Cython。另外,签出numba。
cffi 0.818415880203
numpy 5.61657714844