Thomas JOST 1 Sylvain CONTASSOT-VIVIER 1,2 Stéphane VIALLE 1,3 1 Équipe AlGorille, LORIA 2 Université Henri Poincaré Nancy 1 3 Équipe IMS Supélec (Metz)
1 Introduction 2 Contraintes et algorithmes Structure de données Méthodes itératives Améliorations possibles 3 Performances Tests en simple précision Tests en double précision 4 Conclusion
1 Introduction 2 Contraintes et algorithmes Structure de données Méthodes itératives Améliorations possibles 3 Performances Tests en simple précision Tests en double précision 4 Conclusion
Introduction Cadre général Transport 3D d espèces chimiques dans un cours d eau Étude d algorithmes synchrones et asynchrones Cluster de GPUs Étape centrale : solveur linéaire Un système linéaire différent à résoudre à chaque itération Système de la forme Ax = b Système creux, structuré
1 Introduction 2 Contraintes et algorithmes Structure de données Méthodes itératives Améliorations possibles 3 Performances Tests en simple précision Tests en double précision 4 Conclusion
Nécessité d une nouvelle implémentation Pas de solveur existant adapté Il existe quelques projets : MAGMA, cudaztec, GPUmatrix, CNC... Aucune des solutions existantes ne convient parfaitement...il faut en écrire une nouvelle Contraintes pour le choix de la méthode Méthodes directes : précises, mais lentes peu intéressant Méthodes itératives : moins précises, mais rapides, surtout sur des matrices creuses Nombres flottants en simple précision, implémentation non standard erreurs d arrondis Problème creux : il faut une structure de données adaptée
Structure de données Structure de données Matrice creuse structurée Système de taille n avec plusieurs diagonales non vides. 0 1 4 8 Chaque diagonale est identifiée par un nombre d : tous les éléments a ij de la diagonale vérifient j i = d (modulo n).
Structure de données Structure de données Représentation en mémoire Tableau n d où chaque colonne est une diagonale de la matrice précédente ; Liste de d entiers : correspondance diagonale colonne. Schéma de stockage proche du «DIA» de LAPACK, mais mieux adapté aux contraintes mémoire des GPU. 0 1 4 8
Méthodes itératives Méthodes itératives Idée générale Calculer une suite ( x k) k N qui converge vers x Points délicats Vitesse de convergence (nombre d itérations et durée de chaque itération) mieux vaut quelque chose de rapide Occupation mémoire éviter les matrices intermédiaires Parallélisation soit des kernels simples, soit des opérations CUBLAS Simplicitié temps de debug potentiellement importants sur GPU, donc les méthodes plus simples peuvent être plus intéressantes
Méthodes itératives Algorithme de Jacobi Principe Décomposer A en D (diagonale), U (triangulaire supérieure) et L (triangulaire inférieure) : A = D + L + U x k+1 = D 1 [ b (L + U)x k] Composante par composante : ( x k+1 i = 1 b i ) a ij x k j a ii j i Converge si A est symétrique définie positive
Méthodes itératives Algorithme de Gauss-Seidel Principe Décomposer A en D (diagonale), U (triangulaire supérieure) et L (triangulaire inférieure) : A = D L U (D L)x k+1 = Ux k + b Composante par composante : ( x k+1 i = 1 b i a ii i 1 j=1 a ij x k+1 j n j=i+1 Converge si A est symétrique définie positive a ij x k j )
Méthodes itératives Algorithmes de Jacobi et de Gauss-Seidel Implémentation sur CPU : Gauss-Seidel Implémentation directe avec une boucle for ( x k+1 i = 1 b i a ii i 1 j=1 a ij x k+1 j n j=i+1 a ij x k j ) Implémentation sur GPU : Jacobi Un thread par composante ( x k+1 i = 1 b i ) a ij x k j a ii j i
Méthodes itératives Algorithme du gradient biconjugué Principe Dérive de la méthode du gradient conjugué Construction d une suite de directions conjuguées Descente suivant ces directions Converge même pour des systèmes non symétriques...mais peu de résultats théoriques Numériquement instable
Méthodes itératives Algorithme du gradient biconjugué Difficultés Utilise plusieurs vecteurs intermédiaires À chaque itération : produit par A et par sa transposée heureusement, la structure de données s y prête bien! Algorithme plus complexe une simple boucle for ne suffit pas...
Méthodes itératives Algorithme du gradient biconjugué Implémentation sur GPU Utilisation de CUBLAS pour les opérations sur les vecteurs (norme, produit scalaire, SAXPY) 2 kernels spécifiques Textures pour les accès mémoire...et beaucoup de debug!
Améliorations possibles Amélioration de la précision Émulation de double précision Utiliser deux float pour émuler un double sur GPU Bibliothèque DSFUN90 en Fortran quelqu un en a fait un portage CUDA! Calcul avec des float2 largement plus lent
Améliorations possibles Amélioration de la précision Éviter les erreurs d arrondi Lors des divisions (dans Jacobi / Gauss-Seidel) : Termes diagonaux n interviennent qu au dénominateur Calcul des inverses sur CPU, multiplication par les inverses sur GPU Somme «déséquilibrée» algorithme de sommation de Kahan Code machine (PTX) : éviter les instructions MAD fonction _fmul_rn()...
1 Introduction 2 Contraintes et algorithmes Structure de données Méthodes itératives Améliorations possibles 3 Performances Tests en simple précision Tests en double précision 4 Conclusion
Errata Partie modifiée! Les résultats présentés le 4 juin étaient erronés du fait d un bug qui n a été découvert que quelques jours plus tard. Cette partie a donc été mise à jour avec la version corrigée : courbes corrigées, avec une précision largement meilleure ; inclusion de tests sur des matrices réelles ; inclusion de tests sur des cartes supportant le calcul en double précision ; ajout de l algorithme du Gradient Biconjugué Stabilisé (BiCG-Stab).
Performances des différents algorithmes Données mesurées Temps temps d exécution total de l algorithme, y compris les transferts Précision b Ax (max. en valeur absolue du vecteur d erreur) Données de test Système construit par le programme reproductible Tailles variant entre n = 100 et n = 3 000 000 Matrices réelles provenant de la base de matrices creuses de l Université de Floride (http://www.cise.ufl.edu/ research/sparse/matrices/index.html)
Tests en simple précision Temps 10 5 10 4 Gauss Seidel CPU Jacobi GPU BiCG CPU BiCG GPU BiCG Stab CPU BiCG Stab GPU Temps de convergence (ms) 10 3 10 2 10 1 10 0 10 1 10 2 10 3 10 4 10 5 10 6 Taille du problème
Tests en simple précision Précision 10 5 Gauss Seidel CPU Jacobi GPU BiCG CPU BiCG GPU BiCG Stab CPU BiCG Stab GPU Erreur 10 6 10 2 10 3 10 4 10 5 10 6 Taille du problème
Tests en simple précision Matrices réelles 1E+03 1E+02 1E+01 1E+00 1E-01 Erreur 1E-02 1E-03 CPU GS GPU Jacobi CPU BiCG GPU BiCG CPU BiCG-Stab GPU BiCG-Stab 1E-04 1E-05 1E-06 1E-07 dw4096.bin ex1.bin mcca.bin minsurfo.bin obstclae.bin wathen100.bin
Tests en simple précision Conclusion Conclusion sur cet exemple GPU largement plus rapide que CPU...mais moins précis BiCG converge mieux que Jacobi/Gauss-Seidel, mais avec une précision moins bonne BiCG-Stab converge bien, mais avec une précision encore moins bonne le plus intéressant : BiCG sur GPU
Tests en double précision Temps 10 5 10 4 Gauss Seidel CPU Jacobi GPU BiCG CPU BiCG GPU BiCG Stab CPU BiCG Stab GPU Temps de convergence (ms) 10 3 10 2 10 1 10 0 10 1 10 2 10 3 10 4 10 5 10 6 Taille du problème
Tests en double précision Précision 10 6 10 7 10 8 Gauss Seidel CPU Jacobi GPU BiCG CPU BiCG GPU BiCG Stab CPU BiCG Stab GPU 10 9 Erreur 10 10 10 11 10 12 10 13 10 14 10 15 10 2 10 3 10 4 10 5 10 6 Taille du problème
Tests en double précision Matrices réelles 1E+06 1E+03 1E+00 Erreur 1E-03 1E-06 CPU GS GPU Jacobi CPU BiCG GPU BiCG CPU BiCG-Stab GPU BiCG-Stab 1E-09 1E-12 1E-15 dw4096.bin ex1.bin mcca.bin minsurfo.bin obstclae.bin wathen100.bin
Tests en double précision Conclusion Conclusion sur cet exemple GPU largement plus rapide que CPU GPU très largement moins précis que CPU, et précision beaucoup plus variable Pas de changement notable sur la convergence Dans le pire des cas, résultats équivalents à ceux obtenus en float BiCG sur GPU reste un bon compromis
1 Introduction 2 Contraintes et algorithmes Structure de données Méthodes itératives Améliorations possibles 3 Performances Tests en simple précision Tests en double précision 4 Conclusion
Conclusion Solveurs sur GPU Exploiter la structure des matrices creuses est primordial Rapides, mais imprécis Pas adaptés à tous les problèmes Calculer une solution initiale pour un solveur plus précis sur CPU? Idées à tester Utiliser un préconditionneur pour améliorer la précision et la convergence Utiliser des cartes plus récentes qui supportent le type double
Conclusion Code source des solveurs Sera bientôt publié (licence GPL) Intégration à CNC si on a le temps et le courage
Conclusion Des questions?
Conclusion Des questions? Merci pour votre attention!
Textures Textures Mémoire de texture Cache local (quelques ko par multiprocesseur) Une lecture au plus 1 cache miss, sinon lecture depuis le cache Optimisé pour des accès à des adresses proches au sein d un warp Lecture seule Pas de vérification de cohérence avec la mémoire globale au sein d un appel à un kernel Concrètement : permet de limiter le nombre de transactions DRAM lors d accès mémoire non-coalesced