Reputation: 319
I have OS X El Capitan and Matlab R2016a and I would like to use OpenMP, which has previously worked. I have managed to install gcc-5 via homebrew and have openmp working there. I can see from this thread GCC C/C++ MEX Matlab R2015 Mac OS X (with OpenMP) doesn't work that at least in R2014a, it was possible to insert mexopts.sh manually and edit it. However, I do not have such a file to use in order to redirect the compiler flag (CC) to point at the gcc-5 compiler that works with the -fopenmp flag.
Any suggestions? Am I going entirely the wrong way?
Upvotes: 3
Views: 2869
Reputation: 5157
Update for macOS 10.12, MATLAB 2016b: The general principle of the following still holds true. Scroll down for changes I had to make.
clang
has been updated to include OpenMP support, however, the version installed with Xcode 7.3.1 does not support OpenMP yet. Instead, it can be installed with homebrew
. The previous solution using clang-omp
does not work anymore, because clang-omp
has been removed from brew
.
The following process has been tested with Mac OS X 10.11.6, clang 3.8.1, MATLAB 2016a.
llvm
Install the current version of llvm
from brew
(from Terminal
):
brew install llvm
Then, copy a default mex
compiler configuration file to your MATLAB configuration directory. To find the default configuration, enter mex -setup C++
on your MATLAB prompt. One option should read something like
Xcode Clang++ mex -setup:/Applications/Matlab/MATLAB_R2016a/MATLAB_R2016a.app/bin/maci64/mexopts/clang++_maci64.xml C++
(Here and later we will assume MATLAB 2016a is the version used).
Copy /Applications/Matlab/MATLAB_R2016a/MATLAB_R2016a.app/bin/maci64/mexopts/clang++_maci64.xml
to ~/.matlab/R2016a
, and name it clang++_openmp_maci64.xml
to be able to tell it apart. Open clang++_openmp_maci64.xml
in a text editor and modify it as follows:
At the beginning, enter different values for name etc, again to be able to tell it apart:
Name="LLVM Clang++ OpenMP"
ShortName="Clang++ OpenMP"
Manufacturer="LLVM"
Change the definition of CXX
to point to the location of clang
as installed with brew
. At the default location, this should be
CXX="/usr/local/opt/llvm/bin/clang++"
Add -fopenmp -Wall -I/usr/local/opt/llvm/include
to CXXFLAGS
, so it will read
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"
Add -L/usr/local/opt/llvm/lib -Wl,-rpath,/usr/local/opt/llvm/lib -fopenmp
to LDFLAGS
so it is similar to
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"
To activate this build configuration, enter at the MATLAB prompt:
mex -setup:~/.matlab/R2016a/clang++_openmp_maci64.xml C++
Now, MATLAB has to know about the locations of the libraries at runtime. Check if you have a file ~/.matlab7rc.sh
. If not, copy the template from matlabroot/bin
into your home directory.
Open this file in a text editor. Scroll down to the mac|maci|maci64)
section (line 188 ff). Add /usr/local/opt/llvm/lib
to LDPATH_PREFIX
, so it might read
LDPATH_PREFIX='/usr/local/opt/llvm/lib'
Restart MATLAB.
Create a file mex_par_test.cpp
containing
#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
}
This should compile at the MATLAB prompt:
mex mex_par_test.cpp
Building with 'LLVM Clang++ OpenMP'. MEX completed successfully.
Calling the compiled function with mex_par_test
should yield something like
If parallel processing is enabled, you should see the line "Hello world from thread x", where 'x' represents a thread number. There will be 12 threads in parallel.
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.
/Users/username/Library/Application Support/MathWorks/MATLAB/R2016b
rather than in .matlab/R*/
in the user's home folder (check prefdir
).LDPATH_PREFIX
line in ~/.matlab7rc.sh
. In fact, LDPATH_PREFIX
should not be needed for this combination of OS, clang
, and MATLABllvm
: brew reinstall llvm
MATLAB comes with its own version of libiomp5
, and this should be linked against. Change your build configuration XML (clang++_openmp_maci64.xml
) so that every incidence of -fopenmp
is replaced by -fopenmp=libiomp5
. Add -L$MATLABROOT/sys/os/maci64
before each occurrence of -L/usr/local/opt/llvm/lib
. Finally, linker options should be -Wl,-rpath,$MATLABROOT/sys/os/maci64:/usr/local/opt/llvm/lib
instead of -Wl,-rpath,/usr/local/opt/llvm/lib
. So my CXXFLAGS
and LDFLAGS
now read
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"
This should make the example above compile again and also not crash MATLAB.
Upvotes: 6