David Chen
David Chen

Reputation: 41

how to create a Rcpp NumericVector from Eigen::Tensor without copying underlying data

If I create a large Tensor in Eigen, and I like to return the Tensor back to R as multi-dimension array. I know how to do it with data copy like below. Question: is it possible to do it without the data-copy step?

#include <Rcpp.h>
#include <RcppEigen.h>
#include <unsupported/Eigen/CXX11/Tensor>

// [[Rcpp::depends(RcppEigen)]]
using namespace Rcpp;

template <typename T>
NumericVector copyFromTensor(const T& x) 
{ 
    int n = x.size();
    NumericVector ans(n);
    IntegerVector dim(x.NumDimensions);
    for (int i = 0; i < x.NumDimensions; ++i) {
      dim[i] = x.dimension(i);
    }
    memcpy((double*)ans.begin(), (double*)x.data(), n * sizeof(double));
    ans.attr("dim") = dim;
    return ans;
}

// [[Rcpp::export]]
NumericVector getTensor() {
    Eigen::Tensor<double, 3> x(4, 3, 1);
    x.setRandom();
    return copyFromTensor(x);
}

/*** R
getTensor()
*/

Upvotes: 2

Views: 303

Answers (1)

Dirk is no longer here
Dirk is no longer here

Reputation: 368509

As a general rule you can zero-copy one the way into your C++ code with data coming from R and already managed by R.

On the way out of your C++ code with data returning to R anything that is not created used the R allocator has to be copied.

Here your object x is a stack-allocated so you need a copy. See Writing R Extensions about the R allocator; Eigen may let you use it when you create a new Tensor object. Not a trivial step. I think I would just live with the copy.

Upvotes: 2

Related Questions