对于循环需要很长时间

时间:2016-08-30 06:29:20

标签: performance matlab for-loop

我正在模拟Irwin Hall分布的1,000,000个重复,每个重复是100个均匀随机变量的总和。我创建了这个程序,我认为它是正确的,但是MATLAB已经整夜运行而没有完成,所以有些(显然)错了,但我看不到哪里。这是我的计划,我希望有人可能会看到这个问题。

n=100; % Nb of samples
N=1000000; %Nb of replicates

for jj=1:N
    for ii=1:n
        x(ii)=rand();
    end
    s(jj)=sum(x);
    mu=mean(s);
    sigma2=var(s);
    sigma=std(s);
    S(jj)=1-normcdf((70-mu)/sigma);
    if mod(jj, 100000)==0
        jj
    end
end

histogram(S) 

2 个答案:

答案 0 :(得分:5)

n=1e2; % Nb of samples
N=1e6; % Nb of replicates
s = zeros(1,N); % INITIALISE, INITIALISE, INITIALISE
S = zeros(1,N); % INITIALISE, INITIALISE, INITIALISE

for jj=1:N
    x=rand(n,1); % Remove redundant inner loop
    s(1,jj)=sum(x);
    tmp = s(1,1:jj); % Create temporary storage for convenience
    mu=mean(tmp);
    sigma=std(sigma2); % You don't need the variance at all
    S(1,jj)=1-normcdf((70-mu)/sigma);
     if mod(jj, 1e5)==0
         disp('We are at iteration %i',jj); % Proper display command
     end
end

histogram(S) 

此代码在我的i5-750处理器上使用N=1e4运行半秒钟。

最重要的事情是:不要像jj那样打印到控制台。要么根本不打印,要么使用disp命令来清楚。打印到控制台需要花费大量时间。 initialise your variables也是{{3}}。循环中增长的变量需要很长时间。每次增加变量的长度,在这里增加一百万次,就强制MATLAB首先创建一个初始长度为+ 1的变量,然后复制内容,然后删除旧变量。这可能是你的代码花了很长时间。

我还使用了一个临时变量tmp来使代码中的转换更容易。

答案 1 :(得分:2)

我预先分配了变量S并对某些代码进行了矢量化。

tic;

n=100; % Nb of samples
N=1000000; %Nb of replicates

x = rand(n,N); % x(ii) = rand();
s = sum(x); % s = sum(x);
mu = cumsum(s)./(1:N); % mu = mean(s);

S = zeros(N,1);
for jj=1:N
    sigma=std(s(1:jj));
    S(jj)=1-normcdf((70-mu(jj))/sigma);
    if ~mod(jj,100000)
        fprintf('%d %.2f\n',jj,toc);
    end
end

toc

histogram(S)  

我得到了

N        orginal  modified
----------------------------
1e+05     54.07      31.9
2e+05    246.37     173.6
3e+05    621.06    450.91
4e+05    1161.2    835.03
5e+05    1837.5    1329.4
6e+05    2661.4    1930.3

配备i5-6200U处理器和8GB DDR3内存。

由于随着jj越大,计算越来越重,如果运行N = 10^6的代码,则需要相当长的时间。

由于您没有预先分配变量,因此将N设置得更大时差异会更大。

即使MATLAB可以处理可变大小的修改,MATLAB 高度建议您预先分配内存。每次MATLAB碰到变量的边界时,MATLAB都会尝试重新分配内存,这需要花费更多的时间。即使你无法计算确切的内存大小,最好还是粗略猜测一些变量,然后在循环后删除未使用的部分。