• Aucun résultat trouvé

Pour illustrer le modèle de programmation, nous présentons deux exemples didac-tiques de programmes écrits en Athapascan-1 : un algorithme de calcul récursif du n

ème

terme de la suite de Fibonacci ainsi qu’un algorithme d’élimination de Gauss par colonne. La syntaxe complète et exacte qui est utilisée par la bibliothèque C++ Athapascan-1 implantant ce modèle de programmation sera présentée dans le chapitre 6. Cependant, cette syntaxe utilise des constructions du langage C++ (classe, patrons), et nécessite une certaine connaissance du langage C++. Pour faciliter la présentation des exemples, nous utiliserons donc ici une syntaxe simplifiée basée sur une extension du langage C par les mots clés suivant :

– Le mot clé Fork placé devant un appel de fonction indique une création de tâche. – Les mots clés Shared r w, Shared r, Shared w et Shared cw(

[fonction-accu-mulation]) placés devant un nom de type quelconqueT indiquent une référence contrainte sur un objet partagé de typeT. Le type d’accès possible à la référence contrainte est donc précisé dans le suffixe du mot Shared :

– r w pour un accès en lecture-écriture. – r pour un accès en lecture.

– w pour un accès en écriture.

– cw([fonction-accumulation])pour un accès en accumulation avec la fonc-tion [foncfonc-tion-accumulafonc-tion].

Par ailleurs les accès différés correspondants sont précisés par les suffixes rp wp,

rp, wp et cwp.

– L’accès à l’objet partagé contenu dans une référence contrainte est implicite. Pour le programmeur, la référence s’utilise donc comme si elle était l’objet. Cependant, seul les accès autorisés par la référence contrainte sont permis :

– Aucune modification ne peut être réalisée sur un objet référencé avec un droit d’accès en lecture.

– Seule une affectation d’une nouvelle valeur peut être réalisée sur un objet référencé avec un droit d’accès en écriture.

– Seule une accumulation d’une valeur (par l’intermédiaire de la fonction d’ac-cumulation associée à la référence) peut être réalisée sur un objet référencé avec un droit d’accès en accumulation.

3.2.1 Fibonacci

La figure 3.1 page 48 montre un programme calculant récursivement len

ème terme de la suite de Fibonacci.

1 : void add( Shared cw(add) int res, int b ) {

2 : res += b;

3 : }

4 : void fibo( int n, Shared cw(add) int res ) {

5 : if( n < 2 )

6 : add( res, n );

7 : else {

8 : Fork fibo( n 1, res );

9 : Fork fibo( n 2, res );

10 : }

11 : }

12 : void print int( Shared r int i ) {

13 : printf("%d",i);

14 : }

15 : main() {

16 : Shared rp wp int res(0);

17 : Fork fibo( 20, res );

18 : Fork print int( res );

19 : }

Figure 3.1 – Calcul récursif dun

èmeterme de la suite de Fibonacci, écrit dans le modèle de

programmation Athapascan-1

La ligne 4 déclare et définit la fonction (i.e. le type de tâche)fibo qui prend un paramètre par valeur (le terme de la suite à calculer) ainsi qu’une référenceres sur un objet partagé ayant un droit d’accès en accumulation avec la fonctionadd(là où stocker le résultat). Les seuls accès possibles à l’objet référencé par la référence contrainteres

sont des accumulations réalisées avec la fonctionadd. Une accumulation de ce type est par exemple réalisée ligne 6. Cette fonction crée également d’autre tâche exécutant la fonctionfibo(ligne 8 et 9).

À la ligne 16, un objet partagé référencé parresest créé et initialisé à zéro. Notons que les droits d’accès permis sur cet objets sont différés ( Shared rp wp), c’est-à-dire

Exemples 3.2 que la fonctionmain(i.e. la tâche racine du programme) ne peut pas accéder directement en lecture ou écriture à cet objet. Seules les tâches filles pourrons réaliser des accès sur cet objet.

À la ligne 17 la tâche calculant cen

ème terme est invoquée avec un paramètre par va-leur (ici la constante 20) et la référenceressur l’objet partagé. Pour afficher le résultat, il est ensuite nécessaire de créer une tâche prenant en paramètreres (ligne 18) puisque la tâchemain n’a pas le droit de lecture sur l’objet partagé référencé parres. Ainsi la tâchemain peut s’exécuter sans synchronisation. Par contre la tâcheprint int

ne pourra elle s’exécuter que lorsque toutes les tâchesfibomodifiant l’objet référencé parresseront terminées.

3.2.2 Élimination de Gauss par colonnes

L’élimination de Gauss par colonnes, est un algorithme de base de l’algèbre linéaire. L’algorithme 1 page 49 présente la forme séquentielle et parallèle de l’élimination de Gauss par colonne sans pivot1.

Algorithme 1 : Élimination de Gauss par colonnes. pourk =1jusqu’àn 1faire

pouri=k+1jusqu’ànfaire

A(i;k)=A(i;k)=A(k;k)

pourj =k+1jusqu’àn faire [en parallèle] pouri=k+1jusqu’ànfaire

A(i;j)=A(i;j) A(i;k)A(k;j)

La figure 3.2 montre l’écriture de cet algorithme dans le modèle de programmation dAthapascan-1.

Le parallélisme de cet algorithme est défini sur les opérations sur les colonnes de la matrice. Deux types de tâchesscaletaxpy, réalisant les deux types d’opération sur des colonnes de la matrice, sont alors définies lignes 2 et 7. Le type de tâcheaxpyne modifie pas la colonne référencée par le paramètrex. Pour cette raison, seul un droit d’accès en lecture sur ce paramètrexest indiqué.

Aux lignes 14 et 15, le type de la matrice (de taille nn) est défini. Une matrice est alors constituée d’un tableau de nréférences Shared rp wp sur des objets partagés. Chaque objet partagé de typecolumn, constitué d’un tableauvectorde n éléments, représente alors une colonne de la matrice.

1. L’écriture de l’élimination de Gauss sous cette forme n’est pas la plus efficace. Une écriture dans le modèle de programmation d’Athapascan-1 d’une factorisationLU par élimination de Gauss, utilisant un partitionnement bidimensionnel de la matrice est présentée dans le chapitre 7.

1 : // x ax

2 : void scal(int k, int n, double a, Shared r w column x ) {

3 : for( int i = k+1; i<n ; i++ )

4 : x[i] = a * x[i];

5 : }

6 : // y = a * x + y

7 : void axpy(int k, int n, double a,

8 : Shared r column x, Shared r w column y) {

9 : for( int i = k+1; i<n ; i++ )

10 : y[i] = a * x[i] + y[i];

11 : }

12 : main() {

13 : int n = 100;

14 : int j,k;

15 : typedef double column[n]; // type des colonnes de la matrice

16 : typedef Shared rp wp column matrix[n]; // type de la matrice

17 : 18 : matrix A; 19 : // ici, initialisation de A 20 : 21 : for( k = 0; k < n 1; k++ ) 22 : Fork scal(k, n, 1/A[k][k], A[k]); 23 : for( j = k+1; j<n; j++ ) 24 : Fork axpy(k, n, A[j][k], A[k], A[j]); 25 : }

Figure 3.2 – Élimination de Gauss par colonnes écrite dans le modèle de programmation Athapascan-1

L’algorithme d’élimination de Gauss par colonnes est ensuite implanté de la ligne 20 à la ligne 23 ; chaque opération sur une colonne étant remplacée par la création de la tâche correspondante.