【问题标题】:I want advice about how to optimize my code. It takes too long for execution我想要关于如何优化我的代码的建议。执行时间过长
【发布时间】:2017-06-05 00:53:01
【问题描述】:

我编写了一个 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;

【问题讨论】:

  • 你确定你的内存没有用完吗?因为在我看来,一些小的优化不会有太大的不同。

标签: matlab optimization pre-allocation


【解决方案1】:

如果您有 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

所以你的新循环将是:

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

但不会这么快。

【讨论】:

  • 感谢您的回复。我试过了,但不幸的是它并没有真正改善很多。我认为这是因为文件很大。也许我应该在将文件分成更小的部分后尝试代码。顺便说一句,谢谢你告诉我有用的功能。
  • @LucasSeo 您是否使用了movmean 并没有看到任何改进?这是非常令人惊讶的。我测试了它,发现有很大的不同。你确定这部分函数的瓶颈吗?
  • 我试过你的代码更短。它显着更快地计算平均值,但在“sra=sta./lta”行中,由于“sta”和“lta”的尺寸不相等而发生错误。我该如何解决这个问题?
  • @LucasSeo,你说得对,我有一些错误,现在我已经编辑了解决这个问题的答案,它甚至变得更简单了!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-13
  • 1970-01-01
  • 2021-03-27
  • 1970-01-01
  • 1970-01-01
  • 2022-12-21
  • 2020-04-11
相关资源
最近更新 更多