2017-05-14 5 views
0

Quelles sont les solutions aux dangers de le faire?Fil de sécurité compteur en utilisant OpenMP

#include <iostream> 
#include <unistd.h> 
#include <cstdlib> 
#include <ctime> 

int main(){ 

    int k = 0; 
    #pragma omp parallel for 
    for(int i = 0; i < 100000; i++){ 

     if (i % 2){ /** Conditional based on i **/ 
      #pragma omp atomic 
      k++; 

      usleep(1000 * ((float)std::rand()/RAND_MAX)); 

      #pragma omp task 
      std::cout << k << std::endl; /** Some sort of task **/ 
     } 

    } 
    return 0; 
} 

J'ai besoin que tous les k s soient uniques. Quelle serait la meilleure façon de faire cela?

Modifier

Remarquez comment this question fait référence à un global

En particulier, je veux reproduire des tâches basées sur une variable partagée. Je cours le risque d'avoir une condition de course.

Considérons le thread 2 qui se termine, évalue true pour le conditionnel, et incrémente k avant que le thread 1 n'engendre toutes les tâches.

Éditer modifier

J'ai essayé de forcer une condition de concurrence. Ce n'était pas évident sans le sommeil. Il y a en fait des problèmes. Comment puis-je surmonter cela.

Voici une solution rapide:

...  
#pragma omp atomic 
k++; 
int c = k; 
... 

mais je voudrais une garantie.

Tangentiel. Pourquoi cette implémentation ne fonctionne-t-elle pas?

... 
int c; 
#pragma omp crtical 
{ 
    k++; 
    c = k; 
} 
... 

A la fin de la fonction, std::cout << k;, est toujours inférieure à la sortie attendue 50000 proof

+0

Possible dupliquer de [Comment gérer la variable partagée dans OpenMp] (http://stackoverflow.com/questions/14569954/how-to-manage-shared-variable -in-openmp) – Igor

+0

@Igor Réponse mise à jour soulignant la différence –

+0

La variante 'critical' devrait fonctionner de la même manière que dans 1)' k == 50000' à la fin de la boucle 'c == (i + 1)/2' . Vous devriez cependant 'std :: cout << c' pendant la boucle et lire' k' seulement dans la section critique en dehors de la boucle du parllel. – Zulan

Répondre

1

Je déteste répondre à ma question si vite, mais je trouve une solution pour ce cas particulier.

Au OpenMP 3.1, il est le "atomic capture" pragma

Le cas d'utilisation est pour des problèmes comme ça. Le code résultant:

#include <iostream> 
#include <unistd.h> 
#include <cstdlib> 
#include <ctime> 

int main(){ 

    int k = 0; 
    #pragma omp parallel for 
    for(int i = 0; i < 100000; i++){ 

     if (i % 2){ /** Conditional based on i **/ 
      int c; 
      #pragma omp atomic capture 
      { 
       c = k; 
       k++; 
      } 

      usleep(1000 * ((float)std::rand()/RAND_MAX)); 

      #pragma omp task 
      std::cout << c << std::endl; /** Some sort of task **/ 
     } 
    } 
    std::cout << k << std::endl; /** Some sort of task **/ 
    std::cout.flush(); 
    return 0; 
} 

Je laisserai ce problème ouvert si quelqu'un souhaite apporter des idées/code arch. suggestions pour éviter ces problèmes, raisons pour lesquelles le #pragma omp crtical n'a pas fonctionné

+1

'capture atomique' est la bonne chose à faire dans votre cas. – Zulan