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.
Install llvm
Install the current version of llvm
from brew
(from Terminal
):
brew install llvm
Modify MATLAB build configuration
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++
Modify MATLAB runtime variables
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.
Test configuration
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.
Update for macOS 10.12, MATLAB 2016b
- MATLAB 2016b stores build configurations and other files in
/Users/username/Library/Application Support/MathWorks/MATLAB/R2016b
rather than in .matlab/R*/
in the user's home folder (check prefdir
).
- MATLAB crashes on startup after update to macOS 10.12 if the setup described above has been used. To get it working immediately, just comment out the
LDPATH_PREFIX
line in ~/.matlab7rc.sh
. In fact, LDPATH_PREFIX
should not be needed for this combination of OS, clang
, and MATLAB
- I found I had to reinstall
llvm
: 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.