我有一个结构化的网格,具有大约3e + 6点和
请查看图像: https://i.stack.imgur.com/eUUkQ.jpg
物理域(欧几里得)中的每个点在计算域中都有一个索引( i,j和k )。
我需要遍历计算域索引并使用相应的点进行计算。
例如,在给定索引处,方向 i 上的长度为(伪代码): 长度= vec_len(point( i + 1,j,k )-point( i,j,k ))
同样重要的是找出给定点的长度比。例如,我将在方向 i 上计算两个附近的长度,并在它们之间进行划分。
我想出的东西花费了太多时间,并且可能没有充分利用NumPy提供的全部潜力。
我制作了一个用零填充的ndarray,它可以容纳所有网格XYZ坐标。
block_data =numpy.zeros((i_dim, j_dim, k_dim, 3), dtype='float')
数字3对应于x,y和z这3个元素。
因此,如果我想将 i = 3,j = 7,k = 10 的z值设为:
Z = block_data[3][7][10][2]
欧几里得空间中的一个点将是(1,3)ndarray:
point = block_data[i][j][k]
我计算两点之间的长度的方法是:
numpy.linalg.norm(point2 - point1)
仅长度计算需要大约1.5ms,我想计算所有点和所有方向上的距离: 3e + 6 * 3。
我认为构造主块ndarray(block_data)的方法存在问题,因为它限制了我一次只能对两个点进行计算,即只有两个小点(1,3 )ndarrays。 如果我没记错的话,对小型数组进行计算并不是那么有效。
如何解决问题并使运行时间更快?是否有针对此类问题的书推荐?谢谢:-)
答案 0 :(得分:1)
要计算此大小的数组中的欧式距离,我建议使用矢量化方法:
def euclid_dist(array, direction):
if direction == 'i': # make shifted views depending on the direction
p1 = array[:-1, :, :]
p2 = array[1:, :, :]
elif direction == 'j':
p1 = array[:, :-1, :]
p2 = array[:, 1:, :]
elif direction == 'k':
p1 = array[:, :, :-1]
p2 = array[:, :, 1:]
else:
raise ValueError('direction ' + direction + ' not known.')
# get euclidean distance for all points in direction:
euc_dist = (((p1 - p2)*(p1 - p2)).sum(axis=3))**0.5
return euc_dist
使用带有以下内容的小型测试数组:
arr = np.random.randint(-20, 20, 5*5*5*3).reshape(5, 5, 5, 3)
eu_i = euclid_dist(arr, 'i')
eu_j = euclid_dist(arr, 'j')
# test some values:
print(eu_i[2, 1, 2] == np.linalg.norm(arr[2, 1, 2] - arr[3, 1, 2]))
# Out 64: True
print(eu_j[1, 1, 1] == np.linalg.norm(arr[1, 1, 1] - arr[1, 2, 1]))
# Out 65: True
具有8e6
点和24e6
值的大数组的一些计时:
big_arr = np.random.rand(200, 200, 200, 3)
%timeit euclid_dist(big_arr, 'i')
# 644 ms ± 57.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Imho对于这种大小的数组来说非常快。 :)如果我正确地阅读了您的时间安排,这比您的代码快19000倍。