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

Mehrere for-Schleifen effizient lösen

 

Starfor

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 29.03.2022, 09:19     Titel: Mehrere for-Schleifen effizient lösen
  Antworten mit Zitat      
Hallo zusammen,

ich habe ein Programm, dass mir eine Fouriertransformation, verschiedene Berechnungen und abschließend eine Rücktransformation durchführt. Dazu habe ich einige verschachtelte for-Schleifen verwendet, da ich ansonsten keine Lösungen gefunden hab. Allerdings ist der Code extrem langsam. Hat jemand vielleicht eine clevere Idee wie sich das effizienter Lösen lassen könnte?

freq = 25;
t_end = 150;
I = 445;
J = 300;
dt = 0.04;

Code:

ThetaDCT = single(zeros(J+1,I+1,freq*t_end+1));

%Fourier Transformation
for t = 1:freq*t_end+1
    ThetaDCT(:,:,t) = dct2(T_W_areal(:,:,t));
end

%Ansatz
q_Mat = single(zeros(J,I,freq*t_end+1));

for m=0:I                                                                   % x-Position bzw x-Knoten    
    for l=0:J                                                               % y-Position bzw y-Knoten
       w = sqrt((((pi)/(I*dx))*(l))^2+(((pi)/(J*dy))*(m))^2);
            for n=1:freq*t_end                                              % Anzahl der zeitlichen Schrittpunkte              
            qvar = 0;              
                for k=0:n-1                                                 % Eigentliche Estorf Formel
                    tn = n*dt;    
                    tk = k*dt;
                    tk1 = (k+1)*dt;
                    thetaK = ThetaDCT(l+1,m+1,k+1);
                    thetaK1 = ThetaDCT(l+1,m+1,k+2);
                   
                    if w==0
                        qvar = qvar + (2/sqrt(pi*a_Mat))*((thetaK1-thetaK)/(sqrt(tn-tk1)+sqrt(tn-tk)));
                    else
               
                        qvar = qvar + (((((1/(2*w*a_Mat))+w*(tn-tk))*((thetaK1-thetaK)/dt)+w*thetaK)*(erf(w*sqrt(a_Mat*(tn-tk)))-erf(w*sqrt(a_Mat*(tn-tk1))))...
                                 +((thetaK1-thetaK)/(sqrt(pi*a_Mat)*dt))*(sqrt(tn-tk)*exp((-1)*a_Mat*(w^(2))*(tn-tk))-sqrt(tn-tk1)*exp((-1)*a_Mat*(w^(2))*(tn-tk1)))));                        
                    end
                end
            q_Mat(l+1,m+1,n+1)=Lambda_Mat*((qvar));                         % Wärmestrom zu eine Zeitpunkt an einem Ort nach Estorf
            end
    disp(l)
    end  
disp(m)
end

q_W_areal = zeros(J+1,I+1,freq*t_end+1);

%Rücktranfo
for t = 1:freq*t_end+1
    q_W_areal(:,:,t) = idct2(q_Mat(:,:,t));
end

 


Ich freu mich über jeden Hinweis!

Viele Grüße

Starfor


Harald
Forum-Meister

Forum-Meister


Beiträge: 24.495
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 29.03.2022, 10:27     Titel:
  Antworten mit Zitat      
Hallo,

ohne Daten kann ich es nicht überprüfen, aber die innere for-Schleife for k=0:n-1 sollte sich vektorisieren lassen.

Interessehalber: wie lange ist denn "extrem langsam"?

Hättest du eine NVIDIA-GPU?

Grüße,
Harald
_________________

1.) Ask MATLAB Documentation
2.) Search gomatlab.de, google.de or MATLAB Answers
3.) Ask Technical Support of MathWorks
4.) Go mad, your problem is unsolvable ;)
Private Nachricht senden Benutzer-Profile anzeigen
 
Starfor

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 29.03.2022, 15:43     Titel:
  Antworten mit Zitat      
Hallo Harald,

vielen Dank. Im Anhang eine Datei mit 75 (entspräche einer freq = 0.5) Zeitschritten statt 3750. Für 850 Zeitschritte war die Durchlaufzeit bei etwa einer Stunde. Bei 3750 Zeitschritten scheint die Dauer eher Richtung zwei Tage zu gehen.

Wie würde sich das denn vektorisieren lassen?

Eine NVIDIA-GPU wäre vorhanden.

Vielen Dank und viele Grüße

Starfor

T_W_areal.mat
 Beschreibung:

Download
 Dateiname:  T_W_areal.mat
 Dateigröße:  27.19 MB
 Heruntergeladen:  271 mal
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.495
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 29.03.2022, 16:31     Titel:
  Antworten mit Zitat      
Hallo,

* die for-Schleife weglassen
* mit .* statt * arbeiten
* auf einmal summieren statt +

Etwa so:
Code:
           qvar = 0;              
                %for k=0:n-1                                                 % Eigentliche Estorf Formel
                    tn = n*dt;    
                    tk = (0:n-1)*dt;
                    tk1 = (1:n)*dt;
                    thetaK = ThetaDCT(l+1,m+1,1:n);
                    thetaK1 = ThetaDCT(l+1,m+1,2:n+1);
                   
                    if w==0
                        qvar = sum((2/sqrt(pi*a_Mat))*((thetaK1-thetaK)./(sqrt(tn-tk1)+sqrt(tn-tk))), "all");
                    else
               
                        qvar = sum((((((1/(2.*w.*a_Mat))+w.*(tn-tk)).*((thetaK1-thetaK)/dt)+w.*thetaK).*(erf(w.*sqrt(a_Mat.*(tn-tk)))-erf(w.*sqrt(a_Mat*(tn-tk1))))...
                                 +((thetaK1-thetaK)/(sqrt(pi.*a_Mat).*dt)).*(sqrt(tn-tk).*exp((-1)*a_Mat*(w^(2)).*(tn-tk))-sqrt(tn-tk1).*exp((-1)*a_Mat*(w^(2)).*(tn-tk1))))),"all");                        
                    end
                %end


Da dürfte allerdings noch irgendwo (mindestens) ein Fehler sein, und schneller wurde es leider auch erst mal nicht. Generell finde ich es schwierig, bei so geschachtelten / länglichen Ausdrücken den Überblick zu behalten. Aufspalten in mehrere Befehle kann da besser sein.

Generell bitte alle benötigten Variablen zur Verfügung stellen. Hier fehlten dx, dy, und noch ein paar.

Die Idee mit GPUs wäre, dass du über arrayfun ein Prozess auf jedes Element anwendest.

Grüße,
Harald
_________________

1.) Ask MATLAB Documentation
2.) Search gomatlab.de, google.de or MATLAB Answers
3.) Ask Technical Support of MathWorks
4.) Go mad, your problem is unsolvable ;)
Private Nachricht senden Benutzer-Profile anzeigen
 
Starfor

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 30.03.2022, 07:33     Titel:
  Antworten mit Zitat      
Hallo Harald,

danke für den Hinweis.
Hier noch alle weiteren benötigten Parameter:

a_Mat = 1.0861e-07;
dx = 0.000393447;
dy = 0.000393447;
I = 445;
J = 300;

Besonders die beiden äußeren Schleifen scheinen die Geschwindigkeit massiv zu reduzieren.

Viele Grüße
Starfor
 
Starfor

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 06.04.2022, 09:12     Titel:
  Antworten mit Zitat      
Hallo,

ich wollte hier für alle Interessierten meine Umsetzung zeigen. Ich hab das ganze als Matrix-Operationen umgeschrieben und zwei Schleifen daraus gemacht. Das hat die Geschwindigkeit deutlich verbessert:

Code:

% Matrix-Schreibweise:
w = single(zeros(J,I));
for m=0:I                                                                   % x-Position bzw x-Knoten    
    for l=0:J                                                               % y-Position bzw y-Knoten
        w(l+1,m+1) = sqrt((((pi)/(I*dx))*(l))^2+(((pi)/(J*dy))*(m))^2);
    end
end

for n=1:freq*t_end                                                          % Anzahl der zeitlichen Schrittpunkte              
    qvar = zeros(J+1,I+1);              
    qw0 = zeros(J+1,I+1);              
    for k=0:n-1                                                            
        tn = n*dt;    
        tk = k*dt;
        tk1 = (k+1)*dt;
        thetaK = ThetaDCT(:,:,k+1);
        thetaK1 = ThetaDCT(:,:,k+2);        
        qvar = qvar + (((((1./(2.*w.*a_Mat))+w.*(tn-tk)).*((thetaK1-thetaK)./dt)+w.*thetaK)...
            .*(erf(w.*sqrt(a_Mat.*(tn-tk)))-erf(w.*sqrt(a_Mat.*(tn-tk1))))...
             + ((thetaK1-thetaK)/(sqrt(pi.*a_Mat).*dt)).*(sqrt(tn-tk).*exp((-1).*a_Mat.*(w.^(2)).*(tn-tk))-sqrt(tn-tk1).*exp((-1).*a_Mat.*(w.^(2)).*(tn-tk1)))));                                
        qw0(1,1,:) = qw0(1,1,:) + (2./sqrt(pi.*a_Mat)).*((thetaK1(1,1,:)-thetaK(1,1,:))./(sqrt(tn-tk1)+sqrt(tn-tk))); % Cook-Feldermann-Vereinfachung
    end
    qvar(1,1,:) = qw0(1,1,:);
    q_Mat(:,:,n+1)=Lambda_Mat.*((qvar));                                      
    disp(n)
end
 


Vielen Dank nochmal für die Tipps, Harald!

Beste Grüße Starfor
 
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 - 2024 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.