gpgpu
DESCRIPTION
GPGPUTRANSCRIPT
-
GPGPU
Implmentation dun simple oprateur algbrique linaire sur
GPU: saxpy()
-
2Objectif
Lopration saxpy() : un exemple simple
ne require pratiquement aucun background en algbre linaire
illustre trs bien les concepts GPGPU.
Consiste calculer y = y + alpha * x avec x et y vecteurs de longueur N et alpha une
valeur scalaire
-
3Configuration de OpenGL-GLUT
GLUT (OpenGL Utility Toolkit), : fournit des fonctions pour grer les vnements windows
Permet de crer de simples menus
etc. (voir http://raphaello.univ-fcomte.fr/ig/opengl/Glut.htm)
Nous lutiliserons pour configurer un OpenGL valide afin daccder au priphrique graphique, travers lAPI GL, avec le minimum de ligne de code possible
#include // inclue le fichier header GLUT
// A appeler partir du main()void initGLUT(int argc, char **argv) {
glutInit ( &argc, argv );glutCreateWindow(" TEST SAXPY");
}
-
4Configuration de OpenGL-GLEW
La plupart des mcanismes requis pour faire du GPGPU ne font pas partie du noyau dOpenGL
GLEW (OpenGL Extension Wrangler) est une libraire qui tend OpenGL pour avoir plus de contrle sur le matriel travers lAPI OpenGL
Dautres extensions OpenGL sont disponibles ladresse http://www.opengl.org/registry/
Il est possible dexplorer les extensions supportes par la carte graphique avec les outils : glewinfo (qui est fournit avec GLEW) OpenGL extension viewer GPU Caps Viewer Etc.
-
5Interface minimalistique
void initGLEW (void) {
// initialiser GLEW et obtenir les pointeurs sur les fonctionsint err = glewInit();// Attention : Ce code ne teste pas si lextension est supporte par le matriel // dans le cas chant glewInit() sera gale NULLif (err!=GLEW_OK)
{printf((char*)glewGetErrorString(err));exit(ERROR_GLEW);
} }
-
6Prparation de OpenGL pour un rendu offscreen
Dhabitude, le pipeline graphique se termine au niveau du frame buffer
La taille max des donnes du frame buffer est de 32 bit (RGBA) soit 8 bit par couleur 16 millions de couleurs Chaque couleur prend une valeur entre 0 et 256
Pour pouvoir avec des rels on peut stocker des donnes au format IEEE 32-bit :SEEEEEEEEFFFFFFFFFFFFFFFFFFFFFFF=(-1)s2e-1271.f
Lextension OpenGL appele EXT_framebuffer_object permet dutiliser un offscreen buffer (FBO) pour stocker les vecteurs des rendus
-
7Utilisation de lextension EXT_framebuffer_object
GLuint fb;
void initFBO(void) {
// crer un FBO (off-screen framebuffer)glGenFramebuffersEXT(1, &fb);
// se brancher sur offscreen buffer glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
}
-
8GPGPU concept 1: tableaux = textures
Pour le CPU : nativement sur une seule dimension accds moyennant des indices a[i][j]=a[i*M+j]
Pour le GPU : nativement sur 2 dimensions supporte 1 et 3 dimensions mais implique des pnalits sur les
performances Laccs se fait moyennant des coordonnes de textures appels textures ou texture samplers les dimensions des textures sont limites (peuvent tre obtenues
par une requte OpenGL une fois GLUT initialis)
int maxtexsize;glGetIntegerv(GL_MAX_TEXTURE_SIZE,&maxtexsize);printf("GL_MAX_TEXTURE_SIZE, %d\n",maxtexsize);
-
9Cration des tableaux sur CPU
Rappelons que lon souhaite calculer
y = y + alpha * x
Nous avons besoin de 2 tableaux de rels X et Y de taille N et dun rel alpha
Ces donnes seront allous et initialiss par le CPU malgr que le calcul sera effectu sur GPU
float* dataX = (float*)malloc(N*sizeof(float));float* dataY = (float*)malloc(N*sizeof(float));float alpha;
-
10
Cration de textures avec des nombres virgule flottante sur GPU On va limiter la prsentation 2 texture 2D :
La texture traditionnelle dans OpenGL : GL_TEXTURE_2D
Lextension OpenGL : ARB_texture_rectangle plus facile utiliser par des non graphistes)
Texture2D Texture rectangle
Texture cible GL_TEXTURE_2D GL_TEXTURE_RECTANGLE_ARB
Coordonnes des textures
Doivent tre normalises lintervalle [0,1] sur [0,1] indpendament de la dimension [0,M] sur [0,N] de la texture
Ne sont pas normaliss
Dimensions des textures
Doivent tre une puissance de 2 sauf si le pilote supporte lextension ARB_non_power_of_two ou quil prsente OpenGL 2.0
Les dimensions peuvent tre arbitraires
-
11
Format des textures
Le GPU permet le traitement simultan de : Scalaires : GL_LUMINANCE est le format de texture
adapt pour stocker une seule valeur en virgule flottante par texel 32 bits / texel
Tuples
Triples
Quadriples : GL_RGBA est le format de texture adapt pour stocker quatre valeur en virgule flottante par texel 128 bits / texel
-
12
Formats internes pour les textures
Il existe 3 extensions OpenGL qui prsentent des formats pour les nombres virgule flottante pour les textures : NV_float_buffer
ATI_texture_float
ARB_texture_float
Chaque extension dfinit un ensemble dnumrants (ex. : GL_FLOAT_R32_NV) et des symboles (ex. 0x8880) qui peuvent tre utiliss pour dfinir et allouer les textures
-
13
Enumrants
Les numrants des 2 formats de textures auxquels nous nous intressons sont : GL_FLOAT_R32_NV : informe le GL que nous souhaitons
stocker un seul nombre virgule flottante par texel GL_FLOAT_RGBA32_NV : stocke un 4-tuplet de nombres
virgule flottante
Les 2 extensions ATI_texture_float et ARB_texture_float sont identiques sauf quils dfinissent diffrents numrant pour
le mme symbol (cest une question de prfrences) sont supportes par les carte GeForce 6 (ou +) et ATI ont pour numrants respectifs
GL_LUMINANCE_FLOAT32_ATI GL_RGBA_FLOAT32_ATI GL_LUMINANCE32F_ARB GL_RGBA32F_ARB
-
14
Mapping CPU-GPU
Comment associer un vecteur (CPU) une texture (GPU) ? La solution la plus simple :
Pour les formats LUMINANCE : Associer un vecteur de taille N (on suppose que N est une puissance de 2) une texture de taille sqrt(N) par sqrt(N)
Pour les formats RGBA : Associer un vecteur de taille N une texture de taille sqrt(N/4) par sqrt(N/4). On suppose que N correspond une taille qui soit adapte pour tresupporte par la texture (ex. N=1024^2 peut tre stocke dans une texture de taille 512 sur 512). La valeur correspondante sera stocke dans texSize.
-
15
Rcap.
NVIDIA GeForce FX (NV3x)
NV4x, G7x, G8x (RECT)
NV4x, G7x, G8x (2D)
ATI
Cible texture rectangle texture rectangle
texture2D texture2D et texture rectangle
Format LUMINANCE et RGBA (et RG et RGB)
Attention : ces formats sont supports en tant que textures mais pas comme cible de rendu
Format
interne
NV_float_buffer NV_float_buffer ATI_texture_float NV_float_buffer
-
16
Allocation pour les textures
Il suffit de connatre : La texture cible :
GL_TEXTURE_2D GL_TEXTURE_RECTANGLE_ARB
Le format de la texture GL_LUMINANCE GL_RGBA
Le format interne que lon souhaite utiliser NV_float_buffer ATI_texture_float ARB_texture_float
-
17
Code pour lallocation de la texture
// crer un nouveau id pour une textureGLuint texID;glGenTextures (1, &texID);// associer lid de la texture une texture cibleglBindTexture(texture_target,texID);// Arrter le filtrage et configurer le wrap mode// (obligatoire pour les texures de rels)glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP);glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP);// Configurer le texenv REPLACE la place de la valeur par dfaut MODULATEglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);// Allouer la mmoire graphiqueglTexImage2D(texture_target, 0, internal_format, texSize, texSize, 0, texture_format, GL_FLOAT, 0);
-
18
Association index tableau-coordonnes texture
Dans la suite, nous allons chercher modifier les donnes stockes dans les textures par les donnes du rendu.
Pour pouvoir contrler quel lment traiter ou accder dans la mmoire texture, on a besoin : deffectuer une projection qui permet de passer des coordonnes du
modle 3D en coordonnes daffichage 2D projection orthogonale en plus dun mapping 1:1 entre coordonnes gomtriques (utilises
dans le rendering), les coordonnes de textures (donnes accder pou traitement : entre) et les coordonnes des pixels (rsultat du rendu : sortie) utiliser un bon viewport
Le mapping se base sur la taille (dans chaque dimension) utilise pour allouer les textures.
Pour configurer le mapping on met la valeur de z 0 dans les coordonnes du modle et on applique un mapping 1:1
Les lignes suivant peuvent tre ajout la routine initFBO()
-
19
viewport pour un mapping 1:1
// viewport pour un mapping 1:1 pixel=texel=geometryglMatrixMode(GL_PROJECTION);glLoadIdentity();//gluOrtho2D(0.0, texSize, 0.0, texSize);glMatrixMode(GL_MODELVIEW);glLoadIdentity();glViewport(0, 0, texSize, texSize);
-
20
Utilisation des textures comme cible (sortie)
Lextension framebuffer_object permet de renvoyer le rendu directement dans une texture.
Le problme cest que les textures sont soit en mode lecture soit criture.
Que faire pour y = y + alpha * x ?
Pour utiliser une texture comme cible il faut attacher la texture au FBO en supposant que le framebuffer est dj mis en offscreen
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, //jusqu 4 attachements par FBOtexture_target, texID, 0);
-
21
Transfert de donnes tableau (CPU)texture (GPU)
Pour transfrer les donnes vers les textures il faut les associer des textures cibles et ordonnancer le transfert avec des appels OpenGL.
glBindTexture(texture_target, texID);glTexSubImage2D(texture_target,0,0,0,texSize,texSize,
texture_format,GL_FLOAT,data);
-
22
Transfert de donnes texture (GPU) tableau (CPU)
Il y a 2 faons pour implmenter le transfert des textures GPU vers des tableaux CPU Lapproche traditionnelle OpenGL moyennant un
appel glGetTexImage() qui permet dassocier une texture une texture cible
Si la texture rcuprer est dj attache un FBO, il est possible dutiliser la technique de redirection
glBindTexture(texture_target,texID);glGetTexImage(texture_target,0,texture_format,GL_FLOAT,data);
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);glReadPixels(0,0,texSize,texSize,texture_format,GL_FLOAT,data);
-
23
// initialiser les paramtres de la textureglTexParameteri(GL_TEXTURE_RECTANGLE_ARB,
GL_TEXTURE_MIN_FILTER, GL_NEAREST);glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,
GL_TEXTURE_MAG_FILTER, GL_NEAREST);glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,
GL_TEXTURE_WRAP_S, GL_CLAMP);glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,
GL_TEXTURE_WRAP_T, GL_CLAMP);// dfinir la texture avec le format floating pointglTexImage2D(GL_TEXTURE_RECTANGLE_ARB,0,GL_RGBA32F_ARB,
texSize,texSize,0,GL_RGBA,GL_FLOAT,0);// attacher la textureglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB,tex,0);
// transfrer la donne data textureglTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB,0,0,0,texSize,texSize,
GL_RGBA,GL_FLOAT,data);// faire un read backglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);glReadPixels(0, 0, texSize, texSize,GL_RGBA,GL_FLOAT,result);// imprimer le rsultaprintf("Data before roundtrip:\n");for (int i=0; i
-
Pages de rfrence OpenGL
24
-
GPGPU concept 2 :kernel = shader
y = y + alpha * x
Avec un vecteur de N processeur, pas besoin de boucles (paradigme SIMD)
Kernel : y_new[i] = y_old[i] + alpha * x[i] Le traitement est divis sur lensemble des units de calculs
disponibles
25
for (int i=0; i
-
Cration dun shader avec Cg
26
float saxpy ( float2 coords : TEXCOORD0, uniform sampler2D textureY, uniform sampler2D textureX, uniform float alpha ) : COLOR {
float result; float y = tex2D(textureY,coords); //float yval=y_old[i];float x = tex2D(textureX,coords); //float xval=x[i];result = y + alpha * x; //y_new[i]=yval+alpha*xval;return result;
}
Texture cible : texture2D
-
Cration dun shader avec Cg version 4-tuples en parallle
27
float4 saxpy ( float2 coords : TEXCOORD0, uniform samplerRECTtextureY, uniform samplerRECT textureX, uniform float alpha ) : COLOR {
float4 result; float4 y = texRECT(textureY,coords); float4 x = texRECT(textureX,coords); result = y + alpha*x; // equivalent: result.rgba=y.rgba+alpha*x.rgba return result;
}
Texture cible : texture rectangle
-
O placer le shader ?
Le code source dun shader peut tre stock dans une chane de caractres ou bien dans un fichier .cg et il sera accd par OpenGL via le Cg runtime
28
-
Configuration du runtime Cg
Inclure lentte Cg
Ajouter les librairies pour ldition des liens
Dclaration de certains variables
29
#include // Cg Header#include // Header spcifique Cg OpenGL
#pragma comment( lib, "cg.lib")#pragma comment( lib, "cggl.lib")
CGcontext cgContext; //point dentre pou le runtime CgCGprofile fragmentProfile; //on sintresse au pixel pipelineCGprogram fragmentProgram; //conteneur pour le programmeCGparameter yParam, xParam, alphaParam; char* program_source = "float saxpy( [....] return result; } ";
-
Initialisation du runtime Cg
30
void initCG(void) {// set up CgcgContext = cgCreateContext();fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);cgGLSetOptimalOptions(fragmentProfile);// create fragment programfragmentProgram = cgCreateProgram (
cgContext,CG_SOURCE,program_source, fragmentProfile,"saxpy",NULL);
// load programcgGLLoadProgram (fragmentProgram);// and get parameter handles by nameyParam = cgGetNamedParameter (fragmentProgram,"textureY");xParam = cgGetNamedParameter (fragmentProgram,"textureX");alphaParam = cgGetNamedParameter (fragmentProgram,"alpha");
}
-
GPGPU concept 3 : Calculer = dessiner
Quatre tapes sont ncessaires : Activation du noyaux en utilisant le Cg
runtime
Assignation des tableaux d entre et de sortie au shader runtime Cg
Dclenchement du traitement
31
-
Etape 1 : Activation du noyau
Pour activer le noyau en utilisant le Cg runtime : Le fragment profile doit tre activ
Le shader dj crit et charg est attach
On ne peut activer quun seul shader du mme type la fois
Lactivation est assure par le code suivant :
32
// Activer le profil fragment cgGLEnableProfile(fragmentProfile); // Associer le programme saxpycgGLBindProgram(fragmentProgram);
-
Etape 2 : Configuration des entres tableaux textures
33
// Activer la texture y_old (lecture seule) cgGLSetTextureParameter(yParam, y_oldTexID); cgGLEnableTextureParameter(yParam); // Activer la texture x (lecture seule) cgGLSetTextureParameter(xParam, xTexID); cgGLEnableTextureParameter(xParam); // Activer le scalaire alpha cgSetParameter1f(alphaParam, alpha);
-
Etape 3 : Configuration des sorties tableaux textures
34
// Attacher la texture cible au premier point dattachmentglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, texture_target, y_newTexID, 0); // Configurer la texture comme cible de renduglDrawBuffer (GL_COLOR_ATTACHMENT0_EXT);
-
Etape 4 : Traitement Rappelons ce que nous avons fait.
Activ un mapping 1:1 entre les pixels cibles, les coordonnes de texture et la gomtrie
Prpar un fragment shader excuter sur chaque fragment
Ce qui reste faire : tre sr que chaque donne t transfr correctement dans un
fragment Ceci est relativement facile grce aux settings de la projection et du viewport
Tout ce dont on a besoin cest un carr (quad) qui couvre la totalit du viewport (dfinissable grce au standard OpenGL)
on dfinit 4 vertices coins du carr
On assigne les coordonnes de texture comme attributs des 4 vertices (les vertices seront transforms en espace cran)
La rastrisation (fonction fixe du pipeline) qui se trouve entre le vertex et le fragment pipeline se chargera du de lassociation entre pixel et coordonnes texture pour gnrer un fragment pour chaque pixel couvert par le carr
Chaque valeur sera passe automatiquement au fragment shader
Le quad sert comme un gnrateur de flux de donnes pour le program shader
35
-
j avec une texture rectangles
Les coordonnes de textures sont identiques aux coordonnes des pixels
36
// make quad filled to hit every pixel/texelglPolygonMode(GL_FRONT,GL_FILL); // and render quad glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex2f(0.0, 0.0); glTexCoord2f(texSize, 0.0); glVertex2f(texSize, 0.0); glTexCoord2f(texSize, texSize); glVertex2f(texSize, texSize); glTexCoord2f(0.0, texSize); glVertex2f(0.0, texSize);
glEnd();
-
j avec une texture 2D
Les coordonnes de textures sont normalises
37
// make quad filled to hit every pixel/texel glPolygonMode(GL_FRONT,GL_FILL); // and render quad glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex2f(0.0, 0.0); glTexCoord2f(1.0, 0.0); glVertex2f(texSize, 0.0); glTexCoord2f(1.0, 1.0); glVertex2f(texSize, texSize); glTexCoord2f(0.0, 1.0); glVertex2f(0.0, texSize);
glEnd();