1. GPGPU
Outil g´n´rique pour la r´solution de syst`mes d’´quations
e e e e e
lin´aires sur processeur graphique
e
Caner Candan
M2 MIHP
caner@candan.fr
6 mars 2011
Table des mati`res
e
1 Introduction 2
2 Utilisation de la STL 2
2.1 Transformation de GPGPU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
2.2 Inconv´niant de la STL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
e 2
3 Le type cuComplex 3
3.1 Non-g´n´ricit´ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
e e e 3
3.2 La solution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
4 cuComplex vs cudacomplex 3
5 Conclusion 4
1
2. 1 INTRODUCTION 2
1 Introduction
Se basant sur un outil existant, appel´ GPGPU, nous allons tenter de maximiser la g´n´ricit´
e e e e
du code en faisant appel ` des paradigmes de m´ta-programmations. Nous prendrons toutefois
a e
en compte les diff´rentes contraintes, en terme de performance, qu’elles peuvent engendrer.
e
GPGPU peut ˆtre qualifi´ comme un benchmark permettent de r´soudre et comparer des
e e e
m´thodes de calcul en alg`bre lin´aire.
e e e
Nous commencerons par d´finir la hi´rarchie des composants du projet en figure 1.
e e
Composant Description
MatrixMarket Lecture de fichier de donn´es contenant des matrices
e
GPGPU R´solution de syst`mes d’´quations lin´aires
e e e e
LinAlgCUDA Portage CUDA pour le calcul sur acc´l´rateur
ee
Applications Applications param´trable permettant de tester et g´n´rer des r´sultats significatifs
e e e e
´
Echantillons Des fichiers contenant des matrices de diff´rents types utilis´s par les applications
e e
Figure 1 – D´finition de la structure de GPGPU
e
2 Utilisation de la STL
2.1 Transformation de GPGPU
Dans un premier temps, il a ´t´ convenu de transformer le composant GPGPU qui pour
ee
rappel rassemble des fonctions pour r´soudre des syst`mes d’´quations lin´aires. Pour la trans-
e e e e
formation, il s’agit l` d’´viter la redondance de code pour g´rer des types de donn´es sp´cifique.
a e e e e
Ainsi, pour y parvenir, nous avons utilis´ le concept des template. En effet, le composant
e
GPGPU fournit sp´cifiquement et de mani`re quasi-identique deux versions pour chaque fonc-
e e
tion qu’elle compose pour g´rer les types r´els et complexes.
e e
Bien entendu cela ` poser d’autres contraires : d`s lors o` le code se veut g´n´rique il en
a e u e e
va de mˆme pour les types de donn´es manipul´s. C’est pourquoi il est ´galement essentiel de
e e e e
rendre les manipulations de donn´es g´n´rique. Nous entendons par manipulation tous types
e e e
d’op´rations d’addition, multiplication, ...
e
La classe std::complex fournit par la STL int´gre d´j` ces aspets : g´n´ricit´ du type du
e ea e e e
r´el/imaginaire, compatibilit´ avec les op´rateurs, ... Cependant elle pr´sente ´galement des
e e e e e
inconv´niants...
e
2.2 Inconv´niant de la STL
e
Il a ´t´ remarqu´ lors de la transformation que l’appel aux m´thodes de la classe std::complex
ee e e
ne fonctionne pas depuis une fonction dite kernel, executant le code cˆt´ GPU.
oe
Nous illustrons un exemple de code, employant le type std::complex avec du code CUDA,
en figure 2.
Une premi`re raison consisterait ` dire que les fonctions de la STL, ne d´finissant pas l’at-
e a e
tribut __device__, qui indique de mani`re explicite l’execution de la fonction par un kernel et
e
3. 3 LE TYPE CUCOMPLEX 3
template < typename T > __global__ void kernel( std::complex< T > z )
{
z = z + z;
}
int main()
{
dim3 dimBlock(64, 1, 1);
dim3 dimGrid((1000 + dimBlock.x - 1)/dimBlock.x, 1, 1);
std::complex< double > i(0, 1);
kernel<<<dimGrid , dimBlock>>>( i );
}
Figure 2 – Illustration de code utilisant std : :complex avec CUDA
donc par le GPU, expliquerait le dysfonctionnement vu pr´c´dement.
e e
Cela a ´t´ remarqu´ en premier lieu, dans le code de GPGPU, lors de l’appel ` la librairie
ee e a
interne LinAlgCUDA qui utilise le type complex dans des fonctions kernel.
3 Le type cuComplex
CUDA fournit une primitive permettant d’utiliser les complexes. Ce dernier utilise une
structure commune ` toutes ses primitives ayant pour attributs x, y, z. Dans le cas du type
a
cuComplex, il peut ˆtre de type f loat2 ou double2 selon le souhait d’ˆtre en simple ou double
e e
pr´cision.
e
3.1 Non-g´n´ricit´
e e e
Bien que le type cuComplex pr´sente des avantages certains dans l’utilisation de complexe en
e
CUDA, il pr´sente ´galement un grand inconv´nient qui est la g´n´ricit´. Rappelons que l’outil
e e e e e e
GPGPU se veut g´n´rique, le fait d’utiliser ce type nous obligera ` d´dier du code sp´cifique `
e e a e e a
ce nouveau type, ce que nous souhaitons dans tous les cas ´viter. La raison de sa non-g´n´ricit´
e e e e
s’explique par le fait que cette primitive a ´t´ cr´e en langage C et n’int´gre donc pas les
ee e e
paradigmes de m´ta-programmations.
e
3.2 La solution
Une solution a ´t´ de chercher un ´quivalent C++, template et g´n´rique de ce type. Une
ee e e e
nouvelle classe a donc ´t´ int´gr´ ` l’outil, elle s’appelle _cudacomplex et pr´-d´finit deux
ee e e a e e
primitives : singlecomplex et doublecomplex.
4 cuComplex vs cudacomplex
Comme expliqu´ pr´c´demment, notre nouvelle classe _cudacomplex, bien qu’elle parait
e e e
nouvelle utilise les mˆmes primitives que cuComplex, en effet si l’on utilise singlecomplex, ce
e
type instancie implicitement le type float2, de la mˆme mani`re que doublecomplex qui ins-
e e
tancie le type double2. Et contrairement ` la classe std::complex, les m´thodes sont d´finits
a e e
avec l’attribut __device__ et executable donc sur le GPU.
Nous illustrons un exemple d’utilisation de cette classe en figure 3.
4. 5 CONCLUSION 4
template < typename T2, typename T >
__global__ void kernel( _cudacomplex< T2, T > z )
{
z = z + z;
}
int main()
{
dim3 dimBlock(64, 1, 1);
dim3 dimGrid((1000 + dimBlock.x - 1)/dimBlock.x, 1, 1);
singlecomplex s_i(0, 1);
kernel<<<dimGrid , dimBlock>>>( s_i );
doublecomplex d_i(0, 1);
kernel<<<dimGrid , dimBlock>>>( d_i );
}
Figure 3 – Illustration de code utilisant cudacomplex
5 Conclusion
Ce travail nous a permis dans un premier temps de comprendre l’int´rˆt d’employer un type
ee
complexe adapt´ ` son environnement puis dans un second, l’utilisation de la g´n´ricit´ pour
ea e e e
´viter toute forme de redondance dans le code.
e
Nous avons vu que le type std::complex n’´tant pas adapt´ ` une ex´cution sur GPGPU,
e ea e
il a fallu avoir recours ` un type sp´cifique ` CUDA cuComplex, et finalement, compte tenu de
a e a
la perte de g´n´ricit´, nous nous sommes orient´ vers un type de donn´es nouveau reprenant
e e e e e
les caract´ristiques du type cuComplex et ajoutant le concept de g´n´ricit´.
e e e e
D’autres solutions existent et vont ˆtre utilis´ pour la suite du travail comme thrust 1 , qui se
e e
veut ˆtre un ´quivalent de la STL pour CUDA, et cusp 2 , pour le calcul sur des matrices creuses.
e e
Tous deux respectent la g´n´ricit´ et par la mˆme occasion les types comme complexe.
e e e e
1. Thrust : http://code.google.com/p/thrust/
2. Cusp : http://code.google.com/p/cusp-library/