2

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()
*/
coatless
  • 20,011
  • 13
  • 69
  • 84
David Chen
  • 41
  • 3

1 Answers1

2

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.

Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • Thanks Dirk. In the example code, the object `x` is stack allocated as the dimension is pre-defined. Just to clarify, even if the dimension is from the parameters, i.e. `x` is heap-allocated, your point about the needed copy on the way out still holds? – David Chen Jan 05 '21 at 17:48
  • Sure. Because the heap memory may not be reference counted and will go out of scope. But _if_ you used R's allocator and then use a zero copy constructor with a reference counted R / Rcpp object _then_ you could surpass that. But that is new code of a fragile nature so you have to ask yourself if you want to try that and possibly waste some time setting it up so shave off nanoseconds on each of these calls. – Dirk Eddelbuettel Jan 05 '21 at 18:09