OpenMP - 并行循环

时间:2015-01-04 15:17:13

标签: 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 < 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);
        }
    }
    

2 个答案:

答案 0 :(得分:1)

您需要使用#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,但你肯定可以重新洗牌以获得相同的结果)。

答案 1 :(得分:0)

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

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

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