Data transfer between LibTorch C++ and Eigen

Data transfer between LibTorch C++ and Eigen (Questions and Help)

Hello all,
I’m developing a Data Transfer Tools for C++ Linear Algebra Libraries, as you can see here:


(considering bi-dimensional arrays or matrices)
and I’m wondering if you can help me on the following code for data transfer between LibTorch and Eigen:

std::cout << "Testing LibTorch to Eigen:" << std::endl;
// LibTorch
torch::Device device(torch::cuda::is_available() ? torch::kCUDA : torch::kCPU);
torch::Tensor T = torch::rand({3, 3});
std::cout << "LibTorch:" << std::endl;
std::cout << T << std::endl;
// Eigen
float* data = T.data_ptr<float>();
Eigen::Map<Eigen::MatrixXf> E(data, T.size(0), T.size(1));
std::cout << "EigenMat:\n" << E << std::endl;
// re-check after changes
E(0,0) = 0;
std::cout << "EigenMat:\n" << E << std::endl;
std::cout << "LibTorch:" << std::endl;
std::cout << T << std::endl;

This is the output of the code:

--------------------------------------------------
Testing LibTorch to Eigen:

LibTorch:
 0.6232  0.5574  0.6925
 0.7996  0.9860  0.1471
 0.4431  0.5914  0.8361
[ Variable[CPUFloatType]{3,3} ]

EigenMat (after data transfer):
0.6232 0.7996 0.4431
0.5574  0.986 0.5914
0.6925 0.1471 0.8361

# Modifying EigenMat, set element at (0,0) = 0
EigenMat:
     0 0.7996 0.4431
0.5574  0.986 0.5914
0.6925 0.1471 0.8361

# Now, the LibTorch matrix was also modified (OK), but the rows and columns were switched.
LibTorch:
 0.0000  0.5574  0.6925
 0.7996  0.9860  0.1471
 0.4431  0.5914  0.8361
[ Variable[CPUFloatType]{3,3} ]

Do someone knows what’s happening ?
There’s a better way to do that?

I need also to do the same for Armadillo, ArrayFire and OpenCV (cv::Mat).
Thanks in advance!

1 Like

What great contribution.
A question: I did not see any example of cv2::imread(). Is that because you had issues with ABI compatibility between OpenCV and libtorch?

Thanks,

Thank you @dambo,
Yes, I am still working on it to add more functions and examples.
Cheers,
Andrews

I am working on this issue for several days now. I will share my docker if I am successful.

1 Like

I shall upload the code to this repo once I am done:

1 Like

Hey,

I also needed to transfer data from Eigen to libtorch, so I inspected your example. For a square matrix, it seems that it is a transpose porblem, but if you try the same thing with a non-square matrix, the result is chaotic :slight_smile:

After a bit of thinking, I came out with this solution (I tested on square and non square matrix).

torch::Tensor eigenVectorToTorchTensor(VectorXd e){
    auto t = torch::rand({e.rows()});
    float* data = t.data_ptr<float>();

    Map<VectorXf> ef(data,t.size(0),1);
    ef = e.cast<float>();

    t.requires_grad_(true);
    return t;
}

torch::Tensor eigenMatrixToTorchTensor(MatrixXd e){
    auto t = torch::rand({e.cols(),e.rows()});
    float* data = t.data_ptr<float>();

    Map<MatrixXf> ef(data,t.size(1),t.size(0));
    ef = e.cast<float>();
    t.requires_grad_(true);
    return t.transpose(0,1);
}

NB: Here I am interested into converting an Eigen object to a torch object, but I think that you can easily get the reverse function from this code.

Hope it helps!
A+

/jeremy

2 Likes

Hello all, I’d like to ask whether this issue has been resolved or not?

@999999999 the code from @jmaceiras works for me, and I think that’s a good solution. The one change I would make is to use torch::empty instead of torch::rand so you don’t have to compute random values that are immediately overwritten.

2 Likes

The default memory order of Eigen is ColMajor which each column is stored sequentially. But libtorch use row major so that data stores row by row. You need to use
Matrix<double, -1, -1, RowMajor>
to define a row major matrix.

2 Likes