预分配和矢量化加速

时间:2014-02-04 21:39:32

标签: matlab

我正在努力提高我试图运行的脚本的速度。

这是代码:(我的机器= 4核心胜利7)

clear y;
n=100;
x=linspace(0,1,n);
% no y pre-allocation using zeros
start_time=tic;

for k=1:n,
    y(k) =  (1-(3/5)*x(k)+(3/20)*x(k)^2 -(x(k)^3/60)) / (1+(2/5)*x(k)-(1/20)*x(k)^2);
end

elapsed_time1 = toc(start_time);
fprintf('Computational time for serialized solution: %f\n',elapsed_time1);

上面的代码给出了0.013654的经过时间。

另一方面,我试图通过在上面的代码中添加y = zeros(1,n);来使用预分配,其中注释是,但运行时间类似于~0.01左右。有什么想法吗?有人告诉我它会提高2倍。我错过了什么吗?

最后在Matlab中是否有任何类型的矢量化可以让我忘记上面代码中的for循环?

谢谢,

3 个答案:

答案 0 :(得分:3)

在您的代码中:尝试使用n=10000,您会看到更多差异(我的机器上差不多10倍)。

当变量的大小很大时,与分配相关的这些事情最为明显。在这种情况下,Matlab更难为该变量动态分配内存。


减少操作次数:进行矢量化,并重用中间结果以避免权限:

y = (1 + x.*(-3/5 + x.*(3/20 - x/60))) ./ (1 + x.*(2/5 - x/20));

<强>基准

使用n=100

Parag / venergiac的解决方案:

>> tic
for count = 1:100
y=(1-(3/5)*x+(3/20)*x.^2 -(x.^3/60))./(1+(2/5)*x-(1/20)*x.^2);
end
toc
Elapsed time is 0.010769 seconds.

我的解决方案:

>> tic
for count = 1:100
y = (1 + x.*(-3/5 + x.*(3/20 - x/60))) ./ (1 + x.*(2/5 - x/20));
end
toc
Elapsed time is 0.006186 seconds.

答案 1 :(得分:2)

您不需要for循环。用以下代替for循环,MATLAB将处理它。

y=(1-(3/5)*x+(3/20)*x.^2 -(x.^3/60))./(1+(2/5)*x-(1/20)*x.^2);

当向量变得更大时,这可以提供计算优势。较小的尺寸是您无法看到预分配效果的原因。请阅读this页面,了解有关如何改善效果的其他提示。

编辑:我观察到,在较大的尺寸n>=10^6时,当我尝试以下操作时,我的性能会不断提高:

x=0:1/n:1;

而不是使用linspace。在n=10^7,我使用linspace获得0.05秒(0.03 vs 0.08)。

答案 2 :(得分:1)

尝试每个元素的操作元素(.*.^

clear y;
n=50000;
x=linspace(0,1,n);
% no y pre-allocation using zeros
start_time=tic;

for k=1:n,
    y(k) =  (1-(3/5)*x(k)+(3/20)*x(k)^2 -(x(k)^3/60)) / (1+(2/5)*x(k)-(1/20)*x(k)^2);
end

elapsed_time1 = toc(start_time);
fprintf('Computational time for serialized solution: %f\n',elapsed_time1);

start_time=tic;
y =  (1-(3/5)*x+(3/20)*x.^2 -(x.^3/60)) / (1+(2/5)*x-(1/20)*x.^2);

elapsed_time1 = toc(start_time);
fprintf('Computational time for product solution: %f\n',elapsed_time1);

我的数据

  

序列化解决方案的计算时间:2.578290

     

序列化解决方案的计算时间:0.010060