罗兰对MATLAB的艺术

将想法转化为MATLAB

请注意

罗兰对MATLAB的艺术已存档,不会更新。

MATLAB行为:

传统的MATLAB编程方法是使用循环自动地迫使程序遭受较差的性能。自MATLAB R13(6.5版)以来,MATLAB利用了一些创新来加速许多循环,因此代码的性能与向量化代码或用较低级语言(如C或Fortran)编写的代码相当。显然,这里的细节很重要。有一件事是大多数人,甚至是MathWorks的人都不喜欢的,那就是与一次循环单个元素相比,循环具有更丰富的行为。在我办公室附近的走廊进行的非正式调查发现,即使在经验丰富的MATLAB程序员中,知道这种行为的人也远少于50%。是时候坦白了。

内容

探索“for”的行为

MATLABStatement比许多人意识到的更强大,也更微妙,因为它允许您直接迭代数组,而不是使用显式的索引或下标。下面是一个显示行向量中正数对数的示例:

X = [1 PI -17 1.3 289 -exp(1) -42];Pnum = x(x >)“迭代”日志(pnum)结束
迭代ans = 0迭代ans = 1.1447298858494迭代ans = 0.262364264467491迭代ans = 5.66642668811243

与下面使用显式索引的代码相比,这段代码是精简的印第安纳州,得到相同的结果(除了我在这里添加的关于输出的详细信息)。

Pnums = x(x >);Ind = 1:num (pnums) disp([“迭代…值#”int2str(印第安纳州)])日志(pnums(印第安纳州))结束
迭代…值#1 ans = 0迭代…值#2 ans = 1.1447298858494迭代…值#3 ans = 0.262364264467491迭代…值#4 ans = 5.66642668811243

的行为

使用在第一个例子中,您需要理解这一点循环不遍历数组的第一个维度,而只遍历维度2,直到数组的最大维度。通过变换输入向量(把它变成一列)可以看出这一点。

x = x。Pnum = xt(xt >)“迭代”日志(pnum)结束
xt = 1 3.14159265358979 -17 1.3 289 -2.71828182845905 -42迭代ans = 0 1.1447298858494 0.262364264467491 5.66642668811243

我们看到一个迭代pnum承担责任4-by-1价值[1 PI 1.3 289]。相比之下,无论x的形状如何,带有显式索引的版本都以相同的方式工作。

更多的例子

这个迭代s。

S = [1,-2,8,pi,17], disp(“迭代”), disp (s),结束
迭代1迭代-2迭代8迭代3.14159265358979迭代17

这不会迭代,而是将整个列作为一个实体处理。

S = [1,-2,8,pi,17]',“迭代”), disp (s),结束
迭代1 -2 8 3.14159265358979 17

那么高维呢?

这个遍历A的二维和三维空间。

A = (1:12);A =重塑(A,[2 2 3])
(:: 1) = 1 2 3 4 (:,: 2) = 5 6 7 8 9 (:,:, 3) = 11 10 12
k = A, disp(“迭代”), disp (k),结束
迭代12迭代3 4迭代5 6迭代7 8迭代9 10迭代11 12

文件清楚地表明不遍历第一个维度。迭代A的所有维度,除了第一个(行)维度。您可以预测评估它的迭代次数。

元素个数(1“:”
Ans = 6

回到第一个例子,null (x(x >= 0),1,':')x是行向量吗1当x是列向量时。

可能的用途

为什么使用这个版本的?假设您有一个很大的数据集,并且矢量化计算不能充分利用诸如bsxfun。您可能遇到向量化的内存权衡太高的情况。但是您不希望对每个数组元素进行函数调用,因为函数调用开销也会变得很高。一个可能比较好的折衷方案是基本上以块的形式处理数据,也许是通过“虚拟”列。这样,函数调用开销和内存一样更有限。为了获得这种方法的最佳结果,您应该预先分配输出数组,并在循环时使用适当的索引对其进行赋值。

你用什么?

你知道这件事吗行为?你利用过它吗?您使用什么策略来权衡内存使用和函数调用开销?让我知道在这里




与MATLAB®7.9发布


评论

如欲留言,请点击在这里登录您的MathWorks帐户或创建一个新帐户。