PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Matlab + OpenMP = Crash


Timbaloo
2015-08-18, 00:36:21
Hallo zusammen,

Ich spiele gerade ein wenig mit OpenMP in Matlab herum. Ziel ist es OpenMP zu verwenden um Matlab mex-Funktionen zu beschleunigen.

Leider bin ich auf ein kleines Problem gestossen. Und zwar schaffe ich es (reproduzierbar) Matlab zu crashen wenn ich:


die mex-Funktion mit OpenMP-Support baue (VS 2015, Release, x64)
und direkt nach dem Aufruf der mex-Funktion in Matlab "clear mex" die mex-Funktion wieder "auslade"

Letzteres mache ich damit die mex-dll nicht von Matlab blockiert wird, so dass ich in VS wieder weiterbauen kann.

Verzögere ich "clear mex" ein wenig in dem ich eine Pause einbaue, dann crasht Matlab nicht.
Baue ich ohne OpenMP-Support, dann crasht Matlab auch nicht.

Nun bin ich neu in OpenMP unterwegs, aber ich kann beim besten Willen nicht erkennen was ich falsch machen könnte. Zuerst dachte ich logischerweise an einen fiesen Programmierfehler, aber ich konnte es auf ein minimales Beispiel reduzieren wo ich der Meinung bin dass der Code korrekt ist, siehe unten. Ebenso ist ein Test-Skript mit dem das Problem auftritt angehängt.

Hat jemand eine Idee? Ist es der sprichwörtliche Wald vor lauter Bäumen? Bin ich zertifiziert doof? :frown:

Test-Skript in Matlab:
x = rand (2^10,1);

% test 1 with pause
y = minimalWorkingExample (x);
if all (y == 2*x)
fprintf ('Results verified!\n');
end
pause (0.5);
clear mex;

% test 2 with pause
y = minimalWorkingExample (x);
if all (y == 2*x)
fprintf ('Results verified!\n');
end
pause (0.5);
clear mex;

% test 3 without pause -> this will crash!
y = minimalWorkingExample (x);
if all (y == 2*x)
fprintf ('Results verified!\n');
end
%pause (0.5);
clear mex;

Minimales Beispiel der mex-Funktion:
#include "mex.h"
#include <omp.h>

void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
double *x, *y;
size_t mrows, ncols;
int i, n;

if (nrhs != 1) {
mexErrMsgIdAndTxt("MATLAB:minimalWorkingExample:invalidNumInputs",
"One input required.");
}
else if (nlhs>1) {
mexErrMsgIdAndTxt("MATLAB:minimalWorkingExample:maxlhs",
"Too many output arguments.");
}

mrows = mxGetM(prhs[0]);
ncols = mxGetN(prhs[0]);
if (!mxIsDouble(prhs[0]) || mxIsComplex(prhs[0]) ||
!(mrows == 1 || ncols == 1)) {
mexErrMsgIdAndTxt("MATLAB:minimalWorkingExample:inputNotRealDoubleVector",
"Input must be a noncomplex double vector.");
}

plhs[0] = mxCreateDoubleMatrix((mwSize)mrows, (mwSize)ncols, mxREAL);

x = mxGetPr(prhs[0]);
y = mxGetPr(plhs[0]);
n = (int)(mrows * ncols);

#pragma omp parallel for
for (i = 0; i < n; i++) {
y[i] = 2*x[i];
}
}


Verwendete Versionen:

Matlab R2011b 64Bit
Visual Studio Community 2015

Acid-Beatz
2015-08-18, 22:14:36
Fieser Programmierfehler im Programm, beziehungsweise deren Kombination? Hört sich für mich so an, wie wenn Matlab nach dem Flush noch auf die Daten zugreifen will, die sind dann eben nicht - wartest du ein bisschen, dann bekommt es sein Signal und verzichtet auf diesen Schritt und alles läuft ...

Ich bin zwar kein Programmierer, habe aber selbst genug mit Programmen zu tun, die sehr viel mit Signalen/Flags arbeiten - manchmal hilft einfach nur warten und sich einen Kaffe holen ;)

Achill
2015-08-18, 22:27:56
Ich bin schon eine ganze Zeit aus Matlab und C/C++ raus und zu der Zeit gab es noch kein OpenPM ... das wichtigste ist aber i.d.R. die Fehlermeldung.

Dann ist wichtig was reproduzierbar in dem Context bedeutet, es tritt immer auf => Programm bricht immer ab, es tritt ab und zu auf => Programm läuft mal durch und mal nicht.

Der Zusammenhang zwischen matlab Script und dem C Code ist nicht offensichtlich - ist mexFunction im C-Code die minimalWorkingExample(x) Funktion die im matlab Script aufgerufen wird? Wenn ja, dann passen die Argumente auf den ersten Blick nicht bzw. mir fehlt zu viel wissen. Ich gehe aber mal davon aus, dass hier eine "user defined funktion" in matlab geladen und verwendet wird und diese Funktion ist dein C code?

Ich nehme außerdem an, dass der Code keine Pause braucht, wenn du kein OpenMP nutzt? => Threading Problem bzw. klingt eher wie ein Thread-Management-Problem, da der OpenPM code trivial ist und

Leider ist die Doku nur eingeschränkt von MatLab Verfügbar, unter http://de.mathworks.com/help/matlab/ref/clear.html steht: "clear removes all variables from the current workspace, releasing them from system memory." => Ich tippe darauf, dass OpenMP sicherlich ein Thread-Pool mit Threads erzeugt, sobald man es im Code nutzt. Mit dem clear kann es jetzt sein, dass der Thread-Pool & die Threads nicht sauber beendet werden bzw. hard beendet und dann eine Exception auftritt.

Ein Indiz müsste die Fehlermeldung liefern können bzw. du müsstes nur die letzte auskommentierte "pause (0.5);" benötigen (wenn ich mit meinen Tipp richtig liege).

Kannst du dich in den Code per Debugger hängen?

Ansonsten bei sowas die Frage auf http://stackoverflow.com/ stellen (auch bei anderen Problemen) - bzw. da könnte man auch mal suchen.

Timbaloo
2015-08-18, 23:06:11
Danke für euer Interesse :)

Fieser Programmierfehler im Programm, beziehungsweise deren Kombination? Hört sich für mich so an, wie wenn Matlab nach dem Flush noch auf die Daten zugreifen will, die sind dann eben nicht - wartest du ein bisschen, dann bekommt es sein Signal und verzichtet auf diesen Schritt und alles läuft ...
Ja, sowas wird es sein, denke ich :)

Ich bin schon eine ganze Zeit aus Matlab und C/C++ raus und zu der Zeit gab es noch kein OpenPM ... das wichtigste ist aber i.d.R. die Fehlermeldung.
Keine Fehlermeldung, instant-Crash. Also kein dump in Konsole mit Aufforderung zu speichern und schliessen. Kein Zurück-auf-Los. Instant-Tod. Kann ich eigentlich als "Schliesse Matlab besonders schnell" verwenden :D

Dann ist wichtig was reproduzierbar in dem Context bedeutet, es tritt immer auf => Programm bricht immer ab, es tritt ab und zu auf => Programm läuft mal durch und mal nicht.
Matlab crasht in der Konstellation immer.

Der Zusammenhang zwischen matlab Script und dem C Code ist nicht offensichtlich - ist mexFunction im C-Code die minimalWorkingExample(x) Funktion die im matlab Script aufgerufen wird?
Ja. mexFunction() ist der Einstiegspunkt jeder mex-dll.

Wenn ja, dann passen die Argumente auf den ersten Blick nicht bzw. mir fehlt zu viel wissen.
Das sollte eigentlich passen. Du bekommt die Anzahl der Argumente rechtseitig (nrhs), einen Zeiger auf die Argumente (prhs), und das gleiche für die Argumente linksseitig (nlhs, plhs). Dann hangelt man sich mit mxGetPr() und Konsorten durch und benennt die Argumente sinnvoll (oder auch nicht :P).

Ich gehe aber mal davon aus, dass hier eine "user defined funktion" in matlab geladen und verwendet wird und diese Funktion ist dein C code?
Exakt.

Ich nehme außerdem an, dass der Code keine Pause braucht, wenn du kein OpenMP nutzt? => Threading Problem bzw. klingt eher wie ein Thread-Management-Problem, da der OpenPM code trivial ist und
Ja, die Pause "braucht" es nur wenn man OpenMP nutzt.

Leider ist die Doku nur eingeschränkt von MatLab Verfügbar, unter http://de.mathworks.com/help/matlab/ref/clear.html steht: "clear removes all variables from the current workspace, releasing them from system memory." => Ich tippe darauf, dass OpenMP sicherlich ein Thread-Pool mit Threads erzeugt, sobald man es im Code nutzt. Mit dem clear kann es jetzt sein, dass der Thread-Pool & die Threads nicht sauber beendet werden bzw. hard beendet und dann eine Exception auftritt.
Der relevante Punkt hier ist imho:

"clear mex does not clear locked MEX functions or functions that are currently in use."

Es schaut so aus, als ob zum dem kritischen Zeitpunkt die mex-Funktion (-> dll) aus Matlab-Sicht nicht mehr gelocked oder in use ist, sie wird versucht zu entladen, ist aber tatsächlich noch nicht so ganz fertig.

Ein Indiz müsste die Fehlermeldung liefern können bzw. du müsstes nur die letzte auskommentierte "pause (0.5);" benötigen (wenn ich mit meinen Tipp richtig liege).
Es ist egal welche von den drei pausen ich nutze, es crasht bei jeder. Das Skript sollte der Problemdarstellung helfen :D

Kannst du dich in den Code per Debugger hängen?
Eigentlich sollte das gehen, hab es aber bisher doch noch nicht hinbekommen, ist eine andere Baustelle... Werde ich aber sicher noch versuchen. Zumindest crasht es auch immer im Debug-Build :D

Ansonsten bei sowas die Frage auf http://stackoverflow.com/ stellen (auch bei anderen Problemen) - bzw. da könnte man auch mal suchen.
Wenn ich einen offensichtlichen Fehler meinerseits ausschliessen kann, werde ich mich direkt an den Support wenden, denke ich. Schliesslich zahlt man dafür. Könnte die evtl. auch interessieren. Aber wahrscheinlich erzählen die mir dann was von "VS 2015 Community Edition wird nicht unterstützt ktxhbye".

Timbaloo
2015-08-18, 23:24:49
O.K. Debuggen klappt jetzt (keine Ahnung was gestern los war, Rechner müde, Timbaloo müde...).

Wenn ich einen Breakpoint nach der OpenMP-Sektion setze, dadurch logischerweise warte und dann weiterlaufen lasse, dann crasht Matlab nicht, ohne Breakpoint natürlich immernoch (siehe oben, Crash auch mit Debug-Build). Es wirft zwar immer mal wieder Exeptions bei GUI-Interaktion, aber das scheint bei Matlab "normal" zu sein. Wirklich weiter hilft mir das ohne Debug-Symbole allerdings nicht...

Timbaloo
2015-08-20, 20:42:18
Das Problem ist wohl, dass Matlab selbst intels OpenMP-Lib nutzt und ich logischerweise Microsofts OpenMP-Lib.

Timbaloo
2015-09-03, 20:24:34
Ganz vergessen das Thema hier abzuschliessen:

Wenn man gegen die intel Implementierung von OpenMP linkt (libiomp5md) welche auch mit Matlab geliefert wird, dann klappt es wunderbar.

Allerdings setzt Matlab (mit der intel lib) die Zahl der Threads bei einem 4-Kern / 8-Threader leider auf 4. Das muss man dann entsprechend anpassen wenn man sich daran stört (hat bei mir gut 35% ausgemacht...).