【问题标题】:Parallel OpenMP loop with break statement带有 break 语句的并行 OpenMP 循环
【发布时间】:2012-03-20 19:45:11
【问题描述】:

我知道您不能为 OpenMP 循环使用 break 语句,但我想知道是否有任何解决方法,同时仍然受益于并行性。基本上我有'for'循环,它遍历一个大向量的元素,寻找一个满足特定条件的元素。但是只有一个元素可以满足条件,所以一旦找到,我们就可以跳出循环,在此先感谢

for(int i = 0; i <= 100000; ++i)
  {
    if(element[i] ...)
     {
          ....
          break;
      }
   }

【问题讨论】:

标签: c++ multithreading loops openmp


【解决方案1】:

看到这个sn-p:

volatile bool flag=false;

#pragma omp parallel for shared(flag)
for(int i=0; i<=100000; ++i)
{    
    if(flag) continue;
    if(element[i] ...)
    {
          ...
          flag=true;
    }
}

这种情况更适合pthread。

【讨论】:

【解决方案2】:

您可以尝试手动执行 openmp for 循环所做的事情,使用 while 循环:

const int N = 100000;
std::atomic<bool> go(true);
uint give = 0;

#pragma omp parallel
{
    uint i, stop;

    #pragma omp critical
    {
        i = give;
        give += N/omp_get_num_threads();
        stop = give;

        if(omp_get_thread_num() == omp_get_num_threads()-1)
            stop = N;
    } 


    while(i < stop && go)
    {
        ...
        if(element[i]...)
        {
            go = false;
        }
        i++;
    }
}

这样你必须在每个循环中测试“go”,但这应该没那么重要。更重要的是,这将对应于“静态” omp for 循环,仅当您可以预期所有迭代都花费相似的时间时才有用。否则,3个线程可能已经完成了,而一个还有一半的时间......

【讨论】:

  • 从技术上讲,您必须以原子方式阅读go。此外,除非您将 seq_cst 添加到两个原子操作中,否则内存模型保证不可见。
  • @Zulan,正确,虽然在实践中没有太大的危险(除了一些额外的工作),但从技术上讲,答案包含数据竞争。现在(使用 C++11)我肯定会建议使用 std::atomic&lt;bool&gt; 代替 go。我会相应地编辑答案。
【解决方案3】:

我可能会这样做(从 yyfn 复制一点)

volatile bool flag=false;

for(int j=0; j<=100 && !flag; ++j) {
  int base = 1000*j;
  #pragma omp parallel for shared(flag)
  for(int i = 0; i <= 1000; ++i)
  {

    if(flag) continue;
    if(element[i+base] ...)
     {
          ....
          flag=true;
      }
   }
}

【讨论】:

    【解决方案4】:

    这是已接受答案的更简单版本。

    int ielement = -1;
    #pragma omp parallel
    {
        int i = omp_get_thread_num()*n/omp_get_num_threads();
        int stop = (omp_get_thread_num()+1)*n/omp_get_num_threads();        
        for(;i <stop && ielement<0; ++i){
            if(element[i]) {
                ielement = i;
            }
        }
    }
    

    【讨论】:

      【解决方案5】:
      bool foundCondition = false;
      #pragma omp parallel for
      for(int i = 0; i <= 100000; i++)
      {
          // We can't break out of a parallel for loop, so this is the next best thing.
          if (foundCondition == false && satisfiesComplicatedCondition(element[i]))
          {
              // This is definitely needed if more than one element could satisfy the
              // condition and you are looking for the first one.  Probably still a
              // good idea even if there can only be one.
              #pragma omp critical
              {
                  // do something, store element[i], or whatever you need to do here
                      ....
      
                  foundCondition = true;
              }
          }
      }
      

      【讨论】:

      • 您真的认为将boolfalse 进行比较是否明智?
      猜你喜欢
      • 2014-03-21
      • 2017-03-31
      • 1970-01-01
      • 1970-01-01
      • 2014-05-14
      • 1970-01-01
      • 2020-12-29
      • 2018-08-23
      • 1970-01-01
      相关资源
      最近更新 更多