Fix serialization for non-compressed matrices.

This commit is contained in:
Antonio Sánchez 2022-11-30 18:16:47 +00:00
parent 2260e11eb0
commit dcb042a87d
2 changed files with 39 additions and 28 deletions

View File

@ -694,6 +694,11 @@ class SparseMatrix
Base::operator=(other); Base::operator=(other);
} }
inline SparseMatrix(SparseMatrix&& other) : Base(), m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0)
{
*this = other.derived().markAsRValue();
}
/** Copy constructor (it performs a deep copy) */ /** Copy constructor (it performs a deep copy) */
inline SparseMatrix(const SparseMatrix& other) inline SparseMatrix(const SparseMatrix& other)
: Base(), m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0) : Base(), m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0)
@ -742,6 +747,7 @@ class SparseMatrix
internal::conditional_aligned_delete_auto<StorageIndex, true>(m_innerNonZeros, m_outerSize); internal::conditional_aligned_delete_auto<StorageIndex, true>(m_innerNonZeros, m_outerSize);
m_innerNonZeros = 0; m_innerNonZeros = 0;
} }
inline SparseMatrix& operator=(const SparseMatrix& other) inline SparseMatrix& operator=(const SparseMatrix& other)
{ {
if (other.isRValue()) if (other.isRValue())
@ -767,6 +773,10 @@ class SparseMatrix
return *this; return *this;
} }
inline SparseMatrix& operator=(SparseMatrix&& other) {
return *this = other.derived().markAsRValue();
}
#ifndef EIGEN_PARSED_BY_DOXYGEN #ifndef EIGEN_PARSED_BY_DOXYGEN
template<typename OtherDerived> template<typename OtherDerived>
inline SparseMatrix& operator=(const EigenBase<OtherDerived>& other) inline SparseMatrix& operator=(const EigenBase<OtherDerived>& other)
@ -1497,8 +1507,8 @@ struct evaluator<SparseMatrix<Scalar_,Options_,StorageIndex_> >
} }
// Specialization for SparseMatrix. // Specialization for SparseMatrix.
// Serializes [rows, cols, isCompressed, outerSize, numNonZeros, innerNonZeros, // Serializes [rows, cols, isCompressed, outerSize, innerBufferSize,
// outerIndices, innerIndices, values]. // innerNonZeros, outerIndices, innerIndices, values].
template <typename Scalar, int Options, typename StorageIndex> template <typename Scalar, int Options, typename StorageIndex>
class Serializer<SparseMatrix<Scalar, Options, StorageIndex>, void> { class Serializer<SparseMatrix<Scalar, Options, StorageIndex>, void> {
public: public:
@ -1509,19 +1519,19 @@ class Serializer<SparseMatrix<Scalar, Options, StorageIndex>, void> {
typename SparseMat::Index cols; typename SparseMat::Index cols;
bool compressed; bool compressed;
Index outer_size; Index outer_size;
Index num_non_zeros; Index inner_buffer_size;
}; };
EIGEN_DEVICE_FUNC size_t size(const SparseMat& value) const { EIGEN_DEVICE_FUNC size_t size(const SparseMat& value) const {
// innerNonZeros. // innerNonZeros.
std::size_t num_storage_indices = std::size_t num_storage_indices = value.isCompressed() ? 0 : value.outerSize();
value.isCompressed() ? 0 : value.outerSize();
// Outer indices. // Outer indices.
num_storage_indices += value.outerSize() + 1; num_storage_indices += value.outerSize() + 1;
// Inner indices. // Inner indices.
num_storage_indices += value.nonZeros(); const StorageIndex inner_buffer_size = value.outerIndexPtr()[value.outerSize()];
num_storage_indices += inner_buffer_size;
// Values. // Values.
std::size_t num_values = value.nonZeros(); std::size_t num_values = inner_buffer_size;
return sizeof(Header) + sizeof(Scalar) * num_values + return sizeof(Header) + sizeof(Scalar) * num_values +
sizeof(StorageIndex) * num_storage_indices; sizeof(StorageIndex) * num_storage_indices;
} }
@ -1533,30 +1543,30 @@ class Serializer<SparseMatrix<Scalar, Options, StorageIndex>, void> {
const size_t header_bytes = sizeof(Header); const size_t header_bytes = sizeof(Header);
Header header = {value.rows(), value.cols(), value.isCompressed(), Header header = {value.rows(), value.cols(), value.isCompressed(),
value.outerSize(), value.nonZeros()}; value.outerSize(), value.outerIndexPtr()[value.outerSize()]};
EIGEN_USING_STD(memcpy) EIGEN_USING_STD(memcpy)
memcpy(dest, &header, header_bytes); memcpy(dest, &header, header_bytes);
dest += header_bytes; dest += header_bytes;
// innerNonZeros. // innerNonZeros.
size_t data_bytes = sizeof(StorageIndex) * header.outer_size;
if (!header.compressed) { if (!header.compressed) {
std:size_t data_bytes = sizeof(StorageIndex) * header.outer_size;
memcpy(dest, value.innerNonZeroPtr(), data_bytes); memcpy(dest, value.innerNonZeroPtr(), data_bytes);
dest += data_bytes; dest += data_bytes;
} }
// Outer indices. // Outer indices.
data_bytes = sizeof(StorageIndex) * (header.outer_size + 1); std::size_t data_bytes = sizeof(StorageIndex) * (header.outer_size + 1);
memcpy(dest, value.outerIndexPtr(), data_bytes); memcpy(dest, value.outerIndexPtr(), data_bytes);
dest += data_bytes; dest += data_bytes;
// Inner indices. // Inner indices.
data_bytes = sizeof(StorageIndex) * header.num_non_zeros; data_bytes = sizeof(StorageIndex) * header.inner_buffer_size;
memcpy(dest, value.innerIndexPtr(), data_bytes); memcpy(dest, value.innerIndexPtr(), data_bytes);
dest += data_bytes; dest += data_bytes;
// Values. // Values.
data_bytes = sizeof(Scalar) * header.num_non_zeros; data_bytes = sizeof(Scalar) * header.inner_buffer_size;
memcpy(dest, value.valuePtr(), data_bytes); memcpy(dest, value.valuePtr(), data_bytes);
dest += data_bytes; dest += data_bytes;
@ -1577,37 +1587,38 @@ class Serializer<SparseMatrix<Scalar, Options, StorageIndex>, void> {
value.setZero(); value.setZero();
value.resize(header.rows, header.cols); value.resize(header.rows, header.cols);
// Initialize compressed state and inner non-zeros.
size_t data_bytes = sizeof(StorageIndex) * header.outer_size;
if (EIGEN_PREDICT_FALSE(src + data_bytes > end)) return nullptr;
if (header.compressed) { if (header.compressed) {
value.makeCompressed(); value.makeCompressed();
value.resizeNonZeros(header.num_non_zeros);
} else { } else {
// Temporarily load inner sizes, then reserve.
std::vector<StorageIndex> inner_sizes(header.outer_size);
memcpy(inner_sizes.data(), src, data_bytes);
src += data_bytes;
value.uncompress(); value.uncompress();
value.reserve(inner_sizes); }
memcpy(value.innerNonZeroPtr(), inner_sizes.data(), data_bytes);
// Adjust value ptr size.
value.data().resize(header.inner_buffer_size);
// Initialize compressed state and inner non-zeros.
if (!header.compressed) {
// Inner non-zero counts.
std::size_t data_bytes = sizeof(StorageIndex) * header.outer_size;
if (EIGEN_PREDICT_FALSE(src + data_bytes > end)) return nullptr;
memcpy(value.innerNonZeroPtr(), src, data_bytes);
src += data_bytes;
} }
// Outer indices. // Outer indices.
data_bytes = sizeof(StorageIndex) * (header.outer_size + 1); std::size_t data_bytes = sizeof(StorageIndex) * (header.outer_size + 1);
if (EIGEN_PREDICT_FALSE(src + data_bytes > end)) return nullptr;
memcpy(value.outerIndexPtr(), src, data_bytes); memcpy(value.outerIndexPtr(), src, data_bytes);
src += data_bytes; src += data_bytes;
// Inner indices. // Inner indices.
data_bytes = sizeof(StorageIndex) * header.num_non_zeros; data_bytes = sizeof(StorageIndex) * header.inner_buffer_size;
if (EIGEN_PREDICT_FALSE(src + data_bytes > end)) return nullptr; if (EIGEN_PREDICT_FALSE(src + data_bytes > end)) return nullptr;
memcpy(value.innerIndexPtr(), src, data_bytes); memcpy(value.innerIndexPtr(), src, data_bytes);
src += data_bytes; src += data_bytes;
// Values. // Values.
data_bytes = sizeof(Scalar) * header.num_non_zeros; data_bytes = sizeof(Scalar) * header.inner_buffer_size;
if (EIGEN_PREDICT_FALSE(src + data_bytes > end)) return nullptr; if (EIGEN_PREDICT_FALSE(src + data_bytes > end)) return nullptr;
memcpy(value.valuePtr(), src, data_bytes); memcpy(value.valuePtr(), src, data_bytes);
src += data_bytes; src += data_bytes;

View File

@ -30,7 +30,7 @@ struct RandomImpl<Eigen::SparseMatrix<Scalar, Options, DenseIndex>> {
double density = 0.1; double density = 0.1;
// Reserve some space along each inner dim. // Reserve some space along each inner dim.
int nnz = static_cast<int>(density * 1.5 * M.innerSize()); int nnz = static_cast<int>(std::ceil(density * 1.5 * M.innerSize()));
M.reserve(Eigen::VectorXi::Constant(M.outerSize(), nnz)); M.reserve(Eigen::VectorXi::Constant(M.outerSize(), nnz));
for (int j = 0; j < M.outerSize(); j++) { for (int j = 0; j < M.outerSize(); j++) {