2013-02-18 2 views
2

Étant donné cet exemple de code, l'exercice est à parallèle le code avec OpenMP utilisant des tâches. C'est un ensemble d'éléments et nous voulons compter ceux qui sont bons. OpenMP: conditions de concurrence dans les tâches

int count_good (item_t* item) 
{ 
    int n = 0; 
    while (item) { 
     if (is_good(item)) 
      n++; 
     item = item->next; 
    } 
    return n; 
} 

Ce n'est pas exactement les devoirs. C'est pour la préparation d'un examen. Mon idée est la suivante:

int count_good (item_t* item) 
{ 
    int n = 0; 
    while (item) { 
     #pragma omp task 
     { 
     if (is_good(item)) 
      n++; 
     } 
     item = item->next; 
    } 
    #pragma omp taskwait 
    return n; 
} 
... 

int main() 
{ 
... 
#pragma omp parallel 
{ 
#pragma omp single 
    count_good(some_times); 
} 
} 

Un problème est la n qui est une variable privée du fil unique, mais elle pourrait être renforcée par différentes tâches en même temps. Cela pourrait-il générer une condition de concurrence? Peut-il être évité avec #pragma omp critical?

Répondre

1

vous devez déclarer explicitement n comme shared, sinon il serait firstprivate par défaut (car il est implicitement private dans le contexte englobante). Ensuite, afin d'assurer des incréments atomiques de n, vous devez appliquer la construction atomic update. En fin de votre code devrait ressembler à ceci:

int count_good (item_t* item) 
{ 
    int n = 0; 
    while (item) { 
     #pragma omp task shared(n) 
     { 
     if (is_good(item)) 
      #pragma omp atomic update 
      n++; 
     } 
     item = item->next; 
    } 
    #pragma omp taskwait 
    return n; 
} 

La construction critical a une tête beaucoup plus élevé que les incréments atomiques, au moins sur x86.

1

Vous pouvez utiliser reduction pour compter les "bons" éléments. Le code suivant fera le travail pour vous. Vous voudrez peut-être lire this for reduction et this for traversing linked list

int nCount = 0; 
#pragma omp parallel reduction(+ : nCount) 
{  
    for(struct item_t *listWalk = some_items; listWalk != NULL; 
     listWalk = listWalk->next) 
    { 
     #pragma omp single nowait 
     { 
      if(isGood(listWalk)){ 
      nCount += 1; 
      } 
     }   
    } 
} 
Questions connexes