【问题标题】:How to use OpenMP in my MEX-file without crashing MATLAB?如何在我的 MEX 文件中使用 OpenMP 而不会导致 MATLAB 崩溃?
【发布时间】:2019-09-21 15:35:59
【问题描述】:

我从 Visual Studio 2019 构建了一个 Windows MEX 文件。我的 MATLAB 版本是 R2019a。该代码只是对两个输入 matlab 数组进行了一些“排序”。这是我尝试与 OpenMP 一起使用的示例。 “测试.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;
}

我的测试 M 文件是:

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

理想的输出将是result 中的 2*1 单元格。如果我删除 # pragma 行,则 MEX 文件运行良好。如果我添加它,MATLAB 崩溃了。几天来我一直试图找到问题,但没有找到任何解决方案。 此外,

  1. 我已在我的 Visual Studio 中选择 OpenMP 支持键为“是”。
  2. 我的代码中没有使用mexPrintf。我听说该功能会使 OpenMP 的 MEX 文件崩溃。
  3. 我已经安装了 Intel Studio 并行 XE 2019 和 Matlab R2019a 的更新 5。也许我做了一个错误的并行域定义。我不想将plhs[0] = mxCreateCellMatrix(2, 1); 的最后一部分包含到#pragma 并行部分中。如上代码,我做对了吗?

【问题讨论】:

    标签: c++ matlab openmp mex


    【解决方案1】:

    这可能不是完美的解决方案。我刚刚对代码进行了一些更正,并成功在 Matlab 中构建了 mexw64。至于在 Visual Studio 中编译代码,mex 的运行速度非常低。(VS 构建了 15 秒,Matlab 构建了 0.4 秒。我不知道为什么。) 起初,我纠正了两个严重错误。

    1. 正确使用#pragma... 的花括号。左大括号不能直接在#pragma omp parallel 之后。它应该在一个新行中。如下,
    #pragma omp parallel
    { 
    #pragma omp for
        for (i = 0; i < 2; i++) {
            sort(v[i].begin(), v[i].end());
        };
    }
    

    2 。在并行循环中,我不能使用mwIndex 类型索引。它必须是int 类型。这些问题的代码中不会发生此错误。我只是记下来了。

    然后我使用mex -v COMPFLAGS="$COMPFLAGS /openmp" test.cpp; 构建了 mex 文件。我只是建议不要在一个 m 文件中构建和应用 mex。我的 Matlab 有时会崩溃。我不知道原因。我只是成功地把它们分开了,甚至听起来很奇怪。

    【讨论】:

    • 很高兴你知道了! mwIndex 很奇怪,它只是 long long int 的别名。
    • @CrisLuengo 非常感谢您的帮助和编辑我的问题。我不仅学到了很多代码,还学到了分数。
    【解决方案2】:

    您不能在代码的并行部分调用任何mx...mex... 函数*。您必须在并行部分之前获取指向所有数据的指针,包括创建输出数组并获取它们的指针,然后仅并行执行计算。


    * 这里给出的规则过于宽泛,一些mx... 函数可能可以在并行部分中使用,如James Tursa’s comment 所示。我不喜欢猜测并保持规则简单。

    【讨论】:

    • 感谢您的回答。在上面的例子中,我认为我在并行部分没有做任何事情。你的意思是我需要删除openmp并行部分之前的所有指针和数组?
    • 我以为你在并行部分调用mxCreateCellMatrix。你有更新3吗?该更新增加了对您的编译器的支持,早期版本的 MATLAB 不支持该编译器。可能是另一件需要调查的事情。见mathworks.com/content/dam/mathworks/mathworks-dot-com/support/…
    • 起初,我意识到我错误地使用了花括号。但是在我修改它之后,它仍然给出了错误。我删除了#pragma omp parallel for 之后的花括号,所以后面的唯一for 循环受Openmp 影响。我认为最后一个包含 mx-functions 的for 循环不在并行模式下。 (如果我错了,请指出。)。它一直不好。我正在更新我的 Intel Parallel Studio XE。由于我下载速度慢,我会尽快更新这个问题。谢谢你的建议。
    • 我已经安装了intel studio parallel XE 2019和matlab的更新5。现在好多了。 #pragma omp parallel for 带有一个空的 for 循环效果很好。但是我将向量操作代码放入#pragma omp parallel for`中,它仍然出错。我觉得我必须在定义并行域时做错了什么。你能给我一些建议吗?
    • mx... 或 mex... 函数限制适用于调用 MATLAB 内存管理器的函数,因为这不是线程安全的。简单查询的mx...函数应该没问题(如mxIsDouble、mxIsSparse、mxGetData等)
    猜你喜欢
    • 2011-09-05
    • 1970-01-01
    • 1970-01-01
    • 2014-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多