Pour utiliser OpenMP, il faut:
#include <omp.h>
-fopenmp
en compilant avec GCC.#pragma
dans le programme.#pragma
Pour paralléliser l'exécution d'un bloc :
#pragma omp parallel { // Bloc }
OpenMP exécutera le bloc autant de fois qu'il y a de threads disponibles sur le système.
Pour paralléliser l'exécution d'une boucle for
:
#pragma omp parallel for for (i = 0; i < 10; i++) // ...
Pour définir une variable privée pour chaque bloc parallélisé :
#pragma omp parallel private(somme) { somme = ...; // ... } #pragma omp parallel for private(tmp) for (/* ... */) { tmp = ...; }
Pour choisir le nombre de threads à utiliser :
omp_set_num_threads(10);
Pour réduire une variable à une seule valeur :
#pragma omp parallel for reduce(+:somme) for (/* ... */)
Ici, le for va être parallélisé et chaque thread va calculer une partie de la somme. La réduction permet d'assembler toutes les valeurs calculé en une seule. Puisqu'il s'agit d'une somme ici, on utilise
+
mais on peut faire la même chose avec une soustraction (-
), du calcul booléen (&&
ou||
), etc.
double wtime; wtime = omp_get_wtime(); // ... wtime = omp_get_wtime() - wtime;
Cette fonction peut être utilisé dans un bloc pragma
ou bien à l'extérieur.
#pragma omp parallel private(i) { #pragma omp sections { #pragma omp section for (i = 0; i < 10000; i++) // ... # pragma omp section for (i = 0; i < 10000; i++) // ... } }
Ici, les deux for
s s'éxecuteront en même temps. Contrairement à parallel
, qui va essayer d'exécuter le code sur tous les threads disponibles, section
utilise un seul thread par section créée (ici, 1 thread est utilisé pour le premier for
et 1 autre pour le second).
Quand deux threads ont une directive nowait
(c'est à dire que le code suivant ce bloc peut être exécuté avant la fin de ce bloc), on peut utiliser barrier
pour synchroniser les threads.
#pragma omp parallel { #pragma omp for nowait for (/* ... */) // Boucle 1 #pragma omp for nowait for (/* ... */) // Boucle 2 #pragma omg barrier printf("Eh bien le bonjour !"); }
Ici, la boucle 1 et la boucle 2 peuvent tourner en parallèle mais le printf
ne sera fait qu'une fois la boucle 1 et 2 finies.
Les sections critiques permettent au sein d'un bloc parralélisé de s'assurer qu'une instruction ne sera exécuté que par un seul thread à la fois :
#pragma omp for for (i = 0; i < 1000; i++) { #pragma omp critical if (tab[i] < min) min = tab[i] }
Ici, on évite que deux threads écrasent la valeur de min
en même temps et que min
n'ait pas la valeur du plus petit élément du tableau.