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
diff --git a/internal/ceres/schur_complement_solver.cc b/internal/ceres/schur_complement_solver.cc index 1a1becb..16470fd 100644 --- a/internal/ceres/schur_complement_solver.cc +++ b/internal/ceres/schur_complement_solver.cc
@@ -337,6 +337,9 @@ 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);
diff --git a/internal/ceres/trust_region_preprocessor.cc b/internal/ceres/trust_region_preprocessor.cc index 4020e4c..d3f912c 100644 --- a/internal/ceres/trust_region_preprocessor.cc +++ b/internal/ceres/trust_region_preprocessor.cc
@@ -121,6 +121,7 @@ &pp->error); } + if (options.linear_solver_type == SPARSE_NORMAL_CHOLESKY && !options.dynamic_sparsity) { return ReorderProgramForSparseNormalCholesky( @@ -192,28 +193,40 @@ 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));