Parallélisation automatique avec Intel compiler
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 à :
- Rechercher des boucles qui sont de bons candidats pour une exécution en parallèle
- Effectuer une analyse de flux de données pour vérifier une exécution parallèle
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 :
- Le nombre d'itérations doit être connu avant d'entrer dans la boucle.
- Le corps de la boucle ne doit pas contenir de branchements (goto,…) vers l'intérieur ou l'extérieur de la boucle.
- Les itérations de la boucle doivent être indépendantes : absence de dépendances entre les itérations
Exemple
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.
Voir aussi
Parallélisation avec Introduction à OpenMP