Параллельный цикл OpenMP с оператором break - PullRequest
22 голосов
/ 20 марта 2012

Я знаю, что у вас не может быть оператора break для цикла OpenMP, но мне было интересно, есть ли какое-нибудь решение, которое все еще выигрывает от параллелизма.По сути, у меня есть цикл for, который перебирает элементы большого вектора и ищет один элемент, удовлетворяющий определенному условию.Однако есть только один элемент, который будет удовлетворять условию, поэтому, как только он будет найден, мы можем выйти из цикла, заранее спасибо

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

Ответы [ 5 ]

22 голосов
/ 23 марта 2012

См. Этот фрагмент:

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.

7 голосов
/ 22 марта 2012

Вы можете попытаться вручную сделать то, что делает цикл 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 потока могут быть уже закончены, а один еще на полпути к получению ...

2 голосов
/ 23 марта 2012

Я бы, наверное, сделал (скопировал немного из 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;
      }
   }
}
0 голосов
/ 14 мая 2014

Вот упрощенная версия принятого ответа.

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;
        }
    }
}
0 голосов
/ 14 мая 2014
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;
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...