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