【问题标题】:Strategies for filling an Eigen3 sparse matrix when the order of insertion is known已知插入顺序时填充 Eigen3 稀疏矩阵的策略
【发布时间】:2019-09-04 12:58:25
【问题描述】:

所以在我的非线性有限元求解器中,我使用 Eigen3 稀疏矩阵和 LDLT 分解。

问题是,这个因式分解需要在动态模拟过程中执行多次,并且花费大量时间在基于三元组的迭代矩阵中插入系数(保留存储空间)。

关于如何利用稀疏性不变和插入顺序相同的事实,有什么好的策略吗?当形成这个矩阵,循环模型中的元素、耦合等时,在模拟过程中的每个时间步,插入的顺序都是相同的。

使用 coeffref 将模拟时间增加了大约 10 倍。

我一直在考虑对模型进行一次传递并直接形成指向系数矩阵中相应位置的指针,但这似乎有点危险,尤其是因为 LDLT 分解是在两者之间运行的。

【问题讨论】:

  • LDLT 分解不会改变输入矩阵,所以你的想法应该被保存(当然,你应该用很多额外的断言运行一次)。
  • 谢谢,这是一个很好的观点。如果有确保存储不被更改的好方法,那么形成一个指针数组可能会起作用......

标签: c++ performance sparse-matrix eigen numerical-methods


【解决方案1】:

如果您的矩阵的稀疏模式在每个时间步都没有变化,那么您可以直接使用valuePtr() 更改原始数据数组的值。这非常简单,如果需要可以并行完成。如果你能弄清楚如何以线性方式做到这一点,即

SparseMatrix<double> A;

for(int i = 0; i < n; i++)
   A.valuePtr()[i] = ...

然后它会很快变得愚蠢(与避免缓存未命中和其他黑魔法有关)。至于之前的评论,即 LDLT 分解不会改变,从理论的角度来看是正确的。但是,根据 Eigen 文档:

"在factorize()中,计算系数矩阵的因子。每次矩阵的值变化时都要调用这一步。但是,矩阵的结构模式不应在多个调用之间更改。”

https://eigen.tuxfamily.org/dox/group__TopicSparseSystems.html

我认为这是因为因子存储在求解器对象中,尽管我可能是错的。测试应该很容易以一种或另一种方式确认。也就是说,我认为您必须在更改值后致电factorize()。尽管如此,您只需调用一次analyzePattern() 例程就可以节省大量时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-23
    • 2012-07-28
    • 2023-04-05
    相关资源
    最近更新 更多