Re: [eigen] projects using Eigen2 ? |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/eigen Archives
]
- To: eigen@xxxxxxxxxxxxxxxxxxx
- Subject: Re: [eigen] projects using Eigen2 ?
- From: "Benoit Jacob" <jacob.benoit.1@xxxxxxxxx>
- Date: Sat, 6 Dec 2008 19:44:48 +0100
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from:to :subject:in-reply-to:mime-version:content-type :content-transfer-encoding:content-disposition:references; bh=Dd/4ixdZy4Zo6qKFP4CzAE/n5EnNQmSE8O0BQl8mEIc=; b=Pn5CBnOD44y08vXRUp09g83GCmnRCTw2z+UwbR1KOk+gxxOZ9Xu313ah7rpcguWOwO wb/2RcBCnPXQsb10ixc9PCARrCGxItjiPqY6M2k1RTeydTQjZaJtNBN2LLqSeLRRZcmm 2aSphbFRRkYtYbOomkTiI64jXCmVRXdfjGsTk=
- Domainkey-signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:to:subject:in-reply-to:mime-version :content-type:content-transfer-encoding:content-disposition :references; b=FF4fBwS6sBDf0pzcdncs9h/ArZy57aAO5qYcsvp1esC/FJFJpky6jib/plo/DLxrlb jeHKfUJzxx+nlCugMpQj3E2eh1ArDuTg69Ma7CjdxE2m1MoogJ1lN7AO9hH1mgkZfbJr JbKsn1t2Kmxl+4m7jj/NX725rhSiuiZ3HPoNo=
and do note that if you go the comma-initializer way, it will check
that the sizes match so you can remove your asserts ;)
Cheers,
Benoit
2008/12/6 Benoit Jacob <jacob.benoit.1@xxxxxxxxx>:
> arf i can't resist:
>
> 131 A.block(0,0,n,n).setZero();
> 132 A.block(0,n,n,n)=Eigen::MatrixXd::Identity(n,n);
> 133 A.block(n,0,n,n)=Minvminus*gG;
> 134 A.block(n,n,n,n)=Minvminus*Q;
>
> purely cosmetic this is one of the cases where i think that corner() is neat:
>
> 131 A.corner(Eigen::TopLeft, n,n).setZero();
> 132 A.corner(Eigen::TopRight, n,n)=Eigen::MatrixXd::Identity(n,n);
> 133 A.corner(Eigen::BottomLeft, n,n)=Minvminus*gG;
> 134 A.corner(Eigen::BottomRight, n,n)=Minvminus*Q;
>
> Or alternatively the comma-initializer looks even more futuristic
> (though if you go for it, do benchmark as some compilers like ICC have
> had trouble with it in the past):
>
> A << Eigen::MatrixXd::Zero(n,n), Eigen::MatrixXd::Identity(n,n),
> Minvminus*gG, Minvminus*Q;
>
> Cheers,
> Benoit
>
>
> 2008/12/6 Benoit Jacob <jacob.benoit.1@xxxxxxxxx>:
>> One more remark: for what you're doing it's really much better if
>> christoffel is actually stored in row-major order as this makes the
>> rowwise sum do only contiguous memory accesses. Especially if n is
>> large enough (i guess it is say >= 10 otherwise you'd be using
>> fixed-size, right?) you'll benefit from vectorization.
>>
>> Cheers,
>> Benoit
>>
>> 2008/12/6 Benoit Jacob <jacob.benoit.1@xxxxxxxxx>:
>>> Thanks, i'll add the link to the wiki.
>>>
>>> 2008/12/6 Timothy Hunter <tjhunter@xxxxxxxxxxxx>:
>>>> while the eigen-specific parts are located at:
>>>> http://personalrobots.svn.sourceforge.net/viewvc/personalrobots/pkg/trunk/controllers/control_toolbox/
>>>> (in include/ for the template code, src/serial_chain_model.cpp and
>>>> test/ for the test units)
>>>
>>> OK so I search occurences of "Eigen::" in this file and comment below:
>>>
>>> 90 Eigen::MatrixXd M(n,n);
>>> 91 NEWMAT::Matrix mass(n,n);
>>> 92 chain_->computeMassMatrix(kdl_q,kdl_torque_,mass);
>>> 93 for(int i=0;i<n;i++)
>>> 94 for(int j=0;j<n;j++)
>>> 95 M(i,j)=mass(i+1,j+1);
>>>
>>> Here, if the storage order (colmajor or rowmajor) (Eigen defaults to
>>> column-major) is the same for M and mass, instead of this double for
>>> loop, you are better off using a Eigen::Map as it will potentially
>>> vectorize.
>>>
>>> Something like (using Eigen trunk):
>>> M = Eigen::MatrixXd::Map(mass.array_of_coefficients(), n, n);
>>>
>>> Now if mass is row-major, but it is a priority for you to optimize the
>>> copying from mass to M, then you can just declare M as a row-major
>>> matrix:
>>> Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor> M(n,n);
>>>
>>> 102 // ROS_DEBUG("5-");
>>> 103 for(int i=0;i<n;i++)
>>> 104 for(int j=0;j<n;j++)
>>> 105 for(int k=0;k<n;k++)
>>> 106 Q(i,j)+=christoffel(i*n+j+1,k+1)*kdl_q_dot(j);
>>>
>>> When I see this i want to cry "use Eigen expressions" but it's
>>> nontrivial as you're mixing Eigen with NEWMAT matrices.
>>> Again, assuming that you know the storage order of NEWMAT, you can get
>>> away with a Eigen::Map. Assuming it's column-major:
>>> Eigen::Map<Eigen::MatrixXd>
>>> map_christoffel(christoffel.array_of_coefficients(), n*n, n);
>>> for(int i=0;i<n;i++)
>>> for(int j=0;j<n;j++)
>>> Q(i,j) += map_christoffel.row(i*n+j).sum() * kdl_q_dot(j);
>>> // notice that you were doing unnecessary multiplications in
>>> the inner loop as kdl_q_dot(j) didn't depend on k
>>>
>>> Now from here we can see a further simplification using
>>> rowwise().sum() and a dot product:
>>>
>>> #include<Eigen/Array>
>>> Eigen::Map<Eigen::MatrixXd>
>>> map_christoffel(christoffel.array_of_coefficients(), n*n, n);
>>> for(int i=0;i<n;i++)
>>> Q.row(i) += map_christoffel.rowwise().sum().segment(i*n,n).dot(kdl_q_dot);
>>>
>>> Here I'm handling kdl_q_dot as a Eigen:: vector, i know that's not the
>>> case, but assuming it's stored contiguously in memory you can handle
>>> that again with a Eigen::Map.
>>>
>>> As you can see using Eigen expressions you go from 3 for loops down to
>>> 1. Assuming that the compiler isn't confused by that c++ abstraction,
>>> normally you can get much better performance. Do benchmark it before
>>> using it in production as we sometimes have bad surprises, depending
>>> on the version of GCC, sometimes complex expressions are poorly
>>> optimized.
>>>
>>> I'll stop here for now:)
>>>
>>> Cheers,
>>> Benoit
>>>
>>
>
---