我很惊讶地发现在运行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
唯一的区别在于创建索引列表的方式。我本来怀疑第二个版本要快一些,但是lo!
Elapsed time is 0.055400 seconds.
Elapsed time is 1.695904 seconds.
我的问题有两个:对上述结果负责的是什么,以及在MATLAB编程中这个细微差别(或类似的)发生在哪里?我希望将来能够更好地发现这些低效率。谢谢大家。
答案 0 :(得分:4)
for()
中的文档说明:
for index = values ... end
其中
values
具有以下形式之一:
...
valArray
:在每次迭代时从数组valArray
的后续列创建列向量索引。例如,在第一次迭代中,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
中的问题与此案例中使用的列索引相关。
有关其他详细信息,请参阅此lengthy discussion on (inefficient) indexing。
答案 1 :(得分:2)
我的回答是推测(因为只有Mathworks的人知道他们产品的实现),但我认为第一个k
循环被优化为不创建实际的索引数组,而是逐个扫描它们,因为它明确地显示了值是如何“建立”的。第二个k
循环无法优化,因为解释器事先不知道索引数组的内容是否会均匀增长。因此,每次循环开始时,它都会复制访问原始klist
,这就是性能损失的原因。
稍后编辑:与“动态”创建索引值相比,klist
数组中的索引访问可能会带来另一个性能损失。