循环语句性能和预分配循环语句本身 [英] Looping statements performance and pre-allocating the looping statement itself

查看:24
本文介绍了循环语句性能和预分配循环语句本身的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

This observation is not that important, because the time performance wasted on the loop statements will probably be much higher than the looping itself. But anyway, I will share it since I searched and couldn't find a topic about this. I always had this impression that pre-allocating the array I would loop, and then loop on it, would be better than looping directly on it, and decided to check it. The code would be to compare the efficiency between this two 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

但我得到的结果是:

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.

这到底是为什么呢?预分配不是应该更快吗?

Why the hell is that? Shouldn't pre-allocating be faster?

其实matlab的help for是这样说的:

In fact, the matlab help for says:

当冒号表达式出现时,长循环的内存效率更高在 FOR 语句中,因为从未创建索引向量.

Long loops are more memory efficient when the colon expression appears in the FOR statement since the index vector is never created.

因此,与我的预期相矛盾for 语句中的列表达式更好,因为它不分配向量,因此速度更快.

So, contradicting my expectations the column expression at the for statement is better, because it does not allocate the vector and, because of that, is faster.

我制作了以下脚本来测试我认为会更快的其他场合:

I made the following script to test other occasions that I also would think that would be faster:

% 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

时间是:

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.

结论:

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

但我无法回答的问题是,单元格怎么办,为什么没有时差?开销可能比观察到的要少得多?或者它必须分配单元格,因为它不是双精度型的基本类型?

But the question that I can't answer is, what about the cell, why isn't there time difference? The overhead could be much lesser than the observed? Or it has to allocate the cells since it is not a basic type as a double?

如果您知道有关此主题的其他技巧,请免费添加.

If you know other tricks concerning this topic fill free to add.

只需添加时间即可显示 @Magla 的回答中所说的 feature('accel','off') 转动的结果.

Just adding the timings to show the results of turning feature('accel','off') as said in @Magla's answer.

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.

现在的结果符合预期......

The results now area as expected…

推荐答案

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

This finding has nothing to do with preallocating or not: it deals with matlab being enable or not to compute things with several cores. When you insert the colon operator within the for statement, it tells matlab to use several cores (i.e. multithreading).

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

If you set matlab on one core only with feature('accel','off'), the observed difference with doubles vanishes. Concerning cells, matlab does not make use of multithreading - therefore no difference can be observed (whatever the status of accel is).

for 循环在使用冒号时是多线程的,并且仅当使用冒号时.以下相似长度的向量不参与多个核心:

The for loop is multithreaded when a colon is used, and only if a colon is used. The following vectors of similar length does not engage several cores:

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

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

可以在这个 matlab 的支持页面上找到一个解释.它指出,当由函数执行的算法中的操作很容易划分为可以并发执行的部分"时,可以进行多核处理.使用冒号运算符,Matlab 知道可以对 for 进行分区.

One explanation can be found on this matlab's support page. It states that multi-core processing can be done when "The operations in the algorithm carried out by the function are easily partitioned into sections that can be executed concurrently.". With a colon operator, Matlab knows that for can be partitioned.

这篇关于循环语句性能和预分配循环语句本身的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆