#pragma omp parallel for schedule使我的程序崩溃 我正在为C++中的Autodesk玛雅2013构建插件。我必须尽快解决一组优化问题。我正在使用open MP执行此任务。问题是我没有太多的并行计算经验。我尝试使用: #pragma omp parallel for schedule (static)

#pragma omp parallel for schedule使我的程序崩溃 我正在为C++中的Autodesk玛雅2013构建插件。我必须尽快解决一组优化问题。我正在使用open MP执行此任务。问题是我没有太多的并行计算经验。我尝试使用: #pragma omp parallel for schedule (static),c++,openmp,C++,Openmp,在我的for循环中(没有足够的理解它应该如何工作),它对我的一些代码工作得很好,但使我的另一部分代码崩溃 以下是因omp指令而崩溃的函数示例: void PlanarizationConstraint::fillSparseMatrix(const Optimizer& opt, vector<T>& elements, double mu) { int size = 3; #pragma omp parallel for schedule (stat

在我的for循环中(没有足够的理解它应该如何工作),它对我的一些代码工作得很好,但使我的另一部分代码崩溃

以下是因omp指令而崩溃的函数示例:

void PlanarizationConstraint::fillSparseMatrix(const Optimizer& opt, vector<T>& elements, double mu)
{
    int size = 3;
    #pragma omp parallel for schedule (static)
    for(int i = 0; i < opt.FVIc.outerSize(); i++)
    {
        int index = 3*i;
        Eigen::Matrix<double,3,3> Qxyz = Eigen::Matrix<double,3,3>::Zero();
        for(SpMat::InnerIterator it(opt.FVIc,i); it; ++it)
        {
            int face = it.row();
            for(int n = 0; n < size; n++)
            {
                Qxyz.row(n) += N(face,n)*N.row(face);
                elements.push_back(T(index+n,offset+face,(1 - mu)*N(face,n)));
            }
        }

        for(int n = 0; n < size; n++)
        {
            for(int k = 0; k < size; k++)
            {
                elements.push_back(T(index+n,index+k,(1-mu)*Qxyz(n,k)));
            }
        }
    }

    #pragma omp parallel for schedule (static)
    for(int j = 0; j < opt.VFIc.outerSize(); j++)
    {
        elements.push_back(T(offset+j,offset+j,opt.fvi[j]));
        for(SpMat::InnerIterator it(opt.VFIc,j); it; ++it)
        {
            int index = 3*it.row();
            for(int n = 0; n < size; n++)
            {
                elements.push_back(T(offset+j,index+n,N(j,n)));
            }
        }
    }
}
void planizationconstraint::fillSparseMatrix(常量优化器和opt、向量和元素、双mu)
{
int size=3;
#计划的pragma omp并行(静态)
for(int i=0;i
下面是一个代码示例,它可以很好地处理这些指令(并且因为它而更快)

Eigen::MatrixXd优化器::OptimizeLLGeneral()
{
经理;
表面应变表面(1,真);
平面化约束平面化(1,真,3^Nv,Nf);
manager.addConstraint(&surface);
经理。添加约束(平面化和平面化);
双μ=μ0;
for(int k=0;k

我的问题是,是什么让一个函数与omp指令配合得这么好,是什么让另一个函数崩溃?omp指令的不同之处是什么?

在使用openmp之前,您将一些数据逐个推回向量
元素。但是,使用openmp时,会有多个线程并行运行for循环中的代码。当多个线程同时将数据推回向量
元素
时,当没有代码确保一个线程在另一个线程完成之前不会开始推回时,问题就会发生。这就是你的代码崩溃的原因

要解决这个问题,可以使用局部buff向量。每个线程首先将数据推送到其私有本地缓冲向量,然后可以将这些缓冲向量连接到一个向量中

您会注意到,此方法无法保持向量
元素
中数据元素的原始顺序。如果您想这样做,您可以计算数据元素的每个预期索引,并直接将数据分配到正确的位置

更新
OpenMP提供API,让您知道使用了多少线程以及使用的线程。有关更多信息,请参阅和。

假设崩溃发生在
元素之一。push_back()
调用上是否公平?假设这一点非常公平。问题是存在的,但我对open-mp的理解还不够深入,不知道调用中是什么导致了问题:PAFAIK,
std::vector
可能不是线程安全的,它可能被两个(或更多)线程并行修改。您需要建立一个屏障,以确保一次只修改一个线程。相关:仅
std::vector::operator[]
是线程安全的,因为它不会更改内部存储器的内存组织。如果数据不保持其原始顺序,则没有问题。首先谢谢大家!第二:如何连接为每个线程创建的buff向量?你需要知道你以前有多少线程或者类似的东西?然后创建一个buff向量数组,或者你只需要在opn mp指令中将循环中的一个内部变量声明为private?有关如何获得最大可能线程数以及你在哪个线程中的更多信息,请参阅和。我尝试了这个链接,它起到了作用!谢谢是的,那是一个更优雅的。
Eigen::MatrixXd Optimizer::OptimizeLLGeneral()
{
    ConstraintsManager manager;
    SurfaceConstraint surface(1,true);
    PlanarizationConstraint planarization(1,true,3^Nv,Nf);
    manager.addConstraint(&surface);
    manager.addConstraint(&planarization);
    double mu = mu0;
    for(int k = 0; k < iterations; k++)
    {
        #pragma omp parallel for schedule (static)
        for(int j = 0; j < VFIc.outerSize(); j++)
        {
            manager.calcVariableMatrix(*this,j);
        }
        #pragma omp parallel for schedule (static)
        for(int i = 0; i < FVIc.outerSize(); i++)
        {
            Eigen::MatrixXd A = Eigen::Matrix<double, 3, 3>::Zero();
            Eigen::MatrixXd b = Eigen::Matrix<double, 1, 3>::Zero();
            manager.addLocalMatrixComponent(*this,i,A,b,mu);
            Eigen::VectorXd temp = b.transpose();
            Q.row(i) = A.colPivHouseholderQr().solve(temp);
        }
        mu = r*mu;
    }
    return Q;
}