Si j'utilise un parallèle imbriqué pour des boucles comme celle-ci:
#pragma omp parallel for schedule(dynamic,1)
for (int x = 0; x < x_max; ++x) {
#pragma omp parallel for schedule(dynamic,1)
for (int y = 0; y < y_max; ++y) {
//parallelize this code here
}
//IMPORTANT: no code in here
}
est-ce équivalent à:
for (int x = 0; x < x_max; ++x) {
#pragma omp parallel for schedule(dynamic,1)
for (int y = 0; y < y_max; ++y) {
//parallelize this code here
}
//IMPORTANT: no code in here
}
Le parallèle externe sert-il à autre chose qu'à créer une nouvelle tâche?
Si votre compilateur prend en charge OpenMP 3.0, vous pouvez utiliser la clause collapse
:
#pragma omp parallel for schedule(dynamic,1) collapse(2)
for (int x = 0; x < x_max; ++x) {
for (int y = 0; y < y_max; ++y) {
//parallelize this code here
}
//IMPORTANT: no code in here
}
Si ce n'est pas le cas (par exemple, seul OpenMP 2.5 est pris en charge), il existe une solution simple:
#pragma omp parallel for schedule(dynamic,1)
for (int xy = 0; xy < x_max*y_max; ++xy) {
int x = xy / y_max;
int y = xy % y_max;
//parallelize this code here
}
Vous pouvez activer le parallélisme imbriqué avec omp_set_nested(1);
et votre code omp parallel for
Imbriqué fonctionnera, mais ce n'est peut-être pas la meilleure idée.
Au fait, pourquoi l'ordonnancement dynamique? Chaque itération de boucle est-elle évaluée en temps non constant?
NON.
La première #pragma omp parallel
créera une équipe de threads parallèles et le second essaiera ensuite de créer pour chacun des threads d'origine une autre équipe, c'est-à-dire une équipe d'équipes. Cependant, sur presque toutes les implémentations existantes, la deuxième équipe n'a qu'un seul thread: la deuxième région parallèle n'est essentiellement pas utilisée. Ainsi, votre code ressemble plus à l'équivalent de
#pragma omp parallel for schedule(dynamic,1)
for (int x = 0; x < x_max; ++x) {
// only one x per thread
for (int y = 0; y < y_max; ++y) {
// code here: each thread loops all y
}
}
Si vous ne le souhaitez pas, mais que vous parallélisez uniquement la boucle interne, vous pouvez le faire:
#pragma omp parallel
for (int x = 0; x < x_max; ++x) {
// each thread loops over all x
#pragma omp for schedule(dynamic,1)
for (int y = 0; y < y_max; ++y) {
// code here, only one y per thread
}
}