罗兰关于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)。';
tmpr = 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中,使用嵌套-loops,显然从时间的角度来看,循环的顺序很重要。所以,如果你可以这样写算法,最好是让它们知道数据是按列存储的。我没有展示如果我们不预先分配输出矩阵会有什么影响。你们可以自己试试。
尽管通过处理嵌套循环获得了相当好的加速,但从速度的角度来看,尝试向量化代码仍然是更好的选择。注意我正在使用隐式的扩张来计算Av.还需要注意的是,在循环和等效的矢量化版本之间,速度差的比率并不总是相同的——这在很大程度上取决于每次计算要进行多少工作,以及产生了多少开销。

你的想法呢?

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

评论

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