11

我惊讶地发现运行 MATLAB for 循环之间的成本差异如下:

ksize = 100;
klist = 1:ksize;

tic
for m = 1:100000        
    for k = 1:ksize

    end        
end
toc

tic
for m = 1:100000        
    for k = klist

    end        
end
toc

唯一的区别是创建索引列表的方式。我会怀疑第二个版本更快,但是看!

Elapsed time is 0.055400 seconds.
Elapsed time is 1.695904 seconds.

我的问题是双重的:是什么导致了上述结果,以及这种细微差别(或类似的细微差别)在 MATLAB 编程中还出现在哪里?我希望将来能够更好地发现这些低效率。谢谢大家。

4

2 回答 2

4

for()各州的文档:

for index = values
   ...
end

wherevalues具有以下形式之一:

  • ...

  • valArrayvalArray:在每次迭代时从数组的后续列创建列向量索引。例如,在第一次迭代中,index = valArray(:,1). 循环最多执行n次数,其中n是 valArray 的列数,由 给出numel(valArray, 1, :)。输入valArray可以是任何 MATLAB 数据类型,包括字符串、元胞数组或结构。

因此,我假设有很大的开销并且编译器不会检查是否1:ksize == klist利用更快的实现。换句话说,根据 Eitan 的评论,JIT 适用于前两种类型的接受

整个问题与以下索引任务(列与元素)有关:

tic
for m = 1:100000        
    for k = 1:ksize
        klist(:,k);
    end        
end
toc

tic
for m = 1:100000        
    for k = 1:ksize
        klist(k);
    end        
end
toc

Index column:  ~2.9 sec
Index element: ~0.28 sec

您可以看到如何klist(:,k)有效地减慢更快的循环,表明问题for k = klist与在这种情况下使用的列索引有关。

有关更多详细信息,请参阅关于(低效)索引的冗长讨论

于 2013-04-17T13:18:55.323 回答
2

我的回答是推测(因为只有 Mathworks 的人知道他们产品的实现),但我认为第一个k循环经过优化,不会创建实际的索引数组,而是一个一个地扫描它们,因为它明确地显示了值是“建造”的。第二个k循环无法优化,因为解释器事先不知道索引数组的内容是否会均匀增长。所以,每次循环开始时,它都会复制访问原始文件klist,这就是你有性能损失的原因。

稍后编辑:klist与“动态”创建索引值相比,另一个性能损失可能来自对数组的索引访问。

于 2013-04-17T12:18:21.897 回答