Python 2.7 通过在Cython中重写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.

我有一些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.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函数通常在性能方面并不差,但在更大的问题上,缓存利用率可能不好。也有可能多线程处理您的代码。。。