【发布时间】:2013-05-01 03:16:14
【问题描述】:
我正在构建我的第一个大型 MATLAB 程序,并且我已经设法为所有内容编写原始矢量化代码,直到我开始尝试创建一个表示立体投影中矢量密度的图像。在几次尝试失败后,我访问了 Mathworks 文件交换站点,发现了一个符合我需要的开源程序,由 Malcolm Mclean 提供。使用测试矩阵,他的函数会产生如下内容:
虽然这几乎正是我想要的,但他的代码依赖于三重嵌套的 for 循环。在我的工作站上,在这部分代码中,大小为 25000x2 的测试数据矩阵花费了 65 秒。这是不可接受的,因为我将在我的项目中扩展到大小为 500000x2 的数据矩阵。
到目前为止,我已经能够矢量化最里面的循环(这是最长/最差的循环),但如果可能的话,我想继续并完全摆脱这些循环。这是我需要向量化的 Malcolm 的原始代码:
dmap = zeros(height, width); % height, width: scalar with default value = 32
for ii = 0: height - 1 % 32 iterations of this loop
yi = limits(3) + ii * deltay + deltay/2; % limits(3) & deltay: scalars
for jj = 0 : width - 1 % 32 iterations of this loop
xi = limits(1) + jj * deltax + deltax/2; % limits(1) & deltax: scalars
dd = 0;
for kk = 1: length(x) % up to 500,000 iterations in this loop
dist2 = (x(kk) - xi)^2 + (y(kk) - yi)^2;
dd = dd + 1 / ( dist2 + fudge); % fudge is a scalar
end
dmap(ii+1,jj+1) = dd;
end
end
这就是我已经对最内层循环所做的更改(这是对效率的最大消耗)。这将我机器上相同测试矩阵的时间从 65 秒减少到 12 秒,这比我想要的要好,但仍然慢得多。
dmap = zeros(height, width);
for ii = 0: height - 1
yi = limits(3) + ii * deltay + deltay/2;
for jj = 0 : width - 1
xi = limits(1) + jj * deltax + deltax/2;
dist2 = (x - xi) .^ 2 + (y - yi) .^ 2;
dmap(ii + 1, jj + 1) = sum(1 ./ (dist2 + fudge));
end
end
所以我的主要问题是,我可以做任何进一步的更改来优化此代码吗?甚至是解决问题的替代方法?我已经考虑在程序的这一部分使用 C++ 或 F# 而不是 MATLAB,如果我无法使用 MATLAB 代码达到合理的效率水平,我可能会这样做。
还请注意,此时我没有任何其他工具箱,如果有,我知道这将是微不足道的(例如使用统计工具箱中的 hist3)。
【问题讨论】:
-
xy和fudge是什么?deltax和deltay是什么?它们的尺寸是多少? -
这将有助于了解不同变量的大小和类别(
limits、deltax、deltay、x、y、fudge等 -
在不真正了解不同变量的情况下,我可能会打赌
accumarray和hist来获得这个向量化... -
我没看过,但这里有一个
hist3,有人为 Octave 写的,你很可能可以免费使用(附在底部)octave.1599824.n4.nabble.com/… -
@natan - 我不认为
hist或accumarray是这个特定代码所需要的
标签: performance matlab image-processing vectorization