C++ OpenMP-并行For循环

C++ OpenMP-并行For循环,c++,parallel-processing,openmp,C++,Parallel Processing,Openmp,我使用二维向量。我有两个手术: 使用(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 < objVec

我使用二维向量。我有两个手术:

  • 使用(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);
        }
    }
    
    vectorobjVector;
    向量tempVector(4);
    对于(int i=0;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 */
}
#包括
main()
{
int x;
x=0;
#pragma omp并行共享(x)
{
#pragma-omp-critical
x=x+1;
}/*平行段的末端*/
}
示例取自:


如果我是你,我会有不同的想法(不幸的是,在这种情况下你不能使用#reduce,但你肯定可以重新调整代码以获得相同的结果)。

不幸的是,OpenMP在这种情况下无法防止数据争用。shared子句允许所有线程查看向量变量,但它不会对它们的访问进行排序。Vector的push_back函数不是线程安全的,因为它可能导致Vector的底层存储被重新分配(增长)

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

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