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

Real-time processing

Tags: None
(comma "," separated)
jflebas
Registered Member
Posts
14
Karma
0

Real-time processing

Mon Jun 23, 2014 11:20 am
I'm trying to use Eigen with no heap allocation for real time processing.

As far as I know:

Matrix<double, Dynamic, Dynamic> allocates on the stack
Matrix<double, Dynamic, Dynamic, AutoAlign, 1, 1> allocates on the heap
and Matrix<double, 1, 1> allocates on the stack;

One way to use Eigen in real time is to resize matrices at startup, with a big size, then using only a fraction of this size.

My question is : with functions like : Rm.colPivHouseholderQr().solve(Rhs), how can I perform such computation with dynamic matrices?
The function will take the whole size of the matrix to do the operation which is not good as we want only a portion of this size to be treated.
Also we obviously can't use .resize()

So how to perform operations with real-time processing and big-sized matrices?

thanks
eacousineau
Registered Member
Posts
15
Karma
0
OS

Re: Real-time processing

Mon Jun 23, 2014 6:44 pm
This is more of an aside: I am interested in the same thing (real-time computing with Eigen), but taking the approach of attempting to pre-allocate everythnig during configuration time.

I've been working using these following tips, going off of what Adolfo mentioned, continuing some work that J.D. Yamakoski had been doing:
* http://eigen.tuxfamily.org/dox-devel/To ... tives.html
* http://www.orocos.org/forum/rtt/rtt-dev ... ltime-code

I need to slap in a quick license, but can upload the code in the next week or so.
It's relatively simple, thanks to Eigen's elegance.

I plan to look around for some timing metrics when using dynamic matrices and malloc()'s, in addition to maybe writing a few of my own if needed.
jflebas
Registered Member
Posts
14
Karma
0

Re: Real-time processing

Tue Jun 24, 2014 1:21 pm
hi

thanks for your answer

yes i've seen thoses links.

The only solution i've foound is to use Map<>

unfortunately, it doesn't work for everthing

for example i want to use
Code: Select all
Rm.colPivHouseholderQr().solve(Rhs)


and it raises an error (malloc not allowed) so it must create a temporary array somewhere. This is so frustrating!

i carefully mapped arrays of doubles to matrices.
Code: Select all
Map<MatrixXd> Rhs(denf_temp2.arr, denf_temp2.size1, 1);

i also cannot use fixed size stack arrays (if they are small) because it requires a compile-time fixed-size...

maybe i'll try this solution, but i don't know how to install patches...
http://listengine.tuxfamily.org/lists.tuxfamily.org/eigen/2010/03/msg00026.html

thanks
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS

Re: Real-time processing

Tue Jun 24, 2014 9:03 pm
If you call QR on matrices of the same size, then you can create the solver once and reuse it:

ColPivHouseholderQR<MatrixXd> qr(rows,cols);

qr.compute(A);
x = qr.solve(b);
jflebas
Registered Member
Posts
14
Karma
0

Re: Real-time processing

Wed Jun 25, 2014 7:22 am
thanks but the size of the matrices vary depending of the algorithm, so i cannot use your proposition.

But i got the thing working with no heap allocation, thanks to block<> !!

the thing is to create sufficiently big matrices at startup, then using "block" to limit the size of the matrices for the computation. The result is a bit ugly but works!

(i didn't checked for the results but i guess they are right)
Code: Select all
   Eigen::internal::set_is_malloc_allowed(true);
   Matrix<double, Dynamic,Dynamic> Rm2;
   Matrix<double, Dynamic,Dynamic> Ab;
   Ab.resize(150,50);
   Rm2.resize(150,50);
   Rm2.Random(150,50);

   MatrixXd Rhs2;
   Rhs2.resize(150,1);
   Rhs2.Random(150,1);
   Eigen::internal::set_is_malloc_allowed(false);
   Ab.block<50,1>(0,0) = (Rm2.block<50,50>(0,0)).colPivHouseholderQr().solve(Rhs2.block<50,1>(0,0));


no heap allocation, yay!

EDIT: oh no i cannot use it because it has to be fixed size numbers, so i cannot replace <50, 1> by <a, 1> (int a = 50)

:((((((

i works with const int though, but how to deal with it ? create thousands of switches() ?
darn
jflebas
Registered Member
Posts
14
Karma
0

Re: Real-time processing

Wed Jun 25, 2014 8:17 am
so i cannot use Eigen to solve Ax = b in real time ? that's so super great!

any other libraries that could do it in real time?

thanks

Jeff
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS

Re: Real-time processing  Topic is solved

Wed Jun 25, 2014 11:46 am
You can also do that:
Code: Select all
typedef Matrix<double,Dynamic,Dynamic,0,150,150> RTMatrixType;
ColPivHouseholder<RTMatrixType> qr_solver;
RTMatrixType A;
A.resize(50,50);
...
qr_solver.compute(A);
...
A.resize(99,60);
...
qr_solver.compute(A);
...


BTW, are you the same who is asking there: http://stackoverflow.com/questions/2440 ... pplication
jflebas
Registered Member
Posts
14
Karma
0

Re: Real-time processing

Wed Jun 25, 2014 12:28 pm
yes i'm the same, sorry about that, i don't want to disminish any of the commenters but i need an answer and quite quickly so i've put all the chances behind me. I will put your post to the answer with your name.

back to the topic :
I suppose there is no way to adapt this piece of code with other matrices than stack-created ones ?
Also it only works for fixed sizes of qr_solver (/!\ warning<- this question is potentially stupid) ? 8)

Jeff

Last edited by jflebas on Wed Jun 25, 2014 12:43 pm, edited 1 time in total.
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS

Re: Real-time processing

Wed Jun 25, 2014 12:38 pm
The matrix 'A' can be a Block or a Map. What's important is that the QR solver is allocated on the stack. But you can create it only once.
jflebas
Registered Member
Posts
14
Karma
0

Re: Real-time processing

Wed Jun 25, 2014 1:07 pm
excuse my noobiness, but how do i go from your code to x = b/a ?
jflebas
Registered Member
Posts
14
Karma
0

Re: Real-time processing

Wed Jun 25, 2014 1:12 pm
also when i type ColPivHouseholder, the compiler can't find it. did you mean ColPivHouseholderQR?

sorry i'm a bit lost
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS

Re: Real-time processing

Wed Jun 25, 2014 1:36 pm
A self-contained example:

Code: Select all
#define EIGEN_STACK_ALLOCATION_LIMIT (200*200*8)
#define EIGEN_RUNTIME_NO_MALLOC
#include <Eigen/Dense>
using namespace Eigen;

const int MaxSize = 150;
typedef Matrix<double,Dynamic,Dynamic,0,MaxSize,MaxSize> RTMatrixType;
typedef Matrix<double,Dynamic,1,0,MaxSize,1>             RTVectorType;
 
int main() {
 
  // The solver
  ColPivHouseholderQR<RTMatrixType> qr_solver;
 
  RTMatrixType A1;
  MatrixXd data(MaxSize,MaxSize);
  RTVectorType b, x;
 
  int n = 150;
 
  Eigen::internal::set_is_malloc_allowed(false);
 
  A1.setRandom(n,n);
  b.setRandom(n);
  qr_solver.compute(A1);
  x = qr_solver.solve(b);
 
  n = 60;
  A1.setRandom(n,n);
  b.setRandom(n);
  qr_solver.compute(A1);
  x = qr_solver.solve(b);
 
  n = 40;
  Block<MatrixXd> A2 = data.topLeftCorner(n,n);
  A2.setRandom();
  b.setRandom(n);
  qr_solver.compute(A2);
  x = qr_solver.solve(b);
}
jflebas
Registered Member
Posts
14
Karma
0

Re: Real-time processing

Wed Jun 25, 2014 2:01 pm
omg you rock! wans't obvious at all, and the doc is empty (or is it me?)

only drawback, the size used by matrices has to be small, but it's better than nothing, and i'm happy to stay with Eigen which i love.

Other off topic question : do you think most of the functions in Eigen are malloc-free ? Or will i be in trouble one day or another?

Jeff
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS

Re: Real-time processing

Wed Jun 25, 2014 3:11 pm
There is one complete example there: http://eigen.tuxfamily.org/dox/group__T ... tml#title5, and the ColPivHouseholderQR is documented there: http://eigen.tuxfamily.org/dox/classEig ... derQR.html.

But, yes most of the examples use the shortcuts which is probably not good because the recommended way should be to declare the solvers explicitly...
eacousineau
Registered Member
Posts
15
Karma
0
OS

Re: Real-time processing

Wed Jun 25, 2014 5:01 pm
That is quite awesome indeed!

I had also struggled with computing an inverse and caching it without allocation while also allowing it to be dynamically sized, so I used a combination of pointers and evalTo().

Code: Select all
// For preallocating inverters
typedef Eigen::PartialPivLU<Eigen::MatrixXd> MatrixInverter;
typedef boost::shared_ptr<MatrixInverter> MatrixInverterPtr;
...
class Test
{
  MatrixXd A;
  MatrixXd Ainv;
  MatrixInverterPtr inverter;

  void resize(int n)
  {
     A.resize(n, n);
     Ainv.resizeLike(A);
     inverter.reset(new MatrixInverter(n));
  }
 
  void update(...)
  {
    ...
    inverter->compute(A).inverse().evalTo(Ainv);
    ...
  }
};


The `update()` method passes the `set_is_malloc_allowed(false)` check without the need to allocate on the heap.
However, I guess there could then be issues with heap-fragmentation.

And regarding numericaly efficiency, is it more efficient to use the solver (especially for conditioning) as opposed to caching the matrix inverse?

Last edited by eacousineau on Wed Jun 25, 2014 5:20 pm, edited 4 times in total.


Bookmarks



Who is online

Registered users: Bing [Bot], claydoh, Google [Bot], rblackwell, Yahoo [Bot]