Open keir opened 5 years ago
Hey Keir,
Sorry I have been roadtripping across the US for the last 3 months and just now am reconnecting with the outside world. Anyways I would be happy to contribute my modifications back to Ceres upstream.
I would like to seek your opinion on the design of some of the extra features I added.
The 4 main modifications I would say are:
1,2 are straightforward to implement, and I will start putting together a pull request for Ceres over the next few weeks.
3 I implement right now with some template metaprogramming and is in my opinion quite ugly. I also don't know what will happen if you implement a normal functor and a hessian based one.
Possible solutions are as follows:
4 I still need to think about cause I am not happy with the current solution I have which is to add another template parameter to the solver.
Anyways I'll try and slowly get started on creating a pull request for 1,2 on Gerrit and let me know what opinions you have on features 3,4.
@Edwinem (1), (2) and (4) will improve things while keeping the current semantics. (3) I am hesitant to add. I look forward to reviewing your code!
gentle ping?
TinySolver may be missing a few noalias() calls.
194 jtj_ = jacobian_.transpose() * jacobian_;
195 g_ = jacobian_.transpose() * error_;
241 dx_ = jacobi_scaling_.asDiagonal() * lm_step_;
I would also like to propose a small change to TinySolver, which is to allocate storage using std::vector and use Eigen::Map. It looks roughly like this
void Initialize(int num_residuals, int num_parameters) {
const int num_jacobian = num_residuals * num_parameters;
const int num_hessian = num_parameters * num_parameters;
const int total = num_parameters * 6 + num_residuals * 2 +
num_jacobian * 1 + num_hessian * 2;
storage_.resize(total); // std::vector<Scalar>
auto* s = storage_.data();
new (&dx_) Eigen::Map<Parameters>(s, num_parameters);
// More
I can do a PR if you think this is useful.
I'd like to understand, why do you think we are missing some noalias calls? also I do not understand the reason for your proposed use of std::vector for storage. Could you elaborate, what problem you are trying to solve?
If I remember correctly, matrix multiplication in Eigen assumes alias by default, so adding noalias() to those lines could avoid evaluating into a temporary matrix. For example https://github.com/ceres-solver/ceres-solver/blob/2a2b9bd6fa2a0ee62f58dceb786cb2dc3eb37630/internal/ceres/schur_eliminator.h#L505
For vector storage, it is not trying to solve any problem, it's just a small performance improvement. Whereas before, if a reallocation is needed, all those members will be allocated separately and there's no guarantee where they will end up in memory whereas the proposed change will just do it once. It is also possible to set a max size if one knows in advance the maximum number of residuals and parameters, thus even if the number of residuals changes between calls, as long as it is within the max size, there will only be one allocation on initialization.
Related issue #350
Here is my proposed change https://github.com/versatran01/nano_solver
The change is in the Initialize() function. I made the solver non-template since I want better compilation time in my own project, which is NOT part of the change that I propose here.
See https://github.com/Edwinem/tiny_nlls_solver/issues/1
They have added some interesting stuff like hessian support. It could be interesting to incorporate some of these changes in upstream.