Commit Graph

25 Commits

Author SHA1 Message Date
Dmitriy Korchemkin b158515089 Parallel operations on vectors
Main focus of this change is to parallelize remaining operations (most of them
are operations on vectors) in code-path utilized with iterative Schur
complement.

Parallelization is handled using lazy evaluation of Eigen expressions.

On linux pc with intel 8176 processor parallelization of vector operations has
the following effect:

Running ./bin/parallel_vector_operations_benchmark
Run on (112 X 3200.32 MHz CPU s)
CPU Caches:
  L1 Data 32 KiB (x56)
  L1 Instruction 32 KiB (x56)
  L2 Unified 1024 KiB (x56)
  L3 Unified 39424 KiB (x2)
Load Average: 3.30, 8.41, 11.82
-----------------------------------
Benchmark                      Time
-----------------------------------
SetZero                 10009532 ns
SetZeroParallel/1       10024139 ns
...
SetZeroParallel/16        877606 ns

Negate                   4978856 ns
NegateParallel/1         5145413 ns
...
NegateParallel/16         721823 ns

Assign                  10731408 ns
AssignParallel/1        10749944 ns
...
AssignParallel/16        1829381 ns

D2X                     15214399 ns
D2XParallel/1           15623245 ns
...
D2XParallel/16           2687060 ns

DivideSqrt               8220050 ns
DivideSqrtParallel/1     9088467 ns
...
DivideSqrtParallel/16     905569 ns

Clamp                    3502010 ns
ClampParallel/1          4507897 ns
...
ClampParallel/16          759576 ns

Norm                     4426782 ns
NormParallel/1           4442805 ns
...
NormParallel/16           430290 ns

Dot                      9023276 ns
DotParallel/1            9031304 ns
...
DotParallel/16           1157267 ns

Axpby                   14608289 ns
AxpbyParallel/1         14570825 ns
...
AxpbyParallel/16         2672220 ns
-----------------------------------

Multi-threading of vector operations in ISC and program evaluation results into
the following improvement:

Running ./bin/evaluation_benchmark
--------------------------------------------------------------------------------------
Benchmark                                                               this   2fd81de
--------------------------------------------------------------------------------------
Residuals<problem-13682-4456117-pre.txt>/1                           4136 ms   4292 ms
Residuals<problem-13682-4456117-pre.txt>/2                           2919 ms   2670 ms
Residuals<problem-13682-4456117-pre.txt>/4                           2065 ms   2198 ms
Residuals<problem-13682-4456117-pre.txt>/8                           1458 ms   1609 ms
Residuals<problem-13682-4456117-pre.txt>/16                          1152 ms   1227 ms

ResidualsAndJacobian<problem-13682-4456117-pre.txt>/1               19759 ms  20084 ms
ResidualsAndJacobian<problem-13682-4456117-pre.txt>/2               10921 ms  10977 ms
ResidualsAndJacobian<problem-13682-4456117-pre.txt>/4                6220 ms   6941 ms
ResidualsAndJacobian<problem-13682-4456117-pre.txt>/8                3490 ms   4398 ms
ResidualsAndJacobian<problem-13682-4456117-pre.txt>/16               2277 ms   3172 ms

Plus<problem-13682-4456117-pre.txt>/1                                 339 ms    322 ms
Plus<problem-13682-4456117-pre.txt>/2                                 220 ms
Plus<problem-13682-4456117-pre.txt>/4                                 128 ms
Plus<problem-13682-4456117-pre.txt>/8                                78.0 ms
Plus<problem-13682-4456117-pre.txt>/16                               49.8 ms

ISCRightMultiplyAndAccumulate<problem-13682-4456117-pre.txt>/1       2434 ms   2478 ms
ISCRightMultiplyAndAccumulate<problem-13682-4456117-pre.txt>/2       2706 ms   2688 ms
ISCRightMultiplyAndAccumulate<problem-13682-4456117-pre.txt>/4       1430 ms   1548 ms
ISCRightMultiplyAndAccumulate<problem-13682-4456117-pre.txt>/8        742 ms    883 ms
ISCRightMultiplyAndAccumulate<problem-13682-4456117-pre.txt>/16       438 ms    555 ms

ISCRightMultiplyAndAccumulateDiag<problem-13682-4456117-pre.txt>/1   2438 ms   2481 ms
ISCRightMultiplyAndAccumulateDiag<problem-13682-4456117-pre.txt>/2   2565 ms   2790 ms
ISCRightMultiplyAndAccumulateDiag<problem-13682-4456117-pre.txt>/4   1434 ms   1551 ms
ISCRightMultiplyAndAccumulateDiag<problem-13682-4456117-pre.txt>/8    765 ms    892 ms
ISCRightMultiplyAndAccumulateDiag<problem-13682-4456117-pre.txt>/16   435 ms    559 ms

JacobianSquaredColumnNorm<problem-13682-4456117-pre.txt>/1           1278 ms
JacobianSquaredColumnNorm<problem-13682-4456117-pre.txt>/2           1555 ms
JacobianSquaredColumnNorm<problem-13682-4456117-pre.txt>/4            833 ms
JacobianSquaredColumnNorm<problem-13682-4456117-pre.txt>/8            459 ms
JacobianSquaredColumnNorm<problem-13682-4456117-pre.txt>/16           250 ms

JacobianScaleColumns<problem-13682-4456117-pre.txt>/1                1468 ms
JacobianScaleColumns<problem-13682-4456117-pre.txt>/2                1871 ms
JacobianScaleColumns<problem-13682-4456117-pre.txt>/4                 957 ms
JacobianScaleColumns<problem-13682-4456117-pre.txt>/8                 528 ms
JacobianScaleColumns<problem-13682-4456117-pre.txt>/16                294 ms

End-to-end improvements with bundle_adjuster invoked with
./bin/bundle_adjuster --num_threads 28 --num_iterations 40 \
                      --linear_solver iterative_schur \
                      --preconditioner jacobi --input
---------------------------------------------
Problem                         this  2fd81de
---------------------------------------------
problem-13682-4456117-pre.txt  508.6    892.7
problem-1778-993923-pre.txt    763.8   1129.9
problem-1723-156502-pre.txt      6.3     14.4
problem-356-226730-pre.txt      76.3    116.2
problem-257-65132-pre.txt       38.6     52.0

Change-Id: Ie31cc5015f13fa479c16ffb5ce48c9b880990d49
2022-12-17 02:52:27 +03: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 f90833f5fa Simplify symbol export
Currently, the logic for exporting symbols is rather complicated: when
tests are enabled internal symbols are exported in addition to the
public symbols. Such logic causes several problems. (1) Test binaries
link against a Ceres build that is different from the final release
since fewer optimizations are applied if more symbols are exported. (2)
Also, some toolchains hide symbols by default breaking the existing
logic eventually causing linker errors.

Since internal symbols are not intended to be used outside of the
project, we can compile them into object files and use exactly the same
binary code both for the final build and the tests without relying on
conditionals.

By default, all symbols are now hidden unless annotated as public.
Internal symbols are explicitly marked as not being exported in case
users chose not to hide symbols by default.

Change-Id: I589dd10be2f6f438508783cf99d141af0120057b
2022-02-14 20:19:08 +01: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
Sameer Agarwal 125a0e9be5 LocalParameterization -> Manifold #1
Manifolds are now part of the public API and co-exist
with LocalParameterizations.

1. Add Manifolds to the Problem API.
   a. AddParameterBlock(double*, int, Manifold*)
   b. SetParameterization(double*, Manifold*)
   b. GetManifold(const double*)
   c. HasManifold(const double*)

2. Internally Ceres now only uses Manifolds. When the user uses
   a LocalParameterization, it is wrapped in a ManifoldAdapter.

3. To preserve the API semantics while keeping the internals clean
   we need a new map in ProblemImpl which stores the association
   between parameter blocks and local parameterizations. This
   is temporary, it will go away once this transition is complete.

4. There are NO algorithmic changes, as in we are not using
   any of the expanded interface of the Manifold objects yet.
   That will come later.

5. All tests that use LocalParameterization have been duplicated
   to use Manifolds, and when this transition is complete the
   LocalParameterization based tests will be deleted.

6. Public documentation for the API has been updated. Deprecation
   notices to the documentation as well as C++ annotations will come
   later.

7. Similar changes have been made to GradientProblem.

Change-Id: I8e03c8ced6e141876ef3eca5740c113afa788f0c
2022-01-18 15:59:45 -08:00
Taylor Braun-Jones 3f6d273676 Unify symbol visibility configuration for all compilers
This makes it possible to build unit tests with shared libraries on MSVC.

Change-Id: I1db66a80b2c78c4f3d354e35235244d17bac9809
2020-10-15 16:56:07 -04: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 a614f788a3 Call EvaluationCallback before evaluating the fixed cost.
Fixe a subtle bug in Program::RemoveFixedBlocks, where we call
ResidualBlock::Evaluate on residual blocks with all constant parameter
blocks without paying attention to the presence of an
EvaluationCallback.

In the process also run clang-format on some of the files touched by
this change.

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

Change-Id: I342b66f6f975fdee2eef139a31f24d4a3e568e84
2020-05-27 22:19:16 -07:00
Alex Stewart 0428e2dd0f Fix missing #include of <memory>
Change-Id: I11a4e232305e3866ed418a65041aa87ce385c071
2019-07-12 18:23:26 +01:00
Sameer Agarwal 487c1aa51f Expose SubsetPreconditioner in the API
https://github.com/ceres-solver/ceres-solver/issues/270

Detailed list of changes:

1. Add SUBSET to the PreconditionerType enum.
2. Add Solver::Options::residual_blocks_for_subset_preconditioner
3. Integrate SubsetPreconditioner into the CGNR solver.
4. Add the reordering logic needed for this to TrustRegionPreprocessor.
5. Expect CreateJacobianBlockTranspose to take the starting row block
   so that we can work with subparts of the Jacobian matrix.
6. Extend the denoising example to use this preconditioner.

As an illustration of its performance, we consider the performance of
denoising -input ../data/ceres_noisy.pgm  --foe_file ../data/5x5.foe

tl;dr

For the same cost,

SPARSE_NORMAL_CHOLESKY -  81s
CGNR + JACOBI          - 718s
CGNR + SUBSET          -  57s

SPARSE_NORMAL_CHOLESKY
======================

Cost:
Initial                          2.317806e+05
Final                            2.232323e+04
Change                           2.094574e+05

Minimizer iterations                       10
Successful steps                           10
Unsuccessful steps                          0

Time (in seconds):
Preprocessor                         2.999746

  Residual only evaluation           2.306811 (10)
  Jacobian & residual evaluation     7.421727 (10)
  Linear solver                     65.517273 (10)
Minimizer                           78.731011

Postprocessor                        0.026079
Total                               81.756836

Termination:                      CONVERGENCE (Function tolerance reached. |cost_change|/cost: 8.573046e-04 <= 1.000000e-03)

CGNR + JACOBI
=============
Cost:
Initial                          2.317806e+05
Final                            2.232344e+04
Change                           2.094572e+05

Minimizer iterations                       10
Successful steps                           10
Unsuccessful steps                          0

Time (in seconds):
Preprocessor                         0.648814

  Residual only evaluation           2.297607 (10)
  Jacobian & residual evaluation     7.327886 (10)
  Linear solver                    699.601248 (10)
Minimizer                          712.419493

Postprocessor                        0.024014
Total                              713.092321

Termination:                      CONVERGENCE (Function tolerance reached. |cost_change|/cost: 8.528538e-04 <= 1.000000e-03)

CGNR + SUBSET (random 20% residuals used for the preconditioner)
===============================================================
Cost:
Initial                          2.317806e+05
Final                            2.232327e+04
Change                           2.094574e+05

Minimizer iterations                       10
Successful steps                           10
Unsuccessful steps                          0

Time (in seconds):
Preprocessor                         1.472743

  Residual only evaluation           2.428315 (10)
  Jacobian & residual evaluation     7.367796 (10)
  Linear solver                     42.585999 (10)
Minimizer                           55.664459

Postprocessor                        0.024098
Total                               57.161301

Termination:                      CONVERGENCE (Function tolerance reached. |cost_change|/cost: 8.538277e-04 <= 1.000000e-03)

Change-Id: Ifb011408bd53edbb9439b0b7345649a38f999e18
2019-07-12 16:08:36 +02:00
Sameer Agarwal bf709ecac2 Move EvaluationCallback from Solver::Options to Problem::Options.
Adding it to Solver::Options was a mistake, as it prevents it from
being used in covariance estimation. Also updated associated docs.

https://github.com/ceres-solver/ceres-solver/issues/380
https://github.com/ceres-solver/ceres-solver/issues/401
https://github.com/ceres-solver/ceres-solver/issues/484

Change-Id: I63809a47a58e84c04a58bf8e59ace92f45fc2873
2019-07-08 21:24:08 +02: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 05a07ecc77 Remove using std::string from port.h
Change-Id: I7376f5e7eace22ec1fc05a61eaa858594f08682d
2015-01-07 15:10:46 -08: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 b4a5f7ea25 Program::RemoveFixedBlocks -> Program::CreateReducedProgram.
CreateReducedProgram is a safer API, reduces the possibility of
memory leaks and produces valid programs.

Change-Id: I094d53d207fced970a4d9ea0b66cdb09ce5f0657
2014-06-01 16:38:08 -07:00
Sameer Agarwal e911db19aa Fix a memory leak in program_test.cc
Program::RemoveFixedBocks will happily drop all fixed parameter
and residual blocks. So if it is called on the one and only copy
of a program, like it was being called in the tests, this will
result in a memory leak because we would have lost track of the
fixed parameter and residual blocks.

This is not a problem in actual usage since CreateReducedProgram
will first create a copy of the program and then remove the fixed
blocks from it. But in the tests, we were creating a ProblemImpl
and then calling RemovedFixedBlocks on the underlying program
object causing a memory leak.

The fix to make a copy in the tests and then work on that. I
have also added a warning in program.h

Change-Id: I03a5f7a7f5453aec848451a5c0ace4b065f71e9b
2014-05-31 23:21:44 -07:00
Sameer Agarwal 87a40da145 Refactor Program related functions.
Move

ParameterBlocksAreFinite
IsBoundsConstrained
IsFeasible
RemoveFixedBlocks
IsParameterBlockSetIndependent
CreateJacobianBlockSparsity

from being static methods in SolverImpl to member functions
in the Program class.

Change-Id: I80fa4a429a716ea4371ad6c67864adad438e1553
2014-05-29 21:21:49 -07:00
Sameer Agarwal 324eccb5f6 Restore the state of the Problem after a call to Evaluate.
Calling Problem::Evaluate mutates the state of the parameter blocks.
In particular, depending on the set and order of parameter blocks
passed to the evaluate call, it will change the internal indexing
used by the Program object used by ProblemImpl. This needs to be
undone before Evaluate returns, otherwise the Problem object
is in an invalid state.

To help with testing and debugging in the future, a new method
Program::IsValid has been added which checks whether the problem
has its parameter and residual blocks in the right state.

Thanks to Stefan Leutenegger for reporting this.

Change-Id: I209b486a31433f0cbb58b570047649eca6d42b56
2013-12-03 10:58:24 -08:00
Keir Mierle 51eb229da3 Add Program::ToString() to aid debugging.
Change-Id: I0ab37ed2fe0947ca87a152919d4e7dc9b56dedc6
2012-08-20 11:46:12 -07:00
Sameer Agarwal 4997cbc437 Return jacobians and gradients to the user.
1. Added CRSMatrix object which will store the initial
   and final jacobians if requested by the user.
2. Conversion routine and test for converting a
   CompressedRowSparseMatrix to CRSMatrix.
3. New Evaluator::Evaluate function to do the actual evaluation.
4. Changes to Program::StateVectorToParmeterBlocks and
   Program::SetParameterBlockStatePtrstoUserStatePtrs so that
   they do not try to set the state of constant parameter blocks.
5. Tests for Evaluator::Evaluate.
6. Minor cleanups in SolverImpl.
7. Minor cpplint cleanups triggered by this CL.

Change-Id: I3ac446484692f943c28f2723b719676f8c83ca3d
2012-07-16 12:17:34 -07:00
Keir Mierle f44907f702 Compute the gradient if requested in the evaluator
This extends the Evaluator interface to support evaluating the
gradient in addition to the residuals and jacobian, if requested.

   bool Evaluate(const double* state,
                 double* cost,
                 double* residuals,
                 double* gradient,  <----------- NEW
                 SparseMatrix* jacobian) = 0;

The ProgramEvaluator is extended to support the new gradient
evaluation. This required some gymnastics around the block
evaluate preparer, which now contains a scratch evaluate preparer
for the case that no jacobian is requested but the gradient is.

Gradient evaluation is a prerequisite for the planned suite of
first order methods, including nonlinear conjugate gradient,
CG_DESCENT, L-BFGS, trust region with line search, and more.

This also considerably refactors the evaluator_test to make it
shorter and check the results for all combinations of the optional
parameters [residuals, gradient, jacobian].

Change-Id: Ic7d0fec028dc5ffebc08ee079ad04eeaf6e02582
2012-07-11 09:44:45 -07:00
Keir Mierle 6196cba4e5 Fix broken constant parameter blocks
This fixes the bug introduced in a previous commit,
and adds a test to check that constant parameter
blocks work as expected.

This also refactors the Solver/SolverImpl split so
that SolverImpl is no longer a friend of Problem;
instead, Solver is. This makes it possible to
verify the invariant on parameter block states in
the unit test, and is a more symmetric design
anyway.

Bug: 51
Change-Id: Id503f5b526cfb8bc24aae3aaad2e414b14063d78
2012-06-19 00:09:53 -07:00
Keir Mierle 57d91f5e9e Don't assume program state is user state
The SolverImpl::Solve() method incorrectly assumed that the
state pointers inside the parameter blocks always pointed to
the user state at the start of the method. That is not true.

Change-Id: I73f8eeda453422c99e09d71a3cd0bfa92dd45742
2012-06-17 23:45:23 -07:00
Keir Mierle 8ebb073038 Initial commit of Ceres Solver. 2012-04-30 23:09:08 -07:00