Les compilateurs Intel ® C++ et Fortran ont la capacité d'analyser le flux de données dans les boucles d'un programme afin de déterminer si leurs itérations peuvent être exécutées en parallèle. La parallélisation automatique peut réduire le temps d'exécution sur des architectures multi-coeurs. Le compilateur aide le programmeur à :
Pour activer la parallélisation automatique, il suffit de rajouter l'option -parallel. Toutefois, le succès de la parallélisation est soumise dépend de certains critères :
Prenons un exemple en fortran :
PROGRAM TEST PARAMETER (N=10000000) REAL A, C(N) DO I = 1, N A = 2 * I - 1 C(I) = SQRT(A) ENDDO PRINT*, N, C(1), C(N) END
L'analyse de flux de données confirme que la boucle ne contient pas de dépendances de données. Le compilateur génère un code qui distribue les itérations sur l'ensemble de coeurs (threads) disponibles à l'exécution.
On peut spécifier le nombre de threads à utiliser à la OpenMP
on exportant la variable d'environnement : $OMP_NUM_THREADS.
Par exemple :
$ export $OMP_NUM_THREADS=8
Utilise 8 threads (coeurs) pour l'exécution.
Compilation :
$ ifort -parallel test.f90 -o test test.f90(4): (col. 3) remark: LOOP WAS AUTO-PARALLELIZED
Voici un exemple :
void add (int k, float *a, float *b) { for (int i = 1; i < 10000; i++) a[i] = a[i+k] + b[i]; }
icc -parallel -par-report3 test.c -o test
procedure: add test.c(7): (col. 1) remark: parallel dependence: assumed ANTI dependence between a line 7 and a line 7. flow data dependence assumed ... test.c(7): (col. 1) remark: parallel dependence: assumed FLOW dependence between a line 7 and b line 7.
Analyse
Parce que le compilateur ne connaît pas la valeur de k
, il suppose que les itérations dépendent les unes des autres, comme par exemple si k
est égal à -1
.
Cependant, le programmeur connaît mieux son application (par exemple, k
toujours supérieure à 10000), et peut dans ce cas aider le compilateur à paralléliser la boucle
en lui donnant une indication supplémentaire, en insérant la clause :
#pragma parallel en entrée de la boucle :
void add (int k, float *a, float *b) { #pragma parallel for (int i = 1; i < 10000; i++) a[i] = a[i+k] + b[i]; }
$ icc -parallel -par-report3 test.c -o test
procedure: add test.c(6): (col. 1) remark: LOOP WAS AUTO-PARALLELIZED.
Parallélisation avec Introduction à OpenMP