• Aucun résultat trouvé

lérateurs graphiques

II.2.1 CUDA - NVIDIA

En février 2007, NVIDIA Corporation a rendu publique la version initiale du Com-pute Unified Device Architecture (CUDA) [KH10]. Le kit de développement CUDA permet au programmeur d’utiliser le langage de programmation C pour écrire des algorithmes capables d’être exécutés sur les cartes graphiques NVIDIA (depuis la version GeForce 8). CUDA permet aux développeurs un accès illimité aux architec-tures graphiques massivement parallèles des GPU NVIDIA, par l’intermédiaire d’un jeux d’instructions natif.

La partie hôte du runtime CUDA [NVIc] inclut des fonctions spécifiques permettant de spécifier les caractéristique de l’exécution pour manipuler :

– la gestion du périphérique – la gestion des contextes

– la gestion mémoire

– le contrôle de l’exécution (appels des fonctions kernel) – la gestion des textures

– l’interopérabilité avec les interfaces graphiques OpenGL et Direct3D

Le langage CUDA est composé de deux API qui correspondent à deux niveaux de complexité :

– C runtime for CUDA API est le plus couramment utilisé car il gère automatiquement la configuration des kernels avant leurs lancement, ainsi que leur lancement effectif. Il gère également des initialisations implicites de l’environnement CUDA, la gestion contextes et le passage de paramètres. Il est basé sur des extensions spécifiques du langage C99 ;

– CUDA Driver API est une API de bas niveau, qui offre un meilleur niveau de contrôle, avec l’inconvénient de nécessiter plus de code pour une même tâche et d’être plus difficile à programmer et déboguer. Il n’a aucune dépendance avec la bi-bliothèque d’exécution et n’a aucune des extensions C. Ces particularités permettent à d’autres compilateurs que le compilateur par défaut de NVIDIA d’être utilisé. Le CUDA driver API est supporté par la librairie nvcuda et toutes ses fonctions sont préfixés par cu, tandis que le C runtime for CUDA API est supporté par la librairie cudart et toutes ses fonctions sont préfixés avec cuda.

Un exemple de kernel simple, pour le produit matriciel, est présenté ci-dessous.

Listing II.1: Produit matriciel - kernel CUDA

1 g l o b a l v o i d s h a r e d A B M u l t i p l y ( f l o a t * a , f l o a t * b , f l o a t * c , int N ) 2 { _ _ s h a r e d _ _ f l o a t a T i l e [ T I L E _ D I M ][ T I L E _ D I M ]; 3 _ _ s h a r e d _ _ f l o a t b T i l e [ T I L E _ D I M ][ T I L E _ D I M ]; 4 int row = b l o c k I d x . y * b l o c k D i m . y + t h r e a d I d x . y ; 5 int col = b l o c k I d x . x * b l o c k D i m . x + t h r e a d I d x . x ; 6 f l o a t sum = 0.0 f ; 7 a T i l e [ t h r e a d I d x . y ][ t h r e a d I d x . x ] = a [ row * T I L E _ D I M + t h r e a d I d x . x ]; 8 b T i l e [ t h r e a d I d x . y ][ t h r e a d I d x . x ] = b [ t h r e a d I d x . y * N + col ]; 9 _ _ s y n c t h r e a d s (); 10 for ( int i = 0; i < T I L E _ D I M ; i ++) 11 sum += a T i l e [ t h r e a d I d x . y ][ i ]* b T i l e [ i ][ t h r e a d I d x . x ];

12 c [ row * N + col ] = sum ;

13 }

Listing II.2: Produit matriciel - appel du kernel CUDA

1 // s e t u p e x e c u t i o n p a r a m e t e r s

2 d i m 3 t h r e a d s ( B L O C K _ S I Z E , B L O C K _ S I Z E );

3 d i m 3 g r i d ( WC / t h r e a d s . x , HC / t h r e a d s . y );

4 // e x e c u t e the k e r n e l

5 m a t r i x M u l < < < grid , t h r e a d s > > >( d_C , d_A , d_B , WA , WB );

La dernière version (5) disponible fin 2012, devrait apporter d’autres améliorations significatives :

– support pour le parallélisme dynamique, dans lequel chaque thread pouvait générer et lancer des sous-kernel, ce qui permet d’avoir de la récursivité ;

– technologie GPUDirect pour permettre la communication directe entre deux cartes graphiques ;

– l’édition des liens avec des librairies externes.

II.2.2 Accelerated Parallel Processing - AMD

AMD a rendu publique en décembre 2007 une première version de son kit de dévelop-pement, première version Stream Computing SDK. Le kit de développement inclut « Brook+ », une version optimisée pour le matériel AMD.

Récemment, AMD a abandonné le langage Brook+ pour supporter pleinement le lan-gage OpenCL présenté dans le chapitre suivant et a renommé l’environnement de dé-veloppement Accelerated Parallel Processing SDK. De plus AMD, en partenariat avec Microsoft ont également annoncé un nouveau langage de programmation, C++ Accelerated Massive Parallelism (C++ AMP), qui en effet est une extension du langage C++. A ce jour, C++ AMD n’est pas supportée par le compilateur Microsoft Visual Studio disponible sur Microsoft Windows [Gre11].

Listing II.3: Produit matriciel - kernel C++ AMP (AMD)

1 t e m p l a t e < t y p e n a m e _type , int t i l e _ s i z e >

2 v o i d m x m _ a m p _ t i l e d ( int M , int N , int W , c o n s t std :: vector < _type >& va ,

3 c o n s t std :: vector < _type >& vb , std :: vector < _type >& v r e s u l t )

4 {

5 if (( va . si z e ( ) ! = M * N ) || ( vb . s i z e ( ) ! = N * W ) || ( v r e s u l t . s i z e ( ) ! = M * W ))

6 t h r o w " E x p e c t e d ␣ m a t r i x ␣ d i m e n s i o n ␣ r e s u l t ( M * W )= a ( MxN )* b ( N * W ) " ;

7

8 extent <2 > e_a ( M , N ) , e_b ( N , W ) , e_c ( M , W );

9 10 a s s e r t (( M % t i l e _ s i z e ) == 0); 11 a s s e r t (( W % t i l e _ s i z e ) == 0); 12 a s s e r t (( N % t i l e _ s i z e ) == 0); 13 14 // C o p y in 15 a r r a y _ v i e w < c o n s t _type , 2 > a v _ a ( e_a , va ); 16 a r r a y _ v i e w < c o n s t _type , 2 > a v _ b ( e_b , vb ); 17 a r r a y _ v i e w < _type , 2 > a v _ c ( e_c , v r e s u l t ); 18 19 extent <2 > c o m p u t e _ d o m a i n ( e_c ); 20 21 p a r a l l e l _ f o r _ e a c h ( c o m p u t e _ d o m a i n . tile < t i l e _ s i z e , t i l e _ s i z e >() , \\ 22 [=] ( t i l e d _ i n d e x < t i l e _ s i z e , t i l e _ s i z e > t i d x ) r e s t r i c t ( amp ) 23 { 24 _ t y p e t e m p _ c = 0; 25 26 index <2 > l o c a l I d x = t i d x . l o c a l ; 27 index <2 > g l o b a l I d x = t i d x . g l o b a l ; 28

29 for ( int i = 0; i < N ; i += t i l e _ s i z e ) 30 { 31 t i l e _ s t a t i c _ t y p e l o c a l B [ t i l e _ s i z e ][ t i l e _ s i z e ]; 32 t i l e _ s t a t i c _ t y p e l o c a l A [ t i l e _ s i z e ][ t i l e _ s i z e ]; 33 34 l o c a l A [ l o c a l I d x [ 0 ] ] [ l o c a l I d x [ 1 ] ] = \\ 35 a v _ a ( g l o b a l I d x [0] , i + l o c a l I d x [ 1 ] ) ; 36 l o c a l B [ l o c a l I d x [ 0 ] ] [ l o c a l I d x [ 1 ] ] = \\ 37 a v _ b ( i + l o c a l I d x [0] , g l o b a l I d x [ 1 ] ) ; 38 39 t i d x . b a r r i e r . w a i t (); 40 41 for ( u n s i g n e d k = 0; k < t i l e _ s i z e ; k ++) 42 { 43 t e m p _ c += l o c a l A [ l o c a l I d x [ 0 ] ] [ k ] * \\ 44 l o c a l B [ k ][ l o c a l I d x [ 1 ] ] ; 45 } 46 47 t i d x . b a r r i e r . w a i t (); 48 } 49 50 a v _ c [ t i d x ] = t e m p _ c ; 51 }); 52 // c o p y i n g out d a t a is i m p l i c i t - w h e n a r r a y _ v i e w g o e s out of 53 // s c o p e d a t a is s y n c h r o n i z e d 54 }

Listing II.4: Produit matriciel - appel du kernel C++ AMP sur l’hote (AMD) 1 std :: vector < D A T A _ T Y P E > v_a ( M * N ); 2 std :: vector < D A T A _ T Y P E > v_b ( N * W ); 3 std :: vector < D A T A _ T Y P E > v _ c _ s i m p l e ( M * W ); 4 std :: vector < D A T A _ T Y P E > v _ c _ t i l e d ( M * W ); 5 std :: vector < D A T A _ T Y P E > v _ r e f ( M * W ); 6 7 i n i t i a l i z e _ a r r a y ( v_a , M * N ); 8 i n i t i a l i z e _ a r r a y ( v_b , N * W ); 9 10 m x m _ a m p _ t i l e d < D A T A _ T Y P E , 16 >( M , N , W , v_a , v_b , v _ c _ t i l e d ); 11 12 ...

II.2.3 OpenCL - Kronos

Apple, en collaboration avec AMD, Intel et NVIDIA, se sont réunis au sein du consor-tium Kronos et ils ont proposé les spécifications d’OpenCL (Open Computing Lan-guage) [Ope10]. L’enjeu était de proposer une API portable capable de prendre en charge tous les types d’accélérateurs matériels. La première version des spécifications OpenCL a été rendue publique en novembre 2008. La dernière version (1.2) contient

trois parties [ATI09] :

– spécification du langage (basé sur C99) et de l’interface de programmation (fichiers d’en-tête) permettent d’écrire des programmes portables, qui s’exécutent sur plu-sieurs plateformes hétérogènes constitué de processeurs, de GPU, et d’autres accélé-rateurs

– une couche API traite la gestion des périphériques permettant au développeur d’in-terroger la disponibilité des appareils et leurs caractéristiques, puis sélectionner et ini-tialiser les dispositifs nécessaires aux calculs ; cette API traite également le contexte et la gestion des files d’attente

– l’interface d’exécution (runtime API) permet aux développeurs de créer des objets mémoire associés à des contextes, de compiler et de créer des objets kernel, appeler des commandes vers la file d’attente ou realiser des synchronisations et libérer des ressources utilisées.

Le modèle d’exécution d’OpenCL est similaire à celui du langage bas niveau de CUDA (CUDA driver API ) mais oblige à utiliser, explicitement, des opérations telles que : – la création d’éléments du contexte attaché au périphérique (collection de

périphé-riques OpenCL utilisés par l’hôte), les kernels (fonctions OpenCL qui s’exécutent sur des périphériques), des objets programme (la source du programme et l’exécutable qui met en œuvre les kernels), des objets mémoire (ensemble d’objets visibles à l’hôte et aux dispositifs OpenCL) ;

– la création d’une file d’attente de commandes, qui inclue les instructions planifiées pour s’exécuter sur le périphérique dans le cadre du contexte (instructions d’ap-pel de kernel, instructions mémoire, instructions de synchronisation) ; il est possible d’associer à un seul contexte plusieurs files d’attente indépendantes.

Listing II.5: Produit matriciel - kernel OpenCL

1 _ _ k e r n e l v o i d 2 m a t r i x M u l ( _ _ g l o b a l f l o a t * C , _ _ g l o b a l f l o a t * A , _ _ g l o b a l f l o a t * B , 3 _ _ l o c a l f l o a t As [ B L O C K _ S I Z E * B L O C K _ S I Z E ] , 4 _ _ l o c a l f l o a t Bs [ B L O C K _ S I Z E * B L O C K _ S I Z E ]) 5 { 6 // B l o c k i n d e x 7 int bx = g e t _ g r o u p _ i d ( 0 ) ; 8 int by = g e t _ g r o u p _ i d ( 1 ) ; 9 10 // T h r e a d i n d e x 11 int tx = g e t _ l o c a l _ i d ( 0 ) ; 12 int ty = g e t _ l o c a l _ i d ( 1 ) ; 13

14 // I n d e x of the f i r s t sub - m a t r i x of A p r o c e s s e d by the b l o c k

15 int a B e g i n = WA * B L O C K _ S I Z E * by ;

16

17 // I n d e x of the l a s t sub - m a t r i x of A p r o c e s s e d by the b l o c k

18 int a E n d = a B e g i n + WA - 1;

19

20 // S t e p s i z e u s e d to i t e r a t e t h r o u g h the sub - m a t r i c e s of A

21 int a S t e p = B L O C K _ S I Z E ;

22

24 int b B e g i n = B L O C K _ S I Z E * bx ;

25

26 // S t e p s i z e u s e d to i t e r a t e t h r o u g h the sub - m a t r i c e s of B

27 int b S t e p = B L O C K _ S I Z E * WB ;

28

29 // C s u b is u s e d to s t o r e the e l e m e n t of the b l o c k sub - m a t r i x

30 // t h a t is c o m p u t e d by the t h r e a d

31 f l o a t C s u b = 0;

32

33 // L o o p o v e r all the sub - m a t r i c e s of A and B

34 // r e q u i r e d to c o m p u t e the b l o c k sub - m a t r i x

35 for ( int a = aBegin , b = b B e g i n ;

36 a <= a E n d ; 37 a += aStep , b += b S t e p ) { 38 39 // L o a d the m a t r i c e s f r o m d e v i c e m e m o r y 40 // to s h a r e d m e m o r y ; e a c h t h r e a d l o a d s 41 // one e l e m e n t of e a c h m a t r i x 42 AS ( ty , tx ) = A [ a + WA * ty + tx ]; 43 BS ( ty , tx ) = B [ b + WB * ty + tx ]; 44 45 // S y n c h r o n i z e to m a k e s ur e the m a t r i c e s are l o a d e d 46 b a r r i e r ( C L K _ L O C A L _ M E M _ F E N C E ); 47 48 // M u l t i p l y the two m a t r i c e s t o g e t h e r ; 49 // e a c h t h r e a d c o m p u t e s one e l e m e n t 50 // of the b l o c k sub - m a t r i x 51 for ( int k = 0; k < B L O C K _ S I Z E ; ++ k ) 52 C s u b += AS ( ty , k ) * BS ( k , tx ); 53 54 // S y n c h r o n i z e to m a k e s ur e t h a t the p r e c e d i n g 55 // c o m p u t a t i o n is d o n e b e f o r e l o a d i n g two new

56 // sub - m a t r i c e s of A and B in the n e x t i t e r a t i o n

57 b a r r i e r ( C L K _ L O C A L _ M E M _ F E N C E ); 58 } 59 60 // W r i t e the b l o c k sub - m a t r i x to d e v i c e m e m o r y ; 61 // e a c h t h r e a d w r i t e s one e l e m e n t 62 C [ g e t _ g l o b a l _ i d ( 1 ) * g e t _ g l o b a l _ s i z e ( 0 ) + g e t _ g l o b a l _ i d ( 0 ) ] = C s u b ; 63 64 }

Listing II.6: Produit matriciel - appel du kernel OpenCL

1 s i z e _ t l o c a l W o r k S i z e [] = { B L O C K _ S I Z E , B L O C K _ S I Z E };

2 s i z e _ t g l o b a l W o r k S i z e [] = { s h r R o u n d U p ( B L O C K _ S I Z E , WC ) ,

3 s h r R o u n d U p ( B L O C K _ S I Z E , w o r k S i z e [ 0 ] ) } ;

4 c l E n q u e u e N D R a n g e K e r n e l ( c o m m a n d Q u e u e [ i ] , m u l t i p l i c a t i o n K e r n e l [ i ] ,2 ,0 ,

5 g l o b a l W o r k S i z e , l o c a l W o r k S i z e ,0 , NULL ,& G P U E x e c u t i o n [ i ]);

– Le 20 avril 2009, NVIDIA a été le premier a annoncer qu’il supportait le pilote OpenCL en bêta et quelques semaines plus tard est devenu certifié par le consortium Khronos [ope09b].

– Le 5 août 2009, AMD a dévoilé les premiers outils de développement OpenCL dans le cadre de sa version 2.0 du kit de développement ; ils l’ont proposé comme une alternative à leur langage « Brook+ » [AMD10]. Aujourd’hui AMD a complètement abandonné ce dernier langage et soutient pleinement l’OpenCL.

– Le 28 août 2009, Apple a publié Mac OS X Snow Leopard, qui supporta pleine-ment OpenCL et qui l’utilise pour certaines tâches graphiques du système d’exploi-tation [ope09a].

II.3 Langages de haut niveau pour gérer les

Documents relatifs