MATLAB for 循环索引的最佳实践
Posted
技术标签:
【中文标题】MATLAB for 循环索引的最佳实践【英文标题】:Best practice for MATLAB for loop index 【发布时间】:2013-04-10 04:36:37 【问题描述】:我惊讶地发现运行 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 编程中还出现在哪里?我希望将来能够更好地发现这些低效率。谢谢大家。
【问题讨论】:
这可能是由于 JIT 加速造成的,因为如果您使用feature accel off
将其关闭,则两次运行都会得到相似的结果。
【参考方案1】:
我的回答是推测(因为只有 Mathworks 的人知道他们产品的实现),但我认为第一个 k
循环经过优化,不会创建实际的索引数组,而是一个一个地扫描它们,因为它明确地显示了这些值是如何“构建”的。第二个k
循环无法优化,因为解释器事先不知道索引数组的内容是否会均匀增长。因此,每次循环开始时,它都会复制访问原始的klist
,这就是为什么会有性能损失。
稍后编辑:与“动态”创建索引值相比,另一个性能损失可能来自对 klist
数组的索引访问。
【讨论】:
我想知道您是否可以通过创建一个派生自double
并覆盖copy
的类来测试这个...
@wakjah 检查过,这与复制无关(实际上并没有发生复制——我认为写时复制仍然有效)。这是关于klist
中的下标引用。我更正了 mt 帖子。谢谢你的想法。
@wakjah 另一方面,copy
适用于句柄子类,并且不能同时继承值 和 句柄类(至少在我拥有的 R2010a 中没有) .我想知道我是否真的覆盖了任何东西......:D
这是真的......那么可能在值类的构造函数/subsasgn
中?【参考方案2】:
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。
【讨论】:
以上是关于MATLAB for 循环索引的最佳实践的主要内容,如果未能解决你的问题,请参考以下文章