Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Requiring OpenMP availability for use in an Rcpp package

I have prepared a package in R by using RcppArmadillo and OpenMP libraries and following commands:

RcppArmadillo.package.skeleton("mypackage")
compileAttributes(verbose=TRUE)

Also, in the DESCRIPTION file I added:

Imports: Rcpp (>= 0.12.8), RcppArmadillo
LinkingTo:Rcpp, RcppArmadillo
Depends: RcppArmadillo

and in the NAMESPACE file I added:

import(RcppArmadillo)
importFrom(Rcpp, evalCpp)

Then I run the following codes in cmd:

R CMD build mypackage
R CMD INSTALL mypackage.tar.gz

I build and install the package in my computer and I use it now. But my colleges and friends are not able to install the package. The error messages is about RcppArmadillo and OpenMPlibraries.

For instance:

fatal error: 'omp.h' file not found

Does anyone have previous experience in this case? Which type of settings I have to do in my package for solving this problem?

like image 861
Ham82 Avatar asked Feb 16 '17 17:02

Ham82


1 Answers

Congratulations! You've most likely stumbled across macOS' lack OpenMP support. This has been documented in the Rcpp FAQ as entry 2.10.3.


Defensive coding

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.)


Creating a package requirement for 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.


Helping users get a viable OpenMP compiler

Now, 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/

like image 166
coatless Avatar answered Nov 14 '22 17:11

coatless