2017-01-20 2 views
2

Ich habe einen MATLAB-Code geschrieben, um ein seismisches Signal (zB P-Welle) aus einer SAC-Datei (Seismik) zu finden (die über einen anderen Code gelesen wird). Dieser Algorithmus heißt STA/LTA Trigger-Algorithmus (eigentlich nicht so wichtig für meine Frage)Ich möchte Ratschläge zur Optimierung meines Codes erhalten. Es dauert zu lange für die Ausführung

Wichtig ist, dass eigentlich dieser Code gut funktioniert, aber da meine seismische Datei zu groß ist (1GB, was für zwei Monate ist), Es dauert fast 40 Minuten für die Ausführung, um das Ergebnis zu sehen. Daher habe ich das Bedürfnis, den Code zu optimieren.

Ich hörte, dass das Ersetzen von Schleifen mit erweiterten Funktionen helfen würde, aber da ich ein Neuling in MATLAB bin, kann ich keine Ahnung davon bekommen, wie es zu tun ist, da der Zweck von Code durch die jede Zeitreihe gescannt wird. Ich habe auch gehört, dass die Vorallokation helfen könnte, aber ich habe nur eine Idee, wie man das macht.

Da es sich bei diesem Code um Seismologie handelt, ist es vielleicht schwer zu verstehen, aber meine Notizen oben könnten helfen. Ich hoffe, ich kann hier einen nützlichen Rat bekommen. Folgendes ist mein Code.

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; 
+0

Sind Sie sicher, dass Ihnen nicht mehr genügend Arbeitsspeicher zur Verfügung steht? Weil es mir scheint, dass einige kleinere Optimierungen keinen großen Unterschied machen. –

Antwort

0

Wenn Sie MATLAB 2016a oder höher, können Sie movmean statt Ihrer Schleife verwenden (dies bedeutet, dass Sie auch brauchen nichts preallocate):

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

Der einzige Unterschied ist, dass Sie erhalten sra ohne führende und abschließende Nullen. Dies ist wahrscheinlich der schnellste Weg. Wenn zum Beispiel aseries 'nur' 8 MB ist, dauert diese Methode weniger als 0,02 Sekunden, während die ursprüngliche Methode fast 6 Sekunden dauert!


Aber auch wenn Sie Matlab 2016a nicht, Ihre Schleife bedenkt, können Sie folgendes tun:

  1. Entfernen Sie die else Anweisung - sta(i) bereits Null vom vorbelegen ist.
  2. Starten Sie die Schleife von nl+1, anstatt zu überprüfen, wenn i größer als nl ist.

So wird Ihre neue Schleife wird:

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

Aber es wird nicht so schneller sein.

+0

Danke für Ihre Antwort. Ich habe es versucht, aber es hat sich leider nicht wirklich verbessert. Ich denke es ist wegen der großen Dateigröße. Vielleicht sollte ich den Code nach dem Teilen der Datei in kleinere Stücke versuchen. Übrigens, vielen Dank für die nützliche Funktion. –

+0

@LucasSeo hast du 'Movmean' benutzt und hast keine Verbesserung gesehen? Das ist sehr überraschend. Ich habe es getestet und einen RIESIGEN Unterschied gefunden. Sind Sie sicher, dass dieser Teil der Funktion der Flaschenhals ist? – EBH

+0

@LucasSeo siehe meine Bearbeitung über das Timing. – EBH

Verwandte Themen