【发布时间】:2019-08-21 11:50:32
【问题描述】:
在 Python 中工作时,我正在对 NxM 值网格进行一些物理计算,其中 N 从 1 变为 3108,M 从 1 变为 2304(这对应于大图像)。我需要在这个空间中的每个点计算一个值,总计约 700 万次计算。我目前的方法非常缓慢,我想知道是否有办法完成这项任务并且不需要几个小时......
我的第一种方法只是使用嵌套的 for 循环,但这似乎是解决我的问题的效率最低的方法。我曾尝试使用 NumPy 的 nditer 并单独迭代每个轴,但我读到它实际上并没有加快我的计算速度。我没有单独遍历每个轴,而是尝试制作一个 3-D 数组并遍历外轴,如 Brian 的回答所示 How can I, in python, iterate over multiple 2d lists at once, cleanly? 。这是我的代码的当前状态:
import numpy as np
x,y = np.linspace(1,3108,num=3108),np.linspace(1,2304,num=2304) # x&y dimensions of image
X,Y = np.meshgrid(x,y,indexing='ij')
all_coords = np.dstack((X,Y)) # moves to 3-D
all_coords = all_coords.astype(int) # sets coords to int
作为参考,all_coords 如下所示:
array([[[1.000e+00, 1.000e+00],
[1.000e+00, 2.000e+00],
[1.000e+00, 3.000e+00],
...,
[1.000e+00, 2.302e+03],
[1.000e+00, 2.303e+03],
[1.000e+00, 2.304e+03]],
[[2.000e+00, 1.000e+00],
[2.000e+00, 2.000e+00],
[2.000e+00, 3.000e+00],
...,
[2.000e+00, 2.302e+03],
[2.000e+00, 2.303e+03],
[2.000e+00, 2.304e+03]],
等等。回到我的代码...
'''
- below is a function that does a calculation on the full grid using the distance between x0,y0 and each point on the grid.
- the function takes x0,y0 and returns the calculated values across the grid
'''
def do_calc(x0,y0):
del_x, del_y = X-x0, Y-y0
np.seterr(divide='ignore', invalid='ignore')
dmx_ij = (del_x/((del_x**2)+(del_y**2))) # x component
dmy_ij = (del_y/((del_x**2)+(del_y**2))) # y component
return dmx_ij,dmy_ij
# now the actual loop
def do_loop():
dmx,dmy = 0,0
for pair in all_coords:
for xi,yi in pair:
DM = do_calc(xi,yi)
dmx,dmy = dmx+DM[0],dmy+DM[1]
return dmx,dmy
如您所见,此代码需要非常长的时间才能运行...如果有任何方法可以修改我的代码以使其不需要数小时即可完成,我会非常有兴趣知道如何做那。在此先感谢您的帮助。
【问题讨论】:
-
你给出的代码是你实际计算的吗?可能不会,因为它只会返回一堆
NaNs。目前的代码(在修复NaN问题之后)很容易加速(使用平移不变性),但这可能无法推广到更现实的每点函数。因此,您必须提供更多信息。例如,一切都只依赖于坐标吗?还是像素值也进入计算?真正的计算或至少部分转换是不变的吗? -
上述计算会产生 NaN 的唯一位置是 (x0,y0)。在网格的其余部分,有真正的价值。 NaN 位置是我在实际代码中正确处理的。我在代码中使用的完整计算几乎与上面描述的完全一样,除了前面的另一个由 (x0,y0) 索引的术语,为了简单起见,我没有费心提及或描述。您可以认为上面的代码(除了我适当处理的 NaN 问题)是完整的以及我正在尝试优化的代码。谢谢。
-
有趣的是,当我运行你的代码时,除了
NaNs 什么都没有。提示:网格的每个点在迭代中都是x0, y0一次,单个NaN项足以构成整个总和NaN。无论如何,我会尽快发布答案。 -
太棒了,我对你的解决方案很感兴趣。是的,您对 NaN 的看法是正确的。如果您在除以零时捕获它并将其设置为其他值,那么一切正常。再次感谢。
标签: python performance numpy optimization iteration