【问题标题】:Eigen SparseMatrix with OpenMP - crash when inserting values带有 OpenMP 的 Eigen SparseMatrix - 插入值时崩溃
【发布时间】:2018-06-20 16:38:59
【问题描述】:

对于一个非常简单的测试示例,当尝试在 OpenMP 构造中填充 Eigen::SparseMatrix 时,应用程序崩溃。

SparseMatrix<double> A_mat( nCol, nRow );
//A_mat.reserve( VectorXi::Constant( nCol, nRow ) );  // When commented crashes

auto numThreads = omp_get_max_threads();
#pragma omp parallel for num_threads( numThreads )
for ( int j = 0; j < nCol; ++j )
    {
        for ( int i = 0; i < nRow; ++i )
            {
                if ( i >= j )
                    {
                        double val           = i * nCol + j;
                        A_mat.insert( i, j ) = val;
                    }
            }
    }

仅当我使用1 线程时,此代码才会按预期运行。但是,当使用多个线程运行时,会引发以下错误:

double free or corruption (!prev)
double free or corruption (!prev)
double free or corruption (!prev)
double free or corruption (top)
double free or corruption (!prev)
double free or corruption (out)

当我取消注释以下行时:

A_mat.reserve( VectorXi::Constant( nCol, nRow ) );

然后上面给定的代码块即使在使用多个线程运行时也会再次产生预期的结果。

有人可以向我解释为什么会这样吗?

【问题讨论】:

  • 这是否符合稀疏矩阵的条件?它看起来更像三角形。
  • 为了这个例子没关系。我可以用任何其他方式填写它。

标签: c++ sparse-matrix eigen eigen3


【解决方案1】:

如果不进一步研究SparseMatrix,当您添加的元素超过其容量时,它几乎肯定必须(重新)分配内存。这不是线程安全的操作,因此您永远不应该同时向SparseMatrix 添加元素,除非您知道它不会重新分配。即使那样,您也应该检查文档以验证这样做是线程安全的,因为我对此表示怀疑(但可能同时插入不同的列或行可能没问题)。即使它不安全,它也可能不会崩溃,只会做错事(即未定义的行为)。

为了记录,这类似于std::vector 的行为方式。以向量重新分配的方式同时调用push_back 是重新分配的竞争条件,因此是未定义的行为(并且会很快导致您看到的双重释放)。 [当然,插入本身也会存在竞争条件,SparseMatrix 可能会或可能不会避免在不同坐标的并发插入,但我不会打赌。]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多