Python 2.7 通过在Cython中重写numpy优化代码,可以显著提高速度吗?
我有一些python代码在2d和3d numpy数组上进行数值计算。代码的优化方式是不使用任何for循环,只使用numpy操作。所有操作都在Python 2.7 通过在Cython中重写numpy优化代码,可以显著提高速度吗?,python-2.7,performance,numpy,cython,Python 2.7,Performance,Numpy,Cython,我有一些python代码在2d和3d numpy数组上进行数值计算。代码的优化方式是不使用任何for循环,只使用numpy操作。所有操作都在float类型上完成 这些是使用的numpy操作:numpy.zeros,numpy.restrave,numpy.where,numpy.logical\u或.reduce,numpy.put,numpy.add,numpy.subtract,numpy.true\u设备,numpy.rint> 我运行了一些测试,开销在numpy.where、numpy.
float
类型上完成
这些是使用的numpy操作:numpy.zeros
,numpy.restrave
,numpy.where
,numpy.logical\u或.reduce
,numpy.put
,numpy.add
,numpy.subtract
,numpy.true\u设备
,numpy.rint>
我运行了一些测试,开销在numpy.where
、numpy.put
和numpy.rint
操作中
我的问题是,既然我已经优化了代码,因为它只使用numpy操作,那么在Cython中重写我的代码时,我是否可以期望任何显著的速度提升。或者还有其他选择吗?其余的代码都是用Python编写的,必须留在Python中。一个显著的增长将是平均速度提高20%左右
EDIT1:
# <im> is a 2d floating point numpy array
# <w,h> are the width and hight of <im>
pdt = np.rint(np.add(pix[:,None,:], np.multiply(depthValOfU[:,None], features[:,0]))).astype(int)
d_two = np.zeros(2000*500)
pdt = np.reshape(pdt, (2000*500, 2))
np.put(d_two, np.where(np.logical_or.reduce((pdt[:,0] < 0, pdt[:,0] > w, pdt[:,1] < 0, pdt[:,1] > h))), self.const)
zero_ind = np.where(d_two < 1000)
np.put(d_two, zero_ind, im[pdt[zero_ind,0], pdt[zero_ind,1]])
#是一个二维浮点numpy数组
#宽度和高度是多少
pdt=np.rint(np.add(pix[:,None,:],np.multiply(depthValOfU[:,None],features[:,0])).astype(int)
d_two=np.零(2000*500)
pdt=np.整形(pdt,(2000*500,2))
np.put(d_-two,np.where(np.logical_或.reduce((pdt[:,0]<0,pdt[:,0]>w,pdt[:,1]<0,pdt[:,1]>h)),self.const)
zero_ind=np.式中(d_two<1000)
np.put(d_-two,zero-ind,im[pdt[zero-ind,0],pdt[zero-ind,1])
为了使这段代码能够运行,我需要提供大量代码,但我希望这有助于理解它。您使用的长行和np.put
很难理解。我认为这相当于:
pdt = pix[:,None,:] + depthValOfU[:,None]*features[:,0]
pdt = np.rint(pdt).astype(int)
pdt = np.reshape(pdt, (2000*500, 2))
d_two = np.zeros(2000*500)
idx = np.where(np.logical_or.reduce((pdt[:,0] < 0,
pdt[:,0] > w,
pdt[:,1] < 0,
pdt[:,1] > h)))
d_two[idx] = self.const
zero_ind = np.where(d_two < 1000)
d_two[zero_ind] = im[pdt[zero_ind,0], pdt[zero_ind,1]]
pdt=pix[:,None,:]+depthValOfU[:,None]*功能[:,0]
pdt=np.rint(pdt).astype(int)
pdt=np.整形(pdt,(2000*500,2))
d_two=np.零(2000*500)
idx=np.where(np.logical_或.reduce((pdt[:,0)]<0,
pdt[:,0]>w,
pdt[:,1]<0,
pdt[:,1]>h)))
d_two[idx]=自常数
zero_ind=np.式中(d_two<1000)
d_two[zero_ind]=im[pdt[zero_ind,0],pdt[zero_ind,1]]
根据我的经验,索引作业很快<代码>其中
也很快。可以简化或.reduce
构造
如果按原样将其放入cython
中,则不会获得明显的加速。如果生成-a
html,您将看到大量对python和numpy的黄色调用。指定数组的形状和类型可能会有所帮助。但是如果没有环,赛昂就没有什么可以改进的了
类型化memeoryviews可以使用“本机”cython代码执行许多数组操作,但它们没有numpy数组的强大功能
另一个选择是将其重写为一个纯粹的迭代操作——循环是它们的荣耀。与良好的矢量化numpy相反。然后让cython将其转换为纯C。但这将是大量的工作。如果不查看代码,就很难说任何加速会有多大。通常情况下:如果有任何地方可以对整个阵列进行短路评估,或者如果可以对单个循环中的值应用多个操作,那么Cython可以提供帮助(这只是两个示例)。如果可以,请分享您代码的相关部分(或类似代码的相关片段)。谢谢您的回复。我编辑我的问题是为了提供一段不可运行的代码。如果没有可运行的代码,很难说建议的改进是否有帮助。在大多数情况下,您可以轻松地创建类似于
im=np.randn(w,h)的输入;pix=randn(??)
,依此类推。只要大小与实际数据大致相同,这将有助于显示可能的效果。研究cython文档中键入的MemoryView页面应该可以通过。对于性能测试,有必要提供一段运行的代码,包括代表性的输入和输出测试数据。矢量化numpy函数通常在性能方面并不差,但在更大的问题上,缓存利用率可能不好。也有可能多线程处理您的代码。。。