我想加快我的代码使用cython。将代码翻译成Python的cython后,我看到我没有获得任何加速。我认为问题的根源在于我将numpy数组转换为cython时表现不佳。Cython:缓慢的numpy阵列
我已经想出了一个非常简单的程序,以显示这一点:
############### test.pyx #################
import numpy as np
cimport numpy as np
cimport cython
def func1(long N):
cdef double sum1,sum2,sum3
cdef long i
sum1 = 0.0
sum2 = 0.0
sum3 = 0.0
for i in range(N):
sum1 += i
sum2 += 2.0*i
sum3 += 3.0*i
return sum1,sum2,sum3
def func2(long N):
cdef np.ndarray[np.float64_t,ndim=1] sum_arr
cdef long i
sum_arr = np.zeros(3,dtype=np.float64)
for i in range(N):
sum_arr[0] += i
sum_arr[1] += 2.0*i
sum_arr[2] += 3.0*i
return sum_arr
def func3(long N):
cdef double sum_arr[3]
cdef long i
sum_arr[0] = 0.0
sum_arr[1] = 0.0
sum_arr[2] = 0.0
for i in range(N):
sum_arr[0] += i
sum_arr[1] += 2.0*i
sum_arr[2] += 3.0*i
return sum_arr
##########################################
################## test.py ###############
import time
import test as test
N = 1000000000
for i in xrange(10):
start = time.time()
sum1,sum2,sum3 = test.func1(N)
print 'Time taken = %.3f'%(time.time()-start)
print '\n'
for i in xrange(10):
start = time.time()
sum_arr = test.func2(N)
print 'Time taken = %.3f'%(time.time()-start)
print '\n'
for i in xrange(10):
start = time.time()
sum_arr = test.func3(N)
print 'Time taken = %.3f'%(time.time()-start)
############################################
而且从蟒蛇test.py我得到:
Time taken = 1.445
Time taken = 1.433
Time taken = 1.434
Time taken = 1.428
Time taken = 1.449
Time taken = 1.425
Time taken = 1.421
Time taken = 1.451
Time taken = 1.483
Time taken = 1.418
Time taken = 2.623
Time taken = 2.603
Time taken = 2.977
Time taken = 3.237
Time taken = 2.748
Time taken = 2.798
Time taken = 2.811
Time taken = 2.783
Time taken = 2.585
Time taken = 2.595
Time taken = 1.503
Time taken = 1.529
Time taken = 1.509
Time taken = 1.543
Time taken = 1.427
Time taken = 1.425
Time taken = 1.423
Time taken = 1.415
Time taken = 1.414
Time taken = 1.418
我的问题是:为什么FUNC2几乎是2倍速度较慢比func1和func3?
有没有办法改善这一点?
谢谢!
######## UPDATE我真正的问题如下。我正在调用接受3D数组的函数(比如P [i,j,k])。函数将遍历每个元素并计算几个量:一个数量取决于该位置数组的值(比如A = f(P [i,j,k])),另一个量只取决于位置(B = g(i,j,k))。示意图如下:
for i in xrange(N):
corr1 = h(i,val)
for j in xrange(N):
corr2 = h(j,val)
for k in xrange(N):
corr3 = h(k,val)
A = f(P[i,j,k])
B = g(i,j,k)
Arr[B] += A*corr1*corr2*corr3
其中val是由数字表示的3D数组的属性。这个数字对于不同的领域可能是不同的。
由于我必须对许多3D数组进行这种操作,我认为如果我创建一个接受许多不同输入3D数组的新例程会更好,从而使数组的数量未知。这个想法是因为B在所有数组中都是完全相同的,所以我可以避免为每个数组计算它,只计算一次。问题是,CORR1,CORR2,corr3上面会成为数组:
如果我有一些3D阵列等于num_3D_arrays我做的事情为:
for i in xrange(N):
for p in xrange(num_3D_arrays):
corr1[p] = h(i,val[p])
for j in xrange(N):
for p in xrange(num_3D_arrays):
corr2[p] = h(j,val[p])
for k in xrange(N):
for p in xrange(num_3D_arrays):
corr3[p] = h(k,val[p])
B = g(i,j,k)
for p in xrange(num_3D_arrays):
A[p] = f(P[i,j,k])
Arr[p,B] += A[p]*corr1[p]*corr2[p]*corr3[p]
所以VAL,我改变从标量到数组的变量corr1,corr2,corr3和A正在消除我期望避免执行大循环的性能。
#
代码范围(N): sum_arr [0] + = i sum_arr [1] + = 2.0 * i sum_arr [2] + = 3.0 * i'忽略numpy擅长的所有内容。 Numpy不是很快,因为你可以快速访问索引,但是因为它可以快速进行数字操作。但不是那样。我建议读入numpy –
我想这很难让它更快。因为假如你固执地使用'numpy',你必须在该循环中创建numpy数组,并执行np.sum(),但创建numpy数组可能是该代码片段中最慢的事情。我还建议分别检查每条线,而不是这个简单的时间。 ** [一些阅读分析](http://stackoverflow.com/questions/582336/how-can-you-profile-a-script)** –
好的谢谢!在我的情况下,问题是我不能像func1那样定义单个变量,但是我需要定义一个我不知道先验的大小的数组。有没有不同的方式来做到这一点比使用numpy数组? – Francisco