OpenMP, une directive pour les parralléliser tous

in ULille blockchain2 years ago (edited)

Par @fatieez et @benjil

Présentation de l'API OpenMP

OpenMP est une API de programmation parallèle pour les langages C, C++ et Fortran. Elle permet de définir des régions de code pouvant être exécutées en parallèle. Elle a été définie en octobre 1997 pour Fortran et en octobre 1998 pour C et C++.

image.png

Principes

OpenMP est une API basée sur les threads, lorsque que le programme arrive dans une région marquée comme parallèle, il crée une équipe de threads qui exécutent la région en parallèle. Les threads sont créés à partir du thread principal, qui est appelé thread principal. Les threads sont synchronisés à la fin de la région parallèle, et le thread parallèle reprend l'exécution du programme de manière séquentielle.

Directives

OpenMP utilise un ensemble de directives de préprocesseur pour définir les régions parallèles. Ces directives sont des mots-clés qui commencent par #pragma omp. Les directives sont suivies d'un ensemble d'arguments qui définissent le comportement de la région parallèle. Les directives sont définies dans le fichier omp.h qui est inclus dans les fichiers C et C++ et dans le fichier omp_lib.h qui est inclus dans les fichiers Fortran.

Principales directives

création de régions parallèles

Parallel

Crée une équipe de threads qui exécutent la région parallèle. Le nombre de threads lancés est défini soit :

  • l'évaluation d'une éventuelle clause if
  • de la clause num_threads si elle est présente
  • de la fonction omp_set_num_threads si elle est appelée avant la directive
  • et enfin de la variable d'environnement OMP_NUM_THREADS si elle est définie

for

Une des premières directives que l'on montre lorsque que l'on parle de OpenMP, en effet, elle permet de paralléliser un calcul en n'ajoutant qu'une seule ligne à un programme déjà existant. La directive for permet de paralléliser une boucle for en créant un ensemble de threads qui exécutent la boucle en parallèle. La directive for est définie de la façon suivante :

#pragma omp for
for (int i = 0; i < 100000; i++) {
 // Code de la boucle
}

Directive sur le statut des variables

OpenMP fonctionne sur les machines à mémoire partagée, les variables seront donc partagées entre les threads, on a donc besoin de mécanismes de contrôle permettant d'indiquer quels threads peuvent modifier ou lire une variable.

Private

La directive private permet de définir une liste de variables comme privées, chaque thread aura une copie des variables qui ne sera pas partagée avec les autres.

Shared

Permets de définir une liste de variables comme partagées, les threads d'une même équipe auront accès à la variable.

Firstprivate

La directive firstprivate permet de définir une liste de variables comme privées, mais initialise la variable avec la valeur de la variable du thread principal.

Lastprivate

La directive lastprivate permet de définir une liste de variables comme privées, mais initialise la variable avec la valeur de la variable du dernier thread.

Réduction

La directive reduction permet de définir une liste de variables comme privées, mais initialise la variable avec la valeur de la variable du dernier thread.

Default

Indique le comportement par défaut des variables d'une région parallèle, si aucunes autres directives sur le statut des variables n'est présente, les variables utilisent le comportement par défaut.

Directives de synchronisation

Barrier

La directive barrier permet de synchroniser les threads, quand un thread atteint la directive, il attend les autres threads. Une fois tous les threads arrivés à la directive, les threads peuvent continuer à s'exécuter.

Critical

Cette directive indique que le bloc suivant doit être exécuté par un seul thread à la fois. Si un thread arrive dans la région marquée comme critique alors qu'un thread est déjà à l'intérieur, il attend que l'autre thread sorte de la région critique avant d'y entrer.

Atomic

La directive atomic permet d'exécuter une opération atomique. Une opération atomique est une opération qui ne peut pas être interrompue par un autre thread.

Master

Seul le thread principal peut exécuter le bloc marqué comme master.

Flush

flush force les threads à mettre à jour les variables partagées passées en argument de la directive.

Exemples :

#include<stdio.h>
#include<stdlib.h>
int main (int argc, char const *argv[]){
  int n;
  for(n=0;n<8;n++){
    printf("Element %d traité\n",n);
  }
  return EXIT_SUCCESS;
}

Résultat:

Element 0 traité
Element 1 traité
Element 2 traité
…

Mais en utilisant OpenMp

#include<stdio.h>
#include<stdlib.h>
#include<omp.h>
int main (int argc, char const *argv[]){
  int n;
  #pragma omp parallel for
  for(n=0;n<8;n++){
    printf("Element %d traité par le thread %d \n",n,omp_get_thread_num());
  }
  return EXIT_SUCCESS;
}

Résultat :

Element 0 traité par le thread 0
Element 4 traité par le thread 1
Element 1 traité par le thread 0
Element 5 traité par le thread 1
Element 2 traité par le thread 0
Element 6 traité par le thread 1
Element 3 traité par le thread 0
Element 7 traité par le thread 1

image.png

Avantages et inconvénients

Avantages

  • OpenMP est un standard ancien et reconnu, il y a beaucoup de documentation disponible.
  • OpenMP offre de bonnes performances si le programmeur sait l'utiliser correctement.
  • Pour paralléliser un programme, l'effort de programmation est relativement faible, le programme original n'est pas beaucoup modifié.
  • le code produit est portable, de nombreux compilateurs supportent OpenMP.

Inconvénients

  • C'est au programmeur de trouver où il peut être intéressant de paralléliser son programme, et de trouver les bonnes directives pour le faire.
  • Pour obtenir les meilleures performances, le programmeur doit avoir bien réfléchi à la parallélisation de son programme et bien connaître les directives OpenMP.

Conclusion

Nous pouvons donc conclure que la mise en œuvre d'OpenMP pour optimiser l'utilisation des processeurs à cœurs multiples est simple.
Par contre, l'absence d'un déboguer efficace pour OpenMP complique un peu l'écriture des programmes.
Cependant, c’est un code parallèle plus efficace et de niveau inférieur. Mais également, OpenMP cache les détails de bas niveau et permet au programmeur de décrire le code parallèle avec des constructions de haut niveau, ce qui est aussi simple qu’il peut obtenir. OpenMP a des directives qui permettent au programmeur de spécifier la région parallèle.

Sources

Sort:  

Congratulations @fatieez! You have completed the following achievement on the Hive blockchain And have been rewarded with New badge(s)

You received more than 300 upvotes.
Your next target is to reach 400 upvotes.

You can view your badges on your board and compare yourself to others in the Ranking
If you no longer want to receive notifications, reply to this comment with the word STOP

Check out the last post from @hivebuzz:

HiveBuzz World Cup Contest - Recap of Day 9
Hive Power Up Day - December 1st 2022
HiveBuzz World Cup Contest - Check your ranking
Support the HiveBuzz project. Vote for our proposal!

Bonjour !

En tant que membre francophone de Hive, vous avez été ajouté à l'auto-vote.

La puissance de vote de base est de 25%, deux votes par tranche de 24h et 7 max par semaine.
Vous pouvez augmenter la puissance de vote en déléguant à la Ruche si vous le souhaitez. Voici notre serveur Discord si vous avez des questions ou juste pour discuter avec d'autres francophones de Hive !

https://discord.gg/46gdrud

Bienvenue dans la Ruche !