1. Rename it to small_blas_gemv_benchmark.cc to better reflect
its coverage.
2. Simplify the data generation.
3. Make the two vectors and the matrix in each element live in
separate arrays to ensure that they are not cache coherent.
4. Use "Apply" instead of ArgPair to simplify and unify the
matrix sizes.
5. Update the benchmark numbers and move them to a json
file in the benchmarks directory.
Change-Id: Iaf3764083f902258def739c4be42e0580be103cb
This is in preparation for adding support for a C++11 based parallel
for implementation. The code is behind CERES_USE_CXX11_THREADS which
is not exposed to the user yet.
Tested by building with and without CERES_USE_CXX11_THREADS defined
and the tests pass.
Change-Id: I60f5730fa055feeb0ee0fa6c980633aebd8d87b4
The key idea being, use some subset of the rows of the Jacobian
as the preconditioner.
This CL only implements the preconditioner assuming that the row
selection has already been done. How the rows are selected will be
left to the user based on their knowledge of the problem.
A follow up CL will hook this preconditioner into the rest of the
solver.
Change-Id: I3e18dc57811116534e9ddf35d7b154bcce496d3b
The bundle adjustment test is extremely slow to
run (especially in debug or fastbuild), and since
it is in one binary, there is no way to get CMake
or Bazel to parallelize the test execution.
This change divides the test into a single binary
for each configuration, making parallelized
execution possible.
In this patch, only the Bazel build is updated to
use the new test. The old test still exists to
retain parity with the CMake build. A followup
change will complete the process of adding
equivalent test execution to the CMake build.
Example build output:
% bazel test -c opt :all
INFO: Analysed 123 targets (15 packages loaded).
INFO: Found 2 targets and 121 test targets...
INFO: From Compiling external/com_github_google_glog/src/logging.cc:
external/com_github_google_glog/src/logging.cc: In static member function 'static void google::LogMessage::Fail()':
external/com_github_google_glog/src/logging.cc:1518:1: warning: 'noreturn' function does return
}
^
INFO: Elapsed time: 98.056s, Critical Path: 23.80s
INFO: Build completed successfully, 976 total actions
//:array_utils_test PASSED in 0.1s
//:autodiff_cost_function_test PASSED in 0.2s
//:autodiff_local_parameterization_test PASSED in 0.2s
//:autodiff_test PASSED in 0.1s
//:ba_denseschur_auto_test PASSED in 5.3s
//:ba_denseschur_auto_threads_test PASSED in 0.1s
//:ba_denseschur_user_test PASSED in 5.3s
//:ba_denseschur_user_threads_test PASSED in 0.1s
//:ba_iterschur_jacobi_auto_test PASSED in 6.2s
//:ba_iterschur_jacobi_auto_threads_test PASSED in 0.1s
//:ba_iterschur_jacobi_user_test PASSED in 6.0s
//:ba_iterschur_jacobi_user_threads_test PASSED in 0.2s
//:ba_iterschur_schurjacobi_auto_test PASSED in 6.1s
//:ba_iterschur_schurjacobi_auto_threads_test PASSED in 0.2s
//:ba_iterschur_schurjacobi_user_test PASSED in 5.7s
//:ba_iterschur_schurjacobi_user_threads_test PASSED in 0.1s
//:ba_iterschur_suitesparse_clustjacobi_auto_test PASSED in 0.1s
//:ba_iterschur_suitesparse_clustjacobi_auto_threads_test PASSED in 0.1s
//:ba_iterschur_suitesparse_clustjacobi_user_test PASSED in 0.1s
//:ba_iterschur_suitesparse_clustjacobi_user_threads_test PASSED in 0.1s
//:ba_iterschur_suitesparse_clusttri_auto_test PASSED in 0.1s
//:ba_iterschur_suitesparse_clusttri_auto_threads_test PASSED in 0.1s
//:ba_iterschur_suitesparse_clusttri_user_test PASSED in 0.1s
//:ba_iterschur_suitesparse_clusttri_user_threads_test PASSED in 0.1s
//:ba_sparsecholesky_cxsparse_auto_test PASSED in 0.2s
//:ba_sparsecholesky_cxsparse_auto_threads_test PASSED in 0.2s
//:ba_sparsecholesky_cxsparse_user_test PASSED in 0.1s
//:ba_sparsecholesky_cxsparse_user_threads_test PASSED in 0.1s
//:ba_sparsecholesky_eigensparse_auto_test PASSED in 0.1s
//:ba_sparsecholesky_eigensparse_auto_threads_test PASSED in 0.1s
//:ba_sparsecholesky_eigensparse_user_test PASSED in 0.2s
//:ba_sparsecholesky_eigensparse_user_threads_test PASSED in 0.1s
//:ba_sparsecholesky_suitesparse_auto_test PASSED in 0.1s
//:ba_sparsecholesky_suitesparse_auto_threads_test PASSED in 0.3s
//:ba_sparsecholesky_suitesparse_user_test PASSED in 0.1s
//:ba_sparsecholesky_suitesparse_user_threads_test PASSED in 0.2s
//:ba_sparseschur_cxsparse_auto_test PASSED in 0.1s
//:ba_sparseschur_cxsparse_auto_threads_test PASSED in 0.2s
//:ba_sparseschur_cxsparse_user_test PASSED in 0.1s
//:ba_sparseschur_cxsparse_user_threads_test PASSED in 0.2s
//:ba_sparseschur_eigensparse_auto_test PASSED in 0.2s
//:ba_sparseschur_eigensparse_auto_threads_test PASSED in 0.2s
//:ba_sparseschur_eigensparse_user_test PASSED in 0.1s
//:ba_sparseschur_eigensparse_user_threads_test PASSED in 0.2s
//:ba_sparseschur_suitesparse_auto_test PASSED in 0.3s
//:ba_sparseschur_suitesparse_auto_threads_test PASSED in 0.2s
//:ba_sparseschur_suitesparse_user_test PASSED in 0.2s
//:ba_sparseschur_suitesparse_user_threads_test PASSED in 0.2s
//:block_jacobi_preconditioner_test PASSED in 0.1s
//:block_random_access_dense_matrix_test PASSED in 0.2s
//:block_random_access_diagonal_matrix_test PASSED in 0.4s
//:block_random_access_sparse_matrix_test PASSED in 0.2s
//:block_sparse_matrix_test PASSED in 0.2s
//:c_api_test PASSED in 0.2s
//:canonical_views_clustering_test PASSED in 0.4s
//:compressed_col_sparse_matrix_utils_test PASSED in 0.3s
//:compressed_row_sparse_matrix_test PASSED in 0.3s
//:conditioned_cost_function_test PASSED in 0.2s
//:conjugate_gradients_solver_test PASSED in 0.2s
//:corrector_test PASSED in 0.2s
//:cost_function_to_functor_test PASSED in 0.1s
//:covariance_test PASSED in 0.1s
//:cubic_interpolation_test PASSED in 0.2s
//:dense_linear_solver_test PASSED in 0.1s
//:dense_sparse_matrix_test PASSED in 0.4s
//:detect_structure_test PASSED in 0.3s
//:dogleg_strategy_test PASSED in 0.4s
//:dynamic_autodiff_cost_function_test PASSED in 0.2s
//:dynamic_compressed_row_sparse_matrix_test PASSED in 0.2s
//:dynamic_numeric_diff_cost_function_test PASSED in 0.1s
//:dynamic_sparse_normal_cholesky_solver_test PASSED in 0.4s
//:dynamic_sparsity_test PASSED in 0.3s
//:evaluator_test PASSED in 0.2s
//:gradient_checker_test PASSED in 0.2s
//:gradient_checking_cost_function_test PASSED in 0.2s
//:gradient_problem_solver_test PASSED in 0.2s
//:gradient_problem_test PASSED in 0.4s
//:graph_algorithms_test PASSED in 0.4s
//:graph_test PASSED in 0.2s
//:householder_vector_test PASSED in 0.2s
//:implicit_schur_complement_test PASSED in 0.2s
//:inner_product_computer_test PASSED in 0.3s
//:invert_psd_matrix_test PASSED in 0.1s
//:is_close_test PASSED in 0.4s
//:iterative_schur_complement_solver_test PASSED in 0.3s
//:jet_test PASSED in 0.3s
//:levenberg_marquardt_strategy_test PASSED in 0.2s
//:line_search_minimizer_test PASSED in 0.2s
//:line_search_preprocessor_test PASSED in 0.1s
//:local_parameterization_test PASSED in 0.1s
//:loss_function_test PASSED in 0.1s
//:minimizer_test PASSED in 0.2s
//:normal_prior_test PASSED in 0.3s
//:numeric_diff_cost_function_test PASSED in 0.2s
//:ordered_groups_test PASSED in 0.2s
//:parameter_block_ordering_test PASSED in 0.2s
//:parameter_block_test PASSED in 0.1s
//:partitioned_matrix_view_test PASSED in 0.1s
//:polynomial_test PASSED in 0.1s
//:problem_test PASSED in 0.1s
//:program_test PASSED in 0.2s
//:reorder_program_test PASSED in 0.2s
//:residual_block_test PASSED in 0.2s
//:residual_block_utils_test PASSED in 0.2s
//:rotation_test PASSED in 7.1s
//:schur_complement_solver_test PASSED in 0.2s
//:schur_eliminator_test PASSED in 0.2s
//:single_linkage_clustering_test PASSED in 0.2s
//:small_blas_test PASSED in 0.2s
//:solver_test PASSED in 0.2s
//:sparse_cholesky_test PASSED in 0.2s
//:sparse_normal_cholesky_solver_test PASSED in 0.2s
//:system_test PASSED in 0.1s
//:tiny_solver_autodiff_function_test PASSED in 0.2s
//:tiny_solver_cost_function_adapter_test PASSED in 0.1s
//:tiny_solver_test PASSED in 0.1s
//:triplet_sparse_matrix_test PASSED in 0.2s
//:trust_region_minimizer_test PASSED in 0.2s
//:trust_region_preprocessor_test PASSED in 0.2s
//:visibility_based_preconditioner_test PASSED in 0.1s
//:visibility_test PASSED in 0.2s
Executed 121 out of 121 tests: 121 tests pass.
There were tests whose specified size is too big. Use the --test_verbose_timeout_warnings command line option to see which ones these are.
Change-Id: I32825f1e6278ba69dc296bb2dc05fb8ebda26592
This is in preparation for adding support for a c++11 based parallel
for implementation. The parallel for abstraction does not have the
ability to constrain the total number of threads in nested for loops.
This is solved by distributing the number of threads evenly between
the nested for loops. Adds a TODO to consolidate the next for loops
into a single loop that can be properly split between threads.
Tested by building with TBB and running tests.
Change-Id: I546973b9a4d19b9cdd53caff55d1c80bac8ea953
1. Replace two maps by 1.
2. Update number of calls and the time for the call at the cost
of a single map lookup.
3. Add Solver::Summary::num_linear_solves.
Fixes https://github.com/ceres-solver/ceres-solver/issues/340
Change-Id: I71eb9be7fb363a8cb066591c4c1761f256c81677
1. Fix a typo in auto_diff_cost_function.h
2. Fix and update Solver::Summary::FullReport() text labels.
3. Add logging of the number of residual and jacobian evaluations
to the full report. The GradientProblemSolver already does this.
Change-Id: I41059af5f0ebe0417accbbc30b0808a4b04b9edb
General clean up to the Ceres codebase to remove the functions
Evaluator::Evaluate and ProblemImpl::InternalEvaluate as they are unimplemented.
Change-Id: I77fcb2c5f43aeca69555e953d6472b6c4cd1b778
The non-linear least squares solver had the ability to update the
user's parameters every iteration. Now GradientProblemSolver can
do the same.
Also a few minor Sphinx markup related cleanup to the documentation
which were found in the process of updating Sphinx on my machine
and adding the docs for this feature.
This fixes https://github.com/ceres-solver/ceres-solver/issues/246
Change-Id: Ib6b90ac22be8bfb60b14f25ad52082ba371af164
- Update FindSuiteSparse to use FindTBB.cmake to find TBB.
- Fix logic handling of TBB=ON if TBB is not found to continue with
build after disabling TBB rather than throwing a fatal error.
- Use TBB_LIBRARIES instead of TBB_tbb_LIBRARY as a Ceres dependency,
the former also includes the TBB malloc library.
- Add warning message about GPL licensing if TBB version < 2017.
- Add ‘TBB’ & ‘Mulithreading’ component options to find_package(Ceres),
where ‘Mulithreading’ is equivalent to ‘TBB’ || ‘OpenMP’.
Change-Id: Ifc7f1d01b050ba6e2097ad1913b178805df4769a
Fixes the current implementation where the desired number of threads may
not be honored if another tbb::task_scheduler_init is instantiated. We
are using tbb::task_arena to solve this which is only available in newer
versions of TBB.
Also increases the performance by not creating/destroying the TBB setup
via tbb::task_scheduler_init on every iteration evaluation. This
increases the performance in single threaded mode using TBB by 10x.
By not specifically calling tbb::task_scheduler_init, this will either
respect any active tbb::task_scheduler_init instantiations or use the
default TBB settings which is hardware dependent. Ceres will honor the
user's requested number of threads through the task_arenas.
Tested via compiling with TBB enabled and ran the unit tests.
Change-Id: I5538407563449cdb5a0eaf8b8ccab62263912110
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