如何避免具有Eigen的稀疏表达式中的内存分配

时间:2016-11-14 16:22:34

标签: c++ eigen

我有一个稀疏模式不变的应用程序。让我们说我的计算是

形式
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;
}

是否可以避免这些分配操作?

1 个答案:

答案 0 :(得分:1)

目前这是不可能的,因为默认情况下稀疏矩阵被假定为别名。例如,如果你这样做:

m3 = m3 + m1;

m1的模式未完全包含在m3的模式中,然后直接在m3内评估表达式是不可能的。在 future 中,我们可以使用以下语法强制重用目标内存:

m3.noalias() = m1 + m2;

与此同时,由于您的矩阵很小,您可以通过强制m1m2的模式与m3的模式相同来解决甚至获得更高的性能通过添加一些明确的零。然后,使用Eigen 3.3,您可以将稀疏加法投射到加密的向量中:

m3.coeffs() = m1.coeffs() + m2.coeffs();

即使m1m2之间的交集较小,您也会获得非常高的加速(可能是一个数量级),因为您摆脱了内存间接,并从矢量化中受益(不要不要忘记启用AVX,例如-mavx)。