Rcpp omp_set_num_threads within a package

℡╲_俬逩灬. 提交于 2019-12-08 08:49:00

问题


I wrote the following simple example with Rcpp and OpenMP that works fine when I source the cpp file from RStudio:

#include <Rcpp.h>
#include <omp.h>

// [[Rcpp::plugins(openmp)]]

using namespace Rcpp;

// [[Rcpp::export]]
NumericMatrix my_matrix(int I, int J, int nthreads) {
  NumericMatrix A(I,J);
  int i,j,tid;
  omp_set_num_threads(nthreads);
#pragma omp parallel for private(i, j, tid)
  for(int i = 0; i < I; i++) {
    for(int j = 0; j < J; j++) {
      tid = omp_get_thread_num();
      A(i,j) = tid ;
    }
  }

  return A;
}


/*** R
set.seed(42)
  my_matrix(10,10,5)
*/
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
 [1,]    0    0    0    0    0    0    0    0    0     0
 [2,]    0    0    0    0    0    0    0    0    0     0
 [3,]    1    1    1    1    1    1    1    1    1     1
 [4,]    1    1    1    1    1    1    1    1    1     1
 [5,]    2    2    2    2    2    2    2    2    2     2
 [6,]    2    2    2    2    2    2    2    2    2     2
 [7,]    3    3    3    3    3    3    3    3    3     3
 [8,]    3    3    3    3    3    3    3    3    3     3
 [9,]    4    4    4    4    4    4    4    4    4     4
[10,]    4    4    4    4    4    4    4    4    4     4

However, the same code does not work as expected if I create a package:

> rcpphello::my_matrix(10,10,5)
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
 [1,]    0    0    0    0    0    0    0    0    0     0
 [2,]    0    0    0    0    0    0    0    0    0     0
 [3,]    0    0    0    0    0    0    0    0    0     0
 [4,]    0    0    0    0    0    0    0    0    0     0
 [5,]    0    0    0    0    0    0    0    0    0     0
 [6,]    0    0    0    0    0    0    0    0    0     0
 [7,]    0    0    0    0    0    0    0    0    0     0
 [8,]    0    0    0    0    0    0    0    0    0     0
 [9,]    0    0    0    0    0    0    0    0    0     0
[10,]    0    0    0    0    0    0    0    0    0     0

Why is the same code only using one thread if I call it from within my package? In case it helps, I pushed all the code to this github repo


回答1:


Add to src/Makevars and src/Makevars.win:

PKG_CXXFLAGS = $(SHLIB_OPENMP_CXXFLAGS)
PKG_LIBS = $(SHLIB_OPENMP_CXXFLAGS)

This enables the -fopenmp flag. Otherwise, you will not end up having OpenMP enabled in your package.

Note: When using:

// [[Rcpp::plugins(openmp)]]

This sets the -fopenmp parameter only when run with sourceCpp(). This option does not transfer into a package. Hence, we must establish the setting in Makevars and Makevars.win.

A short example can be found here:

https://github.com/r-pkg-examples/rcpp-and-openmp

Though, I'll need to clean it up a bit.




回答2:


@coatless answered the question already. I would like to add one caveat: Don't use data structures from R or Rcpp within parallel code. You can use RcppParallel, though:

#include <Rcpp.h>
// [[Rcpp::plugins(openmp)]]
#include <omp.h>

// [[Rcpp::depends(RcppParallel)]]
#include <RcppParallel.h>

using namespace Rcpp;

// [[Rcpp::export]]
NumericMatrix my_matrix(int I, int J, int nthreads) {
  NumericMatrix A(I,J);
  // create a thread safe accessor for A
  RcppParallel::RMatrix<double> a(A);
  int tid;
  omp_set_num_threads(nthreads);
#pragma omp parallel for private(tid)
  for(int j = 0; j < J; j++) {
    for(int i = 0; i < I; i++) {
      tid = omp_get_thread_num();
      a(i, j) = tid ;
    }
  }

  return A;
}


/*** R
set.seed(42)
my_matrix(12,10,5)
*/

Note that I have also changed the access to column major and removed the additional declaration of i and j. Note that variables declared inside of a parallel section are automatically private.

And in case you want to use R's RNG (since you are setting the seed), there is another "don't do that". Have a look at packages like sitmo or dqrng for RNGs that can be used with parallel code.



来源:https://stackoverflow.com/questions/54715688/rcpp-omp-set-num-threads-within-a-package

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!