在MATLAB中使用矢量标量乘法实现真正的慢速循环



我做错了什么吗?还是标量乘向量真的很昂贵?MATLAB(ver2012a或更高版本(不是以某种方式优化代码以防止这种好奇心吗?

>> tic; for i=1:100000; x = sin(i)*[1; 1]; end; toc;
Elapsed time is 1.338225 seconds.
>> tic; for i=1:100000; x = sin(i).*[1; 1]; end; toc;
Elapsed time is 1.228331 seconds.
>> tic; for i=1:100000; x = [sin(i); sin(i)]; end; toc;
Elapsed time is 0.073888 seconds.
>> tic; for i=1:100000; tmp=sin(i); x = [tmp; tmp]; end; toc;
Elapsed time is 0.072120 seconds.

你能给我什么指导方针来让MATLAB中的FLOPS花费他们真正需要的时间。

PS。这只是一个示例代码,我所做的是解决ode系统,并且我想在计算所需的差分时优化运行时。以上的情况让我担心我可能会以一种非最佳的方式做一些事情。

"MATLAB(ver2012a或更高版本(不是以某种方式优化了代码吗防止这种好奇心?">

是的,如果代码位于函数m文件内,则会这样做,因为JIT编译器(实时编译器(和/或加速器

然而,正如评论和其他答案中所提到的,如果可能的话,矢量化通常仍然是更好的选择

直接命令行:

tic; for i=1:100000; x1 = sin(i)*[1; 1]; end; toc;
tic; for i=1:100000; x2 = sin(i).*[1; 1]; end; toc;
tic; for i=1:100000; x3 = [sin(i); sin(i)]; end; toc;
tic; for i=1:100000; tmp=sin(i); x4 = [tmp; tmp]; end; toc;
Elapsed time is 1.795528 seconds.
Elapsed time is 1.606081 seconds.
Elapsed time is 0.072672 seconds.
Elapsed time is 0.065904 seconds.

在一个函数内

[x1,x2,x3,x4]=foo();
Elapsed time is 0.029698 seconds.
Elapsed time is 0.035248 seconds.
Elapsed time is 0.064080 seconds.
Elapsed time is 0.054499 seconds.

函数foo保存为:

function [x1,x2,x3,x4]=foo()
tic; for i=1:100000; x1 = sin(i)*[1; 1]; end; toc;
tic; for i=1:100000; x2 = sin(i).*[1; 1]; end; toc;
tic; for i=1:100000; x3 = [sin(i); sin(i)]; end; toc;
tic; for i=1:100000; tmp=sin(i); x4 = [tmp; tmp]; end; toc;
end

编辑

当我试图找到支持上述声明的文档时,我意识到我犯了一个错误,它也加速了脚本m文件,因此函数在之上被编辑

在脚本中

fooscript;
Elapsed time is 0.033536 seconds.
Elapsed time is 0.033720 seconds.
Elapsed time is 0.066050 seconds.
Elapsed time is 0.058428 seconds.

脚本fooscript包含:

tic; for i=1:100000; x1 = sin(i)*[1; 1]; end; toc;
tic; for i=1:100000; x2 = sin(i).*[1; 1]; end; toc;
tic; for i=1:100000; x3 = [sin(i); sin(i)]; end; toc;
tic; for i=1:100000; tmp=sin(i); x4 = [tmp; tmp]; end; toc;

遗憾的是,没有大量关于JIT和加速器的文档(如果有的话(。但是,为了进行比较,您可以使用feature('accel','on'/'off')feature('jit','on'/'off')禁用JIT或加速。(注意:禁用accel也会禁用jit,因为它似乎是accel的一部分。(

如果禁用accel,则性能提高会降低,但是函数和脚本性能仍然相似,并且仍然明显快于命令行。

禁用JIT对性能没有明显影响,因此原始语句是错误的。

你的for循环正在杀死你的

这是你的代码在我的机器上的时间:

tic; for i=1:100000; x = sin(i)*[1; 1]; end; toc;
tic; for i=1:100000; x = sin(i).*[1; 1]; end; toc;
tic; for i=1:100000; x = [sin(i); sin(i)]; end; toc;

运行时间为0.799754秒
运行时间为0.819284秒
运行时间为1.90613秒


如果你把它矢量化,你就会得到

t=1:100000; 
tic;     t=1:100000;   x = sin(t).'*[1; 1].'; toc;
tic;     t=1:100000;   sin(t).*[1;1] ; toc;
tic;     t=1:100000;  [sin(t);sin(t)] ; toc;

运行时间为0.015624秒
运行时间为0.0380838秒
运行时间为0.0322251秒

tmp=sin(i); x = [tmp; tmp];[sin(t);sin(t)]; 相同

MATLAB针对涉及矩阵和向量的运算进行了优化。在许多情况下,您可以重写基于循环的、面向标量的代码,以使用MATLAB矩阵和矢量运算,这一过程称为矢量化。矢量化代码通常比包含循环的相应代码运行得更快。

例如:

>> tic; for i=1:100000; x = sin(i)*[1; 1]; end; toc;
Elapsed time is 2.859756 seconds.

使用矩阵运算可以执行相同的计算:

>> tic; x = [1;1]*sin(1:100000); toc
Elapsed time is 0.007731 seconds.

相关内容

  • 没有找到相关文章

最新更新