I have prepared a package in R by using RcppArmadillo
and OpenMP
libraries and following commands:
RcppArmadillo.package.skeleton(
Congratulations! You've most likely stumbled across macOS' lack OpenMP
support. This has been documented in the Rcpp FAQ as entry 2.10.3.
The reason for the error being apparent is you did not protect the OpenMP
code appropriately... e.g.
Header inclusions are protected with:
#ifdef _OPENMP
#include <omp.h>
#endif
Code has protections given by:
#ifdef _OPENMP
// multithreaded OpenMP version of code
#else
// single-threaded version of code
#endif
This assumes you are not using the preprocessor #omp
tags but more indepth omp function calls. If it is the prior, then the code protection is not important as the preprocessor tags will be discarded.
(For those long time users of the above macro schemes coming here, please note that as of R 3.4.0, the SUPPORT_OPENMP definition was removed completely in favor of _OPENMP.)
OpenMP
via configure.ac
However, the above is just good defensive coding. If your package requires a specific feature, then it may be time to consider using an autoconf
file called configure.ac
to generate a configure
script.
Place the configure.ac
in the top level of your package.
packagename/
|- data/
|- inst/
|- man/
|- src/
|- Makevars
|- HelloWorld.cpp
|- DESCRIPTION
|- NAMESPACE
|- configure.ac
|- configure
The configure.ac
should contain the following:
AC_PREREQ(2.61)
AC_INIT(your_package_name_here, m4_esyscmd_s([awk -e '/^Version:/ {print $2}' DESCRIPTION]))
AC_COPYRIGHT(Copyright (C) 2017 your name?)
## Determine Install Location of R
: ${R_HOME=$(R RHOME)}
if test -z "${R_HOME}"; then
AC_MSG_ERROR([Could not determine R_HOME.])
fi
## Setup RBin
RBIN="${R_HOME}/bin/R"
CXX=`"${RBIN}" CMD config CXX`
CPPFLAGS=`"${RBIN}" CMD config CPPFLAGS`
CXXFLAGS=`"${RBIN}" CMD config CXXFLAGS`
## Package Requires C++
AC_LANG(C++)
AC_REQUIRE_CPP
## Compiler flag check
AC_PROG_CXX
## Borrowed from BHC/imager/icd/randomForest
# Check for OpenMP
AC_OPENMP
# since some systems have broken OMP libraries
# we also check that the actual package will work
ac_pkg_openmp=no
if test -n "${OPENMP_CFLAGS}"; then
AC_MSG_CHECKING([OpenMP detected, checking if viable for package use])
AC_LANG_CONFTEST([AC_LANG_PROGRAM([[#include <omp.h>]], [[ return omp_get_num_threads (); ]])])
"$RBIN" CMD SHLIB conftest.c 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD && "$RBIN" --vanilla -q -e "dyn.load(paste('conftest',.Platform\$dynlib.ext,sep=''))" 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD && ac_pkg_openmp=yes
AC_MSG_RESULT([${ac_pkg_openmp}])
fi
# if ${ac_pkg_openmp} = "yes" then we have OMP, otherwise it will be "no"
if test "${ac_pkg_openmp}" = no; then
AC_MSG_WARN([No OpenMP support. If using GCC, upgrade to >= 4.2. If using clang, upgrade to >= 3.8.0])
AC_MSG_ERROR([Please use a different compiler.])
fi
# Fin
AC_OUTPUT
To generate the configure
script, run:
autoconf
Once this is done, you will need to rebuild your package. Note, you may need to install autoconf
if on Windows and on macOS you likely need to install it via homebrew.
OpenMP
compilerNow, you may want to ensure your colleagues are able to get the speedup gain from your OpenMP
-enabled code. To do so, one must enable OpenMP
by having your colleagues shift away from using the default system compiler to either a "true" gcc
or a viable omp
enabled clang
compiler.
Instructions for both on macOS are given here:
http://thecoatlessprofessor.com/programming/openmp-in-r-on-os-x/