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

Fixed Sized Matrices and Code Performance

Tags: None
(comma "," separated)
amadichinedu
Registered Member
Posts
4
Karma
0
Hello!

I could not think of an apt title but I will go right into it. I am working on an embedded project and I need linear algebra library
so I chose Eigen. It has been very good so far, I tested my code on Visual Studio with optimizations on and it reports that
the code compiled in 0.008 seconds, but my console window doesn't open up that fast. It takes about 30 seconds for it to open
up (I build in release mode by the way).

I have 3 things I want to get some assistance on. Firstly, I have opted for fixed sized matrices of type float because the microcontroller
I am to upload my code to doesn't work well with dynamic sized matrices of type double. I do know that by doing
Code: Select all
Matrix <float, 10, 10> A

I am declaring Matrix A as a fixed size. My question, at what size does using a fixed sized matrix become a performance issue? In my
work the biggest matrix size I have is a
Code: Select all
 48 by 12 Matrix
.

The section of code below will be used to ask my next two questions:

Code: Select all
 
MatrixXf P_output(MatrixXf *A, MatrixXf *C, int *ny)
{
   MatrixXf prod;
   prod = *C * *A;

   int row_size = prod.rows();
   int column_size = prod.cols();

   // P
   MatrixXf P(row_size**ny, column_size); // Declaring P as an empty matrix
   int t = 0; // Px row index

            // A matrix power loop
   for (int i = 1; i < *ny + 1; i++) {
      MatrixXf CAprod = *C * (*A).pow(i); // C times A
                                     // Columns
      for (int l = 0; l < column_size; l++)
      {
         // Rows
         for (int k = 0; k < row_size; k++)
         {
            P(k + (row_size*t), l) = CAprod(k, l);
         }
      } t++;
   }
   return P;
}


So this is a function that takes in the arguments by reference (I did it this way to speed things up, to avoid making copies each time the function
was called). Now the thing is, I know the sizes of matrices A and B, hence I can declare them as fixed matrix types. So how would you think i could
declare the type of the matrix P (I am assuming that you cannot mix dynamic and fixed matrix types)?


Lastly, in this line in the for loop,

Code: Select all

MatrixXf CAprod = *C * (*A).pow(i); // C times A



I am multiplying C with A raised to a power. Is there another way to compute this that is faster? There was a method I tried:

Code: Select all
 
 MatrixXf CAprod = (*C).array()*(*A).array().pow(i);


it is faster but outputs the wrong answer.

I made some tweaks yesterday by changing the dynamically sized matrices ( I could change) to fixed sized ones and it improved my performance but I am
afraid that my STM32F4 microcontroller still isn't as fast. My last option might be to hardcode some of the variables to be
Code: Select all
const static


I tremendously appreciate any input I can get from you. Please ask me for any clarifications. Thank you!
amadichinedu
Registered Member
Posts
4
Karma
0
PS

The console window reporting speed of 0.008 s gets to me especially since it takes 30 seconds
for the window to open. Is this the right way to clock the computation:

Code: Select all

high_resolution_clock::time_point t1 = high_resolution_clock::now();
// Code in between
.
.
.
high_resolution_clock::time_point t2 = high_resolution_clock::now();

duration<double> time_span = t2 - t1;
std::cout << "It took me " << time_span.count() << " seconds.";



Thanks again
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
Why do you use pointers ? References, and even const references would be more appropriate:

MatrixXf P_output(const MatrixTypeA &A, const MatrixTypeC &C, int ny)

and this will make your code more readable. You can mix fixed and dynamic sized objects, you can even fix only one dimension, but unless ny is known at compile-time, there is no way to avoid a dynamic size for P.

Regarding A.pow(i), better compute it incrementally during the for loop, and then make use of Eigen's API to avoid stupid for loops and temporaries:

Code: Select all
const int Rows = MatrixTypeC::RowsAtCompileTime;
const int Cols = MatrixTypeA::ColsAtCompileTime;
Matrix<float,Dynamic,Cols> P;
MatrixTypeA pow_A_i = A;
for (int i = 0; i < ny ; i++) {
  P.middleRows<Rows>(i*Rows).noalias() = C * pow_A_i;
  if(i+1<ny) pow_A_i = pow_A_i * A;
}
return P;


for your embedded platform you might want to enforce a simpler product implementation using lazyProduct:

Code: Select all
  P.middleRows<Rows>(i*Rows).noalias() = C.lazyProduct(pow_A_i);
  if(i+1<ny) pow_A_i = pow_A_i.lazyProduct(A);
amadichinedu
Registered Member
Posts
4
Karma
0
Hello,

I took your advice and decided to have a test run where matrices C and A are dynamically fixed:

Code: Select all
   MatrixXf A;
   A << 0.9f, -0.5f,
      0.0f, 0.8f;

   MatrixXf C;

   C << 2.0f, 0.5f,
      -1.0f, 1.0f;
   int ny = 4;

   const int Rows = MatrixXf::RowsAtCompileTime;
   const int Cols = MatrixXf::ColsAtCompileTime;
   Matrix<float, Dynamic, Cols> P;
   
   MatrixXf pow_A_i = A;

   for (int i = 0; i < ny; i++)
   {
      P.middleRows<Rows>(i*Rows).noalias() = C * pow_A_i;
      if (i + 1<ny) pow_A_i = pow_A_i * A;
   }

   cout << P << endl;



But doing this results in a program crash and this is the only section of code running.

Likewise, if I define the matrices A and C as fixed, it also crashes

Code: Select all
   Matrix2f A;
   A << 0.9f, -0.5f,
      0.0f, 0.8f;

   Matrix2f C;
   C << 2.0f, 0.5f,
      -1.0f, 1.0f;
   int ny = 4;

   const int Rows = Matrix2f::RowsAtCompileTime;
   const int Cols = Matrix2f::ColsAtCompileTime;
   Matrix<float, Dynamic, Cols> P;
   Matrix2f pow_A_i = A;

   for (int i = 0; i < ny; i++)
   {
      P.middleRows<Rows>(i*Rows).noalias() = C * pow_A_i;
      if (i + 1<ny) pow_A_i = pow_A_i * A;
   }

   cout << P << endl;



I am expecting P to output this:

Code: Select all
1.8 -0.6
-0.9 1.3
1.62 -1.38
-0.81 1.49
-1.458 -1.914
-0.729 1.597
1.3122 -2.2602
-0.6561 1.6421


Please let me know what I am doing wrong. Thank you Ggael


Bookmarks



Who is online

Registered users: Bing [Bot], daret, Google [Bot], sandyvee, Sogou [Bot]