【发布时间】:2021-06-18 04:58:44
【问题描述】:
所以我这里有这个定义,
DP[i,j] = f[i,j] + min(DP[i−1, j −1], DP[i−1, j], DP[i−1, j +1])
它定义了从 NxM 矩阵顶部到矩阵底部的最小应计成本。 f 中的每个单元格代表从另一个单元格前往该单元格的价值/成本(1.2、0、10 等)。
矩阵可能很大(1500x1500,它是Gradient map of an image),而我编写的 DP 算法每次运行我的矩阵大约需要一秒。该矩阵每次执行需要运行数百次,因此总程序运行时间长达几分钟。这个循环大约是我瓶颈的 99%,所以我正在尝试使用 Python/numpys 矢量化方法优化这个循环。我只能访问 Numpy 和 Scipy。
注意:我几乎不会在 python 中编程,所以解决方案可能只是显而易见的 idk。
第一次尝试,只是简单的循环,这里的时间大约是每次运行 2-2.5 秒
DP = f.copy()
for r in range(2, len(DP) - 1): # Start at row 2 since row one doesn't change
for c in range(1, len(DP[0]) - 1):
DP[r][c] += min(DP[r - 1, c-1:c+2])
第二次尝试,我尝试利用一些 numpy 矢量化函数“fromiter”一次计算整行而不是逐列计算,这里的时间约为每次运行 1-1.5 秒。我的目标是让这个速度至少快一个数量级,但我不知道如何优化它。
DP = f.copy()
for r in range(2, len(DP) - 1):
def foo(arr):
idx, val = arr
if idx == 0 or idx == len(DP[[0]) - 1:
return np.inf
return val + min(DP[r - 1, idx - 1], DP[r - 1, idx], DP[r - 1, idx + 1])
DP[r, :] = np.fromiter(map(foo, enumerate(DP[r, :])))
【问题讨论】:
-
大多数快速的
numpy方法本质上是“并行的”,使用编译后的代码对数组的所有元素进行操作,没有任何隐含的顺序。看起来您的案例本质上是连续的,r行的值取决于上一行中的窗口。fromiter不是“矢量化”,尽管在某些情况下它可能比其他迭代更快。也就是说,c循环看起来确实可以以“一次”计算所有行值的方式编写。
标签: python numpy scipy vectorization