Using OpenMP with R packages in OS X

Lots of R packages have underlying implementations in C and C++, so they need to be compiled to function properly. But when you install a package in OS X you will probably get a pre-compiled version of said package from CRAN that used their build environment and the default package options.

Using a pre-compiled package is almost never a problem, except when the default options don't fit your requirements. In that case, you'll need to install them from source and make sure you get the compilation environment right.

I recently ran into a package that had the capability of using OpenMP to perform computation in parallel and take advantage of my MacBook Pro's multi-core processor to the fullest. If you are interested in how this works and how to integrate it into your own R packages, check out the Parallelism, R, and OpenMP guide by Drew Schmidt.

So this is all awesome, but there's a catch. There's always a catch, right?

Turns out the binary version of packages available at CRAN are not compiled to use OpenMP, since not all systems are equipped to support it. Moreover, if you try to install the package from source on OS X, it will try to use clang / clang++ which in my experience does not support OpenMP either.

Before I get into how I was eventually able to fix this, if you don't have homebrew installed on your Mac yet, stop everything and go install it. Yes, now. I'll wait.

So, I found lots of outdated references to a homebrew package called clang-omp, but as you can see at its website the project was moved elsewhere. And it doesn't exist in homebrew anymore, so that is a dead end.

What finally worked for me was to install GCC 6 using homebrew, and using it to compile the R packages with OpenMP support. This is how you do it using homebrew:

brew install gcc --without-multilib

It's important to include --without-multilib since it apparently creates problems with OpenMP. Unless you're cross-compiling to different architectures you probably won't miss it anyway.

If you already had gcc installed with homebrew, just replace install above with reinstall.

After you do that, you'll notice that gcc executables should have been linked to /usr/local/bin. Next, what you'll need to do is to create (or edit) ~/.R/Makevars to reference them:

CC=/usr/local/bin/gcc-6
CXX=/usr/local/bin/g++-6
CXX1X=/usr/local/bin/g++-6
CXX11=/usr/local/bin/g++-6
SHLIB_CXXLD=/usr/local/bin/g++-6
FC=/usr/local/bin/gfortran-6
F77=/usr/local/bin/gfortran-6
MAKE=make -j8

SHLIB_OPENMP_CFLAGS=-fopenmp
SHLIB_OPENMP_CXXFLAGS=-fopenmp
SHLIB_OPENMP_FCFLAGS=-fopenmp
SHLIB_OPENMP_FFLAGS=-fopenmp

Make sure you adjust the major version on the executable file names to match what homebrew installed in the last step.

After all this, uninstall the R packages you want to with OpenMP with, and reinstall them from source.

That's it! Hopefully you will now have a working OpenMP-enabled R package to work with.

Go Top