我已经阅读了很长一段时间Stack问题和答案,并找到了很多非常有用的优化。 我有点面临优化以下代码的瓶颈,这对于将笛卡尔地图转换为极坐标地图来说只是“公正”。但是具有增加角度点的密度的特殊性,半径意味着更大的半径用更多的点来描述。
有什么想加快这个过程吗?
Rbin=440
Angbin=440
def cart2pol_alt(data,center,Rfact):
"""
Cubic interpolation
Fastest implementation of the cubic interpolation so far
Faster than max(0,(x+1)**3) by 20% or any of the factorization by bool (x+2>0) by 60-65%
"""
def cubic(x):
p0=lambda y: (y+2)**3 if (y+2>0) else 0
p1=lambda y: (y+1)**3 if (y+1>0) else 0
p2=lambda y: (y)**3 if (y>0) else 0
p3=lambda y: (y-1)**3 if (y-1>0) else 0
return (p0(x)-4*p1(x)+6*p2(x)-4*p3(x))/6.
"""
Adapt the selected area size to polar basis size
"""
rad=Rfact*np.concatenate([r*np.ones(2*r+1) for r in np.arange(Rbin)])
theta=np.concatenate([np.pi*np.arange(t)/t for t in 2*np.arange(Rbin)+1])
x=rad*np.cos(theta) + center[1]
y=-rad*np.sin(theta) + center[0]
#Cubic interpolation
ix=x.astype('int')
iy=y.astype('int')
dx=x-ix
dy=y-iy
polar=np.zeros_like(rad)
nX,nY=data.shape
for index in np.arange(Rbin*Angbin):
for i in np.arange(-1,3):
for j in np.arange(-1,3):
condx=np.logical_and((ix[index]+i)<nX,(ix[index]+i)>=0)
condy=np.logical_and((iy[index]+j)<nY,(iy[index]+j)>=0)
if np.logical_and(condx,condy):
cub=cubic(i-dx[index])*cubic(dy[index]-j)
polar[index]+=data.ravel()[(ix[index]+i)*nY+(iy[index]+j)]*cub
return polar
EDIT。感谢你的帮助。矢量化并不容易,但我设法将执行时间从4分钟减少到2秒,但使用以下代码。我希望它可以帮助一些人。
Rbin=440
Angbin=440
def cart2pol(data,scale,center,Rfact):
"""
Cubic interpolation
Fastest implementation of the cubic interpolation so far for an array
"""
def cubic(y):
p0=(y+2)**3
p0[p0<0]=0
p1 = (y+1)**3
p1[p1<0]=0
p2 = y**3
p2[p2<0]=0
p3 =(y-1)**3
p3[p3<0]=0
return (p0-4.*p1+6.*p2-4.*p3)/6.
rad=Rfact*np.concatenate([r*np.ones(2*r+1) for r in np.arange(Rbin)])
theta=np.concatenate([np.pi*np.arange(t)/t for t in 2*np.arange(Rbin)+1])
x=rad*np.cos(theta) + center[1]
y=-rad*np.sin(theta) + center[0]
#Cubic interpolation
ix=x.astype('int')
iy=y.astype('int')
dx=x-ix
dy=y-iy
polar=np.zeros_like(rad)
i,j=np.meshgrid(np.arange(-1,3),np.arange(-1,3))
i=i.ravel()
j=j.ravel()
I,IX=np.meshgrid(i,ix)
J,IY=np.meshgrid(i,iy)
IXI=IX+I
IYJ=IY+J
nX,nY=data.shape
rule1=(IXI<nX) & (IXI>=0)
rule2=(IYJ<nY) & (IYJ>=0)
cub=cubic(I-dx.reshape((dx.shape[0],1)))*cubic(dy.reshape((dy.shape[0],1))-J)
dat=data.ravel()[(IXI*nY+IYJ).ravel()].reshape(IYJ.shape)
polar+=(dat*cub).sum(axis=1)
return polar
如果有人看到其他优化,请告诉我们!
答案 0 :(得分:1)
你可以将for循环矢量化为:
nX,nY=data.shape
for i in np.arange(-1,3):
for j in np.arange(-1,3):
condx = np.logical_and((ix + i) < nX, (ix + i) >=0)
condx = np.logical_and((iy + j) < nY, (iy + j) >=0)
cub = cubic(i-dx) * cubic(dy - i)
polar += data.ravel()[(ix + i) * nY + (iy + j)] * cub * \
np.logical_and(condx, condy)
您也可以从三次函数中删除if语句
def cubic(x):
p0 = (y+2)**3
p0[p0 < 0] = 0
p1 = (y+1)**3
p1[p1 < 0] = 0
p2 = (y)**3
p2[p2 < 0] = 0
p3 = (y-1)**3
p3[p3 < 0] = 0
return (p0 - 4*p1 + 6*p2 - 4*p3) /6.
答案 1 :(得分:0)
我无法验证它是否会产生与您的代码相同的结果,因为您没有提供任何数据。但我会先用矢量化操作替换一个for-cycle。
for i in np.arange(-1, 3):
ixi = ix+i
condx = (ixi < nX) & (ixi >= 0)
for j in np.arange(-1, 3):
iyj = iy+j
cond = (iyj < nY) & (iyj >= 0) & condx
if cond.any():
cub = cubic(i-dx[cond])*cubic(dy[cond]-j)
polar[cond] += data[ixi[cond], iyj[cond]]*cub