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:
Cheng Wang
2017-03-07 14:57:23 -08:00
parent 0a50cd8244
commit 07dbf31eca
8 changed files with 515 additions and 100 deletions
+37 -11
View File
@@ -275,14 +275,21 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingEigen(
&event_logger);
}
// Compute outerproduct to compressed row lower triangular matrix.
// Eigen SimplicialLDLT default uses lower triangular part of matrix.
// This can change to upper triangular matrix if specifying
// Eigen::SimplicialLDLT< _MatrixType, _UpLo, _Ordering >
// with _UpLo = Upper.
const int stype = 1;
if (outer_product_.get() == NULL) {
outer_product_.reset(
CompressedRowSparseMatrix::CreateOuterProductMatrixAndProgram(
*A, &pattern_));
*A, stype, &pattern_));
}
CompressedRowSparseMatrix::ComputeOuterProduct(
*A, pattern_, outer_product_.get());
*A, stype, pattern_, outer_product_.get());
// Map to an upper triangular column major matrix.
//
@@ -362,20 +369,21 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingCXSparse(
summary.termination_type = LINEAR_SOLVER_SUCCESS;
summary.message = "Success.";
// Compute outerproduct to compressed row lower triangular matrix.
// CXSparse Cholesky factorization uses lower triangular part of the matrix.
const int stype = 1;
// Compute the normal equations. J'J delta = J'f and solve them
// using a sparse Cholesky factorization. Notice that when compared
// to SuiteSparse we have to explicitly compute the normal equations
// before they can be factorized. CHOLMOD/SuiteSparse on the other
// hand can just work off of Jt to compute the Cholesky
// factorization of the normal equations.
// using a sparse Cholesky factorization. Notice that we explicitly
// compute the normal equations before they can be factorized.
if (outer_product_.get() == NULL) {
outer_product_.reset(
CompressedRowSparseMatrix::CreateOuterProductMatrixAndProgram(
*A, &pattern_));
*A, stype, &pattern_));
}
CompressedRowSparseMatrix::ComputeOuterProduct(
*A, pattern_, outer_product_.get());
*A, stype, pattern_, outer_product_.get());
cs_di lhs =
cxsparse_.CreateSparseMatrixTransposeView(outer_product_.get());
@@ -431,8 +439,26 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingSuiteSparse(
summary.num_iterations = 1;
summary.message = "Success.";
// Compute outerproduct to compressed row upper triangular matrix.
// This is the fastest option for the our default natural ordering
// (see comment in cholmod_factorize.c:205 in SuiteSparse).
const int stype = -1;
// Compute the normal equations. J'J delta = J'f and solve them
// using a sparse Cholesky factorization. Notice that we explicitly
// compute the normal equations before they can be factorized.
if (outer_product_.get() == NULL) {
outer_product_.reset(
CompressedRowSparseMatrix::CreateOuterProductMatrixAndProgram(
*A, stype, &pattern_));
}
CompressedRowSparseMatrix::ComputeOuterProduct(
*A, stype, pattern_, outer_product_.get());
const int num_cols = A->num_cols();
cholmod_sparse lhs = ss_.CreateSparseMatrixTransposeView(A);
cholmod_sparse lhs =
ss_.CreateSparseMatrixTransposeView(outer_product_.get(), stype);
event_logger.AddEvent("Setup");
if (options_.dynamic_sparsity) {
@@ -443,7 +469,7 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingSuiteSparse(
if (options_.use_postordering) {
factor_ = ss_.BlockAnalyzeCholesky(&lhs,
A->col_blocks(),
A->row_blocks(),
A->col_blocks(),
&summary.message);
} else {
if (options_.dynamic_sparsity) {