MATLAB for循环索引的最佳实践

时间:2013-04-17 12:11:39

标签: performance matlab for-loop indexing

我很惊讶地发现在运行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编程中这个细微差别(或类似的)发生在哪里?我希望将来能够更好地发现这些低效率。谢谢大家。

2 个答案:

答案 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数组中的索引访问可能会带来另一个性能损失。