我想知道如何优化我的代码。执行需要很长时间

时间:2017-01-20 05:35:31

标签: matlab optimization pre-allocation

我编写了一个MATLAB代码,用于从SAC(地震)文件(通过另一个代码读取)中查找地震信号(例如P波)。这种算法称为STA / LTA触发算法(实际上对我的问题并不重要)

重要的是,实际上这个代码运行良好,但由于我的地震文件太大(1GB,这是两个月),执行时需要将近40分钟来查看结果。因此,我觉得需要优化代码。

我听说用高级函数替换循环会有所帮助,但由于我是MATLAB的新手,我无法理解如何做到这一点,因为代码的目的是扫描每个时间序列。 另外,我听说预分配可能会有所帮助,但我只是想知道如何实际做到这一点。

由于这段代码是关于地震学的,所以可能很难理解,但我在顶部的笔记可能有所帮助。我希望我能在这里得到有用的建议。 以下是我的代码。

function[pstime]=classic_LR(tseries,ltw,stw,thresh,dt)

% This is the code for "Classic LR" algorithm
% 'ns' is the number of measurement in STW-used to calculate STA 
% 'nl' is the number of measurement in LTW-used to calculate LTA
% 'dt' is the time gap between measurements i.e. 0.008s for HHZ and 0.02s for BHZ
% 'ltw' and 'stw' are long and short time windows respectively
% 'lta' and 'sta' are long and short time windows average respectively
% 'sra' is the ratio between 'sta' and 'lta' which will be each component
% for a vector containing the ratio for each measurement point 'i'
% Index 'i' denotes each measurement point and this will be converted to actual time

nl=fix(ltw/dt);
ns=fix(stw/dt);
nt=length(tseries);
aseries=abs(detrend(tseries));
sra=zeros(1,nt);

for i=1:nt-ns
    if  i>nl 
        lta=mean(aseries(i-nl:i));
        sta=mean(aseries(i:i+ns));
        sra(i)=sta/lta;
    else
        sra(i)=0;
    end
end

[k]=find(sra>thresh);
if ~isempty(k)
    pstime=k*dt;
else 
    pstime=0;
end

return;

1 个答案:

答案 0 :(得分:0)

如果你有MATLAB 2016a或更高版本,你可以使用movmean而不是你的循环(这意味着你也不需要预先分配任何东西):

lta = movmean(aseries(1:nt-ns),nl+1,'Endpoints','discard');
sta = movmean(aseries(nl+1:end),ns+1,'Endpoints','discard');
sra = sta./lta;

唯一的区别是,您将获得sra没有前导零和尾随零。这很可能是最快的方式。例如,aseries'仅'8 MB比此方法少于0.02秒,而原始方法花费将近6秒!

但是,即使您没有Matlab 2016a,考虑到您的循环,您仍然可以执行以下操作:

  1. 删除else语句 - 预先分配的sta(i)已经为零。
  2. nl+1开始循环,而不是检查i何时大于nl
  3. 所以你的新循环将是:

    for i=nl+1:nt-ns
        lta = mean(aseries(i-nl:i));
        sta = mean(aseries(i:i+ns));
        sra(i)=sta/lta;
    end
    

    但它不会那么快。

相关问题