Démarrer un thread pour chaque boucle interne dans OpenMP

Je suis assez nouveau dans OpenMP et j’essaie de démarrer un thread individuel pour traiter chaque élément d’un tableau 2D.

Donc, essentiellement, ceci:

for (i = 0; i < dimension; i++) { for (int j = 0; j < dimension; j++) { a[i][j] = b[i][j] + c[i][j]; 

Ce que je fais est ceci:

 #pragma omp parallel for shared(a,b,c) private(i,j) reduction(+:diff) schedule(dynamic) for (i = 0; i < dimension; i++) { for (int j = 0; j < dimension; j++) { a[i][j] = b[i][j] + c[i][j]; 

Cela commence-t-il en fait un fil pour chaque élément 2D ou non? Comment pourrais-je tester cela? Si c’est faux, quelle est la bonne façon de le faire? Merci!

Note: le code a été grandement simplifié

Seule la boucle externe est parallèle dans votre exemple de code. Vous pouvez tester en imprimant omp_get_thread_num() dans la boucle interne et vous verrez que, pour un i donné, le thread num est le même (bien sûr, ce test est démonstratif plutôt que définitif car des exécutions différentes donneront des résultats différents). Par exemple, avec:

 #include  #include  #define dimension 4 int main() { #pragma omp parallel for for (int i = 0; i < dimension; i++) for (int j = 0; j < dimension; j++) printf("i=%d, j=%d, thread = %d\n", i, j, omp_get_thread_num()); } 

Je reçois:

 i=1, j=0, thread = 1 i=3, j=0, thread = 3 i=2, j=0, thread = 2 i=0, j=0, thread = 0 i=1, j=1, thread = 1 i=3, j=1, thread = 3 i=2, j=1, thread = 2 i=0, j=1, thread = 0 i=1, j=2, thread = 1 i=3, j=2, thread = 3 i=2, j=2, thread = 2 i=0, j=2, thread = 0 i=1, j=3, thread = 1 i=3, j=3, thread = 3 i=2, j=3, thread = 2 i=0, j=3, thread = 0 

Pour le rest de votre code, vous voudrez peut-être donner plus de détails dans une nouvelle question (il est difficile de le savoir à partir du petit exemple), mais par exemple, vous ne pouvez pas mettre private(j) lorsque j est déclaré plus tard. C'est automatiquement privé dans mon exemple ci-dessus. Je suppose que diff est une variable que nous ne pouvons pas voir dans l'échantillon. De plus, la variable de boucle i est automatiquement privée (à partir de la version 2.5) - identique à la version 3.0)

La variable d'itération de boucle dans la boucle for d'une construction for ou parallel for est privée dans cette construction.

Edit: Tout ce qui précède est correct pour le code que vous et moi avons affiché, mais les éléments suivants pourraient vous intéresser. Pour OpenMP version 3.0 (disponible par exemple dans la version 4.4 de gcc , mais pas dans la version 4.3), il existe une clause collapse laquelle vous pouvez écrire le code tel #pragma omp parallel for collapse (2) , mais avec #pragma omp parallel for collapse (2) afin de paralléliser les deux boucles for (voir la spec ).

Edit : OK, j’ai téléchargé gcc 4.5.0 et ai exécuté le code ci-dessus, mais en utilisant collapse (2) pour obtenir le résultat suivant, montrant la boucle interne à présent parallélisée:

 i=0, j=0, thread = 0 i=0, j=2, thread = 1 i=1, j=0, thread = 2 i=2, j=0, thread = 4 i=0, j=1, thread = 0 i=1, j=2, thread = 3 i=3, j=0, thread = 6 i=2, j=2, thread = 5 i=3, j=2, thread = 7 i=0, j=3, thread = 1 i=1, j=1, thread = 2 i=2, j=1, thread = 4 i=1, j=3, thread = 3 i=3, j=1, thread = 6 i=2, j=3, thread = 5 i=3, j=3, thread = 7 

Les commentaires ici (recherchez "Solutions de contournement") s'appliquent également aux solutions de contournement de la version 2.5 si vous souhaitez paralléliser les deux boucles, mais les spécifications de la version 2.5 citées ci-dessus sont assez explicites (voir les exemples non conformes de la section A.35 ). .

Vous pouvez essayer d’utiliser des fors parallèles omp nesteds (après l’ omp_set_nested(1) de omp_set_nested(1) ), mais ils ne sont pas pris en charge sur toutes les implémentations openmp.

Donc, je suppose que pour faire une grid 2D et démarrer tous les threads sur la grid à partir de simple pour (exemple pour la grid de threads 4×4 fixe):

 #pragma omp parallel for for(k = 0; k < 16; k++) { int i,j,i_min,j_min,i_max,j_max; i_min=(k/4) * (dimension/4); i_max=(k/4 + 1) * (dimension/4); j_min=(k%4) * (dimension/4); j_max=(k%4 + 1) * (dimension/4); for(i=i_min;i