cArr是以下形式的数组:
cArr=np.array([[0,x0,y0,z0,1],[1,x1,y1,z1,1]])
每行的中间三个数字代表3D中两点的坐标(点0和1用于参考)。其他函数使用每行中的第一个和最后一个值。
cEDA是一个4D阵列形状(100,100,100,4),基本上是随机数。对于每个点0和1,在每个点周围有一个点邻域,坐标在6个基本方向上仅相差一个。
x0,y0,z0
x0+1,y0,z0
x0,y0+1,z0
x0,y0,z0+1
x0-1,y0,z0
x0,y0-1,z0
x0,y0,z0-1
计算与点0和点1相关的这7个点之间的距离(因此点1与点0和点0周围点之间的距离),并与第-2个相应值(100,100,100)相结合)在cEDA中的数组并放置在cEDA中的第i个100,100,100立方体中,其中i分别为0或1。
我是来自C背景的python的新手,并且正在努力摆脱循环思维。我已经尝试了预先计算距离和求和数组但速度要慢得多,但到目前为止最快的方法是通过每个单独的值并分配它。该函数运行了很多次,是代码中的瓶颈,我相信有更好的方法可以做到。
我在概念上理解并且可以使用NumPy但在这种情况下似乎无法应用它 - 关于如何通过使用NumPy加速此功能的任何想法都是正确的方法?我已经尽力解释这个功能的功能对不起我知道这很混乱!
def cF2(cArr, cEDA):
# the coordinates of points 0 and 1 for readability
x0 = cArr[0,1]
y0 = cArr[0,2]
z0 = cArr[0,3]
x1 = cArr[1,1]
y1 = cArr[1,2]
z1 = cArr[1,3]
# for each point around point 0 and the point itself, calculate the distance between this point and point 1
# use this value and the corresponding value in cEDA(x,y,z,-2) and place result in cEDA(x,y,z,0)
cEDA[x0,y0,z0,0] = cEDA[x0,y0,z0,-2]-0.4799/(np.linalg.norm([x0,y0,z0]-cArr[1,1:4]))
cEDA[x0-1,y0,z0,0] = cEDA[x0-1,y0,z0,-2]-0.4799/(np.linalg.norm([x0-1,y0,z0]-cArr[1,1:4]))
cEDA[x0+1,y0,z0,0] = cEDA[x0+1,y0,z0,-2]-0.4799/(np.linalg.norm([x0+1,y0,z0]-cArr[1,1:4]))
cEDA[x0,y0-1,z0,0] = cEDA[x0,y0-1,z0,-2]-0.4799/(np.linalg.norm([x0,y0-1,z0]-cArr[1,1:4]))
cEDA[x0,y0+1,z0,0] = cEDA[x0,y0+1,z0,-2]-0.4799/(np.linalg.norm([x0,y0+1,z0]-cArr[1,1:4]))
cEDA[x0,y0,z0-1,0] = cEDA[x0,y0,z0-1,-2]-0.4799/(np.linalg.norm([x0,y0,z0-1]-cArr[1,1:4]))
cEDA[x0,y0,z0+1,0] = cEDA[x0,y0,z0+1,-2]-0.4799/(np.linalg.norm([x0,y0,z0+1]-cArr[1,1:4]))
cEDA[x1,y1,z1,1] = cEDA[x1,y1,z1,-2]+0.4799/(np.linalg.norm([x1,y1,z1]-cArr[0,1:4]))
cEDA[x1-1,y1,z1,1] = cEDA[x1-1,y1,z1,-2]+0.4799/(np.linalg.norm([x1-1,y1,z1]-cArr[0,1:4]))
cEDA[x1+1,y1,z1,1] = cEDA[x1+1,y1,z1,-2]+0.4799/(np.linalg.norm([x1+1,y1,z1]-cArr[0,1:4]))
cEDA[x1,y1-1,z1,1] = cEDA[x1,y1-1,z1,-2]+0.4799/(np.linalg.norm([x1,y1-1,z1]-cArr[0,1:4]))
cEDA[x1,y1+1,z1,1] = cEDA[x1,y1+1,z1,-2]+0.4799/(np.linalg.norm([x1,y1+1,z1]-cArr[0,1:4]))
cEDA[x1,y1,z1-1,1] = cEDA[x1,y1,z1-1,-2]+0.4799/(np.linalg.norm([x1,y1,z1-1]-cArr[0,1:4]))
cEDA[x1,y1,z1+1,1] = cEDA[x1,y1,z1+1,-2]+0.4799/(np.linalg.norm([x1,y1,z1+1]-cArr[0,1:4]))
return cEDA
答案 0 :(得分:0)
如果你想调用这个很多时间,你需要通过numba或Cython将整个for循环转换为C循环。但是有一些方法可以提高你的功能速度,这是你原来的功能:
def cF2(cArr, cEDA):
# the coordinates of points 0 and 1 for readability
x0 = cArr[0,1]
y0 = cArr[0,2]
z0 = cArr[0,3]
x1 = cArr[1,1]
y1 = cArr[1,2]
z1 = cArr[1,3]
# for each point around point 0 and the point itself, calculate the distance between this point and point 1
# use this value and the corresponding value in cEDA(x,y,z,-2) and place result in cEDA(x,y,z,0)
cEDA[x0,y0,z0,0] = cEDA[x0,y0,z0,-2]-0.4799/(np.linalg.norm([x0,y0,z0]-cArr[1,1:4]))
cEDA[x0-1,y0,z0,0] = cEDA[x0-1,y0,z0,-2]-0.4799/(np.linalg.norm([x0-1,y0,z0]-cArr[1,1:4]))
cEDA[x0+1,y0,z0,0] = cEDA[x0+1,y0,z0,-2]-0.4799/(np.linalg.norm([x0+1,y0,z0]-cArr[1,1:4]))
cEDA[x0,y0-1,z0,0] = cEDA[x0,y0-1,z0,-2]-0.4799/(np.linalg.norm([x0,y0-1,z0]-cArr[1,1:4]))
cEDA[x0,y0+1,z0,0] = cEDA[x0,y0+1,z0,-2]-0.4799/(np.linalg.norm([x0,y0+1,z0]-cArr[1,1:4]))
cEDA[x0,y0,z0-1,0] = cEDA[x0,y0,z0-1,-2]-0.4799/(np.linalg.norm([x0,y0,z0-1]-cArr[1,1:4]))
cEDA[x0,y0,z0+1,0] = cEDA[x0,y0,z0+1,-2]-0.4799/(np.linalg.norm([x0,y0,z0+1]-cArr[1,1:4]))
cEDA[x1,y1,z1,1] = cEDA[x1,y1,z1,-2]+0.4799/(np.linalg.norm([x1,y1,z1]-cArr[0,1:4]))
cEDA[x1-1,y1,z1,1] = cEDA[x1-1,y1,z1,-2]+0.4799/(np.linalg.norm([x1-1,y1,z1]-cArr[0,1:4]))
cEDA[x1+1,y1,z1,1] = cEDA[x1+1,y1,z1,-2]+0.4799/(np.linalg.norm([x1+1,y1,z1]-cArr[0,1:4]))
cEDA[x1,y1-1,z1,1] = cEDA[x1,y1-1,z1,-2]+0.4799/(np.linalg.norm([x1,y1-1,z1]-cArr[0,1:4]))
cEDA[x1,y1+1,z1,1] = cEDA[x1,y1+1,z1,-2]+0.4799/(np.linalg.norm([x1,y1+1,z1]-cArr[0,1:4]))
cEDA[x1,y1,z1-1,1] = cEDA[x1,y1,z1-1,-2]+0.4799/(np.linalg.norm([x1,y1,z1-1]-cArr[0,1:4]))
cEDA[x1,y1,z1+1,1] = cEDA[x1,y1,z1+1,-2]+0.4799/(np.linalg.norm([x1,y1,z1+1]-cArr[0,1:4]))
return cEDA
np.random.seed(42)
cArr = np.random.randint(0, 100, (2, 5))
cEDA = np.random.rand(100, 100, 100, 4)
r1 = cF2(cArr, cEDA)
以下是优化功能:
tmp = np.eye(3)
offsets = np.concatenate((tmp, -tmp, [[0, 0, 0]]), 0).astype(int)[:, None, :]
def fast_cF2(cArr, cEDA):
cArr = cArr[:, 1:4]
t = cArr[None,:,:] + offsets
X0, Y0, Z0 = t[:, 0, :].T
X1, Y1, Z1 = t[:, 1, :].T
d1 = 0.4799/np.linalg.norm(t[:, 0, :] - cArr[1], axis=1)
d0 = 0.4799/np.linalg.norm(t[:, 1, :] - cArr[0], axis=1)
cEDA[X0, Y0, Z0, 0] = cEDA[X0, Y0, Z0, -2] - d1
cEDA[X1, Y1, Z1, 1] = cEDA[X1, Y1, Z1, -2] + d0
return cEDA
np.random.seed(42)
cArr = np.random.randint(0, 100, (2, 5))
cEDA = np.random.rand(100, 100, 100, 4)
r2 = fast_cF2(cArr, cEDA)
print np.allclose(r1, r2)
时间结果:
%timeit cF2(cArr, cEDA)
%timeit fast_cF2(cArr, cEDA)
输出:
1000 loops, best of 3: 320 µs per loop
10000 loops, best of 3: 91.6 µs per loop
答案 1 :(得分:0)
我认为scipy.ndimage.generic_filter会这样做......
def neighborly_function(in_arr1d):
# put your equation below - will have to figure out the details
# below is just an example
# has to return a scalar
return sum(in_arr1d)
import scipy.ndimage as nd
huge_arr3d = [....]
# Since you want the cardinal directions you have to 'footprint'
footprint = np.array([[[False, False, False],
[False, True, False],
[False, False, False]],
[[False, True, False],
[ True, False, True],
[False, True, False]],
[[False, False, False],
[False, True, False],
[False, False, False]]])
out = nd.generic_filter(huge_arr3d, neighborly_function, footprint=footprint)
查看http://docs.scipy.org/doc/scipy/reference/tutorial/ndimage.html上的ndimage文档和http://docs.scipy.org/doc/scipy/reference/tutorial/ndimage.html#generic-filter-functions上的generic_filter