循环语句性能并预先分配循环语句本身

Wer*_*ner 5 matlab for-loop while-loop

这种观察并不重要,因为浪费在循环语句上的时间性能可能远高于循环本身.但无论如何,我会分享它,因为我搜索并找不到关于此的话题.我总是有这样的印象:预先分配我将循环的数组,然后循环它,将比直接循环它更好,并决定检查它.代码将比较这两个fors之间的效率:

disp('Pure for with column on statement:')
tic
for k=1:N
end
toc

disp('Pure for with column declared before statement:')
tic
m=1:N;
for k=m
end
toc
Run Code Online (Sandbox Code Playgroud)

但我得到的结果是:

Pure for with column on statement:
Elapsed time is 0.003309 seconds.
Pure for with column declared before statement:
Elapsed time is 0.208744 seconds.
Run Code Online (Sandbox Code Playgroud)

为什么会这样?不应该预先分配更快?

事实上,matlab help for说:

因为从不创建索引向量,所以当结束表达式出现在FOR语句中时,长循环可以提高内存效率.

因此,与我的期望相反,for语句中的列表达式更好,因为它不分配向量,因此更快.

我做了以下脚本来测试其他场合我也认为会更快:

% For comparison:
N=1000000;

disp('Pure for loop on cell declared on statement:')
tic
for k=repmat({1},1,N)
end
toc

disp('Pure for loop on cell declared before statement:')
tic
mcell=repmat({1},1,N);
for k=mcell
end
toc

disp('Pure for loop calculating length on statement:')
tic 
for k=1:length(mcell)
end
toc

disp('Pure for loop calculating length before statement:')
tic
lMcell = length(mcell);
for k=1:lMcell
end
toc

disp('Pure while loop using le:')
% While comparison:
tic
k=1;
while (k<=N)
  k=k+1;
end
toc

disp('Pure while loop using lt+1:')
% While comparison:
tic
k=1;
while (k<N+1)
  k=k+1;
end
toc


disp('Pure while loop using lt+1 pre allocated:')
tic
k=1;
myComp = N+1;
while (k<myComp)
  k=k+1;
end
toc
Run Code Online (Sandbox Code Playgroud)

时间是:

Pure for loop on cell declared on statement:
Elapsed time is 0.259250 seconds.
Pure for loop on cell declared before statement:
Elapsed time is 0.260368 seconds.
Pure for loop calculating length on statement:
Elapsed time is 0.012132 seconds.
Pure for loop calculating length before statement:
Elapsed time is 0.003027 seconds.
Pure while loop using le:
Elapsed time is 0.005679 seconds.
Pure while loop using lt+1:
Elapsed time is 0.006433 seconds.
Pure while loop using lt+1 pre allocated:
Elapsed time is 0.005664 seconds.
Run Code Online (Sandbox Code Playgroud)

结论:

  • 您可以通过循环逗号语句获得一些性能,但与for循环所花费的时间相比,这可以忽略不计.
  • 对于细胞,差异似乎可以忽略不计.
  • 在进行循环之前最好预先分配长度.
  • 虽然没有预先分配向量,但是while具有与for相同的效率,这如前所述是有意义的
  • 正如所料,最好在while语句之前计算固定表达式.

但我无法回答的问题是,细胞怎么样,为什么没有时间差异?开销可能远低于观察到的开销?或者它必须分配单元格,因为它不是一个基本类型的双重?

如果您知道有关此主题的其他技巧,请填写.


只需添加时间来显示转动的结果,feature('accel','off')就像在@Magla的答案中所说的那样.

Pure for with column on statement:
Elapsed time is 0.181592 seconds.
Pure for with column declared before statement:
Elapsed time is 0.180011 seconds.
Pure for loop on cell declared on statement:
Elapsed time is 0.242995 seconds.
Pure for loop on cell declared before statement:
Elapsed time is 0.228705 seconds.
Pure for loop calculating length on statement:
Elapsed time is 0.178931 seconds.
Pure for loop calculating length before statement:
Elapsed time is 0.178486 seconds.
Pure while loop using le:
Elapsed time is 1.138081 seconds.
Pure while loop using lt+1:
Elapsed time is 1.241420 seconds.
Pure while loop using lt+1 pre allocated:
Elapsed time is 1.162546 seconds.
Run Code Online (Sandbox Code Playgroud)

结果现在按预期区域......

mar*_*sei 3

这一发现与预分配与否无关:它涉及 matlab 是否启用或不使用多个内核进行计算。当您在语句中插入冒号运算符时for,它会告诉 matlab 使用多个内核(即多线程)。

如果您仅将 MATLAB 设置为一个内核feature('accel','off'),则观察到的差异doubles将消失。关于cells,matlab 不使用多线程 - 因此无法观察到任何差异(无论 的状态如何accel)。

for当使用冒号时,并且仅当使用冒号时,循环才是多线程的。以下长度相似的向量不会占用多个核心:

  • for k = randperm(N)
  • for k = linspace(1,N,N)

但是for k = 1:0.9999:N是多线程的。

可以在该matlab 的支持页面上找到一种解释。它指出,当“函数执行的算法中的操作很容易划分为可以同时执行的部分”时,就可以完成多核处理。通过冒号运算符,Matlab 知道for可以进行分区。

  • Matlab 如何提前知道多线程“for”循环是安全的?我的理解是,Matlab 本身会支持“fft”、“eig”、“svd”和“sort”等多线程函数,但要在循环上获得多线程,需要并行处理工具箱和“parfor”构造...有没有讨论此功能的官方文档? (3认同)