Blog - Aneo

Portage d'un simulateur d'ondes sismiques sur des unités de traitement graphique, pour quoi faire ?

Rédigé par Maxime Roux | 17 juillet 2019

 

Comment les unités de traitement graphique peuvent-elles aider les sismologues ? La compréhension de la propagation des ondes sismiques est l'une des questions les plus importantes de la sismographie et a toujours été un défi numérique. Ceci est très important dans l'industrie pour prévenir l'impact des tremblements de terre ou par exemple pendant les opérations d'exploration pétrolière. Dans cet article, nous montrons comment les GPU offrent de grandes opportunités.

SeWaS (Seismic Wave Simulator) [1] est une implémentation d'un simulateur de propagation d'ondes sismiques développé par Aldwin chez ANEO combinant efficacité et précision en utilisant des librairies CPU de pointe. Grâce à l'utilisation de ces bibliothèques HPC, SeWaS est également considéré comme un outil de référence. Étant donné le temps de calcul important requis pour résoudre les cas d'utilisation typiques, il est intéressant d'explorer l'utilisation d'accélérateurs matériels tels que les unités de traitement graphique (GPU) en tant que plate-forme de calcul cible pour SeWaS.

Tout d'abord, présentons SeWaS et pourquoi il pourrait être intéressant de le porter sur un autre matériel que le GPU. Ensuite, nous parlerons du GPGPU. Enfin, nous verrons comment le backend GPU est implémenté tout en conservant la généricité de l'application.

Presentation de SeWaS

SeWaS est un solveur qui peut être utilisé pour la migration temporelle inverse.

L'étude de la propagation des ondes sismiques est basée sur l'élasticité linéaire et plus particulièrement sur l'élastodynamique qui est l'étude des ondes élastiques. Par conséquent, SeWaS utilise certains outils mathématiques tels que les équations élasto-dynamiques pour évaluer les composantes des champs de vitesse et de contrainte. SeWaS nécessite de nombreuses opérations vectorielles, en effet nous devons calculer l'opérateur central de différence finie du 4ème ordre pour calculer les formes discrétisées des champs de vitesse et de contrainte [2]. Pour SeWaS, il était nécessaire de disposer d'une méthode dont le code ressemble beaucoup à des expressions mathématiques "naturelles" tout en étant efficace. Le modèle de conception Expression Templates [3] est un bon moyen de combiner abstraction et performance. Les modèles d'expression sont une technique de métaprogrammation C++ qui construit une structure résultant d'un calcul au moment de la compilation, seul le calcul lui-même étant effectué au moment de l'exécution [4]. C'est pourquoi SeWaS a été construit en utilisant C++14 et Eigen [5].

SeWaS dispose de deux niveaux de parallélisation :

  • Le calcul parallèle de tous les champs de vitesse à un pas de temps fixe : parallélisme des tâches.
  • Le calcul parallèle des dérivées (application de l'opérateur des différences finies) : Parallélisme SIMD

On peut donc se demander si l'utilisation de l'unité centrale comme seul matériel est la méthode la plus efficace.

Utilisation d'un autre matériel ?

Les CPU sont très efficaces pour effectuer rapidement des tâches séquentielles, contrairement aux GPU. En effet, du fait de son architecture différente, le GPU n'est pas efficace pour ce type de tâche mais il est bien adapté au calcul de débit. Jusqu'à présent, SeWaS est construit autour de la parallélisation CPU. Cependant, on peut se demander s'il ne serait pas possible d'améliorer les performances en utilisant le GPGPU (General-Purpose Computing on Graphic Processing Units). Il effectue des calculs génériques sur un processeur graphique, ce qui nous permettrait de bénéficier de la capacité de traitement parallèle du processeur graphique. Le GPU suit le modèle d'exécution SIMT (Single Instruction Multiple Thread) qui est la combinaison de SIMD (Single Instruction Multiple Data) et du multithreading. Cela signifie que plusieurs threads indépendants peuvent exécuter simultanément la même instruction sur des données différentes.

En outre, SeWaS est lié à la mémoire. L'algorithme est donc limité par l'accès à la mémoire RAM. Nous cherchons à tirer parti de la mémoire cache (plus rapide que la mémoire RAM), mais une fois qu'elle est pleine, nous sommes limités par la bande passante de la mémoire. L'unité de traitement graphique dispose d'une meilleure bande passante que l'unité centrale, ce qui pourrait nous permettre d'obtenir de meilleures performances.

Utilisation de différents langages de programmation

Nous pouvons utiliser plusieurs langages de programmation pour programmer sur des unités de traitement graphique telles que OpenCL [6] et CUDA [7], qui sont les deux principaux cadres pour la programmation d'applications GPU. Actuellement, nous ciblons les GPU Nvidia, mais nous envisageons d'exploiter également les FPGA qui peuvent être traités par OpenCL. CUDA est un langage de programmation développé par Nvidia, qui ne fonctionne que sur les GPU Nvidia. OpenCL est un standard ouvert qui permet aux utilisateurs de programmer sur de nombreux GPU (AMD, NVIDIA, Intel...) contrairement à CUDA. CUDA est le plus efficace sur les GPU Nvidia, mais au lieu de CUDA, OpenCL nous permet de programmer sur des FPGA. Plutôt que de programmer deux noyaux (un en CUDA et un en OpenCL), nous avons choisi d'utiliser la programmation générique C++ pour développer le backend multicible de SeWaS. En particulier, nous allons d'abord explorer l'utilisation de la bibliothèque VexCL.

Bibliothèque VexCL

VexCL [8] est une bibliothèque de modèles d'expressions vectorielles pour OpenCL/CUDA. Elle a été développée pour faciliter le développement du GPGPU avec C++, en particulier pour les applications comportant de grandes opérations vectorielles. Elle fournit une notation pratique et intuitive pour l'arithmétique vectorielle. De plus, les calculs multi-appareils et multi-plateformes sont pris en charge. L'utilisation de VexCL nous permet également de passer très facilement de CUDA à OpenCL ou d'OpenCL à CUDA. Tout d'abord, nous nous concentrerons sur le backend CUDA pour programmer sur les GPU Nvidia. Le backend CUDA est programmé à l'aide d'une technique de métaprogrammation comme les modèles d'expression pour les unités de traitement graphique.

Perspectives

Pour résumer, nous avons brièvement présenté SeWaS et pourquoi il serait intéressant d'utiliser une autre architecture plus axée sur le calcul parallèle comme les GPU. Nous parlerons bientôt plus en détail du portage de SeWaS vers les GPU ainsi que des Expression Templates.

En savoir plus sur l'informatique du GPUS ici.

[1] Aneo, «SeWaS,» [En ligne]. Available: https://github.com/aneoconsulting/SeWaS.
[2] S. Moustafa, W. Kirschenmann, F. Dupros et H. Aochi, «Task-Based Programming on Emerging Parallel Architectures for Finite-Differences Seismic Numerical Kernel,» 2018.
[3] T. Veldhuizen, «Expression Templates,» 1995.
[4] W. Kirschenmann, «Vers des noyaux de calcul intensif pérennes,» 2012.
[5] B. Jacob et G. Guennebaud, «Eigen,» [En ligne]. Available: https://eigen.tuxfamily.org/dox/.
[6] K. Group, «OpenCL,» [En ligne]. Available: https://opencl.org/.
[7] Nvidia, «CUDA,» [En ligne]. Available: https://developer.nvidia.com/cuda-toolkit.
[8] D. Demidov, «VexCL,» [En ligne]. Available: https://vexcl.readthedocs.io/en/latest/index.html.