包内的 Rcpp omp_set_num_threads
Rcpp omp_set_num_threads within a package
我使用 Rcpp 和 OpenMP 编写了以下简单示例,当我从 RStudio 获取 cpp 文件时它工作正常:
#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
但是,如果我创建一个包,相同的代码无法按预期工作:
> 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
如果我从我的包中调用它,为什么相同的代码只使用一个线程?如果有帮助,我将所有代码推送到 this github repo
添加到 src/Makevars
和 src/Makevars.win
:
PKG_CXXFLAGS = $(SHLIB_OPENMP_CXXFLAGS)
PKG_LIBS = $(SHLIB_OPENMP_CXXFLAGS)
这会启用 -fopenmp
标志。否则,您最终不会在包中启用 OpenMP。
注:使用时:
// [[Rcpp::plugins(openmp)]]
当 运行 和 sourceCpp()
时,仅 设置 -fopenmp
参数 。此选项 不会 传输到包中。因此,我们必须在 Makevars
和 Makevars.win
.
中建立设置
可以在这里找到一个简短的例子:
https://github.com/r-pkg-examples/rcpp-and-openmp
不过,我需要稍微清理一下。
@coatless 已经回答了这个问题。我想补充一点:不要在并行代码中使用 R 或 Rcpp 的数据结构。您可以使用 RcppParallel,但是:
#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)
*/
请注意,我还更改了对 column major 的访问并删除了 i
和 j
的附加声明。请注意,在 parallel
部分内声明的变量自动是私有的。
如果您想使用 R 的 RNG(因为您正在设置种子),还有另一个 "don't do that"。查看 sitmo or dqrng 等可用于并行代码的 RNG 包。
我使用 Rcpp 和 OpenMP 编写了以下简单示例,当我从 RStudio 获取 cpp 文件时它工作正常:
#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
但是,如果我创建一个包,相同的代码无法按预期工作:
> 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
如果我从我的包中调用它,为什么相同的代码只使用一个线程?如果有帮助,我将所有代码推送到 this github repo
添加到 src/Makevars
和 src/Makevars.win
:
PKG_CXXFLAGS = $(SHLIB_OPENMP_CXXFLAGS)
PKG_LIBS = $(SHLIB_OPENMP_CXXFLAGS)
这会启用 -fopenmp
标志。否则,您最终不会在包中启用 OpenMP。
注:使用时:
// [[Rcpp::plugins(openmp)]]
当 运行 和 sourceCpp()
时,仅 设置 -fopenmp
参数 。此选项 不会 传输到包中。因此,我们必须在 Makevars
和 Makevars.win
.
可以在这里找到一个简短的例子:
https://github.com/r-pkg-examples/rcpp-and-openmp
不过,我需要稍微清理一下。
@coatless 已经回答了这个问题。我想补充一点:不要在并行代码中使用 R 或 Rcpp 的数据结构。您可以使用 RcppParallel,但是:
#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)
*/
请注意,我还更改了对 column major 的访问并删除了 i
和 j
的附加声明。请注意,在 parallel
部分内声明的变量自动是私有的。
如果您想使用 R 的 RNG(因为您正在设置种子),还有另一个 "don't do that"。查看 sitmo or dqrng 等可用于并行代码的 RNG 包。