1. Use hardware_concurrency to configure number of threads.
2. Use user ordering instead of automatic ordering.
Fixes https://github.com/ceres-solver/ceres-solver/issues/874
Change-Id: I4d7d69612e1ee40358943019a0c3a909e419c4e4
* 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
1. Remove an unused variable from block_sparse_matrix.cc
2. Add explicit types to the distributions to get around
-Wctad-maybe-unsupported
Change-Id: Ib7d606fbfe2b93ba4fce408f38ee4f7626b74ff0
With this change, the user can now choose between Approximate Minimum
Degree and Nested Dissection as a fill reducing algorithm when using
a sparse direct factorization based linear solver like SPARSE_NORMAL_CHOLESKY
or SPARSE_SCHUR.
Currenly only SUITE_SPARSE is supported. It requires that
SuiteSparse be compiled with Metis support enabled.
On most problems AMD is still the better choice, but in some cases
like the grid3D dataset from https://lucacarlone.mit.edu/datasets/
the solution time with AMD is 57s and with NESDIS 38 on my M1 Mac.
On some other problems at Google we have observed speedups of 10x,
there is also a corresponding decrease in the total amount of memory
used.
This patch is based on the original work done by NeroBurner in
https://ceres-solver-review.googlesource.com/c/ceres-solver/+/20580
1. Add a new enum to the public api LinearSolverOrderingType and
a setting Solver::Options::linear_solver_ordering_type.
2. TrustRegionPreprocessor had some complicated logic which determined
when linear solvers should reorder their matrices on their own and not
this has been refactored into a more readable function that lives
inside reorder_program.h/cc.
3. Plumbing in reorder_program.cc and trust_region_processor.cc to use
nested dissection.
4. Update bundle_adjuster.cc to use nested dissection.
Change-Id: I388b027934f86c58b4da2b65a4fa5204ea73bf40
In many cases, manifolds stored in ProductManifold have a default
constructor which can simplify ProductManifold initialization even
further. Allow default construction of ProductManifold in this case.
Change-Id: I29b2612870c02232556688019a77049709684a55
Since the number of manifolds used to initialize ProductManifold and
their types are known at compile-time, it is possible to avoid storing
pointers to the base class as required by a homogeneous, currently
dynamically sized container. Instead, we can use std::tuple<> as a
heterogenous container with the number of elements fixed at compile-time
that allows us to store the concrete manifold realizations.
The advantage of this approach is that we can bypass the vtable when
iterating over each manifold within ProductManifold. The indirection is
invoked only once while accessing the ProductManifoldImpl members.
Additionally, potential dynamic memory allocations by a std::vector can
be completely avoided. This makes the ProductManifold implementation
more efficient both in memory and runtime.
Change-Id: Ic71b0c175ab726f8992e9703f7666bca477baf19
This brings it in line with other manifolds like SphereManifold
and LineManifold, where the user has the choice to specify the size
of the manifold at compile time or runtime.
Most of the time the size is known at compile time so this will
speed up the common case.
Change-Id: I0c7ff8b7a9a64a81203eb11afc074874e208815a
Remove logic invoked based on obsolete variable definitions. Use new
(explicit) target_link_libraries syntax to link binaries against
dependencies. Do not rely on prior knowledge about the compiler for
specifying flags and system libraries but instead directly test their
presence to be more robust.
Change-Id: I76e0d10fae6eba4b343048e4404f0a9b08c7cb6c
1. Add CUDADenseQR & tests.
CUDADenseQR uses the cuSolverDN LAPACK implementation
of QR factorization. A key limitation, however, is that
this solver does not perform singularity checking --
this is because cuSolverDN does not have a trtrs
implementation; we instead use cuBLAS' trsv for
backsubstitution.
2. All CPU -> GPU memory transfers are now async, and both
CUDADenseQR and CUDADenseCholesky explicitly manage their
own streams for async operations.
3. Simplified CUDADenseCholesky to only use the legacy 32-bit
cuSolverDN API.
Change-Id: I2a9b7b65469658ddfe33b5b2a3892c8744d6e437
1. Add CUDADenseCholesky64Bit, CUDADenseCholesky32Bit, & tests.
CUDADenseCholesky32Bit uses the legacy versions of potrf/potrs
in cuSolverDN, while CUDADenseCholesky64Bit uses the new 64-bit
versions available since Cuda 11.1. The legacy versions are
provided since some platforms such as the Nvidia Jetsons only
support Cuda 10.2.
2. Expose CUDA as a new option under DenseLinearAlgebraLibraryType.
The relevant option to string and string to option helper functions
are modified accordingly.
3. Add cuda as a dense_linear_algebra_library option in bundle_adjuster
to demonstrate the use of the new CUDA option.
Change-Id: I23615e1d301df5185ed646b3e33ee802508dae86
1. Add EigenDenseQR & tests.
This implementation now uses an in place decomposition,
which means that we are not allocating, deallocating
memory every call.
2. Add LAPACKDenseQR and tests.
The LAPACK implementation instead of using dgels which is a
routine which does the factorization and solve in one
call, now uses dgeqrf for factorization and then
dormqr and dtrtrs for solving. This allows us to
have a factorize and solve interface like DenseCholesky.
And opens the door to iterative refinement and mixed
precision solves.
3. The refactor also allows us to simplify the interface to
DenseSparseMatrix considerably. The internals of this
class were complicated because we had the AppendDiagonal
and RemoveDiagonal methods and we did not want to allocate
deallocate memory every call. But since we pay the cost
of the copy anyways, we can just hold that buffer
in DenseQRSolver.
4. Delete lapack.cc/h
5. The net result is that everything seems to be a bit faster.
For LAPACK we are not doing some of the scaling work that
dgels was doing. For Eigen I think it maybe the inplace
decomposition.
Benchmark Time CPU Time Old Time New CPU Old CPU New
----------------------------------------------------------------------------------------------------------------------------------------------------------
BM_DenseSolver<ceres::EIGEN, ceres::DENSE_QR>/1/1 -0.1154 -0.1159 692 612 691 611
BM_DenseSolver<ceres::EIGEN, ceres::DENSE_QR>/2/1 -0.1601 -0.1553 717 603 712 601
BM_DenseSolver<ceres::EIGEN, ceres::DENSE_QR>/3/1 -0.1673 -0.1575 733 610 724 610
BM_DenseSolver<ceres::EIGEN, ceres::DENSE_QR>/6/2 -0.1008 -0.1003 886 797 884 796
BM_DenseSolver<ceres::EIGEN, ceres::DENSE_QR>/10/3 -0.1489 -0.1514 1283 1092 1281 1087
BM_DenseSolver<ceres::EIGEN, ceres::DENSE_QR>/12/4 -0.1040 -0.1104 1556 1394 1553 1381
BM_DenseSolver<ceres::EIGEN, ceres::DENSE_QR>/20/5 -0.0007 -0.0097 1911 1910 1908 1890
BM_DenseSolver<ceres::EIGEN, ceres::DENSE_QR>/40/5 -0.1033 -0.1022 2981 2673 2957 2655
BM_DenseSolver<ceres::EIGEN, ceres::DENSE_QR>/100/10 -0.0147 +0.0015 9275 9138 9026 9040
BM_DenseSolver<ceres::EIGEN, ceres::DENSE_QR>/200/10 -0.1408 -0.1284 15093 12968 14778 12880
BM_DenseSolver<ceres::EIGEN, ceres::DENSE_QR>/200/20 -0.0310 -0.0355 38973 37765 38837 37460
BM_DenseSolver<ceres::LAPACK, ceres::DENSE_QR>/1/1 -0.1228 -0.1256 736 646 731 640
BM_DenseSolver<ceres::LAPACK, ceres::DENSE_QR>/2/1 -0.1401 -0.1396 740 636 735 633
BM_DenseSolver<ceres::LAPACK, ceres::DENSE_QR>/3/1 -0.1731 -0.1695 744 615 738 613
BM_DenseSolver<ceres::LAPACK, ceres::DENSE_QR>/6/2 -0.1399 -0.1408 1121 965 1113 956
BM_DenseSolver<ceres::LAPACK, ceres::DENSE_QR>/10/3 -0.1110 -0.1145 1571 1397 1560 1382
BM_DenseSolver<ceres::LAPACK, ceres::DENSE_QR>/12/4 -0.1411 -0.1417 2006 1722 1993 1710
BM_DenseSolver<ceres::LAPACK, ceres::DENSE_QR>/20/5 -0.1740 -0.1729 2741 2264 2724 2253
BM_DenseSolver<ceres::LAPACK, ceres::DENSE_QR>/40/5 -0.0966 -0.1123 3462 3128 3425 3040
BM_DenseSolver<ceres::LAPACK, ceres::DENSE_QR>/100/10 -0.0387 -0.0998 10365 9964 10339 9307
BM_DenseSolver<ceres::LAPACK, ceres::DENSE_QR>/200/10 -0.2044 -0.2049 16031 12754 15998 12720
BM_DenseSolver<ceres::LAPACK, ceres::DENSE_QR>/200/20 -0.2391 -0.2386 35777 27223 35716 27193
Change-Id: I782f0d7664efe1435eebda92ddf47a0fe66c9c72
This has been a long requested feature so that users can minimize
functions using numeric differentiation.
As part of this, I have also redone rosenbrock.cc, which now has three
variants.
rosenbrock.cc now uses automatic differentiation.
rosenbrock_numeric_diff.cc uses numeric differentiation.
rosenbrock_analytic_diff.cc uses analytic derivatives.
This is analogus to how the helloworld example code is structured.
The tutorial for GradientProblemSolver has also been updated to reflect
this.
https://github.com/ceres-solver/ceres-solver/issues/691
Change-Id: Ib0fb9e35127fe4c8299d4793bea3558722c70dd7
1. Add function_tolerance based termination, updating the
termination logic to be in line with Ceres.
2. Replace the use of "error" with "residuals" in the code.
Change-Id: I3fd543f3a8226fe7f07eeec358559cba934679b2
This is needed to add a layer of indirection which will allow
us to use gflags in the public version and absl inside Google.
Change-Id: I32f3da23200a01c9b658bbf8aaa66cb8fddc2cc3
When the examples are built from an external repo, the -I flag doesn't
point anywhere useful. Bazel has an includes option to handle this, so
just use that instead.
Change-Id: Ic768bd60c547948959912193765d4097ec0adf8c
- 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
This is mostly just applying the existing clang format config, except:
- Use NOLINT on overlong comment lines.
- Wrap some sections in 'clang-format off' / 'clang format on'.
- Manually split or join some multi-line strings.
Change-Id: Ia1a40eeb92112e12c3a169309afe087af55b2f4f
Add Ownership semantics to the AutoDiffCostFunction
This allows several benefits, such as pointer ordering always being the
same for numerical repeatability (due to blocks being ordered by
pointer address), memory adjacency for better cache performance, and
reduced allocator pressure / overhead.
This is then made use of in libmv by preallocating the errors and
cost functions into vectors
Change-Id: Ia5b97e7249b55a463264b6e26f7a02291927c9f2
- As our minimum required version of gflags (2.2) exports itself as
a CMake package and this is the case for the default 18.04 package
we can use the gflags target directly.
- Replaces forced use of CONFIG in find_package(gflags) with a check
that the gflags imported target exists to avoid ambiguity with
libgflags if installed in a default location. This permits users to
override the gflags detection should they so choose, provided that
they do so via an imported target.
- Also removes some previously removed legacy GLAGS_ vars from the
installation docs.
Change-Id: I015f5a751e5b22f956bbf9df692e63a6825c9f0d
- Removes all workarounds for pre-C++14 versions
- Removes '11' qualifier from C++ threading option and associated
defines.
- Fix missing inclusion of 'Multithreading' in reported Ceres components
when C++ threading model is enabled.
- Update Sphinx documentation to specify C++14 as minimum requirement.
Change-Id: I706c8b367b3221e3c4d1a0aaf669a8f9c911e438
Fix typos in docs/source/features.rst and examples/helloworld.cc. Alter a NULL to nullptr in include/ceres/autodiff_cost_function.h
Change-Id: Ibcf00b6ef665ad6be9af14b3add2dd4f3852e7e6
- This reflects modern CMake style, and also provides a measure of
protection against missing find_package() imports in downstream
clients resulting in linker errors when 'ceres' matches the compiled
library and not the imported target.
- The original 'ceres' target remains, as a local imported interface
target created by CeresConfig for backwards compatibility.
Change-Id: Ie9ed8de9b7059bc0cae1ae5002bb94d8fe617188
This patch integrates the code generation module into the build
system. All depenendcies are tracked through CMake targets.
Modifying the cost functor will automatically trigger code
re-generation.
All this functionality is defined in the CMake function
ceres_generate_cost_function_implementation_for_functor
in CeresCodeGeneration.cmake. A hello world usage example
is included in examples/CMakeLists.txt.
Change-Id: I23b8b6698d1ea51cf3d788a47afcf39f8c5ce327