SPARSE_SCHUR + CX_SPARSE = Faster

There was a bug in the trust region preprocessor where no fill
reducing ordering was computed for the case of SPARSE_SCHUR + CX_SPARSE
but this was not signaled to SchurComplementSolver, so it was using
a naive/natural ordering. To fix this two changes are made:

1. TrustRegionProcessor's logic for signaling the ordering to the
   linear solver has been re-worked. The surrounding code has also
   been re-organized for better readability.
2. In SchurComplementSolver::SolveReducedSystem the row and column
   block structure has been added to the CompressedRowSparseMatrix
   containing the Schur complement so that block AMD can be used.

As a result of these changes the linear solve time for
problem-744-543562-pre.txt has been brought down from 58 seconds to
35 seconds.

Change-Id: I4d82efce05175260f97b1f925f8a1b4a9d650cae
This commit is contained in:
Sameer Agarwal
2017-06-20 09:09:05 -07:00
parent ef31944726
commit 1182fc2884
2 changed files with 35 additions and 19 deletions
@@ -337,6 +337,9 @@ LinearSolver::Summary SparseSchurComplementSolver::SolveReducedLinearSystem(
lhs->set_storage_type(CompressedRowSparseMatrix::LOWER_TRIANGULAR);
}
*lhs->mutable_col_blocks() = blocks_;
*lhs->mutable_row_blocks() = blocks_;
summary.num_iterations = 1;
summary.termination_type = sparse_cholesky_->FactorAndSolve(
lhs.get(), rhs(), solution, &summary.message);
+32 -19
View File
@@ -121,6 +121,7 @@ bool ReorderProgram(PreprocessedProblem* pp) {
&pp->error);
}
if (options.linear_solver_type == SPARSE_NORMAL_CHOLESKY &&
!options.dynamic_sparsity) {
return ReorderProgramForSparseNormalCholesky(
@@ -192,28 +193,40 @@ bool SetupLinearSolver(PreprocessedProblem* pp) {
options.use_explicit_schur_complement;
pp->linear_solver_options.dynamic_sparsity = options.dynamic_sparsity;
pp->linear_solver_options.num_threads = options.num_linear_solver_threads;
// Ignore user's postordering preferences and force it to be true if
// cholmod_camd is not available. This ensures that the linear
// solver does not assume that a fill-reducing pre-ordering has been
// done.
pp->linear_solver_options.use_postordering = options.use_postordering;
if (options.linear_solver_type == SPARSE_SCHUR &&
options.sparse_linear_algebra_library_type == SUITE_SPARSE &&
!SuiteSparse::IsConstrainedApproximateMinimumDegreeOrderingAvailable()) {
pp->linear_solver_options.use_postordering = true;
}
OrderingToGroupSizes(options.linear_solver_ordering.get(),
&pp->linear_solver_options.elimination_groups);
if (IsSchurType(pp->linear_solver_options.type)) {
OrderingToGroupSizes(options.linear_solver_ordering.get(),
&pp->linear_solver_options.elimination_groups);
// Schur type solvers expect at least two elimination groups. If
// there is only one elimination group, then it is guaranteed that
// this group only contains e_blocks. Thus we add a dummy
// elimination group with zero blocks in it.
if (IsSchurType(pp->linear_solver_options.type) &&
pp->linear_solver_options.elimination_groups.size() == 1) {
pp->linear_solver_options.elimination_groups.push_back(0);
// Schur type solvers expect at least two elimination groups. If
// there is only one elimination group, then it is guaranteed that
// this group only contains e_blocks. Thus we add a dummy
// elimination group with zero blocks in it.
if (pp->linear_solver_options.elimination_groups.size() == 1) {
pp->linear_solver_options.elimination_groups.push_back(0);
}
if (options.linear_solver_type == SPARSE_SCHUR) {
// When using SPARSE_SCHUR, we ignore the user's postordering
// preferences in certain cases.
//
// 1. SUITE_SPARSE is the sparse linear algebra library requested
// but cholmod_camd is not available.
// 2. CX_SPARSE is the sparse linear algebra library requested.
//
// This ensures that the linear solver does not assume that a
// fill-reducing pre-ordering has been done.
//
// TODO(sameeragarwal): Implement the reordering of parameter
// blocks for CX_SPARSE.
if ((options.sparse_linear_algebra_library_type == SUITE_SPARSE &&
!SuiteSparse::
IsConstrainedApproximateMinimumDegreeOrderingAvailable()) ||
(options.sparse_linear_algebra_library_type == CX_SPARSE)) {
pp->linear_solver_options.use_postordering = true;
}
}
}
pp->linear_solver.reset(LinearSolver::Create(pp->linear_solver_options));