我正在构建我的第一个大型 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 )。