Consider the following serial example function:
// [[Rcpp::plugins(cpp20)]]
#include <Rcpp.h>
// [[Rcpp::export]]
Rcpp::NumericVector example_fun(int n) {
Rcpp::NumericVector result (n);
for(int i = 0; i < n; ++i) {
result[i] = something();
}
return result;
}
Parallelizing this loop with OpenMP requires the use of e.g. std::vector
or RcppParallel::RVector
, as Rcpp vectors are not thread-safe. The corresponding parallel std::vector
version is
// [[Rcpp::plugins(cpp20)]]
// [[Rcpp::plugins(openmp)]]
#include <Rcpp.h>
#include <omp.h>
#include <vector>
// [[Rcpp::export]]
std::vector<double> example_fun(int n) {
std::vector<double> result (n);
#pragma omp parallel for
for(int i = 0; i < n; ++i) {
result[i] = something();
}
return result;
}
and similarly with RcppParallel::RVector<double> example_fun(int n)
for RcppParallel::RVector
.
If I understand correctly, exporting an Rcpp::NumericVector
makes the data available to R without copying it, as it is essentially R's native data type. What I would like to know, is how exporting a std::vector
or an RcppParallel::RVector
works internally? Is the vector copied? Is it moved? Does it require type conversions? And importantly, is one of the two options clearly more efficient than the other?
As a quick additional question, I would also like to know, if the Rcpp tread safety issue also applies to vectorized simd loops: #pragma omp simd
or #pragma omp parallel for simd
?
Thanks.