罗兰关于MATLAB的艺术

将思想转化为MATLAB

彻底地

我和我的老同事Mike Croucher聊天,他最近加入了MathWorks团队(耶!)关于一堆有趣的话题,其中一些可以作为博客文章的好素材。今天我想讲的是循环。

嵌套循环

在我以前的Fortran编程时代(是的,很久以前了),我很早就知道,如果我安排嵌套,我的代码运行得更快对- - - - - -循环优化。在Fortran中,如果我每次计算一个矩阵中的一个元素,这意味着要确保我按顺序填充元素,这意味着每次循环遍历每一行,每一列,因为这是Fortran(和MATLAB)存储数组的方式。这不是数组在C中的存储方式。
我很好奇今天在MATLAB中如果我尝试以不同的顺序运行嵌套循环会发生什么。让我们看看!
计算Ar c =r*(r+c3)+17

直接循环解决方案,内部循环行

当然我预先分配了我的输出数组,基于“增大化现实”技术
t = 0(1、3);
n = 1000;
抽搐;
基于“增大化现实”技术= 0 (n, n);
[nrows, ncolumns] =大小(Ar);
行= 1:nrows
列= 1:ncolumns
基于“增大化现实”技术(行、列)=行*(行+列^ 3)+ 17;
结束
结束
t (1) = toc;

直接循环解决方案,内环列

现在是另一种顺序。
抽搐;
Ac = 0 (n, n);
[nrows, ncolumns] = (Ac)大小;
列= 1:ncolumns
行= 1:nrows
交流(行、列)=行*(行+列^ 3)+ 17;
结束
结束
t (2) = toc;

矢量化的解决方案

当然,还有矢量化的版本。
抽搐;
tmpr = (1: nrows)。';
Av = tmpr .* (tmpr+(1:ncolumns).^3) + 17;
t (3) = toc;

分析

让我们确保它们也产生相同的结果。
areAnswerEqual = isequal (Ac, Ar, Av)
areAnswerEqual =逻辑
1
那么执行时间呢?
t
t = 1×3
0.1236 0.0190 0.0082

顺序很重要

在MATLAB中,使用嵌套-循环,显然循环的顺序从时间角度来说很重要。因此,如果您能以这种方式编写算法,那么在知道数据是一列一列存储的情况下对它们进行排序将是明智的。我没有展示如果我们不预先分配输出矩阵会有什么影响。你们可以自己试试。
尽管通过处理嵌套循环可以获得相当好的加速,但从速度的角度来看,尝试向量化代码仍然是更可取的。注意我正在使用隐式的扩张来计算Av.还要注意,你不会总是得到相同的循环和等效的向量化版本之间的速度差比率-它将在很大程度上取决于每个计算所进行的工作量和产生的开销。

你的想法呢?

当在MATLAB中使用循环时,从速度的角度来看,最好设置循环,以便尽可能接近顺序地访问元素。您可以从上面的小示例中看到,在列上运行比在行上运行性能更好。这是因为MATLAB存储数组的方式。
你是否遇到过重新排序循环帮助你解决问题的情况?让我们知道在这里
The MathWorks, Inc.版权所有
|

评论

请点击留下评论在这里登录到你的MathWorks帐户或创建一个新的。