c++ - Eigen 中填充稀疏矩阵的速度取决于节点数或边数?

标签 c++ arrays sparse-matrix eigen

我填充了两个网络的边缘。

一个是大约 4000 个节点和 80000 条边。

另一个大约是 80000 个节点和 1300000 个边。

代码如下:

SparseMatrix<int,Eigen::RowMajor> mat(nodenumber,nodenumber); //nodenumber is 4000 or 80000
mat.reserve(VectorXi::Constant(nodenumber,50)); //preserve 50 non-nero elements
for (i,j) in edges:
    mat.insert(i,j) = 1;
    mat.insert(j,i) = 1;
}

(4000 个节点,80000 个边)用 1.5 秒完成。

(80000 个节点,1300000 个边)用 600 秒完成。

但我认为填充矩阵的速度应该取决于边。

对于(80000 个节点,1300000 条边)网络,这应该是 1.5*1300000/80000。

我是对还是错?

如何提高填充矩阵的速度?

谢谢!

最佳答案

查看这一行:mat.reserve(VectorXi::Constant(nodenumber,50));documentation of Eigen on sparse matrix 的这一点:

Note that when calling reserve(), it is not required that nnz is the exact number of nonzero elements in the final matrix. However, an exact estimation will avoid multiple reallocations during the insertion phase.

因此,考虑将 50 更改为大于边数的值,以减少重复分配。尽管如此,它只会略微减少挂钟时间,如 Filling a sparse matrix 部分所述。

Because of the special storage scheme of a SparseMatrix, special care has to be taken when adding new nonzero entries. For instance, the cost of a single purely random insertion into a SparseMatrix is O(nnz), where nnz is the current number of non-zero coefficients.

因此,通过随机插入填充整个矩阵的时间复杂度为 O(nnz^2/2)。实际上,如果您计算 80000^2 和 1300000^2,比率将与 1.5/600 相差不远,这些数字是您报告的执行时间。

为了争取一些时间,您可能对 batch insertion 感兴趣,即一次插入所有边。阅读 Eigen 文档的这一部分:它真的很值得!实际上,此网页上提供的这段代码可能会对您有所帮助。

typedef Eigen::Triplet<double> T;
std::vector<T> tripletList;
tripletList.reserve(nnz);
for(...)
{
    // ...
    tripletList.push_back(T(i,j,v_ij));
}
SparseMatrixType mat(rows,cols);
mat.setFromTriplets(tripletList.begin(), tripletList.end());

作为替代方案,您还可以为每一列保留存储空间,如果您知道每列非空元素的最大数量并且它不是太大的话:

mat.reserve(VectorXi::Constant(cols,6));

关于c++ - Eigen 中填充稀疏矩阵的速度取决于节点数或边数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51941774/

相关文章:

c++ - 使用boost asio获取网页

c++ - "new"没有在类中调用指定的构造函数?

arrays - Coffeescript,数组长度未定义

python - 如何在 Python 中有效地添加稀疏矩阵

python - 带有固定种子的 scipy.sparse.linalg.eigsh

c++ - 将 C++ 实例方法分配给全局函数指针?

C++ 传递未初始化的变量

java - 简单 ViewPager - 单一布局

Python:打印所有以相同字母开头和结尾的名字

complexity-theory - 稀疏对称矩阵预乘全向量最低阶复杂度引用