• Aucun résultat trouvé

6.5 Création d’une bibliothèque BSMLlib certifiée

6.5.1 Echange total

6.5.3 Demander et recevoir des valeurs d’autres processeurs . . . 101 6.5.4 Diffusion en 2 phases . . . 102 6.5.5 Réduction directe . . . 103 6.5.6 Décalage . . . 104 6.5.7 Fonction de tri parallèle . . . 104 6.5.8 Extraction de code . . . 105 6.5.9 Autres applications possibles . . . 106

6.A Code de l’extraction . . . 107

L

Aprogrammation fonctionnelle est un bon cadre de travail pour l’écriture et la preuve de programmes car, sans effet de bord, il est plus simple de prouver la correction des programmes et de les réutiliser en tenant compte de leurs propriétés formelles : la sémantique est dite compositionnelle. Le langage BSML (sans les traits impératifs ni les entrées/sorties) permet de concevoir des programmes parallèles purement fonctionnels. Sa sémantique est aussi compositionnelle. Se pose alors la question de la réalisation de programmes BSML certifiés, c’est-à-dire dont le résultat est toujours celui qui a été spécifié. Ce chapitre traite ce problème et nous utiliserons l’assistant de preuves Coq afin de founir une bibliothèque de fonctions BSML certifiées qui sera un large sous-ensemble de la bibliothèque standard de la BSMLlib.

6.1 Introduction

Le système Coq [30, 254]1est un environnement (et un langage logique) pour le développement de preuves et qui est basé sur le Calcul des Constructions Inductives [75], unλ-calcul typé étendu avec des définitions

1Téléchargeable à l’adresse suivante :http://coq.inria.fr/. 83

inductives. La théorie des types est un bon cadre pour le développement de preuves de programmes

(notam-ment ceux fonctionnels [218]) car elle fournit une grande expressivité logique. Dans l’assistant de preuves

Coq, il existe une interprétation constructive des preuves, c’est-à-dire la possibilité de construire

automa-tiquement uneλ-terme à partir de la preuve d’une formule logique. Ainsi, dans un tel formalisme et grâce

à l’isomorphisme de Curry-Howard, une preuve de la formule∀x.P (x) ⇒ ∃y.(Q y x), appelée une

spé-cification, permet d’obtenir un programme correct qui vérifie en entrée la propriétéP (une pré-condition)

et fournit un résultat qui vérifieQ (une post-condition). Le programme extrait de la preuve (en oubliant les

parties logiques de la preuve [220]) est donc garanti par Coq pour bien réaliser la spécification donnée. On parle alors d’un programme certifié.

Nous allons maintenant nous intéresser à la spécification de programmes BSML et à leur développement (réalisation) en Coq. Tout d’abord, nous présenterons rapidement le système Coq (section 6.2). Nous pour-rons alors expliquer comment intégrer les primitives parallèles dans ce système (section 6.3) pour certifier des éléments de la bibliothèque BSMLlib et ainsi obtenir une bibliothèque certifiée (section 6.5).

6.2 Présentation succinte de Coq

6.2.1 Généralités

Coq est un système d’aide à la preuve basé sur le Calcul des Constructions Inductives (CCI), qui est un λ-calcul typé dans lequel des types sont des termes comme les autres. Il fournit des mécanismes pour écrire

des définitions et pour faire des preuves formelles.

Le système Coq est un programme interactif permettant à l’utilisateur de construire des preuves. Cela permet de :

1. Définir des termes, c’est-à-dire les objets (mathématiques) du discours, comme les entiers, les listes etc., et des propriétés sur ces objets puisque celles-ci sont des types et que types et termes ne sont pas différenciés ;

2. Construire des démonstrations de ces propriétés (qui sont également des termes) à l’aide d’un langage de tactiques permettant de fabriquer interactivement un terme d’un type donné ;

3. Vérifier les preuves ainsi construites, en demandant au programme de les typer.

Le mécanisme de construction des preuves n’a pas besoin d’être certifié puisque le noyau du système Coq, c’est-à-dire la fonction de typage vérifie les preuves. Le noyau fait en revanche l’objet de certifications et de vérifications [22]. Ajoutons que la représentation concrète des preuves a d’autres avantages : par exemple, elle rend possible l’écriture d’un vérificateur de type indépendant de Coq, et elle autorise également l’em-ploie de toutes sortes d’outils pour engendrer des preuves que Coq pourra vérifier a posteriori [107].

Tous les exemples donnés dans la syntaxe Coq seront dans une police verbatim et seront en général suivis de la réponse du système. Les différents exemples de ce chapitre peuvent êtres tapés directement dans Coq. Il n’y a pas d’inférence de type en Coq, celle-ci n’étant pas décidable2. Il est cependant laborieux de devoir annoter toutes les définitions par des informations de type quand celles-ci semblent pouvoir être aisément déduites du contexte. Coq propose donc un mécanisme simple d’inférence, qui, bien sûr, peut échouer. Coq fournit également un mécanisme d’arguments implicites et il s’efforce aussi de les inférer.

Nous nous intéressons donc, dans cette section, au système d’aide à la preuve Coq. Cette section a pour objectif de faire découvrir au lecteur ce système à l’aide d’une rapide description. Bien sûr, cette section n’a pas pour vocation de remplacer la documentation accompagnant le système. Le lecteur pourra donc consulter en complément : le tutoriel et le livre [30] pour une introduction plus graduelle ainsi que le manuel de référence3pour une description formelle et exhaustive de Coq.

6.2.2 Assistant de preuves

L’objectif premier de Coq est d’être un assistant de preuves, et donc de permettre de formaliser le rai-sonnement mathématique. Prenons un énoncé basique :∀A, A ⇒ A. Cet énoncé, qui se lit «pour toute

propositionA(c’est-à-dire objetAde type Prop),Aimplique A», peut être directement transcrit dans le système Coq comme suit :

2Cela correspondrait à un «prouveur» automatique «universel», ce qui est rigoureusement impossible.

85 6.2. PRÉSENTATION SUCCINTE DE COQ

Lemma easy : A : Prop , A→A .

Proof .

Cette portion de script commence par le nom et l’énoncé de notre lemme, où Prop est l’ensemble des propositions logiques. Le système entre alors dans sa nature interactive qui permet de bâtir cette preuve étape par étape (mot clésProof). Pour cela, le système utilise des directives appelées tactiques. Celles-ci reflètent la structure de la preuve en déduction naturelle. Nous avons donc :

1 subgoal

============================

A : Prop , A→A

easy < i n t r o s .

En entrant la tactiquei n t r o s (introduire les hypothèses), le système affiche l’état courant du ou des buts à prouver : 1 subgoal A : Prop H : A ============================ A easy < apply H. Proof completed .

Il s’agit alors de trouver une preuve deAsous l’hypothèseA(cette hypothèse étant nomméeHtel queA

soit de typeProp). La tactique apply Hpermet d’appliquer cette hypothèse, ce qui termine la preuve. Il ne reste plus qu’à faire vérifier l’ensemble de la preuve au système Coq (vérification des types de tous les sous-termes) à l’aide de la tactiqueQed.

De nombreuses interfaces existent pour faciliter cette interaction, comme par exemple CoqIDE4. Il faut également noter que Coq met à la disposition de l’utilisateur une grande variété de tactiques. Ici, par exemple, pour un énoncé aussi simple, les tactiques de recherche automatique telles queautoou t r i v i a l auraient été suffisantes.

La représentation interne d’une preuve est unλ-terme. Le système logique sous-jacent à Coq est le CCI

(Calcul des Constructions Inductives) qui est unλ-calcul typé où les énoncés exprimables en Coq sont des

types du CCI. En application de l’isomorphisme de Curry-Howard [119], vérifier sit est bien une preuve valide de l’énoncéTconsiste à vérifier que le typeTest bien un type légal duλ-terme t. C’est ce qui est effectué par le système avec la tactiqueQed. Par exemple, si on demande à Coq quelle est la représentation interne du lemmeeasyà l’aide d’unP r i n t, nous obtenons :

easy = fun ( A : Prop ) (H : A ) ⇒H

: A : Prop , A→A

fun x : X⇒eest la notation Coq pour l’abstraction typée. Celle-ci est l’effet (d’après l’isomorphisme de Curry-Howard) de la tactiquei n t r o. Quand àapply, son effet est l’utilisation de la variable de contexte

H. De façon générale, une tactique contribue à construire petit à petit leλ-terme CCI de la preuve.

Notons que si l’on connaît à l’avance leλ-terme complet, on peut le donner directement sous la forme

par exemple d’uneD e f i n i t i o n, ce qui donne :

D e f i n i t i o n easy : A : Prop , A→A : = fun (A : Prop ) (H : A ) ⇒H

La quantification universelle∀x : X, T est appelé produit ou type dépendant, puisque, le plus souvent, le

corpsTdu produit dépend de la variablexde la tête du produit. Cette quantification n’étant pas restreinte, le CCI (le système Coq), est donc une logique d’ordre supérieur. Notons que la syntaxeA→Best un sucre syntaxique de Coq pour _ : A , B.

6.2.3 Langage de programmation

On peut également aborder Coq (et c’est ce qui nous intéressera le plus ici) depuis l’autre versant de l’iso-morphisme de Curry-Howard : considérer Coq non pas comme un système logique mais plutôt commme un

λ-calcul, c’est-à-dire un langage de programmation purement fonctionnel. Par exemple, notre lemmeeasy

devient une fonction d’identité sur les propositions logiques.

En tant que langage de programmation, il nous faut pouvoir définir des types de données que l’on ren-contre dans les langages de programmation. Cette définition se fait en Coq à l’aide de types inductifs. Le type des booléens s’obtient par la déclaration :

I n d u c t i v e b o o l : Set : = t r u e : b o o l | f a l s e : b o o l

Cette déclaration crée un nouveau type, nomméb o o l, ainsi que deux nouveaux constructeurs. L’annotation

Setpermet de désigner quel va être le type du type b o o l. C’est le type des objets calculatoires (à la dif-férence deProp qui est le type des objets logiques). De même on peut définir les entiers de Peano de la manière suivante :

I n d u c t i v e n a t : Set : = 0 : n a t | S : n a t→n a t .

0est le zéro etSle successeur d’unn a t. Un dernier exemple usuel est celui des listes paramétriques : I n d u c t i v e l i s t ( A : Set ) : Set : = n i l : l i s t A | cons : A→l i s t A→l i s t A

où la liste dépend d’un paramètreA. Ce paramètre sera fourni en arguments lors de l’utilisation de cette structure de données. Par exemple une liste d’entiers naturels peut être définie par :

I n d u c t i v e l i s t _ n a t : Set : = n i l _ n a t : l i s t _ n a t

| cons_nat : n a t→l i s t _ n a t→l i s t _ n a t

mais plus simplement parD e f i n i t i o n l i s t _ n a t : Set : = ( l i s t n a t ) .

Il faut noter que le système refuse certains inductifs (on parle d’une condition de positivité) dont la définition est syntaxiquement valide. Ces restrictions ont pour but d’assurer la cohérence du système du point de vue logique5, c’est-à-dire l’impossibilité de prouverP et ¬P . Par exemple :

I n d u c t i v e absurde : Set : = C : ( absurde→absurde )→absurde .

E r r o r : Non s t r i c t l y p o s i t i v e occurrence o f " absurde " i n

" ( absurde absurde ) absurde "

L’entrelacement des parties logiques (des propositions) et des parties purement calculatoires est pos-sible dans le système Coq. Cela permet notamment d’enrichir un terme calculatoire avec des pré- et post-conditions, ou encore d’utiliser une récursion bien fondée en justifiant la décroissance d’une mesure à chaque appel récursif.

Outre le besoin d’exprimer la spécification d’une fonction sous la forme de pré- et de post-conditions, les pré-conditions logiques vont également apporter une solution au problème de la définition des fonctions partielles. Considérons, par exemple, une fonction de prédécesseur sur les entiers naturelspred : n a t→n a t, qui n’est pas définie quand son argument est nul. On peut alors exprimer, par une pré-condition logique, le fait que cet argument doit être non nul si l’on veut utiliser cette fonction. Le type depreddevient alors

n : nat , n<>0 n a t. On notera que le type de l’argument n’est plus un type flèche (un produit anonyme)

mais un produit nommé parnafin de s’y référer dans l’assertion logique. La fonctionpredn’est alors plus définie en dehors du domaine de validité de l’assertion logique. La contre-partie est que l’on doit toujours fournir une preuve logique de non-nullité à chaque appel àpred.

Combiner pré- et post-conditions spécificie une fonction dans un style à la Hoare [149]. Ainsi, une fonction de typeA→B de pré-conditionP et de post-conditionQ correspond à la preuve constructive :

∀x : A, (P x) → ∃y : B, (Q x y). Ceci est exprimable en Coq à l’aide d’un type inductifs i g:

I n d u c t i f s i g (A : Set ) ( P : A→Prop ) : Set : =

e x i s t : x : A , ( P x )→( s i g A P ) .

qui s’écrit également avec un sucre syntaxique{ x : A | ( P x ) }. Une spécification complète en Coq de la fonction de prédécesseur entière s’écrit alors :

D e f i n i t i o n pred : n : nat , n<>0 { q : n a t | ( S q )= n }

Il ne reste alors qu’à donner au système unλ-terme répondant à cette spécification (un λ-terme ayant ce

type). On peut le construire par une interaction de tactiques notamment avec une de filtrage (commecase) pour prouver tous les cas des constructeurs.

Une solution plus simple est l’utilisation de la tactique r e f i n e qui permet de donner directement le terme Coq correspondant à la spécification mais avec des fragments vides. Ces fragments (généralement la

87 6.2. PRÉSENTATION SUCCINTE DE COQ

preuve logique que le terme correspond à la spécification) vont générer des buts qui devront être prouvés afin d’accepter le terme. Dans notre cas :

r e f i n e ( fun nmatch n r e t u r n n<>0 { q : n a t | ( S q )= n } with 0⇒fun h :(0 < > 0)⇒_

| ( S p ) fun h : ( ( S p) < >0) ( e x i s t _ p _ ) end ) .

_indique le fragment (trou) du terme à compléter avec des tactiques [218] et oùr e t u r n est une construc-tion syntaxique utilisée lors du filtrage d’un terme provenant d’un type dépendant. Avec lematch, nous distinguons les deux cas possibles du calcul et faisons ressortir la preuvehde la propriété de l’argument. Le retour est l’existence (avece x i s t) d’une valeurpqui vérifie la spécification. Nous avons alors ici deux buts à résoudre : 2 subgoal s n : n a t h : 0<>0 ============================ { q : n a t | S q = 0 } subgoal 2 i s : S p = S p

Le premier but se résout facilement par l’absurde :absurd (0 < > 0); auto . et le second est une trivialité. Nous pouvons maintenant afficher leλ-terme CCI complet de notre fonction :

P r i n t pred . pred = fun n : n a t match n as n0 r e t u r n ( n0<>0 { q : n a t | S q = n0 } ) with | O⇒ fun h:0 < >0 F a l s e _ r e c { q : n a t | S q = 0 } ( l e t H : = h i n ( l e t H0 : = fun H:0= 0 F al se⇒H ( r e f l _ e q u a l 0 ) i n fun H1:0 < >0⇒H0 H1 ) H) | S p⇒ fun _ : S p<>0 e x i s t ( fun q : n a t⇒S q = S p ) p ( r e f l _ e q u a l ( S p ) ) end : n : nat , n<>0 { q : n a t | S q = n }

Il est aussi possible de définir en Coq un terme par récurrence structurelle sur un objet inductif (une liste par exemple). Une définition récursive n’est acceptée que si tout appel récursif interne se fait sur un argument récursif qui est structurellement plus petit que l’argument récursif initial6. La préoccupation est, là encore, celle de la cohérence logique. Sans ces conditions sur les appels récursifs, il serait en effet aisé de construire des termes de n’importe quel typeA:

F i x p o i n t l o o p ( n : n a t ) : A : = l o o p n . D e f i n i t i o n i m p o s s i b l e : A : = l o o p 0 . Le système logique serait alors incohérent.

6.2.4 Coq et BSML

L’originalité du travail présenté dans ce chapitre est le «plongement» de BSML dans un système d’aide à la preuve. De précédents travaux visant à l’axiomatisation d’un langage BSP (voir travaux connexes au chapitre 12) ont montré qu’il était très délicat de tenir compte de tous ces aspects. Dans ce travail, le choix des langages utilisés, Coq et BSML, a été important car cela permet une axiomatisation simple et naturelle. Celle-ci pourra donc être employée pour la preuve de programmes BSP.

BSML apparaît comme un bon candidat pour une telle axiomatisation car il s’agit d’un langage pure-ment fonctionnel dont la sémantique est a priori assez bien adaptée à une description formelle. Coq est apparu comme un système d’aide à la preuve approprié à cette axiomatisation. C’est un système pour la programmation fonctionnelle et les types dépendants se sont avérés (pour l’instant) suffisamment puissants pour exprimer les propriétés formelles de nos fonctions BSML. Nous allons donc exprimer BSML dans ce calcul de types.

6.3 Formalisation des primitives BSML

Dans cette section, nous nous intéresserons à la certification de fonctions BSML. Pour cela, nous allons exprimer la sémantique naturelle de BSML (présentée dans le chapitre 3) dans le système de preuves Coq. Ce codage nous fournit directement un vérificateur des propriétés des fonctions de la bibliothèque standard de la BSMLlib.

Pour représenter nos primitives parallèles et pour avoir une spécification-réalisation des programmes BSML, nous avons choisi une approche classique : une axiomatisation de nos opérateurs (figure 6.1). Les axiomes sont basés sur la sémantique naturelle de BSML et les primitives de BSML sont données via des paramètres. Elles ne dépendent donc pas de leurs implantations (séquentielles ou parallèles). Les pro-grammes certifiés sont donc corrects quelle que soit l’implantation des primitives (tant qu’elle valide les définitions formelles des primitives).

6.3.1 Axiomes et paramètres

Le nombre de processus, bsp_p ( ), est naturellement un nombre entier supposé supérieur à 0 (axiome

good_bsp_p). Le constructeur t t est le constructeur Coq de ( ) d’OCaml. Les vecteurs parallèles sont

in-dexés sur le typeZ(les entiers relatifs de Coq7). Ils sont représentés dans le monde logique par un type dé-pendant :Vector T, oùTest le type des éléments du vecteur. Ce type abstrait est, bien entendu, uniquement manipulé par les primitives données en paramètres. Notre axiomatisation des primitives parallèles BSML est donnée à la figure 6.1. Celle-ci est simple mais suffisante pour notre approche (l’extraction des preuves de nos spécifications pour avoir une bibliothèque certifiée).a t t est une fonction abstraite d’«accès» (qui ne doit pas être utilisée dans les programmes) pour les vecteurs parallèles. Elle donne la valeur locale contenue dans un processus et sera employée par la suite uniquement dans les spécifications des programmes pour donner les valeurs contenues dans les vecteurs parallèles. Elle a un type dépendant pour vérifier que l’entier

iest bel et bien un nom de processus valide.

Les primitives asynchrones, la primitive mkpar et l’application globale apply sont axiomatisés avec mkpar_defetapply_def. Pour une fonctionf,mkpar_defapplique( f i ) sur le processusien employant la fonction d’accèsa t t. De la même manière,apply_defpermet l’application des composantes au processus

i. Le vecteur parallèle résultant est alors décrit avec une égalité qui est donc une proposition logique. Ce résultat est donné pour un paramètrei qui doit être prouvé comme un nom valide de processus.

La primitiveput est axiomatisée avecput_def. Celui-ci transforme un vecteur fonctionnel en un autre vecteur fonctionnel qui permet la communication en utilisant le paramètre j pour lire les valeurs des pro-cessus distants (dans le vecteurVf). Le paramètre j est testé avec la fonctionw i t h i n _ b o u n d sde type :

( i : Z ) , {0 <= i < ( bsp_p t t ) } + {¬(0 <= i < ( bsp_p t t ) ) }

qui indique si un entier est un nom de processus valide ou non et en fournit une preuve (viaH1dans la règle). Ceci est nécessaire car le système Coq est un système avec type dépendant. En effet, pour des preuves de programmes, il est plus aisé de manipuler directement des preuves que des constantes primitives. Si i est bien un nom de processus valide, la valeur sur le processus i est lue sur le processus j avec la fonction d’accèsa t t sur lajème composante du vecteurVf(j est un nom valide de processus ; la preuve est donnée

parw i t h i n _ b o u n d s). Autrement, une constante vide est retournée. Dans une véritable implantation, et pour

des raisons évidentes d’optimisation, les valeurs à émettre sont tout d’abord calculées et ensuite échangées. L’axiomatisation complète contient également la projection globale synchrone. Elle est facilement expri-mable dans le système Coq en utilisant la fonction d’«accès»a t tpour «lire» la valeur au processeurj(dans la jème composante du vecteur parallèleV). Ce paramètre j doit être un nom valide de processus et cette preuve est donnée à la fonction d’«accès»a t tpar un type dépendant.

Nous allons maintenant illustrer cette axiomatisation en employant nos axiomes pour obtenir une biblio-thèque certifiée par l’assistant de preuve Coq. Nous pouvons voir l’ajout de ces axiomes comme le passage de Coq à un «BS-Coq» (comme le passage de ML à BSML par l’utilisation de nos primitives parallèles) avec desBSλ-termes CCI quand les primitives parallèles sont utilisées.

7nous les préférons aux entiers de peanon a tpour des raisons d’efficacité et afin de profiter de la tactiqueOmegaqui autorise la résolution automatique et certifiée d’équations dans l’arithmétique de Presburger

89 6.3. FORMALISATION DES PRIMITIVES BSML

Parameters bsp_p : u n i t→Z .

Vector : Set→Set .

mkpar : T : Set , ( Z→T )→( Vector T ) .

apply : T1 T2 : Set , ( Vector ( T1→T2 ) )

( Vector T1 )( Vector T2 ) .

put : T : Set , ( Vector ( Z→( o p t i o n T ) ) )

( Vector ( Z→( o p t i o n T ) ) ) .

p r o j : T : Set , ( Vector ( o p t i o n T ) )→Z→( o p t i o n T ) .

Parameter a t t : T : Set , ( Vector T )→∀ ( i : Z ) , 0<= i < ( bsp_p t t )→T .

D e f i n i t i o n w i t h i n _ b o u n d : i : Z , {0 <= i < ( bsp_p t t ) } + {¬(0 <= i < ( bsp_p t t ) ) } .

Axiom good_bsp_p : 0 <( bsp_p t t ) .

Axiom mkpar_def : ( T : Set ) ( f : Z→T ) ( i : Z ) (H:0 <= i < ( bsp_p t t ) ) ,

( a t t T ( mkpar T f ) i H) = ( f i ) .

Axiom apply_def : ( T1 T2 : Set ) ( V1 : ( Vector ( T1→T2 ) ) )

( V2 : ( Vector T1 ) ) ( i : Z ) (H:0 <= i < ( bsp_p t t ) ) ,

( a t t T2 ( apppl y T1 T2 V1 V2 ) i H) = ( ( a t t ( T1T2 ) V1 i H) ( a t t T1 V2 i H ) ) .

Axiom put_def : ( T : Set ) ( Vf : ( Vector ( Z→( o p t i o n T ) ) ) ) ( i : Z ) (H:0 <= i < ( bsp_p t t ) ) ,

( ( a t t ( Z( o p t i o n T ) ) ( put T Vf ) i H) = ( fun j : Zmatch ( w i t h i n _ b o u n d j ) with

l e f t H1 ( ( a t t ( Z→( o p t i o n T ) ) Vf j H1 ) i )

| r i g h t _None end ) ) .

Axiom p r o j_d ef : ( T : Set ) ( Vv : ( Vector ( o p t i o n T ) ) ) ,

( p r o j T Vv ) = ( fun j : Zmatch ( w i t h i n _ b o u n d j ) with

l e f t H1 ( a t t ( o p t i o n T ) Vv j H1 )

| r i g h t _None end ) .

Axiom at_H : ( T : Set ) ( v : ( Vector T ) ) ( i : Z ) ( H1 H2:0 <= i < ( bsp_p t t ) ) , ( a t t T v i H1 ) = ( a t t T v i H2 ) .

6.3.2 Cohérence et acceptation de l’ajout des axiomes BSML

Pour prouver la cohérence de nos axiomes dans le système Coq (impossibilité de prouver⊥), nous pouvons

implanter les primitives en Coq à l’aide de listes (chacune de taille «fixe»). Nos précédents axiomes sont alors des lemmes et la cohérence vient de celle de Coq. Ainsi, nos axiomes et nos paramètres (dont on peut donner une implantation certifiée) correspondent à l’exécution séquentielle, mais au moment de la compilation (des fonctions extraites), rien n’empêche d’utiliser l’implantation parallèle (qui a été prouvée équivalente, cf chapitre 3).

Une autre question se pose : est-ce que nos axiomes (sémantiques des primitives) correspondent bien à l’exécution de nos programmes ? En effet, le chapitre 3 propose deux exécutions possibles et équivalentes de nos termes : une version séquentielle et la version distribuée (c’est-à-dire parallèle) associée. Dans les

Documents relatifs