问题
I have an application where the sparsity pattern is constant. Lets say that my computations are in the form
sm3 = sm1 + sm2
However, even I have set the sparsity pattern to be the same in all of those operands, my profiler shows that most of the time is spent in allocating and deallocating the result matrix.
Here is my MWE:
#include <eigen3/Eigen/Sparse>
#include <iostream>
int main(int argc, char *argv[])
{
using namespace Eigen;
SparseMatrix<double> sm1(2, 2), sm2(2, 2), sm3(2, 2);
// Populate sm1 and sm2
sm1.insert(0,0) = 2.0;
sm2.insert(1,1) = 3.0;
// Compute the result pattern
sm3 = sm1 + sm2;
// Copy the augmented pattern into the operands
sm1 = sm2 = sm3;
// This loop triggers a lot of new[] and delete[] calls
for(int i = 0; i < 1000; i++)
sm3 = sm2 + sm1;
}
Can those allocating operations be avoided?
回答1:
This is currently not possible because sparse matrices are assumed to alias by default. For instance, if you do:
m3 = m3 + m1;
with the pattern of m1
not entirely included in the one of m3
, then evaluating the expression directly within m3
would not be possible. In the future, we could enforce re-use of the destination memory with a syntax like:
m3.noalias() = m1 + m2;
In the meantime, since your matrices are small, you can workaround and even get higher performance by enforcing that the pattern of m1
and m2
are the same than the pattern of m3
by adding some explicit zeros. Then, with Eigen 3.3, you can cast the sparse addition into the addition of dense vectors:
m3.coeffs() = m1.coeffs() + m2.coeffs();
Even if the intersection between m1
and m2
is small, you will get very high speedups (probably one order of magnitude) because you get rid of the memory indirections, and benefit from vectorization (don't forget to enable AVX with, e.g., -mavx
).
来源:https://stackoverflow.com/questions/40593324/how-to-avoid-memory-allocations-in-sparse-expressions-with-eigen