WICHTIG: Der Betrieb von goMatlab.de wird privat finanziert fortgesetzt. - Mehr Infos...

Mein MATLAB Forum - goMatlab.de

Mein MATLAB Forum

 
Gast > Registrieren       Autologin?   

Partner:




Forum
      Option
[Erweitert]
  • Diese Seite per Mail weiterempfehlen
     


Gehe zu:  
Neues Thema eröffnen Neue Antwort erstellen

Schleife beschleunigen

 

..Sven..

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 29.08.2013, 10:07     Titel: Schleife beschleunigen
  Antworten mit Zitat      
Hallo zusammen,

derzeit schreibe ich an einem Skript Funktion mit der folgenden Funktion:

Ein Frequenzbereichs-Signal wird bei mehreren Durchläufen jeweils einmal Bandpassgefiltert. Der Bandpass wird bei jedem Durchlauf zu einer höheren Frequenz verschoben. Das Verschieben des Bandpasses macht eine for Schleife.

Das Ausgangssignal wird in den Zeitbereich überführt (ifft) und anschließend wird der Maximalwert des Zeitsignals an der i-ten Stelle eines Ausgabevektors gespeichert (i wächst mit der Schleife).

Der Code (funktionsfähig aber langsam) sieht so aus:

Code:
for Lauf1=1:Bandabtastung:Ende
   
        Filter = zeros(size(Y));
        Filter(Lauf1:Lauf1+B) = 1;      %Erstellen Bandpass
   
        GefiltertesSignal = Filter.* Y;    %Bandpassfilter anwenden
 
        GefiltertZeitbereich=ifft(GefiltertesSignal);
        Ausgabevektor(i)=max(abs(GefiltertZeitbereich));  
       
        i = i+1;

    end;


Die For-Schleife läuft ca 9000 Mal durch, das zu filternde Signal hat ca 3-4 Millionen Werte. Die Rechenzeit liegt bei ca 20-30 Minuten.

Zunächst habe ich mein Glück darin gesucht, die Schleife auf eine parfor Schleife umzustellen. Dadurch wurde die Funktion leider langsamer Sad

Nächster Versuch: Die ifft auf der Grafikkarte rechnen.

Code:
GefiltertesSignal_GPU = gpuArray(GefiltertesSignal);
GefiltertZeitbereich=ifft(GefiltertesSignal_GPU);
MaxPeak(i)=max(gather(abs(GefiltertZeitbereich)));


Das bringt ca Faktor 4 schnellere Rechenzeit, leider habe ich nur selten Zugriff auf einen Rechner mit einer entsprechenden Graffikkarte. Sad

Als nächsten Versuch wollte ich die Schleife durch Vektorielle Schreibweise ersetzen. Das sah dann am Ende vereinfacht dargestellt etwa so aus:

Code:
Gefiltertes_Signal = (1:2^21);      %Erstellung Signal mit ca 3 Millionen Werten
Anzahl_Durchlauefe = 9000;

MaxPeak_Skalar = max(ifft((repmat(Gefiltertes_Signal,Anzahl_Durchlauefe,1))'));


Leider kann ich die Schleife nicht ausführen da der Speicher nicht ausreicht. Auf meinem Aktuellen PC (ca 4GB) kann ich statt der benötigten 9000 durchläufe maximal 10 (!) ausführen, unsere Worksation mit 64 GB dürfte also ebenfalls nicht ausreichen.

Hat jemand von euch eine Idee? Würde mich über Hilfe sehr freuen Smile


HauNei
Forum-Fortgeschrittener

Forum-Fortgeschrittener


Beiträge: 55
Anmeldedatum: 18.04.13
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 29.08.2013, 10:50     Titel:
  Antworten mit Zitat      
Hallo;
Als erstes würde ich den Ausgabevektor mit sovielen Nullen vorbelegen,
wie deine For-Schleife an durchgängen hat.
also
Code:
Ausgaveketor = zeros(1,size(1:Bandabtastung:Ende,2)

Das ganze vor der for-Schleife. Dies könnte schon weiterhelfen.
Ansonsten müsste ich mal weiter überlegen.
Grüße
Private Nachricht senden Benutzer-Profile anzeigen
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.501
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 29.08.2013, 11:02     Titel:
  Antworten mit Zitat      
Hallo,

zum Ausprobieren bitte auch typische Werte für B, Bandabtastung und Ende zur Verfügung stellen - letzten Endes ein lauffähiges Beispiel der ersten Variante.

Man könnte parallele for-Schleifen (parfor) verwenden, um mehrere Rechenkerne zu nutzen.

Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 29.08.2013, 11:30     Titel: Re: Schleife beschleunigen
  Antworten mit Zitat      
Hallo ..Sven..,

Ich gehe davon aus, das die meiste Zeit in IFFT verbracht wird. Deswegen vermute ich, dass diese anderen Versuche nicht viel helfen:

Code:
LoopIndex = 1:Bandabtastung:Ende;
Ausgabevektor = zeros(1, length(LoopIndex));  % pre-allocation!!!
GefiltertZeitbereich = zeros(size(Y));
for Lauf1 = LoopIndex
     GefiltertZeitbereich(Lauf1:Lauf1+B) = Y(Lauf1:Lauf1+B);
     GefiltertZeitbereich = ifft(GefiltertesSignal);
     Ausgabevektor(i) = max(abs(GefiltertZeitbereich));  
     i = i+1;
     GefiltertZeitbereich(Lauf1:Lauf1+B) = 0;   % Clean up
end

Die meiste Arbeit passiert hier in IFFT, wobei fast der gesamte Input aus Nullen besteht, oder?Wäre es dann nicht sinnvoller, immer nur den von Null verschiedenen Teil zu betrachten?
Code:
GefiltertZeitbereich = Y(Lauf1:Lauf1+B);

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
Gast



Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 30.08.2013, 14:28     Titel:
  Antworten mit Zitat      
Hallo zusammen,

Danke für die Antworten!

Der Ausgabevektor wird nur ca 8000 Zeichen lang, auch ohne Vor-Allokierung braucht man hier wenig Rechenleistung.

Zu den Zahlenwerten: 9000 Durchläufe, Eingangsvektor mit 3,5 Millionen Werten... das Filtern vom Signal benötigt kaum Zeit, ich bräuchte eher eine Variante die FFT irgendwie zu beschleunigen.

Nur den von 0 verschiedenen Teil zu betrachten habe ich auch schon überlegt... aber wenn ich den Teil mit Nullen betrachte ... kommt da das gleiche aus der ifft raus? Immerhin verwandelt sich die Rechteck-Filterung in ein Si-Funktion welche den Zeitbereich deutlich beeinflusst?

Gruß und Dank,
Sven
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 30.08.2013, 16:04     Titel:
  Antworten mit Zitat      
Hallo,

Zitat:
Der Ausgabevektor wird nur ca 8000 Zeichen lang, auch ohne Vor-Allokierung braucht man hier wenig Rechenleistung.

Wenn Du einen Vektor mit 8000 Elementen des Typs DOUBLE iterative vergrößerst, müssen insgesamt 128'032 kB alloziert und kopiert werden. Das bracuht auf modernen Rechnern kaum Zeit, aber wenn dann eigenlich doch nur 64 kB benötigt werden, ist die Verschwendung doch vermeidbar.

Zitat:
Zu den Zahlenwerten: 9000 Durchläufe, ...

Wieso bekommst Du für 9000 Durchläufe 8000 Werte? Was ist genau ein "Durchlauf"?
Wie groß ist eigentlich "Bandabtastung" und "B" in Deinem Code?

Die Werte der IFFT sollten schon davon abhängen, wie viele Nullen vor und nach dem Signal-Stück erscheinen. Aber Wenn von den 3.5 Millionen Elementen nur B Stück von Null verschieden sind, sollte je nach Größe von B auch eine in Matlab handprogrammierte IFFT schneller sein als der optimierte IFFT Befehl.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
Neues Thema eröffnen Neue Antwort erstellen



Einstellungen und Berechtigungen
Beiträge der letzten Zeit anzeigen:

Du kannst Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.
Du kannst Dateien in diesem Forum posten
Du kannst Dateien in diesem Forum herunterladen
.





 Impressum  | Nutzungsbedingungen  | Datenschutz | FAQ | goMatlab RSS Button RSS

Hosted by:


Copyright © 2007 - 2025 goMatlab.de | Dies ist keine offizielle Website der Firma The Mathworks

MATLAB, Simulink, Stateflow, Handle Graphics, Real-Time Workshop, SimBiology, SimHydraulics, SimEvents, and xPC TargetBox are registered trademarks and The MathWorks, the L-shaped membrane logo, and Embedded MATLAB are trademarks of The MathWorks, Inc.