我有一个稀疏模式不变的应用程序。让我们说我的计算是
形式sm3 = sm1 + sm2
然而,即使我将稀疏模式设置为在所有这些操作数中都相同,我的分析器显示大部分时间都花在分配和释放结果矩阵上。
这是我的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;
}
是否可以避免这些分配操作?
答案 0 :(得分:1)
目前这是不可能的,因为默认情况下稀疏矩阵被假定为别名。例如,如果你这样做:
m3 = m3 + m1;
m1
的模式未完全包含在m3
的模式中,然后直接在m3
内评估表达式是不可能的。在 future 中,我们可以使用以下语法强制重用目标内存:
m3.noalias() = m1 + m2;
与此同时,由于您的矩阵很小,您可以通过强制m1
和m2
的模式与m3
的模式相同来解决甚至获得更高的性能通过添加一些明确的零。然后,使用Eigen 3.3,您可以将稀疏加法投射到加密的向量中:
m3.coeffs() = m1.coeffs() + m2.coeffs();
即使m1
和m2
之间的交集较小,您也会获得非常高的加速(可能是一个数量级),因为您摆脱了内存间接,并从矢量化中受益(不要不要忘记启用AVX,例如-mavx
)。