罗兰谈MATLAB的艺术

将想法转化为MATLAB

请注意

罗兰谈MATLAB的艺术已退役,不会更新。

最近关于子数组计算速度的问题

最近有人让我解释使用循环和数组索引进行计算与先获得子数组的速度行为。

内容

例子

假设我有一个有两个输入的函数,第一个输入是列(一个正方形数组的),第二个输入是标量,输出是一个向量。

Myfun = @(x,z) x'*x+z;

尽管这可能是以完全向量化的方式计算的,但让我们探索一下当我们处理来自数组输入的子数组时会发生什么。

我现在正在创建输入数组x并输出两种计算方式的结果数组,其中一种方法中有额外的中间步骤。

N = 500;X = randn(n,n);Result1 = 0 (n,1);Result2 = 0 (n,1);

第一个方法

这里我们看到了第一种方法。在这个例子中,我们创建了一个临时数组x (:, k)n通过外圈的次数。

抽搐K = 1:nZ = 1:n result1(Z) = myfun(x(:,k), Z);结束Result1 = Result1 +x(:,k);结束运行时间(1)= toc;

第二种方法

在此方法中,我们首先在外部循环中提取感兴趣的列,然后每次通过内部循环重用该临时数组。我们再次观察并计时结果。

抽搐K = 1:n xt = x(:, K);Z = 1:n result2(Z) = myfun(xt, Z);结束Result2 = Result2 +x(:,k);结束Runtime (2) = toc;

相同的结果吗?

首先,我们要确保两边得到的答案是一样的。你可以看到我们做到了。

same = isequal(result1,result2)
same = 1

对比运行时

接下来,让我们比较一下时间。我想提醒您,从脚本执行计时通常比在函数中运行相同的代码有更多的开销。我们只是想看到相对的行为,所以我们应该从这个练习中得到一些见解。

disp ([“运行时间为:”num2str(运行时)])
运行时为:2.3936 1.9558

发生什么事情了?

事情是这样的。在第一个方法中,我们创建了一个临时变量n遍历外层循环,即使该数组对于固定列来说是常量。在第二种方法中,我们提取相关列一次,并重用它n通过内循环的次数。

如果你真的要玩这个,请考虑周到。根据函数的细节,如果每次所做的计算都比提取列向量的时间大,那么这两种方法之间可能没有太大区别。但是,如果计算的持续时间足够短,那么重复创建临时变量可能会给计算增加大量开销。一般来说,总是捕获临时数组的次数越少越好。

你的结果吗?

在分析你的算法时,你是否注意到类似的时间“谜题”?我很想知道更多在这里




MATLAB®R2013a发布

|