web-dev-qa-db-fra.com

Boucle OpenMP parallèle avec instruction break

Je sais que vous ne pouvez pas avoir d'instruction break pour une boucle OpenMP, mais je me demandais s'il existait une solution de contournement tout en bénéficiant du parallélisme. Fondamentalement, j'ai une boucle "pour" qui parcourt les éléments d'un grand vecteur à la recherche d'un élément qui satisfait à une certaine condition. Cependant, il n’ya qu’un élément qui satisfasse à la condition, donc, une fois celle-ci trouvée, nous pouvons sortir de la boucle, merci d’avance.

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

Vous pouvez essayer de faire manuellement ce que fait la boucle openmp for, en utilisant une boucle 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++;
    }
}

De cette façon, vous devez tester chaque cycle, mais cela ne devrait pas avoir d’importance. Plus important encore, cela correspond à une boucle omp for "statique", ce qui n’est utile que si vous pouvez vous attendre à ce que toutes les itérations prennent le même temps. Sinon, 3 threads peuvent être déjà finis alors qu'il en reste encore à mi-chemin ...

7
Haatschii

Voir cet extrait:

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;
    }
}

Cette situation est plus appropriée pour pthread.

19
yyfn

Je ferais probablement (copié un peu de 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;
      }
   }
}
2
enobayram

Voici une version simplifiée de la réponse acceptée.

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
Z boson
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;
        }
    }
}
0
Peter Smartt