populate sparse matrix with `insert` rather than `setFromTriplets`

About 5% speed improvement.
release/4.3a0
Gerry Chen 2021-01-19 20:56:18 -05:00
parent 9584860da0
commit b5951d033e
1 changed files with 11 additions and 3 deletions

View File

@ -39,14 +39,22 @@ SparseEigen sparseJacobianEigen(
const GaussianFactorGraph &gfg, const Ordering &ordering) { const GaussianFactorGraph &gfg, const Ordering &ordering) {
gttic_(SparseEigen_sparseJacobianEigen); gttic_(SparseEigen_sparseJacobianEigen);
// intermediate `entries` vector is kind of unavoidable due to how expensive // intermediate `entries` vector is kind of unavoidable due to how expensive
// factor->rows() is, which prevents us from populating SparseEigen directly // factor->rows() is, which prevents us from populating SparseEigen directly.
// Triplet is about 11% faster than boost tuple.
std::vector<Eigen::Triplet<double>> entries; std::vector<Eigen::Triplet<double>> entries;
entries.reserve(60 * gfg.size()); entries.reserve(60 * gfg.size());
size_t nrows, ncols; size_t nrows, ncols;
gfg.sparseJacobianInPlace(entries, ordering, nrows, ncols); gfg.sparseJacobianInPlace(entries, ordering, nrows, ncols);
// create sparse matrix // declare sparse matrix
SparseEigen Ab(nrows, ncols); SparseEigen Ab(nrows, ncols);
Ab.setFromTriplets(entries.begin(), entries.end()); // See Eigen::set_from_triplets. This is about 5% faster.
// pass 1: count the nnz per inner-vector
std::vector<int> nnz(ncols, 0);
for (const auto &entry : entries) nnz[entry.col()]++;
// pass 2: insert the elements
Ab.reserve(nnz);
for (const auto &entry : entries)
Ab.insert(entry.row(), entry.col()) = entry.value();
return Ab; return Ab;
} }