简体   繁体   中英

How to use OpenMP in my MEX-file without crashing MATLAB?

I built a Windows MEX-file from Visual Studio 2019. My MATLAB version is R2019a. The code just does some "sort" to the two input matlab array. This is an example which I try to use with OpenMP. "test.cpp"

#include "mex.h"
#include <vector>
#include <iostream>
#include <algorithm>
#include <omp.h>
using namespace std;
void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])
{ 
    mxDouble *p0 = mxGetDoubles(prhs[0]);
    mwSize size0 = mxGetNumberOfElements(prhs[0]);
    mxDouble* p1 = mxGetDoubles(prhs[1]);
    mwSize size1 = mxGetNumberOfElements(prhs[1]);
    vector<vector<int>> v(2);
    int i;
    for (i = 0; i < size0; i++) {
        v[0].push_back(int(*p0++));
    };
    for (i = 0; i < size1; i++) {
        v[1].push_back(int(*p1++));
    };
#pragma omp parallel for 
    for (i = 0; i < 2; i++) {
        sort(v[i].begin(), v[i].end());
    };


    plhs[0] = mxCreateCellMatrix(2, 1);
    for (int i = 0; i < 2; i++) {
        mxArray* str = mxCreateNumericMatrix(1, v[i].size(), mxDOUBLE_CLASS, mxREAL);
        copy(v[i].begin(), v[i].end(), mxGetPr(str));
        mxSetCell(plhs[0], i, mxDuplicateArray(str));
        mxDestroyArray(str);
    };
    return;
}

My test M-file is:

a1= [1,2,3,4,5];
a2= [1,1,1,1];
result = test(a1,a2);
clear mex;

The ideal output will be a 2*1 cell in result . If I remove the # pragma line the MEX-file works well. If I add it,MATLAB crashed. I have been trying to find the problem for several days and have not find any solution. Besides,

  1. I have choose the OpenMP support key to "yes" in my Visual Studio.
  2. I don't use mexPrintf in my code. I heard that function will crash the MEX-file with OpenMP.
  3. I have installed the Intel Studio parallel XE 2019 and update 5 of Matlab R2019a. Perhaps I made a wrong parallel domain definition. I don't want to include the last part from plhs[0] = mxCreateCellMatrix(2, 1);into the #pragma parallel part. As the codes above, am I do it right?

You cannot call any mx... or mex... functions in the parallel part of your code*. You must get pointers to the all the data before the parallel section, including creating output arrays and getting their pointers, then do only your computations in parallel.


* The rule given here is overly broad, some mx... functions might be OK to use in a parallel section, as indicated in James Tursa's comment . I prefer not guessing and keeping the rules simple.

This may not be the perfect solution. I just made some correction for the codes and succeeded in building the mexw64 inside Matlab. As for compiling the code in visual studio, the mex rans very low.(VS built 15s and Matlab built 0.4sI could not figure out why. ) At first, I corrected two critical errors.

  1. using the curly brace for #pragma... correctly. The left curly brace must not directly after #pragma omp parallel . It should be in a new line. As below,
#pragma omp parallel
{ 
#pragma omp for
    for (i = 0; i < 2; i++) {
        sort(v[i].begin(), v[i].end());
    };
}

2. In the parallel loop, I can't use the mwIndex type index. It must be int type. This error not happens in the codes in these questions. I just note it down.

Then I used mex -v COMPFLAGS="$COMPFLAGS /openmp" test.cpp; to build the mex file. I just suggest not to build and apply the mex in one m file. My Matlab crashed sometimes. I don't know the reason. I just succeeded in the way separating them, even sounds very weird.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM