【问题标题】:How to improve the Matlab code for faster processing time?如何改进 Matlab 代码以加快处理时间?
【发布时间】:2014-08-06 18:05:02
【问题描述】:

我为我的硕士项目开发了一些代码,将使用 1000 个不同的数据集模拟 90 年的每日数据。代码运行良好,并给出了我想要的正确输出,但处理时间非常长。完成模拟大约需要 8 个小时。这是我使用的代码:

    tic
%% importing the csv file with selected column
files=dir('*_scen_*.csv');
for i=1:length(files);
    LHR=importcsv(files(i).name);

%% Definable variables
% Define These Value
TAW=-216;     %total available water
RAW=-129;     %readily available water
KC=1.0;       %crop coefficient
IRL=15;       %intense rain level
RC=(80/100);  %percentage of recharge 
RO=(1-RC);    %percentage of runoff

% The very first row of Soil Moisture Deficit
for j=1
    SMD(j,i)=(LHR.RAIN(j)-LHR.PET(j));
 if     SMD(j,i)>0;
        SMD(j,i)=0;
 elseif SMD(j,i)<RAW;
        SMD(j,i)=(LHR.RAIN(j)-(LHR.PET(j)*((TAW-SMD(j-1))/(TAW-RAW))));
 end
end

%for the following SMD Calculation
for k=2:(length(LHR.RAIN));
    SMD(k,i)=SMD(k-1,i)+(LHR.RAIN(k)-LHR.PET(k));
    % The SMD conditions
    if SMD(k,i)>0;
       SMD(k,i)=0;
 elseif SMD(k,i)<RAW;
     SMD(k,i)=SMD(k-1,i)+(LHR.RAIN(k)-(LHR.PET(k)*((TAW-SMD(k-1,i))/(TAW-RAW))));
    end
end
%Convert negative SMD to Positive
SMD=abs(SMD);

 %%Evapotranspiration Calculation
 for l=1:(length(SMD));
    if SMD(l,i)<abs(RAW);
        AET(l,i)=LHR.PET(l);
    elseif SMD(l,i)>abs(RAW);
        AET(l,i)=KC*LHR.PET(l)*((abs(TAW)-(SMD(l,i)))/(abs(TAW)-abs(RAW)));
    end
end
for m=2:(length(SMD));
    if SMD(m,i)<abs(RAW);
        AET(m,i)=LHR.PET(m);
    elseif SMD(m,i)>abs(RAW);
       AET(m,i)=KC*LHR.PET(m)*((abs(TAW)-(SMD(m-1,i)))/(abs(TAW)-abs(RAW)));
    end
end
%% HER calculation
for n=1:length(SMD);
    if SMD(n,i)<(LHR.RAIN(n)-AET(n,i));
        HER(n,i)=(LHR.RAIN(n)-AET(n,i)-SMD(n,i));
    elseif SMD(n,i)>(LHR.RAIN(n)-AET(n,i));
        HER(n,i)=0;
    end
end
%% Calculation of recharge anf runoff
for o=1:(length(HER));
    if (HER(o,i)+(abs(TAW)-SMD(o,i)))<abs(TAW);
        RUNOFF(o,i)=0;
    elseif (HER(o,i)+(abs(TAW)-SMD(o,i)))>abs(TAW);
        if HER(o,i)>IRL;
            RUNOFF(o,i)=RO*HER(o,i);
        elseif HER(o,i)<IRL;
            RUNOFF(o,i)=0;    
        end
    end
    if (HER(o,i)+(abs(TAW)-SMD(o,i)))<abs(TAW);
        RECHARGE(o,i)=0;
    elseif (HER(o,i)+(abs(TAW)-SMD(o,i)))>abs(TAW);
        if HER(o,i)>IRL;
            RECHARGE(o,i)=RC*HER(o,i);
        elseif HER(o,i)<IRL;
            RECHARGE(o,i)=HER(o,i);
        end
    end
end
%% rainfall
for p=1:length(LHR.RAIN);
RAINFALL(p,i)=LHR.RAIN(p);
PET(p,i)=LHR.PET(p);
end

end
clear i
clear j
clear k
clear l
clear m
clear n
clear o
clear p

toc

此代码是否有任何改进范围可以减少处理时间?对不起,如果代码看起来不专业,因为我处于 MATLAB 编程的初学者阶段。

【问题讨论】:

  • 你有并行处理工具箱吗?
  • 使用 matlab profiler 查看瓶颈。您可以使用以下命令序列执行此操作:profile on、run_code、profiler viewer。
  • 对不起,我是 matlab 新手,我不确定我有没有。如何检查我是否有并行处理工具箱?
  • 从正确格式化代码开始。
  • 这是代码审查的更多主题吗? (codereview.stackexchange.com)

标签: performance matlab for-loop


【解决方案1】:

如果说 Matlab 擅长一件事,那就是矩阵和向量计算。使用类似循环的代码,尤其是对于大型数据集,您完全失去了这个优势。

我没有仔细研究细节,但您的所有循环似乎都在进行元素计算和逻辑运算。你可以用矩阵计算来代替这些。

例如,让我们考虑您的第一个循环:

for k=2:(length(LHR.RAIN));
    SMD(k,i)=SMD(k-1,i)+(LHR.RAIN(k)-LHR.PET(k));
  % …
end

可以替换为(未经测试的)SMD(2:end,i)=SMD(1:end-1,i)+LHR.RAIN(1:end-1)-LHR.PET(1:end-1)

还有这样的逻辑运算:

for k=2:(length(LHR.RAIN));
    % ...
    % The SMD conditions
    if SMD(k,i)>0;
       SMD(k,i)=0;
    % ...
end

可以这样替换:

SMD(SMD>0)=0;

等等

【讨论】:

    【解决方案2】:

    加速(很多!)脚本的一件事是在进入循环之前声明您的矩阵。例如,对于您的 SMD、AET、RECHARGE 等矩阵,您应该使用类似

    SMD=NaN(nrow,ncol);
    

    其中nrowncol 是最终矩阵的大小(如果当然知道的话)。

    然后做你的循环。

    【讨论】:

      猜你喜欢
      • 2013-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-17
      • 2014-10-07
      • 1970-01-01
      • 1970-01-01
      • 2021-05-10
      相关资源
      最近更新 更多