Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CRAN-acceptable way of linking to OpenMP some C code called from Rcpp

Tags:

r

rcpp

openmp

I’m building an R package that has some .c files with code that uses OpenMP, and these C functions are called from .cpp files, but the .cpp files themselves don’t make any use of OpenMP.

e.g. cfile.c:

int parallel_function(double *x, int n)
{   
    int i;
    #pragma omp parallel for firstprivate(x, n)
    for (i = 0; i < n; i++){ x[i] *= 2; }
}

cppfile.cpp:

#include <Rcpp.h>
using namespace Rcpp;
extern “C” {
    int parallel_function(double *x, int n);
}
// [[Rcpp::export]]
void multiply_by_two(NumericVector x, int n){parallel_function(x.begin(), n);}

In order to enable OpenMP for the C files, my first though was to construct a Makevars like this, following the R extensions manual:

PKG_CFLAGS = $(SHLIB_OPENMP_CFLAGS)
PKG_LIBS = $(SHLIB_OPENMP_CFLAGS)

But that will throw me the following:

Check: use of SHLIB_OPENMP_*FLAGS in Makefiles, Result: NOTE
    src/Makevars: SHLIB_OPENMP_CFLAGS is included in PKG_LIBS but linking is by C++
  Use of these macros is discussed in sect 1.2.1.1 of 'Writing R
  Extensions'. The macros for different languages may differ so the
  matching macro must be used in PKG_CXXFLAGS (etc) and match that used
  in PKG_LIBS (except for Fortran: see the manual).

So then, if I try instead:

PKG_CFLAGS = $(SHLIB_OPENMP_CFLAGS)
PKG_LIBS = $(SHLIB_OPENMP_CXXFLAGS)

I would get:

Check: use of SHLIB_OPENMP_*FLAGS in Makefiles, Result: NOTE
    src/Makevars: SHLIB_OPENMP_CFLAGS is included in PKG_CFLAGS but not in PKG_LIBS
    src/Makevars: SHLIB_OPENMP_CXXFLAGS is included in PKG_LIBS but not in PKG_CXXFLAGS
  Use of these macros is discussed in sect 1.2.1.1 of 'Writing R
  Extensions'. The macros for different languages may differ so the
  matching macro must be used in PKG_CXXFLAGS (etc) and match that used
  in PKG_LIBS (except for Fortran: see the manual).

Even if I use both flags like this:

PKG_CFLAGS = $(SHLIB_OPENMP_CFLAGS)
PKG_CXXFLAGS = $(SHLIB_OPENMP_CXXFLAGS)
PKG_LIBS = $(SHLIB_OPENMP_CXXFLAGS) $(SHLIB_OPENMP_CFLAGS)

I would get:

Check: use of SHLIB_OPENMP_*FLAGS in Makefiles, Result: NOTE
    src/Makevars: SHLIB_OPENMP_CFLAGS is included in PKG_LIBS but linking is by C++
    src/Makevars: it is not portable to include multiple SHLIB_OPENMP_*' macros in PKG_LIBS
  Use of these macros is discussed in sect 1.2.1.1 of 'Writing R
  Extensions'. The macros for different languages may differ so the
  matching macro must be used in PKG_CXXFLAGS (etc) and match that used
  in PKG_LIBS (except for Fortran: see the manual).

So, since the .cpp code does not require omp linkage, I’m wondering what would be the correct and minimalist way of linking the .c files but not the .cpp files.

like image 408
anymous.asker Avatar asked Jan 05 '19 21:01

anymous.asker


1 Answers

In general, we can mix C and C++ code in an R package.

Once OpenMP enters, CRAN now seems to stronly prefer consistent use of either SHLIB_OPENMP_CFLAGS or SHLIB_OPENMP_CXXFLAGS.

Now, given that g++ will enter for linking, it would seem that you should use SHLIB_OPENMP_CXXFLAGS throughout -- which suggests renaming your C files to be C++ files.

It all seems a little over the top, but that is what I would try. And the CRAN checks are usually all there for a good reason so experience has taught most of to play along with them.

like image 58
Dirk Eddelbuettel Avatar answered Nov 05 '22 15:11

Dirk Eddelbuettel