mirror of
https://github.com/ceres-solver/ceres-solver.git
synced 2026-08-29 16:40:38 +08:00
Optimize J' * J in sparse_normal_cholesky_solver.
1. Add stype to the outerproduct computation to control the output matrix in upper or lower triangular matrix. For SuiteSparse, upper triangular matrix is generated. SuiteSparse can directly use this matrix format for cholesky without matrix transpose overhead. 2. Change the outerproduct computation to block multiplication. This reduces the computation complexity for the sort in preprocessing, also allows formulation of the block outerproduct computation as dense Eigen block matrix multiplication. 3. Solve 32 Tango problems on Qualcomm MSM8994 Cortex-A53 (1.55GHz) before change: 140 seconds after change: 131 seconds Change-Id: I8054114cef911de6a303310a448821ca296e4744
This commit is contained in:
@@ -89,6 +89,13 @@ class CompressedRowSparseMatrixTest : public ::testing::Test {
|
||||
vector<int>* col_blocks = crsm->mutable_col_blocks();
|
||||
col_blocks->resize(num_cols);
|
||||
std::fill(col_blocks->begin(), col_blocks->end(), 1);
|
||||
|
||||
// With all blocks of size 1, crsb_rows and crsb_cols are equivalent to
|
||||
// rows and cols.
|
||||
std::copy(crsm->rows(), crsm->rows() + crsm->num_rows() + 1,
|
||||
std::back_inserter(*crsm->mutable_crsb_rows()));
|
||||
std::copy(crsm->cols(), crsm->cols() + crsm->num_nonzeros(),
|
||||
std::back_inserter(*crsm->mutable_crsb_cols()));
|
||||
}
|
||||
|
||||
int num_rows;
|
||||
@@ -142,6 +149,9 @@ TEST_F(CompressedRowSparseMatrixTest, DeleteRows) {
|
||||
// Clear the row and column blocks as these are purely scalar tests.
|
||||
crsm->mutable_row_blocks()->clear();
|
||||
crsm->mutable_col_blocks()->clear();
|
||||
crsm->mutable_crsb_rows()->clear();
|
||||
crsm->mutable_crsb_cols()->clear();
|
||||
|
||||
for (int i = 0; i < num_rows; ++i) {
|
||||
tsm->Resize(num_rows - i, num_cols);
|
||||
crsm->DeleteRows(crsm->num_rows() - tsm->num_rows());
|
||||
@@ -153,6 +163,8 @@ TEST_F(CompressedRowSparseMatrixTest, AppendRows) {
|
||||
// Clear the row and column blocks as these are purely scalar tests.
|
||||
crsm->mutable_row_blocks()->clear();
|
||||
crsm->mutable_col_blocks()->clear();
|
||||
crsm->mutable_crsb_rows()->clear();
|
||||
crsm->mutable_crsb_cols()->clear();
|
||||
|
||||
for (int i = 0; i < num_rows; ++i) {
|
||||
TripletSparseMatrix tsm_appendage(*tsm);
|
||||
@@ -182,6 +194,9 @@ TEST_F(CompressedRowSparseMatrixTest, AppendAndDeleteBlockDiagonalMatrix) {
|
||||
const vector<int> pre_row_blocks = crsm->row_blocks();
|
||||
const vector<int> pre_col_blocks = crsm->col_blocks();
|
||||
|
||||
const vector<int> pre_crsb_rows = crsm->crsb_rows();
|
||||
const vector<int> pre_crsb_cols = crsm->crsb_cols();
|
||||
|
||||
scoped_ptr<CompressedRowSparseMatrix> appendage(
|
||||
CompressedRowSparseMatrix::CreateBlockDiagonalMatrix(
|
||||
diagonal.get(), row_and_column_blocks));
|
||||
@@ -202,9 +217,23 @@ TEST_F(CompressedRowSparseMatrixTest, AppendAndDeleteBlockDiagonalMatrix) {
|
||||
EXPECT_EQ(expected_row_blocks, crsm->row_blocks());
|
||||
EXPECT_EQ(expected_col_blocks, crsm->col_blocks());
|
||||
|
||||
EXPECT_EQ(crsm->crsb_cols().size(),
|
||||
pre_crsb_cols.size() + row_and_column_blocks.size());
|
||||
EXPECT_EQ(crsm->crsb_rows().size(),
|
||||
pre_crsb_rows.size() + row_and_column_blocks.size());
|
||||
for (int i = 0; i < row_and_column_blocks.size(); ++i) {
|
||||
EXPECT_EQ(crsm->crsb_rows()[i + pre_crsb_rows.size()],
|
||||
pre_crsb_rows.back() + i + 1);
|
||||
EXPECT_EQ(crsm->crsb_cols()[i + pre_crsb_cols.size()], i);
|
||||
}
|
||||
|
||||
crsm->DeleteRows(num_diagonal_rows);
|
||||
EXPECT_EQ(crsm->row_blocks(), pre_row_blocks);
|
||||
EXPECT_EQ(crsm->col_blocks(), pre_col_blocks);
|
||||
|
||||
EXPECT_EQ(crsm->crsb_rows(), pre_crsb_rows);
|
||||
EXPECT_EQ(crsm->crsb_cols(), pre_crsb_cols);
|
||||
|
||||
}
|
||||
|
||||
TEST_F(CompressedRowSparseMatrixTest, ToDenseMatrix) {
|
||||
@@ -357,6 +386,14 @@ TEST(CompressedRowSparseMatrix, Transpose) {
|
||||
matrix.mutable_col_blocks()->push_back(4);
|
||||
matrix.mutable_col_blocks()->push_back(2);
|
||||
|
||||
matrix.mutable_crsb_rows()->push_back(0);
|
||||
matrix.mutable_crsb_rows()->push_back(2);
|
||||
matrix.mutable_crsb_rows()->push_back(4);
|
||||
matrix.mutable_crsb_cols()->push_back(0);
|
||||
matrix.mutable_crsb_cols()->push_back(1);
|
||||
matrix.mutable_crsb_cols()->push_back(0);
|
||||
matrix.mutable_crsb_cols()->push_back(1);
|
||||
|
||||
rows[0] = 0;
|
||||
cols[0] = 1;
|
||||
cols[1] = 3;
|
||||
@@ -440,10 +477,16 @@ CompressedRowSparseMatrix* CreateRandomCompressedRowSparseMatrix(
|
||||
vector<int> cols;
|
||||
vector<double> values;
|
||||
|
||||
vector<int> crsb_rows;
|
||||
vector<int> crsb_cols;
|
||||
|
||||
while (values.size() == 0) {
|
||||
int row_block_begin = 0;
|
||||
crsb_rows.clear();
|
||||
crsb_cols.clear();
|
||||
for (int r = 0; r < options.num_row_blocks; ++r) {
|
||||
int col_block_begin = 0;
|
||||
crsb_rows.push_back(crsb_cols.size());
|
||||
for (int c = 0; c < options.num_col_blocks; ++c) {
|
||||
if (RandDouble() <= options.block_density) {
|
||||
for (int i = 0; i < row_blocks[r]; ++i) {
|
||||
@@ -453,11 +496,13 @@ CompressedRowSparseMatrix* CreateRandomCompressedRowSparseMatrix(
|
||||
values.push_back(RandNormal());
|
||||
}
|
||||
}
|
||||
crsb_cols.push_back(c);
|
||||
}
|
||||
col_block_begin += col_blocks[c];
|
||||
}
|
||||
row_block_begin += row_blocks[r];
|
||||
}
|
||||
crsb_rows.push_back(crsb_cols.size());
|
||||
}
|
||||
|
||||
const int num_rows = std::accumulate(row_blocks.begin(), row_blocks.end(), 0);
|
||||
@@ -472,6 +517,8 @@ CompressedRowSparseMatrix* CreateRandomCompressedRowSparseMatrix(
|
||||
CompressedRowSparseMatrix* matrix = new CompressedRowSparseMatrix(tsm);
|
||||
(*matrix->mutable_row_blocks()) = row_blocks;
|
||||
(*matrix->mutable_col_blocks()) = col_blocks;
|
||||
(*matrix->mutable_crsb_rows()) = crsb_rows;
|
||||
(*matrix->mutable_crsb_cols()) = crsb_cols;
|
||||
return matrix;
|
||||
}
|
||||
|
||||
@@ -534,11 +581,14 @@ TEST(CompressedRowSparseMatrix, ComputeOuterProduct) {
|
||||
cs_di* expected_outer_product =
|
||||
cxsparse.MatrixMatrixMultiply(&cs_matrix_transpose, cs_matrix);
|
||||
|
||||
// Use compressed row lower triangular matrix for cxsparse.
|
||||
const int stype = 1;
|
||||
vector<int> program;
|
||||
scoped_ptr<CompressedRowSparseMatrix> outer_product(
|
||||
CompressedRowSparseMatrix::CreateOuterProductMatrixAndProgram(
|
||||
*matrix, &program));
|
||||
*matrix, stype, &program));
|
||||
CompressedRowSparseMatrix::ComputeOuterProduct(*matrix,
|
||||
stype,
|
||||
program,
|
||||
outer_product.get());
|
||||
|
||||
@@ -556,6 +606,7 @@ TEST(CompressedRowSparseMatrix, ComputeOuterProduct) {
|
||||
expected_matrix.triangularView<Eigen::StrictlyLower>().setZero();
|
||||
|
||||
ToDenseMatrix(&actual_outer_product, &actual_matrix);
|
||||
actual_matrix.triangularView<Eigen::StrictlyLower>().setZero();
|
||||
const double diff_norm =
|
||||
(actual_matrix - expected_matrix).norm() / expected_matrix.norm();
|
||||
ASSERT_NEAR(diff_norm, 0.0, kTolerance)
|
||||
|
||||
Reference in New Issue
Block a user