Télécharger la présentation
La présentation est en train de télécharger. S'il vous plaît, attendez
Publié parElvire Dubus Modifié depuis plus de 10 années
1
Athapascan-1 Interface C++ de programmation parallèle
Je vais vous présenter les résultats de mes travaux de recherche intitulés : "Athapascan-1 : Interprétation distribuée du flot de données d'un programme parallèle" Ces recherches ont été menées au sein du (tout nouveau) Laboratoire ID (Informatique et Distribution) sous la direction de Jean-Louis Roch et s'intègrent dans le projet APACHE qui vise à définir un environnement de programmation portable et efficace des machines parallèles. Jean-Guillaume Dumas, Nicolas Maillard Jean-Louis Roch, Thierry Gautier Mathias Doreille, François Galilée, Gerson Cavalheiro Équipe APACHE LMC/ID - IMAG
2
Caractéristique du modèle de programmation (coté utilisateur du modèle)
Granularité explicite grain de donnée = objet partagé Shared< int > n ; … Shared< array > tab ; grain de calcul = tâche (appel de procédure) Fork fn( n) ; Parallélisme entre les tâches implicite Indication des actions des tâches sur les objets partagés par typage explicite { lecture r, écriture w, modification r_w, accumulation cw} void fn ( Shared_r < int > a ) { … } Sémantique naturelle, de type séquentielle toute lecture d’une donnée voit la dernière écriture dans l’exécution séquentielle
3
Programmation en Athapascan-1
Pré-requis : un peu de C++ Beaucoup d’Athapascan-1 Interface : Fork et Shared un exemple de programme accumulation, accès différé, ordre format, compilation, exécution
4
Pré-requis : un peu de C++
Pointeur int* Référence int& Attribut const Classe : constructeur (de recopie), destructeur class cplx { private: double re, im ; public: cplx(double x, double y){re = x; im = y; } // Constructeur cplx(const cplx& z) { re = z.re ; im = z.im; } // Cstor recopie double reel() { return re ; } // méthode ~cplx() { … } // Destructeur }; Flots : opérateurs << et >> ostream& operator<< (ostream& o, const cplx& z) { cout << z.reel() << ‘’ + i. ‘’ << z.imag() ; } Fonction-classe : struct module1 { double operator() ( const double x, double y){return x.reel()+x.imag(); } cplx a; cout << module1()( a ) ;
5
Athapascan-1 : librairie C++
Fork < f > ; exécution « parallèle » de la fonction f struct Hello { void operator()( int i ) { cout << « ( Hello » << i << « ) » ; } }; void main() { …. Hello() ( 0 ) ; for (int i=1 ; i < 10; i++ ) a1::Fork<Hello>() ( i ) ; // création de tâche Sortie possible : ( Hello 0 ) (Hello 3) ( Hello 1) (Hello (Hello 7 (Hello …
6
Que peut prendre une tâche en paramètre ?
Tout type qui se comporte comme un int constructeur vide : T() { … } constructeur de recopie : recopie physique destructeur Opérateurs d’emballage/déballage (distribué) a1::ostream& operator<<( a1_ostream& out, const cplx& x) { out << x.re << x.im ; } ; A1::istream& operator>>( a1_istream& in, cplx& x) { in >> x.re >> x.im ; } ; Passage par valeur ou par référence
7
Passage par référence : shared
Objet partagé : Shared<T> x Déclaration avec initialisation : a1::Shared<int> x ( new int(1) ) ; Exemple : a1::Fork<facto>() ( x, 3 ) ; a1::Fork<print>() (x ) ; Les 2 tâches accèdent le même objet x : -> il faut contrôler les dépendances
8
Dépendance : typage des accès
lecture=R : pas possible de modifier l ’objet : accès à la valeur de x : x.read() struct print { void operator()(Shared_r<int> a) { cout << a.read(); }}; écriture=W : pas possible de ;}}; lire l ’objet : affectation de x : x.write( T* val ) struct facto { void operator()(Shared_w<int> r, int n) { int x = n; for( int i=n ; i ; x*= --i) ; r.write ( x ) ;}}; lecture-écriture=R_W : accès en modification accès en maj de x : x.access() struct incr { void operator()(Shared_r_w<int> a) { a.access() += 1 ;}}; lecture=R : pas possible de modifier l ’objet : accès à la valeur de x : x.read() struct print { void operator()(Shared_r<int> a) { cout << a.read(); }}; écriture=W : pas possible de ;}}; lire l ’objet : affectation de x : x.write( T* val ) struct facto { void operator()(Shared_w<int> r, int n) { int x = n; for( int i=n ; i ; x*= --i) ; r.write ( new int( x ) ) ;}}; lecture-écriture=R_W : accès en modification accès en maj de x : x.access() struct incr { void operator()(Shared_r_w<int> a) { a.access() += 1 ;}};
9
Sémantique séquentielle
Toute lecture voit la dernière écriture selon l’ordre séquentiel shared<T> A[n][n], B[n][n], C[n][n] ; … // Initialisations A, B et C for (int i=0; i<N; i++) for (int j=0; j<N; j++) for (int k=0; k<N; k++) Fork< axpy_in > () ( C[i][j], A[i][k], B[k][j] ) ; struct axpy_in { void operator() (Shared_rw<T> c, Shared_r<T> a, Shared_r<T> b ) { c.access() += a.read() * b.read() ; } };
10
Programmation en Athapascan-1
Beaucoup d’Athapascan-1 Interface : Fork et Shared un exemple de programme accumulation, accès différé, ordre format, compilation, exécution
11
Ex : Fibonacci récursif
F(0) = 0, F(1) = 1 F(n) = F(n-1) + F(n-2) struct fib { void operator()( int n, Shared_w< int > r ) { if( n<2 ) r.write(new int(n)); else { Shared< int > x, y; Fork< fib >() ( n-1, x ); Fork< fib >() ( n-2, y ); Fork< sum >() ( x, y, r ); } F(0) F(1) F(2) F(3) + 1 F(4) struct sum {void operator() ( Shared_r< int > a, Shared_r< int > b, Shared_w< int > c ) { c.write( new int( a.read() + b.read() ) ; }
12
Analyse dynamique du flot de données fib(3)
F(0) = 0, F(1) = 1 F(n) = F(n-1) + F(n-2) Terminé Prêt Attente Exécution sum r/x r/y fib(2) fib(1) fib(3) fib(3) fib(3) r fib(3) Shared<int> x, y; Fork<fib>()( n-1, x ); Fork<fib>()( n-2, y ); Fork<sum>()( x, y, r );
13
Analyse dynamique du flot de données fib(3)
F(0) = 0, F(1) = 1 F(n) = F(n-1) + F(n-2) sum r/x r/y fib(1) fib(0) Terminé Prêt Attente Exécution fib(2) fib(2) fib(2) fib(1) sum r/x r/y r fib(1) 1
14
Analyse dynamique du flot de données fib(3)
F(0) = 0, F(1) = 1 F(n) = F(n-1) + F(n-2) fib(1) fib(0) 1 sum 1 sum r/x r/y fib(1) fib(0) r Terminé Prêt Attente Exécution 1 fib(3) = 2 gestion du graphe contrôle de la sémantique [Chap. 3, Prop. 4] sum 1 sum 1 sum sum 2
15
Programmation en Athapascan-1
Beaucoup d’Athapascan-1 Interface : Fork et Shared un exemple de programme accumulation, accès différé, ordre format, compilation, exécution
16
Ecriture concurrente - Accumulation
CW : Concurrent write : Possibilité d’accumuler en concurrence à partir d’une valeur initiale Typage accès : Shared_cw<fn_cumul, T > x Accumulation : x.cumul( val ) ; struct fn_cumul { void operator()(T& res, const T& s) { res += s ; // accumulation de s sur res Accumulations avec même fonction :concurrentes > ordre quelconque (commutatif + associatif)
17
Accumulation: exemple
shared<T> A[n][n], B[n][n], C[n][n] ; … // Initialisations A, B et C for (int i=0; i<N; i++) … for j … for k Fork< axpy_in > () ( C[i][j], A[i][k], B[k][j] ) ; struct add void operator()(T& res, const T& s) { res += s ; } struct axpy_in { void operator() (Shared_cw<add,T> c, Shared_r<T> a, Shared_r<T> b ) { c.cumul( a.read()*b.read()) ; } };
18
Shared<T> : déclaration et passage
Déclaration : Shared<T> x ( val_init ) ; Passage en paramètre : typage du droit d’accès droit d’accès avec accès autorisé : _r _w _r_w _cw < F_cumul, > droit d’accès avec accès différé : _rp _wp _rp_wp _cwp < F_cumul, > la tâche ne peut que transmettre le droit d’accès (via Fork) mais ne peut pas accéder la valeur
19
Restrictions Pas d’effets de bord sur des objets partagés : Shared variables globales : a1_global_tsp<F,T1,T2> … x … ; Fork<F>() ( x ) ; Autorisé ssi le droit possédé par l’appelant sur x est supérieur à celui requis par F (l’appelé) Ordre partiel : Shared > tout évidemment Shared_rp_wp > Shared_rp = Shared_r Shared_rp_wp > Shared_wp > Shared_w > Shared_cw[p] Shared_rp_wp > Shared_r_w = Attention : _r_w maj de la valeur possible, mais pas de Fork !
20
Justification des restrictions
Détection du parallélisme + éviter les copies Restrictions sémantique naturelle sans perte de parallélisme Conséquence : ces 2 programmes Athapascan-1 sont équivalents struct { void operator () ( <args> ) { deque d ; stmts_1 ; push(d, <args1 > ) ; stmts_2 ; push(d, <args2 > ) ; stmts_3 ; Fork<F1>()( pop(d) ); Fork<F2>()( pop(d) ); } struct { void operator () ( <args> ) { stmts_1 ; Fork<F1>()( <args1 > ) ; stmts_2 ; Fork<F2>()( <args2 > ) ; stmts_3 ; }
21
Programmation en Athapascan-1
Beaucoup d’Athapascan-1 Interface : Fork et Shared un exemple de programme accumulation, accès différé, ordre format, initialisation, compilation, exécution
22
Initialisation/Terminaison
int main( int argc, char** argv) { …. a1_system::init( argc, argv ) ; …. // tous les processus lourds exécutent a1_system::init_commit() ; // synchronisation …. if (a1_system::self_node() == 0) { …. // le « corps » du main : Fork, … } a1_system::terminate(); // attente fin des tâches return 0 ; }
23
Compilation / Exécution
Environnement : source ~maillard/ATHAPASCAN/sparc_DIST_INSTALL/bin/a1_setup.csh ou …/ix86_SMP_INSTALL/… etc Makefile : gmake clean; gmake fibo include $(A1_MAKEFILE) # CXXFLAGS += -DSEQUENTIAL Exécution : séquentiel : fibo 12 SMP : fibo 12 -a1_pool 4 distribué : a0run fibo 12 -a0n 3 -a1_pool 4:2: a1_stat -a1_trace_file fich Annotation ordonnancement, visualisation : cf doc
24
Projet APACHE et environnement de programmation parallèle ATHAPASCAN
Programmation efficace et portable des machines parallèles Applications cibles : applications régulières ou irrégulières Machines cibles : SMP, architecture distribuée, grape de SMP Thème de la thèse : définition de l’interface applicative validation pour la programmation en calcul scientifique Applications Athapascan-1 Visualisation Interface applicative Athapascan-0 Portabilité matérielle Communications (MPI,…) Threads (POSIX, Marcel, …)
Présentations similaires
© 2024 SlidePlayer.fr Inc.
All rights reserved.