OpenMP - 并行循环

OpenMP - Parallel For Loop

本文关键字:循环 并行 OpenMP      更新时间:2023-10-16

我使用二维向量。我有两个操作:

  • 使用 (i,j) 从向量读取数据
  • 将项添加到矢量 (i,j)如何对准此代码?如果我只添加#pragma omp parallel for shared(tempVector, objVector),OpenMP可以防止日期竞赛吗?

    vector < myObject > objVector;
    vector< vector <int> > tempVector(4);
    for(int i = 0; i < objVector.size(); i++) {
        int x = objVector[i].X,
            y = objVector[i].Y;
        if(x <= Xmiddle+DIAMETER && y <= Ymiddle+DIAMETER)
        {
            tempVector[0].push_back(i);
        }
        if(x >= Xmiddle-DIAMETER && y <= Ymiddle+DIAMETER)
        {
             tempVector[1].push_back(i);
        }
        if(x <= Xmiddle+DIAMETER && y >= Ymiddle-DIAMETER)
        {
             tempVector[2].push_back(i);
        }
        if(x >= Xmiddle-DIAMETER && y >= Ymiddle-DIAMETER)
        {
             tempVector[3].push_back(i);
        }
    }
    

您需要使用 #critical 指令来正确访问共享变量:

#include <omp.h>
main()
{
   int x; 
   x = 0;
   #pragma omp parallel shared(x) 
   {
      #pragma omp critical 
      x = x + 1;
   }  /* end of parallel section */
}

示例取自:https://computing.llnl.gov/tutorials/openMP/#CRITICAL

如果我是你,我会考虑一些不同的东西(不幸的是,在这种情况下你不能使用 #reduction,但你绝对可以重新洗牌代码以获得相同的结果)。

不幸的是,在这种情况下,OpenMP 无法阻止数据竞争。共享子句允许所有线程查看向量变量,但它对它们的访问不执行任何操作。Vector 的 push_back 函数不是线程安全的,因为它可能导致 vector 的基础存储被重新分配(增长)。

此代码可以并行化,但它的扩展程度取决于您愿意投入多少实现工作。要确定适当的工作量,请确定整个应用程序花费多少时间。以下是并行化问题的两种(在众多可能的方法中):

  • 省力,性能稳定 - 使 tempVector 1D 和与 objVector 相同的大小。与其将 4 个带有索引列表的向量放入 objVector,不如让 tempVector[i] 成为 0-3 个 objVector[i] 的哪个箱。这可以通过一个简单的 openmp 并行来完成。稍后使用 tempVector 时,获取特定箱的所有值将涉及扫描所有 tempVector。如果只有 4 个箱,这实际上可能表现得很好。
  • 通过最佳可扩展性投入更多精力 - 为每个线程提供自己的本地 tempVector,并使用 openmp 并行跨 objVector 并行化。这样,每个线程都可以使用 vector 的 push_back 函数,因为它们是唯一访问该 vector 的线程。将 tempVector 的所有本地副本合并到单个共享的 tempVector 中可以通过原子方式添加大小,然后批量复制这些片段来完成。