【问题标题】:Eigen Iterate over inner iterator in sparse matrix with SIMD使用 SIMD 对稀疏矩阵中的内部迭代器进行 Eigen 迭代
【发布时间】:2018-11-15 10:14:51
【问题描述】:

在稀疏矩阵的特征内迭代器上应用simd:

for(auto i = 0; i < smat.outerSize(); i++){
    #pragma omp simd
    for(SMat::InnerIterator iter(smat,i); it; ++it){
        it.valueRef() = value;
    }
}

这不起作用,因为 for 循环中括号初始化的错误与 simd 不兼容。接下来我试试:

    SMat::InnerIterator iter(smat,i);
    #pragma omp simd
    for(;it;++it){ // error, declaration or initialization expected

    for(it;it;++it){ // error, declaration or initialization expected

然后我用谷歌搜索文档,只遇到一个短语提到 simd 在添加稀疏矩阵时是隐式的(所以我知道这是可能的,并且在 eigen 的模板化肠子中的某个地方,有一个 simd 循环内向量;但我不知道怎么做)。

接下来,我检查并发现Eigen 在整个代码中只有三个对omp 的调用。这是否意味着 Eigen 仅依赖于编译器标志来激活 simd?

最后,我尝试将循环更改为规范形式(根据下面的评论),并得到一个不同的错误:

for(auto it = typename SMat::InnerIterator(smat,i); it; ++it)

// error: '#pragma omp simd' used with class iteration variable 'it'

使用 simd 触发或迭代 Eigen::SparseMatrix&lt;double&gt; 中的内部向量的预期方式是什么?

【问题讨论】:

  • 您的编译器支持什么版本的 OpenMP?无论如何,在 OpenMP 中,循环必须采用所谓的规范形式,在您的情况下应该类似于for (auto it = Eigen::SparseMatrix&lt;double&gt;::InnerIterator(smat, i); it != false; ++it)
  • Eigen 中的 SIMD 几乎完全使用编译器内在函数完成。您在哪里找到“添加稀疏矩阵时 simd 是隐式的”? (取决于您实际添加的内容,但尤其是添加两个具有不同非零模式的稀疏矩阵,这听起来很困难。
  • InnerIterator 目前确实没有记录。它可以与标准的随机访问迭代器兼容(它缺少一些运算符,如it-diff--itit-=diff)。供参考,来源在这里:bitbucket.org/eigen/eigen/src/0fdf0e56237f92e5/Eigen/src/…
  • @chtz: InnerIteratoreigen.tuxfamily.org/dox/group__TutorialSparse.html 中被提及,但这是一个教程,并没有详细说明类型属性。
  • @DanielLangr 规范循环形式 not 允许 != 作为运算符。

标签: c++ openmp eigen simd


【解决方案1】:

在这种情况下无法应用#pragma omp simd。根据 OpenMP 规范(2.6 规范循环形式),“在 simd 构造中,唯一允许的随机访问迭代器类型 [...] 是指针类型。”。所涉及的迭代器显然不是指针类型。可以将它们更改为允许 OpenMP simd 循环,但这需要深入了解相关类型的实现和数据布局。

【讨论】:

  • 如果稀疏矩阵连续打包它们的行数据,并且有一个单独的列表来列出非零元素的位置,InnerIterator 可能只是循环相当于std::vector&lt;double&gt;。在这种情况下,可以将其重新表述为与 OpenMP 兼容的循环。
  • eigen.tuxfamily.org/dox/group__TutorialSparse.html 表示有 4 个紧凑数组。其中之一是Values,它“存储非零的系数值”。所以是的,根据 Eigen 教程,存储布局的记录行为。以及为什么InnerIterator可以高效实现。所以你只需要&amp;Values[0] 和一个长度或结束指针就可以了,就像std::vector&lt;&gt;
【解决方案2】:

如果您想更改每个条目并且您的矩阵是压缩形式,您可以使用.coeffs() 成员函数:

smat.coeffs() = value;

遍历单个列会有点困难,但您可以通过查看 smat.outerIndexPtr()[col] 找出每列的开头(col+1 的开头是 col 的结尾)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-15
    • 1970-01-01
    • 2021-07-10
    • 2014-04-20
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    相关资源
    最近更新 更多