1. Change the ordering from NUM_PARAMETERS, NUM_RESIDUALS to
NUM_RESIDUALS, NUM_PARAMETERS in docs and in code.
2. TinySolver::solve -> TinySolver::Solve
Change-Id: I4dca87b971fd9168f1200b53c362669cffc82c1b
Tiny solver is targeted towards small dense least square
solves, where the overhead of calling normal Ceres is too
high. For example, when solving for inverse camera
distortion for every pixel location in a many-megapixel
image. Anecdotally, at one point in the past, tiny solver
was ~20x faster than Ceres for the problems it's intended
for. This is due to two key aspects:
1. Memory is allocated up front: repeated solves incur no
allocation overhead beyond a few scalars on the stack.
2. The cost function is fully inlined into the solver
loop, removing even the cost function call overhead.
Tiny solver originated many years ago as part of
libmv/Blender, where it is still used for distortion solving
today, but the time has come for it to migrate into Ceres.
This commit is just the initial import into Ceres. Follow
up patches will add further cleanups, and add CostFunction
and Jet adapters to make it easier to call tiny solver
(though by using adapters, some performance advantages will
be lost).
Change-Id: I8079535cd41382b1e0ac0ca2fca141711c72b7f8
In case one has a small problem to solve, where
completion is reached within a few milliseconds,
then four decimal places are not enough to accurately
represent the timings of all the separate sub-steps.
Thus, we extend the reported timings to include
six decimal places.
Change-Id: Iaf88a94a1b8896ea7370c75b1de2f05d8671206e
This fixes a Windows specific issue where the
problem-summary reports timings as zero, as long as
the time difference in question is smaller than one
second.
Change-Id: Ibd91874294423af6acda2575eae80f01aabed6d3
Delete CostFunctions and LossFunctions when there are no more
ResidualBlocks referring to them. This is done by maintaining
a map with reference counts for CostFunctions and
LossFunctions.
The same maps are also used at the time of the destruction
of the ProblemImpl object itself. Previously vectors of these
objects were constructed, uniqed and the objects destroyed.
The update to the maps increases the cost of calling AddResidualBlock,
this has been mitigated, actually making AddResidualBlock faster, by
reusing a temporary vector rather than allocating one on the stack
every time.
Change-Id: I28b5287511713d28069ae428e2ff69224c0d03b4
There are platforms where OpenMP is not available. This
patch adds support for Intel Threading Building Blocks (TBB)
as an alternative threading backend.
Change-Id: I94497d7cba0c3cfaccfc992169236f17fe948ae9
- Previously the LAPACK option meant would Ceres link against LAPACK,
whether directly or indirectly via SuiteSparse (if SUITESPARSE=ON),
as such if LAPACK=OFF, the use of SuiteSparse was disabled, even if
it was found.
- To support the use-case of using a limited LAPACK implementation that
satisfies SuiteSparse’s requirements, but potentially not Ceres’ we
now adopt the more conventional terminology whereby the LAPACK option
refers only to whether Ceres itself will directly call LAPACK
routines, not whether it or any of its dependencies will.
- This means that the LAPACK and SUITESPARSE options are now
independent.
- Also unnecessary calls to find_package(BLAS), as find_package(LAPACK)
already searches for BLAS, and appends the resulting libraries to
LAPACK_LIBRARIES if they are found.
Change-Id: I9cf5fa5e4cb621812f6f0526db8d16a7a39c9c8f
The row, E, F block pattern 2, 4, 6 is a common one for
bundle adjustment with reprojection error (2 residuals),
homogeneous 3d points (4 params in the E-block), and camera
poses (3 rotation + 3 position = 6 params for the
F-block). This provides a major speedup for BA in the
TheiaSfM library and likely in other applications.
Change-Id: If5df8bfadc7f154856b74c3b38479c14856db47d
The JacobiSVD algorithm in Eigen does not accept fixed sized
matrices when performing a thin SVD. The assert enforcing this
is only triggered in non-Release builds.
So this change calls JacobiSVD with dynamically sized matrices
as a template parameter rather than a fixed size matrix.
https://github.com/ceres-solver/ceres-solver/issues/304#issuecomment-317965814
Thanks to @debalance for reporting this and @leokoppel for
providing a reproduction.
Change-Id: Ifc3d9ff20d5597f08c0f8573bf2fd99a3ed3d4d3
Skip the test in dynamic_sparsity_test when there are no sparse
linear algebra libraries available.
Also fix a minor typo in version_history.rst
Change-Id: Ie7cc14e655c58b6bd9625ce9f9025f94d0624d2d
1. Replace LineSearch::Summary::optimal_step_size with
LineSearch:Summary::optimal_point which is a FunctionSample.
2. Add the actual vector position and vector gradient of the
point in the FunctionSample
3. Use the above two to get rid of an extraneous function evalation
in LineSearchMinimizer.
Runtime performance is almost 2x improved as a result.
Thanks to @svenpilz for reporting this.
https://github.com/ceres-solver/ceres-solver/issues/296
Change-Id: Iebf2db7acecb2c95c9b1683b73cdc5faab78b02e
1. Move FunctionSample to its own .h/.cc files.
2. Migrate LineSearchFunction::Evaluate to use FunctionSample
for input and output.
Change-Id: I8bfb97e1900d95a4686c9621dda5b584458b45c0
We keep track of evaluator call and time statistics
via a hashmap containing magic strings. These strings
need to be consistent across the GradientProblemSolver
and Solver as the LineSearchMinimizer is used by both
of these solvers. Previously they were inconsistent
in a manner that GradientProblemSolver was not getting
information about the evaluation timing, and in the
process of fixing that I made it so that the TrustRegionMinimizer
when solving bounds constrained probelms will access/update
this information correctly.
So while I look for a more elegant solution, this CL
is meant to fix the inconsistency by making sure that the
same magic strings are used everywhere.
Change-Id: I120ca0bd1c2f77fde2db15edd9e33286a49dbae9
1. Fix a bug which was causing the cost and gradient evaluation
time to not be reported.
2. Add the number of times cost and gradients are evaluated to
the Summary object and to the output of FullReport.
Change-Id: Id0703cd2dafbf437f3e537fbdc30ae81d5f4f540
1. Remove unused variable.
2. Make inner_product_computer compatible with older versions of Eigen,
which don't have a named enum for Eigen::Upper/Lower.
Change-Id: I927af297f93fc74f7f4b29b39e400ef2d75edbd4
Remove outer product computation code from CompressedRowSparseMatrix.
In the process also remove the crsb_cols and crsb_rows vectors from
the matrix, which were added to carry the block sparsity of the matrix
so that the outer product could be computed fast.
InnerProductComputer and its reliance on BlockSparseMatrix has
rendered all of this code moot.
Change-Id: If3ee0dc8ad4ff79594fd1eebc15a647c4495d726
Despite its relative size, this is very significant change
to Ceres.
Why
===
Up till now, when the user chose SPARSE_NORMAL_CHOLESKY,
the Jacobian was evaluated in a CompressedRowSparseMatrix,
which was then use to compute the normal equations which were
passed to a sparse linear algebra library for factorization.
The reason to do this was because in the case of SuiteSparse,
we were able to pass the Jacobian matrix directly without
computing the normal equations and SuiteSparse/CHOLMOD did the
normal equation computation.
This turned out to be slow, so Cheng Wang implemented a high
performance version of the matrix-matrix multiply to compute
the normal equations, and all the sparse linear algebra libraries
now are passed the normal equations.
So that raises the question, as to what the best representation
of the Jacobian which is suitable for the normal equation computation.
Turns out BlockSparseMatrix is ideal. It brings two advantages.
1. Jacobian evaluation into a BlockSparseMatrix is considerably
faster when using a BlockSparseMatrix than
CompressedRowSparseMatrix. This is because we save on a bunch
of memory copies.
2. To make the matrix multiplication fast and use the block structure
Cheng Wang had to essentially make the CompressedRowSparseMatrix
carry a bunch of sidecar information about the block sparsity,
essentially making it behave like a BlockSparseMatrix. The resulting
code had fairly complicated indexing and complicated the semantics
of CompressedRowSparseMatrix. The new InnerProductComputer class
does away with all that and once this CL goes in, I will be able to
remove all that code and simplify the semantics of
CompressedRowSparseMatrix.
Changes
=======
1. Use InnerProductComputer in SparseNormalCholeskySolver.
2. Change the evaluator instantiated for SPARSE_NORMAL_CHOLESKY with
static sparsity inside evaluator.cc
3. The former change necessitates that we change ProblemImpl::Evaluate
to create the evaluate it needs on its own, because it was
depending on passing "SPARSE_NORMAL_CHOLESKY" as linear solver type
to the evaluator factor to get an Evaluator which can use
CompressedRowSparseMatrix objects for storing the Jacobian.
4. Update the tests for SparseNormalCholeskySolver.
5. Separate out the tests for DynamicSparseNormalCholeskySolver into its
own file.
Change-Id: I2ef7ef8fbfbb4967d0c1ec2068c1c778248fdf5b
Add a class that given a block sparse matrix m will compute
the product m'*m efficiently.
This code is refactoring and cleanup of the code in
CompressedRowSparseMatrix devoted to computing the inner product.
In that class, the code is mistakenly said to be computing
the outer product. It is also devoted to computing the inner
product of a CompressedRowSparseMatrix with itself.
This code works with BlockSparseMatrix objects instead, which
are simpler to deal with as they are better structured to handle
block sparse matrices.
Change-Id: I920fee1a396bb0fcae9e6f7e46a308c7391d21aa
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
It appears that interspersing ifdefs with macros causes problems
with Visual Studio. This patch changes the way we condition
the tests for dense linear solvers based on whether LAPACK is
available or not.
Change-Id: I306247496265c3551edad6bc8fcec9d4cf09e68d
1. Break up unsymmetric_linear_solver_test into
a. dense_linear_solver_test which covers DENSE_QR and
DENSE_NORMAL_CHOLESKY.
b. sparse_normal_cholesky_solver_test which covers
SPARSE_NORMAL_CHOLESKY.
2. dense_linear_solver_test has been completely re-written. It now
uses value parameterized tests for better logging. The number of
test problems as been increased to 2. Last but not the least
the actual test of correctness is not based on a golden solution
computed using another linear solver. We now compute the residual
and ensure that it is small.
https://github.com/ceres-solver/ceres-solver/issues/279
Change-Id: I9546a43e8ae85c31b2096a99405e47da326755ee
SchurComplementSolver implements a variant of ITERATIVE_SCHUR
when explicit_schur_complement is set to true. In this case
the SparseCholesky object should not be instantiated. Even
though there is no CPU cost, it can be the case that ITERATIVE_SCHUR
is being used when there are not sparse linear algebra libraries
are available, and this can result in a crash.
Change-Id: I349d5f79201782689b3ab0ccc2c5001804b44c7b
Parametric tests in gunit use tuple, which can be in the std::tr1
or the std namespaces depending on the version of STL one is using.
This change adds conditions the choice of namespace on whether
CXX11 mode is enabled or not.
It is entirely possible that we will have to come back and add
detection for this along the lines of shared_ptr.
Change-Id: I7fc85a32cf9f3f3bf30f86d9ba972ac67c6635fb
The code for creating and updating preconditioners has been pulled
out in into its own function for better readability.
Change-Id: I5335de3b158a8485cf6d052ee37d0d8fd57145e9
The addition of crsb_rows and crsb_cols to CompressedRowSparseMatrix
broke the build for problems with dynamic sparsity.
The fix is to remove unnecessarily filling of row_blocks and col_blocks,
which was triggering a check inside CompressedRowSparseMatrix around
block handling, since block structure makes no sense for matrices with
dynamic sparsity anyways.
Also added a test "dynamic_sparsity_test" based on i
examples/ellipse_approximation.cc
Thanks to Richard Stebbing for reporting this.
Change-Id: Ic1d49e97690ac17e0ea2949772271bd915277d68
SparseCholesky is an interface to sparse cholesky factorization
routines across sparse linear algebra libraries. Each sparse
linear algebra library is responsible for implementing its own
instance of this interface.
As a result the various places - SparseNormalCholeskySolver,
SparseSchurComplementSolver and VisibilityBasedPreconditioner
are significantly simplified.
Change-Id: I8b465705eae83bba9e1adfffcc741a05c70faf2e
1. Convert a CompressedRowSparseMatrix constructor which
takes a TripletSparseMatrix as input into a factory method
which allows the input to be transposed.
2. Move the random matrix creation routine for CompressedRowSparseMatrix
from being a standalone function to a static method.
3. Add a corresponding random matrix generation static method to
TripletSparseMatrix.
4. Add a new constructor to TripletSparseMatrix, which takes as input
the row, col and values arrays.
Change-Id: Iec7b184646818f432a5e6822bea3b2f3128a82aa