在 IDL 中优化最大核运算
8476 给这篇文章评分:
暂无评分
在 IDL 中优化最大核运算
匿名 2016年12月1日,星期四
我在 comp.lang.idl-pvwave 上发现了这个优化问题,并决定尝试解决一下。问题是实现一个算法,将二维数组中的每个元素替换为其邻域内的最大值。在这个例子中,邻域大小为 101x101(即 -50 到 +50),数组大小为 3200x3248。使用嵌套 FOR 循环的方法如下面的代码片段所示。
data = randomu(seed,3200,3248)
dim = size(data,/dimension)
nx = dim[0]
ny = dim[1]
t0 = tic('Nested FOR')
result2 = data
for i=0,nx-1 do begin
for j=0,ny-1 do begin
result2[i,j] = max(data[(i-50)>0:(i+50)<(nx-1),(j-50)>0:(j+50)<(ny-1)])
endfor
endfor
toc,t0
我首先想到的是使用 > 运算符,它返回两个参数中的较大者。它可以对数组进行操作,与 SHIFT 函数结合使用时,可以返回两个相邻元素中较大的一个。这里的另一个技巧是,由于我们寻找的是 101x101 邻域的最大值,我们可以以一种结构化的方式,使用较小邻域最大值的组合作为输入,以实现精确的 101x101 邻域大小。经过一些尝试,我最终得到的代码如下。
t0 = tic('Iterative >')
; 使用 SHIFT 和 > 进行迭代运算
padded = replicate(min(data),size(data,/dimension)+100)
padded[50,50] = data
tmp3 = shift(padded,1,0) > padded > shift(padded,-1,0)
tmp9 = shift(tmp3,3,0) > tmp3 > shift(tmp3,-3,0)
tmp27 = shift(tmp9,9,0) > tmp9 > shift(tmp9,-9,0)
tmp81 = shift(tmp27,27,0) > tmp27 > shift(temporary(tmp27),-27,0)
tmp99 = shift(tmp9,44,0) > temporary(tmp81) > shift(temporary(tmp9),-44,0)
tmp101 = shift(tmp3,49,0) > temporary(tmp99) > shift(temporary(tmp3),-49,0)
; 对 Y 维度执行相同操作
tmp3 = shift(tmp101,0,1) > tmp101 > shift(temporary(tmp101),0,-1)
tmp9 = shift(tmp3,0,3) > tmp3 > shift(tmp3,0,-3)
tmp27 = shift(tmp9,0,9) > tmp9 > shift(tmp9,0,-9)
tmp81 = shift(tmp27,0,27) > tmp27 > shift(temporary(tmp27),0,-27)
tmp99 = shift(tmp9,0,44) > temporary(tmp81) > shift(temporary(tmp9),0,-44)
tmp101 = shift(tmp3,0,49) > temporary(tmp99) > shift(temporary(tmp3),0,-49)
result1 = (temporary(tmp101))[50:50+nx-1,50:50+ny-1]
toc,t0
我没有说优化后的代码总是看起来漂亮,但这里的目标是运行速度快。添加一些结果对比检查,以确保结果是等效的。
print, array_equal(result1,result2) ? 'Results are matching' : 'SOMETHING went wrong'
最后,以下是结果,它带来了令人印象深刻的速度提升,执行时间从 189.4 秒减少到 1.4 秒,并且结果相同:
% Time elapsed Nested FOR: 189.39470 seconds.
% Time elapsed Iterative >: 1.4241931 seconds.
Results are matching
ENVI 5.4 新功能:ENVITask 返回虚拟栅格 在 IDL 8.6 中保持向后兼容性——保持冷静并阅读您的发行说明