79 Commits

Author SHA1 Message Date
Sameer Agarwal 42475eec77 Use absl::btree_map instead of std::map
Change-Id: Iece280a6cb0f37fa0bc572046b9d7f79ca825ebc
2024-09-17 12:18:31 -07:00
Sameer Agarwal b97ffeadbb Use absl::time
Replace WallTimeInSeconds with absl::Now and use
absl::Time and absl::Duration objects instead of doubles.

wall_time.h/cc -> event_logger.h/cc

Change-Id: I41279961368840fbdf6bb3456ffdbdf2f9bfb85b
2024-08-08 07:18:44 -07:00
Sameer Agarwal 57e26182f3 Add more missing headers
Change-Id: I35875ca856b7b80c622562a1c14b4c8ced10f740
2024-07-18 11:37:07 -07:00
Yuriy Chernyshov 1f2e6313a5 Add missing std qualifiers
Change-Id: Ib7bc432c56f7a8ba062a6d74a206733872c3d089
2024-04-22 17:20:54 +00:00
Sameer Agarwal 5a30cae583 Preparing for 2.2.0rc1
1. Add a version history
2. Update copyright years across the code base
3. Run format_all.sh
4. Update version strings from 2.1.0 to 2.2.0 in the docs and
   elsewhere.

Change-Id: I46d8d479d54bd6002d532785e67342106e73c9ac
2023-09-21 11:23:38 -07:00
Dmitriy Korchemkin 77ad8bb4e5 Change storage in BlockRandomAccessSparseMatrix
- TripletSparseMatrix in BlockRandomAccessSparseMatrix is replaced with
   BlockSparseMatrix
 - BlockSparseMatrix::ToCompressedRowSparseMatrix is performed in a
   direct sort-less way

Change-Id: Ib951fda1b9394050e2c47a9721172c5e3c674801
2023-04-18 01:34:30 +03:00
Sameer Agarwal 9602ed7b76 ClangFormat changes
Change-Id: I88c9e38b0450aed26c60e1dd54964ab6571e3eef
2023-01-14 05:54:24 -08:00
Alexander Ivanov f1113c08ab Commenting unused parameters for better readibility
Change-Id: Idc285fa68ba787636a69a3ea3350e0282b9f8569
2023-01-12 17:25:42 +00:00
Sameer Agarwal 19ab2c1793 BlockRandomAccessMatrix Refactor
1. Add threading to all three subclasses of BlockRandomAccessMatrix.
   i.e. BlockRandomAccessDenseMatrix, BlockRandomAccessSparseMatrix
   and BlockRandomAccessDenseMatrix.

   For BlockRandomAccessDenseMatrix and BlockRandomAccessSparseMatrix
   this just means SetZero is parallelized. Which by itself is no
   big deal, but by doing so, the constructor for all three subclasses
   become uniform.

   BlockRandomAccessSparseMatrix::SymmetricRightMultiplyAndAccumulate
   maybe threaded in the future if needed.

   BlockRandomAccessDiagonalMatrix is the biggest beneficiary. SetZero
   Invert and RightMultiplyAndAccumulate are all threaded now.

2. Change the storage in BlockRandomAccessDiagonalMatrix from
   TripletSparseMatrix to CompressedRowSparseMatrix. This has no
   performance implications since we do not really use the capabilities
   of the underlying matrix indexing representation. This is a forward
   looking change when we decide to transfer this matrix to the GPU,
   a CompressedRowSparseMatrix will save on a data conversion.

3. Use std::unique_ptr as needed and eliminate the need for custom
   destructors.

4. Modify CompressedRowSparseMatrix::CreateBlockDiagonalMatrix to
   take a nullptr as the data vector.

Fixes https://github.com/ceres-solver/ceres-solver/issues/936
Fixes https://github.com/ceres-solver/ceres-solver/issues/935

Change-Id: Ia6487f2d924fbe669835bdcc38abf2b451bda4ee
2022-12-23 06:45:28 -08:00
Sameer Agarwal e9e9957401 ClangTidy fixes
Change-Id: Ifc6adb4d6e78668d25d2f06043e0f0d766acdc05
2022-09-12 16:20:30 -07:00
Sameer Agarwal f86a3bdbea Unify Block handling across matrix types
Previously some matrices used Block to keep track of
row/column block sizes and some would just use ints, and
then compute the position of each row and column from it.

By uniformly using Block everywhere, we reduce duplicate
computation and data copies.

I also cleaned up a bunch of c++17 related stuff as I edited
these files.

Change-Id: I4c86b1593fd4c91f9057fbb38314f62f303e0477
2022-09-11 07:31:28 -07:00
Joydeep Biswas 829089053e CUDA CGNR, Part 4: CudaCgnrSolver
* Added CudaCgnrSolver, a new CUDA-accelerated CGNR.
* To use CudaCgnrSolver, the user must select CGNR as the linear_solver
  and CUDA_SPARSE as the sparse_linear_algebra_library.
* Updated ConjugateGradientSolver to work with an array of pointers to
  scratch to support CudaVectors as scratch.
* Moved CUDA initialization to run in Solver::Solve as needed.

Some performance comparisons on an Ubuntu 20.04 desktop with an
Intel i9-9940X CPU @ 3.30GHz, and an nVidia Quadro RTX 6000,
all configurations run with 24 threads, and 10 iterations.

=================================================
CGNR + CUDA_SPARSE + IDENTITY Preconditioner
problem-1778-993923-pre.txt
=================================================
Cost:
Initial                          2.563973e+08
Final                            1.724755e+06
Change                           2.546725e+08

Minimizer iterations                       11
Successful steps                            7
Unsuccessful steps                          4

Time (in seconds):
Preprocessor                         4.020158

  Residual only evaluation           1.567092 (10)
  Jacobian & residual evaluation     7.847130 (7)
  Linear solver                     31.688898 (10)
Minimizer                           46.834987

Postprocessor                        0.353974
Total                               51.209120

=================================================
SPARSE_SCHUR (CPU) + SUITE_SPARSE + AMD
problem-1778-993923-pre.txt
=================================================
Cost:
Initial                          2.563973e+08
Final                            1.651617e+06
Change                           2.547457e+08

Minimizer iterations                       11
Successful steps                           11
Unsuccessful steps                          0

Time (in seconds):
Preprocessor                        35.812003

  Residual only evaluation           1.658980 (10)
  Jacobian & residual evaluation    12.218799 (11)
  Linear solver                     76.409992 (10)
Minimizer                           98.809773

Postprocessor                        0.372712
Total                              134.994489

=================================================
ITERATIVE_SCHUR (CPU) + JACOBI Preconditioner
problem-1778-993923-pre.txt
=================================================
Cost:
Initial                          2.563973e+08
Final                            1.684447e+06
Change                           2.547128e+08

Minimizer iterations                       11
Successful steps                            8
Unsuccessful steps                          3

Time (in seconds):
Preprocessor                        15.331614

  Residual only evaluation           1.606114 (10)
  Jacobian & residual evaluation     8.502166 (8)
  Linear solver                    351.910080 (10)
Minimizer                          368.797327

Postprocessor                        0.363536
Total                              384.492478

=================================================
CGNR + CUDA_SPARSE + IDENTITY Preconditioner
problem-13682-4456117-pre.txt
=================================================
Cost:
Initial                          1.126372e+09
Final                            2.269329e+07
Change                           1.103678e+09

Minimizer iterations                       11
Successful steps                            7
Unsuccessful steps                          4

Time (in seconds):
Preprocessor                        19.140087

  Residual only evaluation           8.721920 (10)
  Jacobian & residual evaluation    41.955923 (7)
  Linear solver                    214.121861 (10)
Minimizer                          296.636890

Postprocessor                        1.971827
Total                              317.748804

Change-Id: I3a09f31aa6903f661e91f595afd39d427583e856
2022-08-15 23:44:34 -05:00
Sergiu Deitsch 242fc07959 Remove unnecessary destructors
Change-Id: I1d1cc9b15606955ee1d99d2f81585f118bc92aef
2022-08-13 20:34:52 +00:00
Sergiu Deitsch 9c968d4066 Silence Clang warning
Clang emits the following warning:

internal/ceres/schur_complement_solver.cc:71:51: warning: class with destructor marked 'final' cannot be inherited from [-Wfinal-dtor-non-final-class]
  virtual ~BlockRandomAccessSparseMatrixAdapter() final {}

Change-Id: I9da96711fd1e924ce8504988ff171cb476b6222f
2022-08-13 21:32:11 +02:00
Sameer Agarwal 7b0bb0e3f5 ClangTidy cleanups
Change-Id: I514ca5fd91c08866b412021e6c0f5d6f97c4bf8f
2022-08-12 21:49:02 -07:00
Sameer Agarwal 04899645cc LinearOperator::FooMultiply -> LinearOperator::FooMultiplyAndAccumulate
These methods were historically poorly named and every time I read code
I get confused whether they are just multiplying or multiplying and
adding. Clarifying them also gives us the changce to introduce
RightMultiply and LeftMultiply methods in the base class which will
simplify a number call sites in a subsequent CL.

Fixes https://github.com/ceres-solver/ceres-solver/issues/855

Change-Id: Ice4fb483f1acd02527a6dd753ef0c5a66037f4b0
2022-08-10 10:03:03 -07:00
Sameer Agarwal 288a3fde6b Add missing virtual destructors to matrix adapters
Change-Id: Ieb0e67fbc9042410a6ae63e7cf0f96cc90603829
2022-08-09 22:16:38 -07:00
Sameer Agarwal 1da72ac39e Refactor ConjugateGradientsSolver
1. Convert it from a class to a template function. Where the
   template parameter is "DenseVectorType". This allows us
   to have a single implementation of Conjugate Gradients
   without worrying about where the matrix and the vectors
   are stored or what their internal representation is.

   For the case of CPU based vectors, we abstract operations
   on Eigen vectors using eigen_vector_ops.
2. Introduce ConjugateGradientsLinearOperator which is
   templated on DenseVectorType. It is the matrix vector
   multiplication abstraction.
3. Port the tests and all usages of ConjugateGradientsSolver
   to this new implementation.
4. Introduce Eigen::Vector based RightMultiply and LeftMultiply
   methods into LinearOperator which by default delete to the
   bare pointer based interfaces.
5. Add an identity preconditioner.

These changes are being made in preparation for adding a CUDA
based CGNR solver.

Change-Id: I9da36dc6c131856dd1a4aa7e645aaf12d25dd79b
2022-08-09 13:33:08 +00:00
Sameer Agarwal c8493fc366 Convert internal enums to be class enums.
Change-Id: Ide89c7115c3b12c0f2452a2969dc5523b3a7970f
2022-05-16 12:47:15 -07:00
Sameer Agarwal caf614a6c1 Modernize code using c++17 constructs
Mostly done using

find . \( -name '*.cc' -o -name '*.h' \) -a -type f -exec clang-tidy -p \
cmake-build -checks='-*,google-*,modernize-*,-modernize-use-nodiscard,-modernize-use-trailing-return-type' {} -fix \;

Change-Id: Ifccbcabe7a1d9a32a09d28ac4f3f8466696c1a50
2022-04-22 06:11:18 -07:00
Sergiu Deitsch c8658c8992 Modernize more
Apply clang-tidy Google and modernize fixes without trailing return type
using:

$ clang-tidy -p <build-dir> \
  -checks='-*,google-*,modernize-*,-modernize-use-trailing-return-type' {} -fix

Change-Id: I7450cc58ea9abf928f73a467e87876083217fa26
2022-02-26 22:16:56 +00:00
Sameer Agarwal 84e1696f4e Add final specifier to internal classes.
This should help the compiler devirtualize a bunch of function
calls.

https://github.com/ceres-solver/ceres-solver/issues/747

Change-Id: I9913e68d85e0e9c9f955a249cc710a657875c869
2022-02-18 18:07:06 +00:00
Sergiu Deitsch c14f360e63 Drop trivial special members
Do not define trivial constructors or destructors unless necessary
(e.g., for implementing pimpl) following the rule of zero. Define
virtual base class destructors out-of-line to avoid emitting vtables in
every translation unit.

Change-Id: Iea2d8978e62a8ee5a97b86cbb4e858d56e0fb274
2022-02-09 21:30:14 +01:00
Sameer Agarwal ae65219e04 ClangTidy cleanups
1. NULL -> nullptr
2. foo.reset(new Bar) -> = foo = std::make_unique<Bar>()
3. Missing std library includes & prefixes

Change-Id: I260b261b484554be681ee5a7398126fdb3b3a789
2022-02-09 10:06:49 -08:00
Sergiu Deitsch a35bd1bf90 Use = default for trivial special members
Applied changes correspond to clang-tidy fixes
stemming from the modernize-use-equals-default check.

Change-Id: I254b0908a76d464131564b637cd0e42a6b03fb5a
2022-02-09 18:38:52 +01:00
Sergiu Deitsch 484d3414e4 Replace virtual keyword by override
virtual can be ambiguous. Applied changes correspond to clang-tidy fixes
stemming from the modernize-use-override check.

Change-Id: I973afd4680a5df587419777504aeb94467196b89
2022-02-09 00:34:05 +01:00
Sameer Agarwal 2092a720ec Fix some nits.
Change-Id: I1af74d6ae8c6c368642989f1b1e857999264a454
2022-02-08 13:40:39 -08:00
Sameer Agarwal 408af7b1a8 Move the constructor and destructor for SchurComplementSolver
Change-Id: I277778d039b6acfe03e0c46f91bd71673f215345
2022-02-07 06:39:47 -08:00
Sameer Agarwal d51672d1cc Move the constructor and destructor for DenseSchurComplementSolver
Change-Id: I8d852c3e6af28d6d70742f0d1607154d47bec9bd
2022-02-07 06:26:07 -08:00
Sameer Agarwal 6d06e9b98f Add DenseCholesky
Like SparseCholesky, the DenseCholesky interface abstracts
away the solution of dense linear systems using Cholesky factorization.
This allows the client code to not worry about the type of dense
linear algebra library being used.

DenseNormalCholeskySolver and DenseSchurComplementSolver code
is considerably simpler as a result.

Change-Id: Ie15f09ee376d5f9a64609e6a55ad83e99c76352a
2022-01-23 09:00:36 -08:00
Nikolaus Demmel 7b8f675bfd fix formatting for (non-generated) internal source files
- Change formatting standard to Cpp11. Main difference is not having
  the space between two closing >> for nested templates. We don't
  choose c++14, because older versions of clang-format (version 9
  and earlier) don't know this value yet, and it doesn't make a
  difference in the formatting.
- Apply clang-format to all (non generated) internal source files.
- Manually fix some code sections (clang-format on/off) and c-strings
- Exclude some embedded external files with very different formatting
  (gtest/gmock)
- Add script to format all source files

Change-Id: Ic6cea41575ad6e37c9e136dbce176b0d505dc44d
2020-09-21 02:52:07 +02:00
Sameer Agarwal 667062dcc8 Introduce BlockSparseMatrixData
A number of algorithms like the SchurEliminator do not need
access to the full BlockSparseMatrix interface. They only
need read only access to the values array and the block structure.

This change introduces, BlockSparseDataMatrix a struct that carries
these two bits of information and modifies the Schur type algorithms
to use it.

What this change will allow us to do, in a subsequent CL is to
take the values array of a BlockSparseMatrix and pair it with
a different blocks structure for subset preconditioning.

Change-Id: I1808f12531b586c9ff4d6a70b3d390c7b0d9f441
2019-09-24 06:53:30 -07:00
Sameer Agarwal be15b842a7 Integrate the SchurEliminatorForOneFBlock for the case <2,3,6>
Also run clang-format on schur_complement_solver.cc.

A more elaborate integration is not done, because it will cause
binary bloat.

Change-Id: Idf4e9e1794f7401a39f05fb145ec06459209a1e1
2019-08-06 16:34:47 +00:00
Sameer Agarwal 2ffddaccfe Use override & final instead of just using virtual.
This is safer than using virtual and this lead to a minor
bug fixes.

Change-Id: Id69cb1cc569bf6bf245f22f029c7871b6c712568
2019-07-25 16:29:14 -07:00
Kuang Fangjun 189f0c2f6e fix typos.
Change-Id: I9255d3c6cc0604b227ddfe065c2cdb770dceaf5c
2018-09-23 10:56:34 +08:00
Sameer Agarwal 94712db5c7 Convert calls to CHECK_NOTNULL to CHECK.
CHECK_NOTNULL is being deprecated and removed from the
glog library.

Change-Id: I4a6d1eec6e82a768c7861c8f776bf1f9c0b50c74
2018-08-28 08:14:19 -07:00
Sameer Agarwal f973e107d2 Enable mixed precision solves.
1. Add Solver::Options::use_mixed_precision_solves,
   and Solver::Options::max_num_refinement_iterations.
2. Make SparseCholesky::Create return a unique_ptr.
3. SparseCholesky::Create now takes LinearSolver::Options
   as an argument.
4. IterativeRefiner's constructor does not require num_cols
   as an argument.
5. SparseNormalCholeskySolver now uses a separate rhs vector.

This basic implementation results in a 10% reduction in solver time
and 30% reduction in linear solver memory usage.

Change-Id: I6830f32cae2febf082d2733262eb2c9f0482b0ea
2018-04-10 11:01:38 -07:00
Sameer Agarwal e49507cbea More C++ification.
"> >" -> ">>"
"> > >" -> ">>>"

Change-Id: Id1ddd9dbf030fe21d57207741b4ca8403068e55b
2018-04-03 10:58:15 -07:00
Keir Mierle 7c4e8a454e Replace scoped_ptr with C++11's unique_ptr
Change-Id: Ib5a504c491e3a79af52a95accf009df473470c6b
2018-04-02 14:47:47 -07:00
Sameer Agarwal 1182fc2884 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
2017-06-20 09:13:02 -07:00
Sameer Agarwal 99aca60b2c Do not create a SparseCholesky object when not needed.
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
2017-06-02 11:08:11 -07:00
Sameer Agarwal 29c21f5680 Add SparseCholesky
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
2017-05-24 00:00:25 -07:00
Sameer Agarwal 086ff01aca Matrix generation cleanup
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
2017-05-01 22:53:21 -07:00
Sameer Agarwal 0859fe8a57 Integrate InvertPSDMatrix into the SchurEliminator.
SchurEliminator::Init now takes a bool that tells it whether
it can assume that the diagonal blocks it is inverting can
be assumed to be full rank or not.

This information is then passed onto InvertPSDMatrix.

Change-Id: I26037b6233f2aad5584fed245f631c3959928afe
2017-04-25 10:08:45 -07:00
Sameer Agarwal ed32e6a44a Add logging for sparse Cholesky factorization using Eigen
Print information about the fill-in when using Eigen to perform
Simplicial sparse Cholesky factorization.

Change-Id: I09013b7f4ed2f6c55ae8ce8922447e23d63580a8
2015-12-17 20:22:48 +00:00
Sameer Agarwal e712ce1810 Revert 81219ff.
Eigen upstream was broken a little while ago, and it seemed to be
the case that we needed a fix for using the LLT factorization on
ARM.

This has been fixed and AFAIK there are no stable eigen releases
with this bug in it.

For full gore, see

http://eigen.tuxfamily.org/bz/show_bug.cgi?id=992

In light of the fix, the extra layer of indirection introduced earlier
is not needed and we are reverting to normal programming.

Change-Id: I16929d2145253b38339b573b27b6b8fabd523704
2015-04-07 14:13:25 -07:00
Sameer Agarwal 81219fff78 Allow using Eigen's LDLT factorization instead of LLT factorization
It seems that Eigen's LLT factorization is broken on ARM.
This patch enables the use of LDLT factorization instead of LLT
factorization. The switch is controlled at compile time using a
preprocessor define - CERES_USE_EIGEN_LDLT.

By default we continue to use LLT factorization though.

To make the switching easier without introducing the Cholesky factorization
based inversion and linear system solve routines have been abstracted into
two new functions.

Android.mk has been updated to enable the LDLT factorization, but
the cmake file has not been updated as I will leave it to Alex's
capable hands to do proper detection of ARM as a target platform.

Change-Id: Iffe3abd2ce894de2a388b454df3da909b482d5e5
2015-04-05 22:50:41 -07:00
Keir Mierle 7492b0d8de Update copyright headers with new year and URL
Since Ceres is moving to using GitHub for issues, and the Google
Code URL in the current copyright header will soon become invalid,
update all the headers.

Change-Id: I1fce70375d1bcf098591f07b4d8f01a5c1e0789c
2015-03-18 05:43:23 +00:00
Sameer Agarwal bcc865f81c Remove using namespace std;
For historical reasons we had a "using namespace std;" in port.h. This
is generally a bad idea. So removing it and along the way doing a bunch
of cpplint cleanup.

Change-Id: Ia125601a55ae62695e247fb0250df4c6f86c46c6
2015-01-07 14:26:53 -08:00
Sameer Agarwal b44cfdef25 Let ITERATIVE_SCHUR use an explicit Schur Complement matrix.
Up till now ITERATIVE_SCHUR evaluates matrix-vector products
between the Schur complement and a vector implicitly by exploiting
the algebraic expression for the Schur complement.

This cost of this evaluation scales with the number of non-zeros
in the Jacobian.

For small to medium sized problems there is a sweet spot where
computing the Schur complement is cheap enough that it is much
more efficient to explicitly compute it and use it for evaluating
the matrix-vector products.

This changes implements support for an explicit Schur complement
in ITERATIVE_SCHUR in combination with the SCHUR_JACOBI preconditioner.

API wise a new bool Solver::Options::use_explicit_schur_complement
has been added.

The implementation extends the SparseSchurComplementSolver to use
Conjugate Gradients.

Example speedup:

use_explicit_schur_complement = false

Time (in seconds):
Preprocessor                            0.585

  Residual evaluation                   0.319
  Jacobian evaluation                   1.590
  Linear solver                        25.685
Minimizer                              27.990

Postprocessor                           0.010
Total                                  28.585

use_explicit_schur_complement = true

Time (in seconds):
Preprocessor                            0.638

  Residual evaluation                   0.318
  Jacobian evaluation                   1.507
  Linear solver                         5.930
Minimizer                               8.144

Postprocessor                           0.010
Total                                   8.791

Which indicates an end-to-end speedup of more than 3x, with the linear
solver being sped up by > 4x.

The idea to explore this optimization was inspired by the recent paper:

Mining structure fragments for smart bundle adjustment
L. Carlone, P. Alcantarilla, H. Chiu, K. Zsolt, F. Dellaert
British Machine Vision Conference, 2014

which uses a more complicated algorithm to compute parts of the
Schur complement to speed up the matrix-vector product.

Change-Id: I95324af0ab351faa1600f5204039a1d2a64ae61d
2014-09-29 10:29:32 -07:00