verwenden um die mehrfache Ausführung einer Funktion zu parallelisieren. Hierbei tritt jedoch ein Fehler auf dessen Ursache sich mir nicht erschließt.
Ich erhoffe mir von euch einen Hinweis für die weitere Recherche, oder aber eine Erklärung, weshalb es zu diesem Fehler kommt.
Dies ist ein Minimalbeispiel meiner Funktion:
Code:
function ElementsOut = ComputeParallel(FunctionHandle, ElementsIn, NOut)
% Diese Funktion ist eine Alternative zu cellfun, die zusätzlich die % Funktionen der Parallel Computing Toolbox nutzt. % --------------------------------------------------------------------- % % FunctionHandle ist eine beliebige Funktion, die NIn Parameter % verlangt. % % ElementsIn ist ein NElements x NIn großes cell array, welches alle % Eingabeparameter für die Berechnungen der Funktion FunctionHandle % umfasst. % % NOut gibt an, wie viele Ausgabeparameter FunctionHandle generiert, % bzw. wieviele Ausgabeparameter gespeichert werden sollen.
Error using ComputeParallel>(parfor body)(line22)
The left hand side has ElementsOut{:} inside brackets, which requires that ElementsOut be defined, so that the number of expected results can be computed.
Caused by:
The left hand side has ElementsOut{:} inside brackets, which requires that ElementsOut be defined, so that the number of expected results can be
computed.
function ElementsOut = ComputeParallel(FunctionHandle, ElementsIn, NOut)
% Diese Funktion ist eine Alternative zu cellfun, die zusätzlich die % Funktionen der Parallel Computing Toolbox nutzt. % --------------------------------------------------------------------- % % FunctionHandle ist eine beliebige Funktion, die NIn Parameter % verlangt. % % ElementsIn ist ein NElements x NIn großes cell array, welches alle % Eingabeparameter für die Berechnungen der Funktion FunctionHandle % umfasst. % % NOut gibt an, wie viele Ausgabeparameter FunctionHandle generiert, % bzw. wieviele Ausgabeparameter gespeichert werden sollen.
Die Funktion ist jetzt lauffähig, ich habe sie allerdings noch dahingehend abgeändert, dass sie auch function handle, die mehrere Eingabeparameter verlangen, verarbeiten kann.
Code:
function ElementsOut = ComputeParallel(FunctionHandle, ElementsIn, NOut)
Alternativ bin ich auch auf diese Lösung gekommen, die keiner weiteren lokalen Funktion bedarf, dafür aber jede Rückgabe in einer eigenen cell kapselt und eine Warnung bezüglich möglicherweise großem "communication overhead" ausgibt:
Code:
function ElementsOut = ComputeParallel(FunctionHandle, ElementsIn, NOut)
Ich habe mich für die Lösung mit deinem Ansatz entschieden, allerdings tritt nun bei beiden Varianten gleichermaßen folgendes Phänomen auf:
Außerhalb der eigentlichen Berechnung des Schleifeninhalts vergeht ca. noch einmal das 2-fache der eigentlichen Ausführungszeit, scheinbar um die parallele Berechnung zu initialisieren, oder ähnliches ...
In meinem Beispiel handelt es sich um 32 Schleifendurchläufe, ich habe 2 Worker aktiv.
Nun habe ich einmal a) alle Zeiten gemessen, die für die Ausführung jeder Schleifeniteration benötigt werden, und diese aufsummiert und b) die Zeit für den Durchlauf des gesamten Schleifenkörpers.
Im Vergleich zwischen seriellem (for) und parallelem Durchlauf (parfor) zeigt sich das beschriebene Problem:
Finished all serial calculations.
sum of all execution runtimes: 2.5465s
whole loop runtime: 2.5471s
Finished all parallelized calculations.
sum of all execution runtimes: 3.6171s
whole loop runtime: 11.0728s
Nun habe ich vermutet, dass vielleicht das Kopieren der zu verarbeitenden Daten (vom Host auf die Worker?) ein Problem darstellen könnte, allerdings scheint dem nicht so zu sein, da eine einfachere Funktion, wie @abs mit den selben Daten wesentlich weniger absoluten Laufzeitunterschied zwischen paralleler und serieller Verarbeitung zeigt, jedoch proportional ist zu der eigentlichen Rechenzeit innerhalb der Schleife:
Finished all serial calculations.
sum of all execution runtimes: 0.11155s
whole loop runtime: 0.1125s
Finished all parallelized calculations.
sum of all execution runtimes: 0.14114s
whole loop runtime: 0.83217s
Hast du oder jemand anderes eine Vermutung wie die Rechenzeitverlängerung zustande kommt?
Ich arbeite mit MATLAB R2013a unter Windows 7 Professional.
% Verwendet für die Ergebnisse der 1. Zeitmessung: Input = @(Phase, Mask) unwrapDataSet(Phase, Mask, Pos2Indices([0, 0, 0], 'Phys', Repo{1}.Header.Orientation, 2), [-pi, pi], 3);
% Verwendet für die Ergebnisse der 2. Zeitmessung: % Input = @(Phase, Mask) abs(Phase) + abs(Mask);
Hierzu ist zu sagen, dass 'Repo{1}' eine größere Struktur von ca. 450 MB ist.
Das Feld namens Input entspricht der auszuführenden Funktion.
Beide von mir verwendeten Funktionen, für die ich die Zeiten in meiner vorigen Antwort gelistet habe, sind im oberen Codebeispiel enthalten (die zweite auskommentiert).
auf einen Teilbereich des Repositories 'Repo{1}.Header.Orientation' zugegriffen wird (nur wenige Byte groß) und dies vielleicht auf Grund der Größe vom gesamten 'Repo{1}' problematisch sein könnte.
wie ergibt sich elementsIn aus den Eingabeargumenten?
Wenn du eine recht kurze Ausführungszeit mit großen Datenmengen hast, dann ist das nicht ideal für parfor. Man sollte darauf achten, nur die Daten an die Worker zu schicken, die sie auch wirklich benötigen.
Grüße,
Harald
Einstellungen und Berechtigungen
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
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.