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

How to resize properly big matrices

Tags: None
(comma "," separated)
noir.sender
Registered Member
Posts
6
Karma
0

How to resize properly big matrices

Thu Feb 26, 2009 6:01 pm
Hi there all,

First of all congrats for the library, looks really great. I am a new user to eigen so i have some questions and observations

I deal with very big matrices (e.g. 150000 x 1000) and i do not know the size in advance so initially i alllocate a very big matrix and then start chopping columns and rows. However, i noticed the following:: resize(int, int) is desctructiveand data are not preserved. I wud expect when u resize something: e.g in shrinking u throw away the extra data preserving the existing ones and in expanding u reallocate but keep the previous ones and fill with zeros or whatever value u desire the new elements. I think the logic of resize() is quite straightforward and a welcome feature for many users.

I solve the shrinking problem like this: e.g.
MatrixXf data(1000,1000);
/* calculations here*/
data = data.block(0 ,0, 900,900).eval();

Expanding:
MatrixXf data(1000,1000);
//new matrix
MatrixXf new_data (1500,1500);
new_data.block(1000,1000) = data;
data = new_data; //not ellegant

Any proposals?? Better ways??
In another post: solved-problem-wit ... 22998.html

i saw one solution:
MatrixXd mat = MatrixXd::Zero(10,10);
mat.set( (MatrixXd(11,10) << mat, vec.transpose()).finished() );

but there is no set() function...

In general it wud be quite handy to inserting and extracting row/columns or matrices with automatic resize or maybe i am missing something in the API...

thanks,

noir
User avatar
bjacob
Registered Member
Posts
658
Karma
3
Conservative resizing is much more costly than destructive, that's why resize() is destructive. If you want conservative resizing, right now we don't offer it so indeed you have to do it yourself, but then you could make it a Matrix plugin (see http://eigen.tuxfamily.org/dox/Customiz ... MatrixBase but here you want to do a EIGEN_MATRIX_PLUGIN instead) so afterwards you can use matrix.conservativeResize() as if it were part of Eigen.

I solve the shrinking problem like this: e.g.
MatrixXf data(1000,1000);
/* calculations here*/
data = data.block(0 ,0, 900,900).eval();

Expanding:
MatrixXf data(1000,1000);
//new matrix
MatrixXf new_data (1500,1500);
new_data.block(1000,1000) = data;
data = new_data; //not ellegant


That's not optimally efficient as you perform 1 redundant deep copy when it's enough to copy pointers. Indeed it's difficult to do that optimization from outside Eigen but at least you can do it in a EIGEN_MATRIX_PLUGIN.

i saw one solution:
MatrixXd mat = MatrixXd::Zero(10,10);
mat.set( (MatrixXd(11,10) << mat, vec.transpose()).finished() );
but there is no set() function...

It was removed, use operator= instead now.


Join us on Eigen's IRC channel: #eigen on irc.freenode.net
Have a serious interest in Eigen? Then join the mailing list!
noir.sender
Registered Member
Posts
6
Karma
0
bjacob wrote:Conservative resizing is much more costly than destructive, that's why resize() is destructive. If you want conservative resizing, right now we don't offer it so indeed you have to do it yourself, but then you could make it a Matrix plugin (see http://eigen.tuxfamily.org/dox/Customiz ... MatrixBase but here you want to do a EIGEN_MATRIX_PLUGIN instead) so afterwards you can use matrix.conservativeResize() as if it were part of Eigen.

I solve the shrinking problem like this: e.g.
MatrixXf data(1000,1000);
/* calculations here*/
data = data.block(0 ,0, 900,900).eval();

Expanding:
MatrixXf data(1000,1000);
//new matrix
MatrixXf new_data (1500,1500);
new_data.block(1000,1000) = data;
data = new_data; //not ellegant


That's not optimally efficient as you perform 1 redundant deep copy when it's enough to copy pointers. Indeed it's difficult to do that optimization from outside Eigen but at least you can do it in a EIGEN_MATRIX_PLUGIN.

i saw one solution:
MatrixXd mat = MatrixXd::Zero(10,10);
mat.set( (MatrixXd(11,10) << mat, vec.transpose()).finished() );
but there is no set() function...

It was removed, use operator= instead now.



Thanks for the quick reply. Yes the deep copy is really inellegant.
So i replace this line: data = new_data; //not ellegant
with: data.swap(new_data);

If i get free time i will try to contribute using EIGEN_MATRIX_PLUGIN;

Cheers,

noir

noir
with
User avatar
bjacob
Registered Member
Posts
658
Karma
3
Thanks for the quick reply. Yes the deep copy is really inellegant.
So i replace this line: data = new_data; //not ellegant
with: data.swap(new_data);


ah yes, indeed this is efficient as it just swaps pointers.

If i get free time i will try to contribute using EIGEN_MATRIX_PLUGIN;


it's for yourself, if it's more convenient for you :)

I don't know yet whether we want this _in_ Eigen (no strong opinion)


Join us on Eigen's IRC channel: #eigen on irc.freenode.net
Have a serious interest in Eigen? Then join the mailing list!
Hauke
Registered Member
Posts
109
Karma
3
OS
Hi,

noir.sender wrote:If i get free time i will try to contribute using EIGEN_MATRIX_PLUGIN;


In case there is still some interest in this method - I just had to implement it.

Code: Select all
inline void conservativeResize(int rows, int cols)
{
   PlainMatrixType tmp(rows, cols); // alternatively: PlainMatrixType::Zero(rows,cols)
   const int common_rows = std::min(rows, this->rows());
   const int common_cols = std::min(cols, this->cols());
   tmp.block(0,0,common_rows,common_cols) = this->block(0,0,common_rows,common_cols);
   this->derived().swap(tmp);
}

inline void conservativeResize(int size)
{
   EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)

   if (RowsAtCompileTime == 1)
   {
      PlainMatrixType tmp(1,size); // alternatively: PlainMatrixType::Zero(1,size)
      const int common_size = std::min(cols(),size);
      tmp.block(0,0,1,common_size) = this->block(0,0,1,common_size);
      this->derived().swap(tmp);
   }
   else
   {
      PlainMatrixType tmp(size,1); // alternatively: PlainMatrixType::Zero(size,1)
      const int common_size = std::min(rows(),size);
      tmp.block(0,0,common_size,1) = this->block(0,0,common_size,1);
      this->derived().swap(tmp);
   }
}


- Hauke
noir.sender
Registered Member
Posts
6
Karma
0
nice stuff hauke! thanks for the feedback!

had already used some partial temporary solutions but this is much better!

g.

noir
daviddoria
Registered Member
Posts
46
Karma
0
OS
Just an update - .conservativeResize(rows, cols) now seems to be a part of Eigen!


Bookmarks



Who is online

Registered users: Bing [Bot], Google [Bot], kesang, Sogou [Bot], Yahoo [Bot]