Reputation: 66
Eigen reallocate too many times.
[ Problem ]
setZero does not free the memory - and that is great. setZero set the innerNNZ to zero : that is (almost) correct since I want a zero matrix.
If I want to set a value on an allocated location in the matrix, the code looks after innerNNZ to determine that nothing has been allocated and reallocate everything.
Apparently, using coeffRef() instead of insert() won't help for the same reason.
[ Background ]
I'm manipulating SparseMatrix. At first I preallocate the matrix based on some pattern. Secondly I open a loop to : - set the matrix to zero - stamp values in it - do some math
I want to zero the matrix at the beginning of the loop (I do not stamp on the same pattern each time). Setting it to zero leads innerNNZ to be zeroed and the stamping (element by element) will realloacte : huge lost amount of time.
[ Code to test ]
int nx = 10;
int ny = nx;
Eigen::VectorXi sizeToReserve(nx);
for(int i = 0; i < nx; i++)
sizeToReserve[i] = myOwnBusiness(i);
SparseMatrix<double> mat;
mat.uncompress();
mat.reserve(sizeToReserve);
for(int i = 0; i < nbRun; i++) {
mat.setZero();
for(int j = 0; j < nx; j++) {
for (int k = 0; k < ny; k++) {
mat.insert(j,k) = aValue(i,j,k);
}
}
// Do fancy stuff
}
I would expect mat.insert to not reallocate the memory.
[ Trick ]
I will scale the matrix to zero to avoid touching the innerNNZ and outerIndex array.
Upvotes: 1
Views: 317
Reputation: 10596
You can iterate over the non-zeros with (adapted from the docs):
for (int k=0; k<mat.outerSize(); ++k)
for (SparseMatrix<double>::InnerIterator it(mat,k); it; ++it)
it.valueRef() = 0.0;
Another option would be to wrap the data pointer in an Eigen::Map<VectorXd>
and use that to setZero()
:
Map<VectorXf> myMap(mat.valuePtr(), mat.nonZeros());
myMap.setZero();
Upvotes: 2