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

Triviale if-Abfrage verlangsamt Code extrem

 

eey
Forum-Fortgeschrittener

Forum-Fortgeschrittener


Beiträge: 86
Anmeldedatum: 31.03.12
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 25.04.2012, 11:40     Titel: Triviale if-Abfrage verlangsamt Code extrem
  Antworten mit Zitat      
Hallo zusammen,

ich habe ein sehr merkwürdiges Problem mit meinem aktuellsten Programm. Dort wird an einer Stelle eine relativ aufwändige Gleichung ausgerechnet (ca.40 Multiplikationen).

Jetzt wollte ich diese nur noch unter bestimmten Vorraussetzungen ausrechnen lassen, jedoch wird mein Programm dadurch extrem viel langsamer. Nach längerem testen konnte ich das Problem identifizieren: Die if-Abfrage.

Ich verstehe aber überhaupt nicht wieso diese mein Programm so extrem verlangsamt, hier mal als Beispiel:

Code:

for i=1:1000
    flag = 1

    % hier steht die komplizierte Gleichung
end
 


Das dauert ca. 1 Millisekunde.

Code:

for i=1:1000
    flag = 1
    if flag == 1
        % hier steht die komplizierte Gleichung
    end
end
 


Das dauert ca. 12 Millisekunden.

Dabei machen beide Varianten exakt das selbe (was ja auch logisch ist)... Wie kann es sein dass eine simple if-Abfrage soviel Laufzeit frisst? Und wie könnte man das beheben? (Sprungbefehle wie Goto gibt es ja nach meiner Recherche nicht wirklich in Matlab)

Freue mich über Hilfe!

Schöne Grüße,
eey
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: 25.04.2012, 15:46     Titel: Re: Triviale if-Abfrage verlangsamt Code extrem
  Antworten mit Zitat      
Hallo eey,

Dies kann mehrere Ursachen haben.
1. Möglicherweise ist Deine Zeitmessung ungenau. Wie misst Du die Laufzeit?
2. Matlab verwendet eine Art Laufzeit-Kompiler, die JIT-Acceleration. Diese analysiert den Code und kan Schleifen dadurch sehr stark beschleunigen. Eine IF-Abfrage kann dabei verwirrend wirken, so dass bei der Analyse nicht mehr klar ist, ob der Code nun für jede Iteration ausgeführt wird.
3. Während 40 Multiplikationen Prozessor-intern out-of-order berechnet werden können, kann eine IF-Abfrage dazu führen, dass die Pipeline des Prozessors mit falsch geratenen Befehlen befüllt wird. Der Prozessor lädt nämlich schonmal die Befehel in seinen Speicher, die wohl als nächstes bearbeitet werden. Bei IF muss er raten, welche Befehle kommen werden, und dieses Raten kann systematisch falsch sein.

Um sinnvolle Ratschläge für eine Beschleunigung des Codes zu geben, müssten wir den gesamten relevanten Abschnitt sehen. Wenn man nur den geposteten Ausschnitt sieht, ist dies der einzige logische Rat:
Die IF-Abfrage ist überflüssig direkt nachdem der Wert von "flag" gesetzt wurde. Deshalb läßt man sie einfach weg.

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

Forum-Fortgeschrittener

Forum-Fortgeschrittener


Beiträge: 86
Anmeldedatum: 31.03.12
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 27.04.2012, 08:08     Titel:
  Antworten mit Zitat      
Hallo Jan,

vielen Dank schonmal für deine Antwort. Also ich poste einfach den gesamten Code mal hier. Das führt letztendlich eine kubische Spline Interpolation aus (die deutlich schneller als die von Matlab ist). Die relevante if-Abfrage ist bei "if neuerSpline == 1", ohne diese if-Abfrage läuft das ganze ca 10 mal so schnell obwohl die große Gleichung dahinter nur wesentlich weniger oft gelöst werden muss.

Ich muss sagen ich bin relatv ratlos warum das so ist. Wenn ich die if-Abfrage um eine andere Zeile in der gleichen Schleife mach tritt das Phänomen nämlich nicht auf.

Code:

function [ yi ] = interp(x,y,xi )
    %tic;



    AnzahlStellen = length(x);
    AnzahlNeueStellen = length(xi);
   
    A = zeros(AnzahlStellen, AnzahlStellen);
    b = zeros(AnzahlStellen,1);
    yi = zeros(AnzahlNeueStellen,1);

    % Matrix A befüllen
    % Erste Zeile extra
    A(1,1) = x(3) - x(2);
    A(1,2) = -((x(2) - x(1)) + (x(3) - x(2)));
    A(1,3) = x(2) - x(1);
    b(1) = 0;
    d_save = (y(2) - y(1))/(x(2) - x(1));
    h_save = x(2) - x(1);
    % Restliche Matrix
    for i=1:AnzahlStellen - 2
        h_neu = x(i + 2) - x(i + 1);
        h_alt = h_save;
       
        A(i + 1,i) = h_alt;
        A(i + 1,i + 1) = 2*(h_alt + h_neu);
        A(i + 1,i + 2) = h_neu;
       
        d_neu = (y(i + 2) - y(i + 1))/h_neu;
        d_alt = d_save;
       
        b(i + 1) = 6*(d_neu - d_alt);
       
        d_save = d_neu;
        h_save = h_neu;
    end
    % Letzte Zeile extra
    A(AnzahlStellen,AnzahlStellen - 2) = h_neu;
    A(AnzahlStellen,AnzahlStellen - 1) = -(h_neu + h_alt);
    A(AnzahlStellen,AnzahlStellen) = h_alt;
    b(AnzahlStellen) = 0;

    % Gleichungssystem lösen
    M = A\b;

    p = 1;
    q = 0;

    yi(1) = y(1);
    jStart = 1;
    maxWert = x(AnzahlStellen);
    neuerSpline = 1;
    jSave = 0;

    for i=2:AnzahlNeueStellen

        Wert = xi(i);

        if i > x(p) && i<= maxWert
            p = p + 1;
            if q < AnzahlStellen - 2
                q = q + 1;
            end
        end
       
        for j=jStart:AnzahlStellen
           if Wert < x(j)
               q = j - 1;
               break;
           end
        end
       
        if jSave ~= j
            neuerSpline = 1;
        end

        jStart = q;
        q = q - 1;

        Neu = 2 + q;
        Alt = 1 + q;

        h = x(Neu) - x(Alt);
        hInv = 1/h;
        a = 1/6;
 


        % Auswertung des Splines im jeweiligen Intervall
        if neuerSpline == 1
       
            Faktor = a * hInv;
            xAltHoch2 = x(Alt)*x(Alt);
            xNeuHoch2 = x(Neu)*x(Neu);

            xHoch3Term = Faktor * (M(Neu) - M(Alt));
            xHoch2Term = 3 * Faktor * (M(Alt)  * x(Neu) -  M(Neu) * x(Alt));
            xHoch1Term = 3 * Faktor * (M(Neu)  * xAltHoch2 - M(Alt) * xNeuHoch2) + hInv * (y(Neu) - y(Alt)) - h * a * (M(Neu) - M(Alt));
            xHoch0Term = Faktor * (M(Alt) *  xNeuHoch2*x(Neu) - M(Neu) * xAltHoch2*x(Alt)) + (hInv * (y(Neu) - y(Alt)) - h * a * (M(Neu) - M(Alt))) * (-0.5 * (x(Alt) + x(Neu))) + 0.5 * (-a * h*h * (M(Neu) + M(Alt)) + (y(Neu) + y(Alt)));
            neuerSpline = 0;
        end
       


        yi(i) = Wert * (Wert * (xHoch3Term * Wert + xHoch2Term) + xHoch1Term) + xHoch0Term;
       
    end


    %toc
end


 
Private Nachricht senden Benutzer-Profile anzeigen
 
eey
Themenstarter

Forum-Fortgeschrittener

Forum-Fortgeschrittener


Beiträge: 86
Anmeldedatum: 31.03.12
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 30.04.2012, 10:32     Titel:
  Antworten mit Zitat      
Keiner eine Idee? Bin ziemlich ratlos, was dieses Problem angeht Sad
Private Nachricht senden Benutzer-Profile anzeigen
 
Andy386
Forum-Guru

Forum-Guru


Beiträge: 485
Anmeldedatum: 24.06.09
Wohnort: ---
Version: 7.1/8
     Beitrag Verfasst am: 02.05.2012, 12:02     Titel:
  Antworten mit Zitat      
Du könnest mal versuchen, den Teil in der if-Abfrage in eine extra-Funktion zu packen. Vielleicht ist es nur ein Profiler-Problem und das machen des neuen Splines dauert einfach?

Wie ist denn die Zeit wenn du bspw. if neuerSpline == neuerSpline schreibst?
Entsprechend sooft-Mal höher?
_________________

Ich hasse es wenn die Leute Fragen stellen, man dann versucht sich Mühe zu geben, und diejenigen ihren Thread nie wieder besuchen...
Private Nachricht senden Benutzer-Profile anzeigen
 
eey
Themenstarter

Forum-Fortgeschrittener

Forum-Fortgeschrittener


Beiträge: 86
Anmeldedatum: 31.03.12
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 03.05.2012, 12:09     Titel:
  Antworten mit Zitat      
Hallo Andy,

danke schonmal für die Antwort. Ich hab das Programm heute nochmal getestet und es ist sehr seltsam: Obwohl ich nichts daran verändert habe ist das Problem deutlich abgeschwächt. Die if-Abfrage verlangsamt den Code zwar immernoch ein bisschen (ca. 20 bis 30 %), was aber deutlich weniger ist als vorhin (Faktor 10 bis 12).

Seltsam ist das aber trotzdem, da der Code ja eigentlich beschleunigt werden sollte.

Deine Tipps hab ich probiert, egal ob ich neuerSpline == neuerSpline oder als extra Funktion, der Geschwindigkeitsverlust bleibt. Lediglich bei 1 == 1 läuft die if-Abfrage so schnell wie als wäre sie nicht da.

Wie ist das denn bei dir, wenn du den Code ausführst? Braucht das dann auch mit if-Abfrage länger?

Schöne Grüße,
eey
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.