This forum has been archived. All content is frozen. Please use KDE Discuss instead.

AutoDiff use/performance in LevenbergMarquard

Tags: None
(comma "," separated)
mtosas
Registered Member
Posts
6
Karma
0
Hi,

I'm using a few of Eigen unsupported modules (as they are there, I prefer to use them rather than adding other third party dependencies). I'm using the LevenbergMarquardt module and the NumericalDiff module (to compute the Jacobian of my error function).

I want to speed up the minimization, and I thought of using the AutoDiff module to compute the Jacobian -— as then I'll have 6 times fewer evaluations of my error function (the Jacobian for my error function is 6 inputs by 104 outputs)

I got the minimization working well with a derivative calculated with AutoDiff. However, to my disappointment, the performance is about 6 times slower with AutoDiff than with NumericalDiff (same error function).

I'm not sure if this is to expect from Automatic Differentiation in general for this size of Jacobian, or maybe the AutoDiff module is not optimized, or maybe I'm using AutoDiff module the wrong way???

I add the parts of my code that use AutoDiff to clarify how I'm using it.
Please, any help on usage or potential performance of AutoDiff would be highly appreciated.

Code: Select all
   #include <unsupported/Eigen/LevenbergMarquardt>
    #include <unsupported/Eigen/AutoDiff>

    ....
       
   class lmdif_functor: public DenseFunctor<double>
   {
   public:
      lmdif_functor(Matches &matches,
               Camera &camera):
                           _matches(matches),
                           _camera(camera),
                           DenseFunctor<double>(6,matches.rows()*2) {}


      template<typename T>
      int error_function(const Matrix<T,6,1> &params, Matrix<T,-1,1> &fvec)
      {

            ...
           
         return 0;
      }

      int operator()(const VectorXd &params, VectorXd &fvec)
      {
         return error_function<double>(params, fvec);
      }

      typedef AutoDiffScalar<Matrix<double, InputsAtCompileTime,1> > ADS;
      typedef Matrix<ADS, InputsAtCompileTime, 1> VectorXad_in;
      typedef Matrix<ADS, ValuesAtCompileTime, 1> VectorXad_out;

      int df(const VectorXd &params, JacobianType &fjac)
      {
         VectorXad_out fvec_ad(this->values());
         VectorXad_in params_ad(this->inputs());
         for(int i=0; i<this->inputs(); ++i)
            params_ad(i) = ADS(params(i), this->inputs(), i);

         error_function<ADS>(params_ad, fvec_ad);

         for(int i=0; i<fjac.rows(); ++i)
            fjac.row(i) = fvec_ad[i].derivatives();

         return 0;
      }
        ...
       
   };
   
    void compute_pose(....)
    {
        ....
       
        lmdif_functor functor(matches, camera, original_params);
        LevenbergMarquardt<lmdif_functor> lm(functor);

        int info = lm.minimize(params);       
       
        ....
    }
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
Make sure that InputsAtCompileTime is 6 so that you can avoid very expensive heap allocation within AutoDiffScalar.
twithaar
Registered Member
Posts
23
Karma
0
I got the minimization working well with a derivative calculated with AutoDiff. However, to my disappointment, the performance is about 6 times slower with AutoDiff than with NumericalDiff (same error function).


For the problems I'm working on (large datasets, few parameters), there are typically common sub-expressions between the various derivatives (and the error function itself).
I'd be impressed if the compiler can combine those. I always end up calculating the symbolic derivatives using wxMaxima.
The main drawback there is that a typo is easily made. Using Autodiff to verify these derivatives might help.

But with Eigen you never know, it is amazing how close it gets to optimal code by tweaking the expressions a bit.
mtosas
Registered Member
Posts
6
Karma
0
ggael wrote:Make sure that InputsAtCompileTime is 6 so that you can avoid very expensive heap allocation within AutoDiffScalar.


Thanks for your reply ggael. I'm sorry it's taken me so long to get back to this, I had to leave this work aside and I haven't had a chance to look at it again until now!

I find that InputsAtCompileTime is -1 and I guess this is the reason for the slow down.
But now the problem is that I don't know how to get InputsAtCompileTime = 6 at compile time.

After looking at the DenseFunctor definition in LevenbergMarquardt.h, I have tried this change in my example code:

Code: Select all
 
class lmdif_functor: public DenseFunctor<double, 6, -1>
{
   public:
      lmdif_functor(Matches &matches,
               Camera &camera):
                           _matches(matches),
                           _camera(camera),
                           DenseFunctor(6,matches.rows()*2) {}

  ....


This should set InputsAtCompileTime = 6, and ValuesAtCompileTime = -1 in DenseFunctor,
however I get the compile error below which seems to indicate that lmqrsolv expects a PermutationMatrix with dynamic size...

Code: Select all
t:\eigen\eigen3.2.5\unsupported\eigen\src\levenbergmarquardt\lmpar.h(118): error C2784: 'void Eigen::internal::lmqrsolv(Eigen::Matrix<Scalar,Rows,Cols> &,const Eigen::PermutationMatrix<-1,-1,Index> &,const Eigen::Matrix<Index,-1,1> &,const Eigen::Matrix<Index,-1,1> &,Eigen::Matrix<Index,-1,1> &,Eigen::Matrix<Index,-1,1> &)' : could not deduce template argument for 'const Eigen::PermutationMatrix<-1,-1,Index> &' from 'const Eigen::PermutationMatrix<SizeAtCompileTime,MaxSizeAtCompileTime>'
          with
          [
              SizeAtCompileTime=6,
              MaxSizeAtCompileTime=6
          ]
          t:\eigen\eigen3.2.5\unsupported\eigen\src\levenbergmarquardt\lmqrsolv.h(23) : see declaration of 'Eigen::internal::lmqrsolv'
          t:\eigen\eigen3.2.5\unsupported\eigen\src\levenbergmarquardt\lmonestep.h(92) : see reference to function template instantiation 'void Eigen::internal::lmpar2<Eigen::ColPivHouseholderQR<_MatrixType>,Eigen::Matrix<_Scalar,_Rows,_Cols>>(const QRSolver &,const VectorType &,const VectorType &,double,double &,VectorType &)' being compiled
          with
          [
              _MatrixType=Eigen::Matrix<double,-1,6>,
              _Scalar=double,
              _Rows=-1,
              _Cols=1,
              QRSolver=Eigen::ColPivHouseholderQR<Eigen::Matrix<double,-1,6>>,
              VectorType=Eigen::Matrix<double,-1,1>
          ]
          t:\eigen\eigen3.2.5\unsupported\eigen\src\levenbergmarquardt\lmonestep.h(22) : while compiling class template member function 'Eigen::LevenbergMarquardtSpace::Status Eigen::LevenbergMarquardt<_FunctorType>::minimizeOneStep(Eigen::Matrix<_Scalar,_Rows,_Cols> &)'
          with
          [
              _FunctorType=`anonymous-namespace'::lmdif_functor,
              _Scalar=double,
              _Rows=-1,
              _Cols=1
          ]
          t:\eigen\eigen3.2.5\unsupported\eigen\src\levenbergmarquardt\levenbergmarquardt.h(259) : while compiling class template member function 'Eigen::LevenbergMarquardtSpace::Status Eigen::LevenbergMarquardt<_FunctorType>::minimize(Eigen::Matrix<_Scalar,_Rows,_Cols> &)'
          with
          [
              _FunctorType=`anonymous-namespace'::lmdif_functor,
              _Scalar=double,
              _Rows=-1,
              _Cols=1
          ]
          leastsq_pose.cpp(223) : see reference to class template instantiation 'Eigen::LevenbergMarquardt<_FunctorType>' being compiled
          with
          [
              _FunctorType=`anonymous-namespace'::lmdif_functor
          ]


I don't know how to get around this error.
How could I change my example code to get InputsAtCompileTime = 6 at compile time?

Last edited by mtosas on Wed Sep 23, 2015 2:28 pm, edited 2 times in total.
mtosas
Registered Member
Posts
6
Karma
0
I always end up calculating the symbolic derivatives using wxMaxima.
The main drawback there is that a typo is easily made. Using Autodiff to verify these derivatives might help.

Thanks twithaar, wxMaxima sounds very interesting I'll have a look at it.
mtosas
Registered Member
Posts
6
Karma
0
I'm still trying to find a solution for this. Any help?


Bookmarks



Who is online

Registered users: Bing [Bot], Google [Bot], q.ignora, watchstar