首页 > 解决方案 > OpenMP 以原子方式更新数组值

问题描述

我试图解决的问题如下:

我有一个很大的点集,我尝试将其分成较小的点集。我知道较小的尺寸,我正在尝试使用较大的并行填充较小的尺寸。为了做到这一点,我有一个每个较小点集的索引数组,这将帮助我正确填充我的点集。我开发了以下代码。但是该omp atomic capture指令并不能帮助我获得与顺序相同的结果。

// points
std::vector<Eigen::Matrix3Xd> points(numberofPointSets);

// initialize arrays
for (auto& pointSetInformation: pointSetsInformation)
{
    int pointSetSize = getPointSetSize();
    int index = getIndexOfPointsSet();

    points[index].resize(3, pointSetSize);
}

// currentIndices to assign specific columns of the matrix in parallel
std::vector<int> currentIndices(numberofPointSets, -1);

// Assign arrays
#pragma omp parallel num_threads(numberOfThreads) shared(pointsArray, points, currentIndices) default(none)
{
    int index;
    int currentIndexInCurrentPointSet;
    double point[3];

    #pragma omp for schedule(static)
    for (int i = 0; i < input->GetNumberOfPoints(); ++i)
    {
        index = getIndexOfPointsSet();

        // update currentIndices (we start from -1, that's why this happens first)
        #pragma omp atomic capture
        currentIndexInCurrentPointSet = ++currentIndices[index];

        pointsArray->GetPoint(i, point);
        points[index](0, currentIndexInCurrentPointSet) = point[0];
        points[index](1, currentIndexInCurrentPointSet) = point[1];
        points[index](2, currentIndexInCurrentPointSet) = point[2];
    }
}

我错过了什么吗?指令可以omp atomic capture更新数组单元格,还是只更新变量?

提前非常感谢。

编辑:

i有没有办法强制执行与变量相同的操作顺序?

标签: c++multithreadingparallel-processingopenmpatomic

解决方案


有没有办法强制执行与 i 变量相同的操作顺序?

您尝试使用 OpenMP有序子句

#pragma omp parallel num_threads(numberOfThreads) shared(pointsArray, points, currentIndices) default(none)
{
    int index;
    int currentIndexInCurrentPointSet;
    double point[3];

    #pragma omp for ordered schedule(static, 1)
    for (int i = 0; i < input->GetNumberOfPoints(); ++i)
    {
        #pragma omp ordered
        {
            index = getIndexOfPointsSet();
            currentIndexInCurrentPointSet = ++currentIndices[index];
        }
        pointsArray->GetPoint(i, point);
        points[index](0, currentIndexInCurrentPointSet) = point[0];
        points[index](1, currentIndexInCurrentPointSet) = point[1];
        points[index](2, currentIndexInCurrentPointSet) = point[2];
    }
}

推荐阅读