Python 将值指定给数组切片的速度很慢
我试图通过在Cython中实现Python算法来优化它。我的问题是关于以下代码中存在的某个性能瓶颈:Python 将值指定给数组切片的速度很慢,python,performance,numpy,cython,Python,Performance,Numpy,Cython,我试图通过在Cython中实现Python算法来优化它。我的问题是关于以下代码中存在的某个性能瓶颈: @cython.boundscheck(False) # turn off bounds-checking for entire function def anglesToRGB( np.ndarray[double, ndim=2] y, np.ndarray[double, ndim=2] x ): cdef double angle cdef double Hp cdef double
@cython.boundscheck(False) # turn off bounds-checking for entire function
def anglesToRGB( np.ndarray[double, ndim=2] y, np.ndarray[double, ndim=2] x ):
cdef double angle
cdef double Hp
cdef double C
cdef double X
cdef np.ndarray[double, ndim=3] res = np.zeros([y.shape[0], y.shape[1], 3], dtype=np.float64)
for i in xrange(y.shape[0]):
for j in xrange(y.shape[1]):
angle = atan2( y[i,j], x[i,j] )*180.0/PI+180
C = sqrt(pow(y[i,j],2)+pow(x[i,j],2))/360.0 #Chroma
Hp = angle/60.0
X = C*(1-fabs( Hp%2-1))
C *= 255
X *= 255
if (0. <= Hp < 1.):
res[i,j,:] = [C,X,0]
elif (1. <= Hp < 2.):
res[i,j,:] = [X,C,0]
elif (2. <= Hp < 3.):
res[i,j,:] = [0,C,X]
elif (3. <= Hp < 4.):
res[i,j,:] = [0,X,C]
elif (4. <= Hp < 5.):
res[i,j,:] = [X,C,C]
else:
res[i,j,:] = [C,0,X]
return res
但是,如果我将作业更改为
res[i,j,0] = C
res[i,j,1] = X
res[i,j,2] = 0
这样代码运行速度就快了几个数量级。
对我来说这很奇怪,因为Cython编译器应该足够聪明来为我做这件事吗?或者我需要先提供一些提示吗?
我应该注意,将切片更改为0:3而不是:并且将值列表设置为numpy数组并不会提高性能
我想知道的是,为什么这个操作会如此严重地破坏性能,以及是否有任何方法可以在不牺牲方便的列表和切片表示法的情况下解决它
最好的祝愿不,Cython(用0.17测试)不够聪明,无法优化此切片分配。如果您查看生成的C代码(使用cython-a
并单击HTML报告中的任意一行以查看生成的代码),那么您可以看到
res[i,j,:] = [C,X,0]
编译为
- C和Python浮点类型之间的转换
- 列表的分配
[C,X,0]
- 元组的分配
(i,j,切片(无))
- 调用
res.\uuuuu setitem\uuuuuu
- 对所有这些进行错误检查
- 已分配结构的解除分配
cdefdouble v1、v2、v3
李>
v1、v2、v3=C、X、0等,优化为三个C赋值李>
在条件块之后,将v1、v2、v3
分配给res[i、j、0]
等三个单独的赋值
问题的一部分可能是[C,X,0]
导致python分配一个新列表?也许使用元组会更快:(C,X,0)
@NathanVillaescusa:元组不是也被分配了吗?@Dietrich是的,但它们的内存效率更高,分配速度更快@NathanVillaescusa:这只适用于常量元组。
res[i,j,:] = [C,X,0]