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

for-Schleife

 

Heisenberg
Forum-Newbie

Forum-Newbie


Beiträge: 5
Anmeldedatum: 27.06.16
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 27.06.2016, 21:36     Titel: for-Schleife
  Antworten mit Zitat      
Hallo, ich hoffe ihr könnt mir weiterhelfen.
Ich beschäftige mich nun seit ein paar Wochen im Rahmen einer Studienarbeit mit MATLAB. Nun habe ich das Problem, dass aufgrund der for-Schleife im Programm der Rechenaufwand zu groß wird. Leider habe ich keine Idee wie ich diese ersetzen kann, ohne Auswirkung auf die Ausgabe.
Die for-Schleife sieht wie folgt aus:
Code:

for i=1:nn
    if(Rand(i)==0)
        % Koeffizienten von u_xx in Matrix schreiben.
        c_p=0.5*(c(i+1)+c(i)); c_m=0.5*(c(i-1)+c(i));
        A(i,i-1)=-c_m/dx^2;
        A(i,i+1)=-c_p/dx^2;
        A(i,i)=A(i,i)+(c_m+c_p)/dx^2;
       
        % Koeffizienten von u_yy in Matrix schreiben.
        c_p=0.5*(c(i+n)+c(i)); c_m=0.5*(c(i-n)+c(i));
        A(i,i-n)=-c_m/dx^2;
        A(i,i+n)=-c_p/dx^2;
        A(i,i)=A(i,i)+(c_m+c_p)/dx^2;
    end
end
 


Vielen Dank im Voraus!

Zuletzt bearbeitet von Heisenberg am 27.06.2016, 23:07, insgesamt einmal bearbeitet
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: 27.06.2016, 22:47     Titel:
  Antworten mit Zitat      
Hallo,

poste doch bitte ein komplett reproduzierbares Beispiel.

Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
Heisenberg
Themenstarter

Forum-Newbie

Forum-Newbie


Beiträge: 5
Anmeldedatum: 27.06.16
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 27.06.2016, 23:05     Titel:
  Antworten mit Zitat      
Code:

function [ u ] = s(X,Y,c,dx)
% Eingabe:  X: X-Koordinaten in Matrixform (n,n)
%           Y: Y-Koordinaten in Matrixform (n,n)

% Initialisierungen
N=size(X); n=N(1); nn=n^2;
A=sparse(nn,nn);
Rand=sparse(nn,1);

% Rechte Seite
f=X.*sin(X).*sin(Y)-Y.*cos(X).*cos(Y)+2*X.*Y.*cos(Y).*sin(X);
u=sin(x)*cos(y)
%f=2*sin(X).*cos(Y);
f=reshape(f,nn,1);


% Erzeuge einen Vektor, der fuer alle Randknoten den Wert 1 und fuer alle
% inneren Knoten den Wert 0 enthaelt.
Rand(1:n)=1; Rand((n-1)*n+1:nn)=1;
for i=2:n-1
    Rand(i*n)=1;
end

for i=1:n-1
    Rand(i*n+1)=1;
end

for i=1:nn
    if(Rand(i)==0)
        % Koeffizienten von u_xx in Matrix schreiben.
        c_p=0.5*(c(i+1)+c(i)); c_m=0.5*(c(i-1)+c(i));
        A(i,i-1)=-c_m/dx^2;
        A(i,i+1)=-c_p/dx^2;
        A(i,i)=A(i,i)+(c_m+c_p)/dx^2;
       
        % Koeffizienten von u_yy in Matrix schreiben.
        c_p=0.5*(c(i+n)+c(i)); c_m=0.5*(c(i-n)+c(i));
        A(i,i-n)=-c_m/dx^2;
        A(i,i+n)=-c_p/dx^2;
        A(i,i)=A(i,i)+(c_m+c_p)/dx^2;
    end
end

% Setzen der Randwerte. Ueberschreiben der zugehoerigen Matrixzeile mit dem
% Einheitsvektor und überschreiben der rechten Seite mit dem Randwert.
for i=1:nn
   if(Rand(i))==1
       f(i)=0;
       A(i,:)=0;
       A(i,i)=1;
   end
end
u=mldivide(A,f);
end
 
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: 28.06.2016, 12:56     Titel:
  Antworten mit Zitat      
Hallo Heisenberg,

Einfache Regel: Vermeide alle wiederholten Berechnungen innerhalb der Schleife.

Welche Größe haben die Inputs etwa? Es ist ein Unterschied, ob es um hunderte oder Milliarden Iterationen geht.

Code:
function [ u ] = s(X,Y,c,dx)
N=size(X);
n=N(1);      % IMMER nur ein Befehl pro Zeile!!!
nn = n^2;
A=sparse(nn,nn);
Rand = zeros(nn,1);  % Sparse-Vektoren sind wahrscheinlich Zeit-Verschwendung

% Rechte Seite
f = X.*sin(X).*sin(Y)-Y.*cos(X).*cos(Y)+2*X.*Y.*cos(Y).*sin(X);
u = sin(x)*cos(y);
%f=2*sin(X).*cos(Y);
f = reshape(f,nn,1);


% Erzeuge einen Vektor, der fuer alle Randknoten den Wert 1 und fuer alle
% inneren Knoten den Wert 0 enthaelt.
Rand(1:n) = 1;
Rand((n-1)*n+1:nn) = 1;
Rand(2*n:n:n*n-n) = 1;
Rand((1:n-1)*n+1) = 1;

for i=1:nn
    if Rand(i)==0
        % Koeffizienten von u_xx in Matrix schreiben.
        c_p=0.5*(c(i+1)+c(i));
        c_m=0.5*(c(i-1)+c(i));
        A(i,i-1) = -c_m;
        A(i,i+1) = -c_p;
       
        % Koeffizienten von u_yy in Matrix schreiben.
        c_p2 = 0.5*(c(i+n)+c(i));
        c_m2 = 0.5*(c(i-n)+c(i));
        A(i,i-n)=-c_m2;
        A(i,i+n)=-c_p2;

        A(i,i)=(c_m+c_p+cm2+c_p2);  % Das A(ii)+ ist überflüssig, oder?
    end
end

A = A / dx^2;

% Setzen der Randwerte. Ueberschreiben der zugehoerigen Matrixzeile mit dem
% Einheitsvektor und überschreiben der rechten Seite mit dem Randwert.
match = (Rand == 1);
f(match) = 0;
for i=1:nn
   if match(i)
       A(i,:)=0;
       A(i,i)=1;
   end
end
u=mldivide(A,f);
end

Und? Wie groß ist der Unterschied? Welche Zeilen benötigen laut Profiler die meiste Zeit?
Der Zugriff auf die Sparse_Elemente ist zeitraubend. Du könntest die Indices und Werte in Full-Vektoren speichern und die Sparse-Matrix A nach der Schleife erzeugen.


Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
Heisenberg
Themenstarter

Forum-Newbie

Forum-Newbie


Beiträge: 5
Anmeldedatum: 27.06.16
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 28.06.2016, 20:30     Titel:
  Antworten mit Zitat      
Vielen Dank für die Antwort,
die Berechnungen in der for-Schleife sind alle von der Laufvariable i abhängig, sodass ich keine Werte außerhalb der Schleife berechnen kann. oder seh ich das falsch?
Die for-Schleife benötigt 0.500159 seconds.
Und die eigentliche Berechnung 0.039881 seconds.
Dort stimmt das Verhältnis also überhaupt nicht.
n ist die Länge des x-Vektors.
Inputs sind folgende
Code:

x=linspace(pi,3*pi,100);
y=linspace(pi/2,5/2*pi,100);
dx=x(2)-x(1);
 



Ich habe jetzt Vektoren erstellt, sodass in der Schleife nicht ständig auf die sparse Matrix A zugegriffen werden muss. Wie Sie vorgeschlagen haben, habe ich die full Vektoren in die sparse Matrix geschrieben, jedoch hat das nicht die Rechenzeit verkürzt.

Code:

function [ u ] = s(X,Y,c,dx)

% Initialisierungen
N=size(X);
n=N(1);
nn=n^2;
A=sparse(nn,nn);
Rand=sparse(nn,1);
vec_xunten=zeros(nn,1);
vec_xdiagonale=zeros(nn,1);
vec_xoben=zeros(nn,1);

vec_yunten=zeros(nn,1);
vec_ydiagonale=zeros(nn,1);
vec_yoben=zeros(nn,1);

% Rechte Seite
f=X.*sin(X).*sin(Y)-Y.*cos(X).*cos(Y)+2*X.*Y.*cos(Y).*sin(X); % fuer c=xy; u=sin(x)*cos(y)
%f=2*sin(X).*cos(Y);
f=reshape(f,nn,1);


% Erzeuge einen Vektor, der fuer alle Randknoten den Wert 1 und fuer alle
% inneren Knoten den Wert 0 enthaelt.
Rand(1:n) = 1;
Rand((n-1)*n+1:nn) = 1;
Rand(2*n:n:n*n-n) = 1;
Rand((1:n-1)*n+1) = 1;


tic
for i=1:nn
    if(Rand(i)==0)
        % Koeffizienten von u_xx in Matrix schreiben. Randknoten werden zunaechst ausgelassen.
        c_p=0.5*(c(i+1)+c(i)); c_m=0.5*(c(i-1)+c(i));
        vec_xunten(i)=-c_m/dx^2;
        vec_xoben(i)=-c_p/dx^2;
        vec_xdiagonale(i)=vec_xdiagonale(i)+(c_m+c_p)/dx^2
       
       
        % Koeffizienten von u_yy in Matrix schreiben. Randknoten werden zunaechst ausgelassen.
        c_p=0.5*(c(i+n)+c(i)); c_m=0.5*(c(i-n)+c(i));
        vec_yunten(i)=-c_m/dx^2;
        vec_yoben(i)=-c_p/dx^2;
        vec_ydiagonale(i)=vec_xdiagonale(i)+(c_m+c_p)/dx^2;
    end
end

for i=1:nn
    if(Rand(i)==0)
        A(i,i-1)=vec_xunten(i);
        A(i,i+1)=vec_xoben(i);
        A(i,i)=vec_xdiagonale(i);

        A(i,i-n)=vec_yunten(i);
        A(i,i+n)=vec_yoben(i);
        A(i,i)=vec_ydiagonale(i);
    end
end
toc

% Setzen der Randwerte. Ueberschreiben der zugehoerigen Matrixzeile mit dem
% Einheitsvektor und überschreiben der rechten Seite mit dem Randwert.
for i=1:nn
   if(Rand(i)==1)
       f(i)=0;
       A(i,:)=0;
       A(i,i)=1;
   end
end


tic
u=mldivide(A,f);
toc
end


 
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.06.2016, 14:21     Titel:
  Antworten mit Zitat      
Hallo Heisenberg,

Wir duzen uns hier im Forum alle :-)

Der Power-Operator ist ziemlich teuer. Da in jeder Iteration mehrfach "/dx^2" berechnet wird, ist es sinnvoller, das aus der Schleife heraus zu ziehen.

Zitat:
Die for-Schleife benötigt 0.500159 seconds.
Und die eigentliche Berechnung 0.039881 seconds.

Welche der FOR-Schleifen und welche Zeile ist "die eigentliche Berechnung"?

Wie große sind die Input-Array typischerweise? 100 Elemente?

Der Hinweis, nur einen Befehl pro Zeile zu verwenden, kann sehr wichtig sein. Andernfalls kann nämlich Matlabs JIT-Beschleunigung die Schleifen nicht effizient bearbeiten.

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.