在Mac上的Matlab中使用mex进行Open操作

Sup*_*ker 3 macos matlab gcc openmp mex

我有OS X El Capitan和Matlab R2016a,我想使用之前有效的OpenMP.我已经设法通过自制软件安装gcc-5并在那里运行openmp.我可以从这个线程中看到GCC C/C++ MEX Matlab R2015 Mac OS X(带有OpenMP)至少在R2014a中不起作用,可以手动插入mexopts.sh并进行编辑.但是,我没有使用这样的文件来重定向编译器标志(CC)以指向与-fopenmp标志一起使用的gcc-5编译器.

有什么建议?我完全走错了路吗?

zee*_*eez 5

更新macOS 10.12,MATLAB 2016b:以下 的一般原则仍然适用.向下滚动以查看我必须进行的更改.


clang已更新为包含OpenMP支持,但是,随Xcode 7.3.1安装的版本尚不支持OpenMP.相反,它可以安装homebrew.在以前的解决方案使用clang-omp不工作了,因为clang-omp已移出brew.

以下过程已使用Mac OS X 10.11.6,clang 3.8.1,MATLAB 2016a进行了测试.

安装 llvm

安装当前版本的llvmfrom brew(from Terminal):

brew install llvm
Run Code Online (Sandbox Code Playgroud)

修改MATLAB构建配置

然后,将默认mex编译器配置文件复制到MATLAB配置目录.要查找默认配置,请mex -setup C++在MATLAB提示符下输入.一个选项应该是这样的

Xcode Clang++ mex -setup:/Applications/Matlab/MATLAB_R2016a/MATLAB_R2016a.app/bin/maci64/mexopts/clang++_maci64.xml C++

(此处和之后我们将假设MATLAB 2016a是使用的版本).复制/Applications/Matlab/MATLAB_R2016a/MATLAB_R2016a.app/bin/maci64/mexopts/clang++_maci64.xml~/.matlab/R2016a,并将其命名clang++_openmp_maci64.xml为能够区分它.clang++_openmp_maci64.xml在文本编辑器中打开并按如下所示进行修改:首先,为名称等输入不同的值,再次将其分开:

Name="LLVM Clang++ OpenMP"
ShortName="Clang++ OpenMP"
Manufacturer="LLVM"
Run Code Online (Sandbox Code Playgroud)

将定义更改CXX为指向clang安装的位置brew.在默认位置,这应该是

CXX="/usr/local/opt/llvm/bin/clang++"
Run Code Online (Sandbox Code Playgroud)

添加-fopenmp -Wall -I/usr/local/opt/llvm/includeCXXFLAGS,所以它会读取

CXXFLAGS="-fno-common -arch x86_64 -mmacosx-version-min=$SDKVER -fexceptions -isysroot $ISYSROOT -fobjc-arc -std=c++11 -stdlib=libc++ -fopenmp -Wall -I/usr/local/opt/llvm/include"
Run Code Online (Sandbox Code Playgroud)

添加-L/usr/local/opt/llvm/lib -Wl,-rpath,/usr/local/opt/llvm/lib -fopenmpLDFLAGS它类似于

LDFLAGS="-Wl,-twolevel_namespace -undefined error -arch x86_64 -mmacosx-version-min=$SDKVER -Wl,-syslibroot,$ISYSROOT -framework Cocoa $LDBUNDLE $LINKEXPORT -stdlib=libc++ -L/usr/local/opt/llvm/lib -Wl,-rpath,/usr/local/opt/llvm/lib -fopenmp"
Run Code Online (Sandbox Code Playgroud)

要激活此构建配置,请在MATLAB提示符下输入:

mex -setup:~/.matlab/R2016a/clang++_openmp_maci64.xml C++
Run Code Online (Sandbox Code Playgroud)

修改MATLAB运行时变量

现在,MATLAB必须在运行时了解库的位置.检查您是否有文件~/.matlab7rc.sh.如果没有,请将模板复制matlabroot/bin到主目录中.在文本编辑器中打开此文件.向下滚动到该mac|maci|maci64)部分(第188行).添加/usr/local/opt/llvm/libLDPATH_PREFIX,所以它可能会读取

LDPATH_PREFIX='/usr/local/opt/llvm/lib'
Run Code Online (Sandbox Code Playgroud)

重启MATLAB.

测试配置

创建一个mex_par_test.cpp包含的文件

#include "mex.h"
#if defined(_OPENMP)
#include <omp.h>
#endif
void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
#if defined(_OPENMP)
    if (nrhs > 0) {
        omp_set_num_threads(mxGetScalar(prhs[0]));
    }
    {
        mexPrintf("If parallel processing is enabled, you should see the line\n\"Hello world from thread x\", where 'x' represents a thread number.\nThere will be %i threads in parallel.\n\n", omp_get_max_threads());
#pragma omp parallel
        {
#pragma omp critical
            mexPrintf("Hello world from thread %i.\n", omp_get_thread_num());
        }
    }
#else
    mexPrintf("SSIMS Toolbox was not compiled with support for parallelization.\n\n");
#endif
}
Run Code Online (Sandbox Code Playgroud)

这应该在MATLAB提示符下编译:

mex mex_par_test.cpp
Run Code Online (Sandbox Code Playgroud)

Building with 'LLVM Clang++ OpenMP'. MEX completed successfully.

调用编译的函数mex_par_test应该产生类似的东西

如果启用了并行处理,您应该看到"来自线程x的Hello world"行,其中"x"表示线程号.将有12个并行线程.

Hello world from thread 0. Hello world from thread 3. Hello world from thread 8. Hello world from thread 1. Hello world from thread 2. Hello world from thread 11. Hello world from thread 4. Hello world from thread 7. Hello world from thread 10. Hello world from thread 9. Hello world from thread 5. Hello world from thread 6.

更新macOS 10.12,MATLAB 2016b

  • MATLAB 2016b存储构建配置和其他文件,/Users/username/Library/Application Support/MathWorks/MATLAB/R2016b而不是存储在.matlab/R*/用户的主文件夹中(检查prefdir).
  • 如果使用上述设置,则在更新到macOS 10.12后,MATLAB在启动时崩溃.要立即使用它,只需注释掉该LDPATH_PREFIX~/.matlab7rc.sh.事实上,LDPATH_PREFIXOS clang和MATLAB的这种组合不应该需要
  • 我发现我必须重新安装llvm:brew reinstall llvm
  • MATLAB有自己的版本libiomp5,这应该链接.更改构建配置XML(clang++_openmp_maci64.xml),以便-fopenmp替换每个事件-fopenmp=libiomp5.-L$MATLABROOT/sys/os/maci64每次出现之前添加-L/usr/local/opt/llvm/lib.最后,链接器选项应该-Wl,-rpath,$MATLABROOT/sys/os/maci64:/usr/local/opt/llvm/lib代替-Wl,-rpath,/usr/local/opt/llvm/lib.所以,我CXXFLAGSLDFLAGS现在读

    CXXFLAGS="-fno-common -arch x86_64 -fexceptions -fobjc-arc -std=c++11 -stdlib=libc++ -fopenmp=libiomp5 -Wall -I/usr/local/opt/llvm/include"
    LDFLAGS="-Wl,-twolevel_namespace -undefined error -arch x86_64 -Wl $LDBUNDLE $LINKEXPORT -stdlib=libc++ -L$MATLABROOT/sys/os/maci64 -L/usr/local/opt/llvm/lib -Wl,-rpath,$MATLABROOT/sys/os/maci64:/usr/local/opt/llvm/lib -fopenmp=libiomp5"
    
    Run Code Online (Sandbox Code Playgroud)

这应该使上面的例子再次编译,也不会崩溃MATLAB.