1 .. _chapter-tricks: 2 3 =================== 4 FAQS, Tips & Tricks 5 =================== 6 7 Answers to frequently asked questions, tricks of the trade and general 8 wisdom. 9 10 Building 11 ======== 12 13 #. Use `google-glog <http://code.google.com/p/google-glog>`_. 14 15 Ceres has extensive support for logging detailed information about 16 memory allocations and time consumed in various parts of the solve, 17 internal error conditions etc. This is done logging using the 18 `google-glog <http://code.google.com/p/google-glog>`_ library. We 19 use it extensively to observe and analyze Ceres's 20 performance. `google-glog <http://code.google.com/p/google-glog>`_ 21 allows you to control its behaviour from the command line `flags 22 <http://google-glog.googlecode.com/svn/trunk/doc/glog.html>`_. Starting 23 with ``-logtostdterr`` you can add ``-v=N`` for increasing values 24 of ``N`` to get more and more verbose and detailed information 25 about Ceres internals. 26 27 In an attempt to reduce dependencies, it is tempting to use 28 `miniglog` - a minimal implementation of the ``glog`` interface 29 that ships with Ceres. This is a bad idea. ``miniglog`` was written 30 primarily for building and using Ceres on Android because the 31 current version of `google-glog 32 <http://code.google.com/p/google-glog>`_ does not build using the 33 NDK. It has worse performance than the full fledged glog library 34 and is much harder to control and use. 35 36 37 Modeling 38 ======== 39 40 #. Use analytical/automatic derivatives. 41 42 This is the single most important piece of advice we can give to 43 you. It is tempting to take the easy way out and use numeric 44 differentiation. This is a bad idea. Numeric differentiation is 45 slow, ill-behaved, hard to get right, and results in poor 46 convergence behaviour. 47 48 Ceres allows the user to define templated functors which will 49 be automatically differentiated. For most situations this is enough 50 and we recommend using this facility. In some cases the derivatives 51 are simple enough or the performance considerations are such that 52 the overhead of automatic differentiation is too much. In such 53 cases, analytic derivatives are recommended. 54 55 The use of numerical derivatives should be a measure of last 56 resort, where it is simply not possible to write a templated 57 implementation of the cost function. 58 59 In many cases it is not possible to do analytic or automatic 60 differentiation of the entire cost function, but it is generally 61 the case that it is possible to decompose the cost function into 62 parts that need to be numerically differentiated and parts that can 63 be automatically or analytically differentiated. 64 65 To this end, Ceres has extensive support for mixing analytic, 66 automatic and numeric differentiation. See 67 :class:`NumericDiffFunctor` and :class:`CostFunctionToFunctor`. 68 69 #. Putting `Inverse Function Theorem 70 <http://en.wikipedia.org/wiki/Inverse_function_theorem>`_ to use. 71 72 Every now and then we have to deal with functions which cannot be 73 evaluated analytically. Computing the Jacobian in such cases is 74 tricky. A particularly interesting case is where the inverse of the 75 function is easy to compute analytically. An example of such a 76 function is the Coordinate transformation between the `ECEF 77 <http://en.wikipedia.org/wiki/ECEF>`_ and the `WGS84 78 <http://en.wikipedia.org/wiki/World_Geodetic_System>`_ where the 79 conversion from WGS84 from ECEF is analytic, but the conversion 80 back to ECEF uses an iterative algorithm. So how do you compute the 81 derivative of the ECEF to WGS84 transformation? 82 83 One obvious approach would be to numerically 84 differentiate the conversion function. This is not a good idea. For 85 one, it will be slow, but it will also be numerically quite 86 bad. 87 88 Turns out you can use the `Inverse Function Theorem 89 <http://en.wikipedia.org/wiki/Inverse_function_theorem>`_ in this 90 case to compute the derivatives more or less analytically. 91 92 The key result here is. If :math:`x = f^{-1}(y)`, and :math:`Df(x)` 93 is the invertible Jacobian of :math:`f` at :math:`x`. Then the 94 Jacobian :math:`Df^{-1}(y) = [Df(x)]^{-1}`, i.e., the Jacobian of 95 the :math:`f^{-1}` is the inverse of the Jacobian of :math:`f`. 96 97 Algorithmically this means that given :math:`y`, compute :math:`x = 98 f^{-1}(y)` by whatever means you can. Evaluate the Jacobian of 99 :math:`f` at :math:`x`. If the Jacobian matrix is invertible, then 100 the inverse is the Jacobian of the inverse at :math:`y`. 101 102 One can put this into practice with the following code fragment. 103 104 .. code-block:: c++ 105 106 Eigen::Vector3d ecef; // Fill some values 107 // Iterative computation. 108 Eigen::Vector3d lla = ECEFToLLA(ecef); 109 // Analytic derivatives 110 Eigen::Matrix3d lla_to_ecef_jacobian = LLAToECEFJacobian(lla); 111 bool invertible; 112 Eigen::Matrix3d ecef_to_lla_jacobian; 113 lla_to_ecef_jacobian.computeInverseWithCheck(ecef_to_lla_jacobian, invertible); 114 115 #. When using Quaternions, use :class:`QuaternionParameterization`. 116 117 TBD 118 119 #. How to choose a parameter block size? 120 121 TBD 122 123 Solving 124 ======= 125 126 #. Choosing a linear solver. 127 128 When using the ``TRUST_REGION`` minimizer, the choice of linear 129 solver is an important decision. It affects solution quality and 130 runtime. Here is a simple way to reason about it. 131 132 1. For small (a few hundred parameters) or dense problems use 133 ``DENSE_QR``. 134 135 2. For general sparse problems (i.e., the Jacobian matrix has a 136 substantial number of zeros) use 137 ``SPARSE_NORMAL_CHOLESKY``. This requires that you have 138 ``SuiteSparse`` or ``CXSparse`` installed. 139 140 3. For bundle adjustment problems with up to a hundred or so 141 cameras, use ``DENSE_SCHUR``. 142 143 4. For larger bundle adjustment problems with sparse Schur 144 Complement/Reduced camera matrices use ``SPARSE_SCHUR``. This 145 requires that you have ``SuiteSparse`` or ``CXSparse`` 146 installed. 147 148 5. For large bundle adjustment problems (a few thousand cameras or 149 more) use the ``ITERATIVE_SCHUR`` solver. There are a number of 150 preconditioner choices here. ``SCHUR_JACOBI`` offers an 151 excellent balance of speed and accuracy. This is also the 152 recommended option if you are solving medium sized problems for 153 which ``DENSE_SCHUR`` is too slow but ``SuiteSparse`` is not 154 available. 155 156 If you are not satisfied with ``SCHUR_JACOBI``'s performance try 157 ``CLUSTER_JACOBI`` and ``CLUSTER_TRIDIAGONAL`` in that 158 order. They require that you have ``SuiteSparse`` 159 installed. Both of these preconditioners use a clustering 160 algorithm. Use ``SINGLE_LINKAGE`` before ``CANONICAL_VIEWS``. 161 162 #. Use `Solver::Summary::FullReport` to diagnose performance problems. 163 164 When diagnosing Ceres performance issues - runtime and convergence, 165 the first place to start is by looking at the output of 166 ``Solver::Summary::FullReport``. Here is an example 167 168 .. code-block:: bash 169 170 ./bin/bundle_adjuster --input ../data/problem-16-22106-pre.txt 171 172 iter cost cost_change |gradient| |step| tr_ratio tr_radius ls_iter iter_time total_time 173 0 4.185660e+06 0.00e+00 2.16e+07 0.00e+00 0.00e+00 1.00e+04 0 7.50e-02 3.58e-01 174 1 1.980525e+05 3.99e+06 5.34e+06 2.40e+03 9.60e-01 3.00e+04 1 1.84e-01 5.42e-01 175 2 5.086543e+04 1.47e+05 2.11e+06 1.01e+03 8.22e-01 4.09e+04 1 1.53e-01 6.95e-01 176 3 1.859667e+04 3.23e+04 2.87e+05 2.64e+02 9.85e-01 1.23e+05 1 1.71e-01 8.66e-01 177 4 1.803857e+04 5.58e+02 2.69e+04 8.66e+01 9.93e-01 3.69e+05 1 1.61e-01 1.03e+00 178 5 1.803391e+04 4.66e+00 3.11e+02 1.02e+01 1.00e+00 1.11e+06 1 1.49e-01 1.18e+00 179 180 Ceres Solver v1.10.0 Solve Report 181 ---------------------------------- 182 Original Reduced 183 Parameter blocks 22122 22122 184 Parameters 66462 66462 185 Residual blocks 83718 83718 186 Residual 167436 167436 187 188 Minimizer TRUST_REGION 189 190 Sparse linear algebra library SUITE_SPARSE 191 Trust region strategy LEVENBERG_MARQUARDT 192 193 Given Used 194 Linear solver SPARSE_SCHUR SPARSE_SCHUR 195 Threads 1 1 196 Linear solver threads 1 1 197 Linear solver ordering AUTOMATIC 22106, 16 198 199 Cost: 200 Initial 4.185660e+06 201 Final 1.803391e+04 202 Change 4.167626e+06 203 204 Minimizer iterations 5 205 Successful steps 5 206 Unsuccessful steps 0 207 208 Time (in seconds): 209 Preprocessor 0.283 210 211 Residual evaluation 0.061 212 Jacobian evaluation 0.361 213 Linear solver 0.382 214 Minimizer 0.895 215 216 Postprocessor 0.002 217 Total 1.220 218 219 Termination: NO_CONVERGENCE (Maximum number of iterations reached.) 220 221 Let us focus on run-time performance. The relevant lines to look at 222 are 223 224 225 .. code-block:: bash 226 227 Time (in seconds): 228 Preprocessor 0.283 229 230 Residual evaluation 0.061 231 Jacobian evaluation 0.361 232 Linear solver 0.382 233 Minimizer 0.895 234 235 Postprocessor 0.002 236 Total 1.220 237 238 239 Which tell us that of the total 1.2 seconds, about .3 seconds was 240 spent in the linear solver and the rest was mostly spent in 241 preprocessing and jacobian evaluation. 242 243 The preprocessing seems particularly expensive. Looking back at the 244 report, we observe 245 246 .. code-block:: bash 247 248 Linear solver ordering AUTOMATIC 22106, 16 249 250 Which indicates that we are using automatic ordering for the 251 ``SPARSE_SCHUR`` solver. This can be expensive at times. A straight 252 forward way to deal with this is to give the ordering manually. For 253 ``bundle_adjuster`` this can be done by passing the flag 254 ``-ordering=user``. Doing so and looking at the timing block of the 255 full report gives us 256 257 .. code-block:: bash 258 259 Time (in seconds): 260 Preprocessor 0.051 261 262 Residual evaluation 0.053 263 Jacobian evaluation 0.344 264 Linear solver 0.372 265 Minimizer 0.854 266 267 Postprocessor 0.002 268 Total 0.935 269 270 271 272 The preprocessor time has gone down by more than 5.5x!. 273 274 Further Reading 275 =============== 276 277 For a short but informative introduction to the subject we recommend 278 the booklet by [Madsen]_ . For a general introduction to non-linear 279 optimization we recommend [NocedalWright]_. [Bjorck]_ remains the 280 seminal reference on least squares problems. [TrefethenBau]_ book is 281 our favorite text on introductory numerical linear algebra. [Triggs]_ 282 provides a thorough coverage of the bundle adjustment problem. 283