Mein MATLAB Forum - goMatlab.de

Mein MATLAB Forum

 
Gast > Registrieren       Autologin?   
Bücher:

Fachkräfte:
weitere Angebote

Partner:


Vermarktungspartner


Forum
      Option
[Erweitert]
  • Diese Seite per Mail weiterempfehlen
     


Gehe zu:  
Neues Thema eröffnen Neue Antwort erstellen

Probleme mit parfor und struct

 

Max Classic

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 02.05.2019, 15:25     Titel: Probleme mit parfor und struct
  Antworten mit Zitat      
Hallo Leute,
ich möchte in Matlab eine umfangreiche Rechnung durchführen welche als Daten zwei Structures hat. In beiden Structures sind mehrere Werte gespeichert die für die Berechnung benötigt werden. Durch zwei Schleifen sollen beide Structures mit einander verrechnet werden. Sprich struct1(1) mit strucht2(1 bis n), strucht1(2) mit struct2(1 bis n), ..., struct(m) mit struct2(1 bis n).
Da die Berechnung umfangreich wird, wollte ich mit parfor arbeiten um schneller rechnen zu können. Bei der Nutzung von parfor müssen aber mehrere Dinge beachtet werden und ich bin bis jetzt leider noch nicht zu einer Lösung gekommen.

Hier mal ein Code, wie ich mir gewünscht hätte, dass es funktioniert. Smile

Code:

struct1(200)=struct();
for k = 1:200
    struct1(k).konstante.A = round(5 + rand(1)*10);
    struct1(k).konstante.B = round(2 + rand(1)*10);
end

struct2(500)=struct();
for a = 1 : 500
    struct2(a).d = 1+rand(1);
end


tic
parfor k = 1 : 200
   
    for a = 1 : 500
        [ausgabe_z(a)] = rechnung(struct1(k), struct2(a));
    end
   
end
toc

function [struct1] = rechnung(struct1, struct2)

    struct1.pv = struct1.konstante.A + struct1.konstante.B * struct2.d;

end
 


Mein zweiter Lösungsansatz funktioniert, ist aber sehr langsam. Die parfor Schleife ist langsamer als eine for Schleife. Das liegt an dem:
Code:
ausgabe(:, k) = ausgabe_z;
ich weiß bloß nicht, wie ich die Daten sonst aus der Schleife bekomme.
Code:

struct1(200)=struct();
for k = 1:200
    struct1(k).konstante.A = round(5 + rand(1)*10);
    struct1(k).konstante.B = round(2 + rand(1)*10);
end

struct2(500)=struct();
for a = 1 : 500
    struct2(a).d = 1+rand(1);
end


tic
parfor k = 1 : 200
   
    [ausgabe_z] = schleife(struct1(k), struct2)
    ausgabe(:, k) = ausgabe_z;
 
end
toc

function [ausgabe] = schleife(struct1, struct2)

    for a = 1 : 500
        [ausgabe(a)] = rechnung(struct1, struct2(a));
    end
   
end

function [struct1] = rechnung(struct1, struct2)

    struct1.pv = struct1.konstante.A + struct1.konstante.B * struct2.d;

end
 


Ich bin über sämtliche Anregungen, Tipps, Denkhilfen dankbar. Smile


Harald
Forum-Meister

Forum-Meister


Beiträge: 19.929
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2014a
     Beitrag Verfasst am: 02.05.2019, 16:40     Titel:
  Antworten mit Zitat      
Hallo,

der zweite Ansatz ist sinnvoll. Man kann höchstens die beiden Zeilen in eine kombinieren:
Code:
ausgabe(:, k)  = schleife(struct1(k), struct2)


Wie lange ist denn die Gesamtlaufzeit des tatsächlichen Codes?

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
 
Max Classic

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 03.05.2019, 09:03     Titel:
  Antworten mit Zitat      
Danke für deine Antwort. Leider ändert die vereinfachte Schreibweise nichts an der Geschwindigkeit.

Mein eigentliches Programm braucht mit parfor ca. 30 s und als for ca. 12s.
Da dieses Programm aber immer umfangreicher werden soll, muss ich jetzt schon eine vernünftige Basis aufbauen.
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 19.929
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2014a
     Beitrag Verfasst am: 03.05.2019, 10:03     Titel:
  Antworten mit Zitat      
Hallo,

wie viele Kerne hat der Rechner?
Ist bei den 30 Sekunden die Zeit für das Öffnen des Parallel Pool enthalten oder nicht? Falls enthalten, mal vorab den Parallel Pool öffnen (z.B. mit parpool ) und dann die Zeitmessung durchführen.

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
 
Max Classic

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 06.05.2019, 08:56     Titel:
  Antworten mit Zitat      
Hallo Harald,

den Parallel Pool habe ich vorab geöffnet, also nicht in der Zeit enthalten. Der Prozessor hat 4 Kerne.

MfG

Max
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 19.929
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2014a
     Beitrag Verfasst am: 06.05.2019, 09:06     Titel:
  Antworten mit Zitat      
Hallo,

um das näher zu untersuchen, müsste man das konkrete Beispiel oder ein Beispiel, anhand dessen sich das Verhalten reproduzieren lässt sehen. Alternative: Technischer Support.

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
 
Jan S
Moderator

Moderator


Beiträge: 10.803
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 16.05.2019, 14:51     Titel: Re: Probleme mit parfor und struct
  Antworten mit Zitat      
Hallo Max Classic,
Code:
   for a = 1 : 500
        [ausgabe_z(a)] = rechnung(struct1(k), struct2(a));
    end

Das ist wegen der fehlenden Pre-Allocation extrem nachlässig mit den Resourcen. Besser:
Code:
   ausgabe_z = zeros(1, 500);   % Pre-allocation!
    for a = 1 : 500
        ausgabe_z(a) = rechnung(struct1(k), struct2(a));
    end

Dass das in einer parfor Schleife aufgerufen wird, sieht erst mal sinnfrei aus, weil die Daten in "ausgabe_z" immer wieder überschrieben werden. Hier wäre ein realistisches Beispiel angebrachter.

Code:
function [struct1] = rechnung(struct1, struct2)
    struct1.pv = struct1.konstante.A + struct1.konstante.B * struct2.d;
end

So kleine Funktionen sind effizienter, wenn sie direkt im Code eingefügt werden. Der Overheader zum Aufruf der Funktion kann so gespart werden.

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
.


goMatlab ist ein Teil des goForen-Labels
goForen.de goMATLAB.de goLaTeX.de


 Impressum  | Nutzungsbedingungen  | Datenschutz  | Werbung/Mediadaten | Studentenversion | FAQ | goMatlab RSS Button RSS


Copyright © 2007 - 2019 goMatlab.de | Dies ist keine offizielle Website der Firma The Mathworks
Partner: LabVIEWforum.de

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.