| Introduction 
      GPGPU General Purpose Graphic Processor Unit 
      Programmation GPGPU Technique de programmation visant à l'implantation des applications en exécution sur
    les cartes graphiques (GPU) au lieu des processeurs centraux (CPU). Technique développée depuis le début des années 2000, moment où les fabriquants de
    cartes graphiques (NVidia, ATI, 3D Labs, ...) ont rendu possible l'implantation de
    programmes tiers sur leurs adaptateurs graphiques (fonctionnalité obligatoire pour
    l'implantation de Microsoft DirectX 9). Historiquement il n'existait pas d'API spécifique.-> Les développements se faisaient par détournement des langages de programmation de
    shaders graphiques à des fins autres que la programmation d'algorithmes de l'infographie:
 - GLSL pour OpenGL,
 - HLSL pour DirectX,
 - CG pour les cartes graphiques NVidia.
 Apparition d'API spécifiques indépendantes des API graphiques:- CUDA pour les cartes graphiques NVidia
 - Streams pour les cartes graphiques ATI
 - OpenCL, API générique spécifiée par khronos
 
      Avantages 
      La puissance de calcul théoriquement disponible (puissance de crête) sur les GPU est
        très largement supérieure à celle proposée par les CPU les plus rapides. 
      
        | 
          
            | CPU | Puissance de crête | TDP |  
            | Intel Pentium 4 - 2.8 Ghz - 1 cur - x86 | 2.7 GFlops | 70 W |  
            | Intel Centrino Duo - 1.66 Ghz - 2 curs - x86 | 3.1 GFlops | 30 W |  
            | Intel Xeon 5410 - 2.33 Ghz - 4 curs - x64 | 9,5 GFlops | 100 W |  
            | Intel Core I7 980x - 3.33 Ghz - 6 coeurs - x64 | 20 GFlops | 130 W |  
            | AMD Athlon 64 x2 - 3.0 Ghz - 2 curs - x64 | 5,9 GFlops | 65 W |  
            | AMD Phenom II x6 - 3.0 Ghz - 6 curs - x64 | 17,8 GFlops | 100 W |  |  
        | 
          
            | GPU | Puissance de crête | TDP |  
            | NVidia 9800 GT - 112 curs - 600 Mhz | 370 GFlops | 230 W |  
            | NVidia GT240 - 96 coeurs - 550 Mhz | 260 GFlops | 180 W |  
            | NVidia GTX 285 - 240 curs - 648 Mhz | 700 GFlops | 370 W |  
            | NVidia GTX 480 - 480 curs - 700 Mhz | 1350 GFlops | 410 W |  
            | ATI HD 3870 - 320 curs - 775 Mhz | 490 GFlops | 240 W |  
            | ATI HD 4890 - 800 curs - 850 Mhz | 1360 GFlops | 290 W |  
            | ATI HD 5970 - 3200 curs - 725 Mhz | 4640 GFlops | 430 W |  |  
      Les adaptateurs graphiques sont peu couteux.L'efficacité énergétique est meilleure sur les GPU que sur les CPU:- de 5 à 10 Watt / GFlops pour les CPU,
 - de 0.1 à 1 Watt / GFlops pour les GPU.
 
      Inconvénients 
      Les GPU ayant prioritairement été conçus pour une utilisation dans le
        cadre d'algorithmes de l'infographie, ils peuvent présenter certaines limites techniques
        (abscence de certaines opérations mathématiques, entiers et réels simple précision,
        ...).Les API actuelles ne font pas appel aux concepts de la programmation
        orientée objet mais seulement à la programmation structurée.La programmation parallèle est obligatoire.Les modèles de programmation parallèle utilisables sont limités.-> Il faut que l'application développée se prête bien à ce type de développement.
L'exploitation pleine et entière de la puissance de calcul disponible
        n'est pas simple à obtenir. Les langages de développement de shader Les API 3D modernes permettent de développer de petits programmes, les
    "shaders", destinés à être exécutés directement sur les GPU de la carte
    graphique.C'est le cas sous DirectX depuis la version 9.0 de cette bibliothèque. Sous OpenGL, c'est
    aussi le cas depuis la version 2.0.
 Il existe différents types de shaders. Les types les plus courants sont
    les "vertex shaders" et les "fragment shaders" aussi appelés
    "pixel shaders". Le vertex shader configuré pour une opération d'affichage sera appelé
    pour traiter chacun des vertices (sommets) de définition des primitives graphiques de
    modélisation géométrique de la scène.Le fragment shader configuré sera appelé pour traiter chacun des pixels issus de la
    rasterisation des primitives graphiques de modélisation.
 Un premier type de parallèlisation pourra être obtenu en utilisant les
    vertex shaders:En effet, les sommets d'une primitive graphique seront gérés en parallèle par
    traitement au moyen du vertex shader simultanément sur plusieurs GPU. Plusieurs
    primitives graphiques pourront même voir leurs sommets traités en parallèle sur
    plusieurs GPU.
 Un deuxième type de parallèlisation pourra être obtenu en utilisant les
    fragment shaders:Les pixels de rasterisation d'une primitive seront gérés en parallèle par traitement au
    moyen du fragment shader exécuté simultanément sur plusieurs GPU.
 Les shaders sont de "relativement petits" programmes destinés
    à être exécutés un très très grand nombre de fois. Les problèmes solvables au moins
    d'une tâche unique exécutée de multiple fois sur des données différentes de type
    identique sont succeptibles de bien être adaptés à une programmation au moyen d'un
    langage de shader. Contrainte: La communication des données et la
    récupération des résultats doivent s'intégrer dans le cadre d'un fonctionnement de
    type "programme avec affichage graphique 3D". Données:- positions de sommets
 - normales
 - couleur de tracé
 - valeur de matériel
 - texture
 - variable d'environnement
 - ...
 Résultats:
 - une image
 
      OpenGL GLSL GLSL est le langage de développement de shaders introduit dans OpenGL
    avec la version 2.0 de l'API. Il permet de créer des vertex shaders et des fragment
    shaders. Si ni vertex shader ni fragment shader n'est spécifié, OpenGL utilise
    ses propres shaders "fixes". Si un vertex shader est employé, celui-ci sera
    utilisé en lieu et place du vertex shader d'OpenGL. Si un fragment shader est employé,
    celui-ci sera utilisé en lieu et place du fragment shader d'OpenGL.-> Pour obtenir le même résultat écran qu'avec les shaders de base OpenGL, tout
    shader installé devra réaliser l'ensemble des opérations réalisées par le shader de
    base qu'il remplace.
 
      
        Rôles des vertex shaders GLSL Le but du vertex shader est de traiter le sommet qu'il reçoit en gestion
    pour préparer les informations qui seront transmises au vertex shader exécuté pour
    chacun des pixels de rastérisation de la primitive auquel appartient le sommet. 
      Réalisation de la transformation géométrique de passage des coordonnées de
        modélisation spécifiées par glVertex en coordonnées écran.Réalisation des calculs d'éclairage si l'illumination "flat" ou Gouraud est
        utilisée.Calcul de toute autre information à transmettre au fragment shader.... 
      
        Rôles des fragment shaders GLSL Le but du fragment shader est de calculer la couleur du pixel pour lequel
    il est lancé. Toute information reçue du vertex shader est automatiquement interpolée
    entre les valeurs calculées par le vertex shader et en fonction de la position du pixel
    au sein de la primitive à laquelle il appartient. 
      Réalisation des calculs d'éclairage si l'illumination Phong est utilisée.Réalisation du plaçage de texture.... 
      
        Syntaxe Syntaxe proche de celle du langage C. Exemple de vertex shader 
      
        | uniform float RotationY; varying vec3 MCposition;
varying vec3 Direction; void main() {   
  Direction = vec3(0.0,0.0,-1.0);
  mat3 ry = mat3( cos(RotationY), 0.0, sin(RotationY),
                             0.0, 1.0,            0.0,
                 -sin(RotationY), 0.0, cos(RotationY));
  MCposition = ry*vec3(gl_Vertex);
  Direction = ry*Direction;
  gl_Position = ftransform();
} |  Exemple de fragment shader 
      
        | uniform vec3 Dimensions;
uniform sampler3D Texture3D; varying vec3 MCposition;
varying vec3 Direction; vec4 rayTracing(float x,float y,float z,
                float incx,float incy,float incz) {
  float alpha = 1.0;
  vec4 cl = vec4(0.0,0.0,0.0,1.0);
  do {
    vec4 c = texture3D(Texture3D,vec3(x,y,z));
    float aa = c.a*alpha;
    cl.r = cl.r + c.r*aa;
    cl.g = cl.g + c.g*aa;
    cl.b = cl.b + c.b*aa;
    alpha *= (1.0-c.a);
    x += incx;
    y += incy;
    z += incz; }
  while ( ( x >= 0.0 ) && ( x < 1.0 ) &&
          ( y >= 0.0 ) && ( y < 1.0 ) &&
          ( z >= 0.0 ) && ( z < 1.0 ) );
  return(cl);
}void main() {
    float x = MCposition.x/Dimensions.x+0.5;
    float y = MCposition.y/Dimensions.y+0.5;
    float z = MCposition.z/Dimensions.z+0.5;
    gl_FragColor = rayTracing(x,y,z,
                              Direction.x/Dimensions.x,
                              Direction.y/Dimensions.y,
                              Direction.z/Dimensions.z);
} |  Les variables "uniform" sont directement reçue de l'host. Les variables
    "varying" permettent la transmission d'information (avec interpolation) du
    vertex shader vers le fragment shader.Dans le vertex shader, la variable gl_position est la variable qui doit être affectée
    pour indiquer la coordonnée écran du sommet.
 Dans le fragment shader, la variable gl_FragColor est la variable qui doit être affectée
    pour indiquer la couleur du pixel.
 Les shaders sont chargés et compilés directement sur la carte graphique par le pilote
    logiciel de la carte au moyen d'un jeu de fonction d'extension d'OpenGL. 
      
        Limitations 
      Tous les processeurs exécutent le même vertex shader.Tous les processeurs exécutent le même fragment shader.Pas de réel double précision.Pas d'entier long.Pas de récursivité! Les API spécialisées Les contraintes liées à l'utilisation des API graphiques pour les
    détourner à une autre fin que le calcul d'images sont trop importantes. Elles ne rendent
    pas cette technique suffisamment souple pour qu'elle soit adaptée à un large spectre
    applicatif. Des API spécialisées ont été créées pour rendre plus versatile
    l'emploi des GPU. Les trois principales sont NVidia CUDA, ATI Streams et OpenCL. CUDA et
    Streams sont des API propriétaires. OpenCL est une API libre développée par le
    consortium Kronos qui est en charge d'OpenGL, OpenML, ... 
      CUDA CUDA permet la création de programmes destinés à être exécutés sur
    les multiples processeurs présents sur une carte graphique. Le kit de développement CUDA inclut un compilateur destiné à générer
    le code exécutable sur la carte graphique.Il inclut aussi une API permettant de contrôler les interactions entre le CPU, nommé
    host, et la(les) carte(s) graphique(s) utilisée(s), nommé device(s). Entre autres, cette
    API permet d'organiser l'allocation de mémoire sur les devices, les transferts mémoire
    host -> devices et devices -> host et bien entendu le lancement des programmes CUDA
    sur les devices.
 La syntaxe du langage associé à CUDA, le CUDA-C est proche de celle du
    langage C. 
      
        Avantages 
      Beaucoup plus souple que les langages de shadingAssez propreLangage très proche du langage C -> pas déstabilisant... 
      
        Inconvénients 
      Allers et retours mémoire entre host et devices très néfastes en terme de performanceSaturation possible de la bande passante mémoireGros challenge pour obtenir les performances de crête (exploitation maximale des caches
        mémoire, ...).... |