Zero-copy construction of an Eigen SparseMatrix

2019-07-06 04:27发布

问题:

I have the following problem:

I have an Eigen::SparseMatrix I need to send over the network, and my network library only supports sending arrays of primitive types.

I can retrieve the pointers to the backing arrays of my SparseMatrix by doing something like (here's the backing object's code):

// Get pointers to the indices and values, send data over the network
int num_items = sparse_matrix.nonZeros()
auto values_ptr = sparse_matrix.data().valuePtr()
auto index_ptr = sparse_matrix.data().indexPtr()

network_lib::send(values_ptr, num_items)
network_lib::send(index_ptr, 2 * num_items) // Times two b/c we have 2 indices per value

Now on the other side I have access to these two arrays. But AFAIK there is no way to create a SparseArray without copying all the data into a new SparseMatrix (see docs for construction).

I'd like to do something like:

Eigen::SparseMatrix<float> zero_copy_matrix(num_rows, num_cols);
zero_copy_matrix.data().valuePtr() = received_values_ptr;
zero_copy_matrix.data().indexPtr() = received_index_ptr;

But this throws a compiler error:

error: lvalue required as left operand of assignment zero_copy_matrix.data().valuePtr() = received_values_ptr;

Any idea on how we could zero-copy construct a sparse Eigen matrix from existing arrays of indexes and data?

Another approach I tried that didn't work (this is local, no communication):

zero_copy_matrix.reserve(num_non_zeros);
zero_copy_matrix.data().swap(original_matrix.data());

When I try to print out the zero_copy_matrix it has no values in it.

回答1:

After digging around I think a good option for me would be to use an Eigen::Map<Eigen::SparseMatrix<float>> as such:

Eigen::Map<Eigen::SparseMatrix<float>> sparse_map(num_rows, num_cols, num_non_zeros,
                             original_outer_index_ptr, original_inner_index_ptr,
                             original_values_ptr);

AFAIK, this should be zero-copy. Answer from here.