Académique Documents
Professionnel Documents
Culture Documents
Prsent par
Adil JAAFAR
Intitul
PES la Facult des Sciences Mekns Encadrant PES la Facult des Sciences Mekns PES LEcole Nationale Suprieure dArts et Mtiers.
Ddicaces
A mes trs chers parents, pour leur amour infini ; A mes chres surs, en tmoignage de leur affection ; A tous les membres de ma famille ; A tous mes amis ; Je ddie ce travail. Adil
2/90
Remerciements
Je tiens remercier et exprimer toute ma gratitude toutes les personnes qui ont t prsentes pour moi lors de la ralisation de ce travail, et plus particulirement : M. Hassane ALLOUCHE, mon encadrant et professeur danalyse numrique et informatique, dont les conseils judicieux et clairs mont aiguillonn sur limportance de ce domaine dans la recherche scientifique, et mont fait prendre conscience de son impact dcisif sur lvolution de nombreuses applications techniques et industrielles. Mille mercis et mon ternelle gratitude celui qui a toujours su faire preuve de disponibilit pour me fournir lencadrement adquat et lassistance tout au long de la ralisation de ce projet. Jexprime galement mes remerciements et ma profonde gratitude aux membres du jury, D. Seghir Professeur la Facult des Sciences de Mekns et M. El Ghilani Professeur lEcole Nationale Suprieur des Arts et Mtiers qui mont honor en acceptant de juger ce travail. Mes professeurs ainsi que lensemble du corps administratif de la Facult des Sciences, notamment M. le Doyen Mohamed Kerouad et le Vice Doyen responsable des affaires estudiantines, M. Hamid ELMIR qui nont mnag aucun effort pour nous assurer le droulement de nos tudes et travaux dans des conditions pdagogique optimales. Ainsi qu tous ceux qui mont soutenu pour raliser ce travail.
3/90
Sommaire
DEDICACES
.....................................................................................................................................
2
REMERCIEMENTS
...........................................................................................................................
3
SOMMAIRE
....................................................................................................................................
4
LISTE
DES
ILLUSTRATIONS
..............................................................................................................
7
RESUME
.........................................................................................................................................
8
INTRODUCTION
..............................................................................................................................
9
PARTIE
I
LE
CALCUL
PARALLELE
.....................................................................................................
10 I
LE
CALCUL
DISTRIBUE
..............................................................................................................
11 II
III
LE
CALCUL
PARALLELE
............................................................................................................
12 SOLUTION
HYBRIDE
..............................................................................................................
13
IV MESURES DE PERFORMANCE ................................................................................................ 14 1 ACCELERATION (SPEED UP) : ......................................................................................................... 14 2 VOLUTIVIT (SCALABILITY) : .................................................................................................. 14 3 LOI DAMDAHL : ....................................................................................................................... 14 PARTIE II LES OUTILS : OPENMP .................................................................................................... 16 I INTRODUCTION ....................................................................................................................... 17 II III PRINCIPE ................................................................................................................................ 18 PARTAGE DU TRAVAIL ........................................................................................................... 19
1 PARALLEL FOR ............................................................................................................................ 19 2 SECTIONS .................................................................................................................................. 19 3 SYNCHRONISATION ...................................................................................................................... 19 PARTIE III ETUDE THEORIQUE ....................................................................................................... 20 I CONTEXTE ............................................................................................................................... 21 1 A EST SYMETRIQUE : .................................................................................................................... 21 2 A! , A ! ET A ! SONT DEFINIES POSITIVES : .......................................................................................... 22 3 LE SYSTEME EQUIVALENT : ............................................................................................................ 22 4 VALEUR DE Z : ............................................................................................................................ 22 PFE de Adil Jaafar dirig par H. Allouche
4/90
CALCUL PARALLELE : APPLICATION A LA RESOLUTION DES GRANDS SYSTEMES LINEAIRES CREUX 5 VALEURS DE X ET Y : .................................................................................................................... 23
II
1 GRADIENT A PAS OPTIMAL : .......................................................................................................... 24 2 GRADIENT CONJUGUE : ................................................................................................................ 25 PARTIE IV IMPLEMENTATION ....................................................................................................... 26 I ALGORITHME ........................................................................................................................... 27 1 GRADIENT A PAS OPTIMAL : .......................................................................................................... 27 1.1 ORGANIGRAMME : .......................................................................................................................... 27 2 GRADIENT CONJUGUE : ................................................................................................................ 29 2.1 ORGANIGRAMME : .......................................................................................................................... 29 II OPTIMISATION DES CALCULS PARALLELES .............................................................................. 31
1
STOCKAGE
DES
MATRICES
:
............................................................................................................
31 1.1
LES
MATRICES
B! ET
B! :
.................................................................................................................
31
1.2
LES
MATRICES
A! ,
A !
ET
A ! :
..........................................................................................................
31
2
MEMOIRE
CACHE
ET
OPTIMISATION
:
...............................................................................................
32 2.1
LOCALITE
SPATIALE
:
........................................................................................................................
32
2.2
LOCALITE
TEMPORELLE
:
...................................................................................................................
32
3
CALCUL
DES
PRODUITS
:
...............................................................................................................
32 3.1
PRODUIT
DES
MATRICES
B!
-
VECTEUR
:
..............................................................................................
32
Produit
B! v :
...................................................................................................................................
32
!
Produit
B! w :
.................................................................................................................................
33
3.2
PRODUIT
DES
MATRICES
A !
-
VECTEUR
:
..............................................................................................
33
1 GENERATEUR DES MATRICES DE TEST : ............................................................................................. 35 1.1 PRESENTATION : ............................................................................................................................. 35 1.2 UTILISATION DES CLASSES: (EXEMPLES) ............................................................................................... 36 2 PROGRAMME PRINCIPAL : DESCRIPTION DE LA DEMARCHE ................................................................... 36 Gradient conjugu : Rsolution de AX = b (globalement) ............................................................ 36 Gradient pas optimal : Rsolution de AX = b (par bloc) ............................................................ 36 Gradient conjugu : Rsolution de AX = b (par bloc) ................................................................... 36 IV RESULTATS ET COMPARAISONS ............................................................................................. 37 1 MATERIEL UTILISE : ..................................................................................................................... 37 2 RESULTAT DES EXECUTIONS : ......................................................................................................... 37 2.1 GRADIENT CONJUGUE : RESOLUTION DE AX = B (GLOBALEMENT) ......................................................... 37 2.2 GRADIENT A PAS OPTIMAL : RESOLUTION DE AX = B PAR BLOCS ............................................................ 38 2.3 GRADIENT CONJUGUE : RESOLUTION DE AX = B PAR BLOCS ................................................................. 39 PFE de Adil Jaafar dirig par H. Allouche
5/90
CALCUL PARALLELE : APPLICATION A LA RESOLUTION DES GRANDS SYSTEMES LINEAIRES CREUX 3 ANALYSE DE PERFORMANCE : ........................................................................................................ 40
CONCLUSION ................................................................................................................................ 42 BIBLIOGRAPHIE/WEBOGRAPHIE ................................................................................................... 43 ANNEXES ...................................................................................................................................... 44 LISTING 1. GENERATEUR DE MATRICES TEST - VECTEUR.H ........................................................................... 45 LISTING 2. GENERATEUR DE MATRICES TEST - VECTEUR.CPP ........................................................................ 45 LISTING 3. GENERATEUR DE MATRICES TEST - MATRICE.H .......................................................................... 46 LISTING 4. GENERATEUR DE MATRICES TEST - MATRICE.CPP ....................................................................... 47 LISTING 5. GENERATEUR DE MATRICES TEST - MATRICESYMETRIQUE.H ......................................................... 48 LISTING 6. GENERATEUR DE MATRICES TEST - MATRICESYMETRIQUE.CPP ...................................................... 49 LISTING 7. GENERATEUR DE MATRICES TEST LE PROGRAMME PRINCIPAL ..................................................... 50 LISTING 8. GRADIENT CONJUGUE RESOLUTION GLOBALE GC-GLB.C .......................................................... 54 LISTING 9. GRADIENT CONJUGUE RESOLUTION PAR BLOC GC_SEQ.C ........................................................ 58 LISTING 10. GRADIENT CONJUGUE RESOLUTION PAR BLOC GC_PAR.C ...................................................... 65 LISTING 11. GRADIENT A PAS OPTIMAL RESOLUTION PAR BLOC GPO_SEQ.C .............................................. 72 LISTING 12. GRADIENT A PAS OPTIMAL RESOLUTION PAR BLOC GPO_PAR.C .............................................. 79 FIGURE 13. OPENMP API 3.1 C/C++ ................................................................................................... 87 FIGURE 14. EXAMEN ANALYSE NUMERIQUE SESSION DE RATTRAPAGE 2011/2012 ...................................... 89
6/90
7/90
Rsum
Depuis lapparition en 2001 du premier microprocesseur bi-cur dIBM, cette technologie rvolutionnaire sest rpandue dune manire foudroyante au point que mme les ordinateurs personnels en sont quips actuellement, et quon trouve sur le march grand public des bi-curs, 5 curs ou 8 curs, voire mme davantage. Il conviendrait cependant de noter quil y a, gnralement, confusion entre le calcul parallle et le calcul distribu. En effet, bien que ces deux concepts se ressemblent quant leur finalit, savoir l Acclration des calculs en utilisant plusieurs units de calcul , il y a, toutefois, une grande diffrence de fond. La premire partie traite cette diffrence et prsente quelques outils pour valuer lefficacit du paralllisme dun algorithme spcifique.
Pour mettre en uvre la programmation parallle, plusieurs choix nous sont disponibles. On a opt pour lAPI openMP, qui est intgre dans le compilateur C/C++ : gcc. Dans la deuxime partie, nous prsentons une description dopenMP et comment lutiliser.
Pour juger lapport de la programmation parallle en termes de temps dexcution, nous proposons de coder des algorithmes de rsolution de systmes linaires et de comparer le temps de leur excution avec celui de la version parallle. La partie trois a pour objectif dtudier une mthode de rsolution de = (Systme de taille 2 + ) ne faisant intervenir que des rsolutions de systmes linaires de taille et .
Les premires proccupations dun programmeur au moment de limplmentation dun algorithme sont loptimisation du stockage des donnes dans la mmoire et la rduction du temps dexcution. La 4me partie est ddie laspect pratique de ce projet. Durant toutes les tapes de programmation, une attention bien particulire a t prte pour rduire le temps dexcution et lespace mmoire utilis, et les algorithmes standard de produit matrice-vecteur ont t revus pour rpondre aux besoins de notre cas dtude.
8/90
Introduction
Dans la qute incessante de plus de performance dans les calculs des diffrentes modlisations et simulations, les mathmaticiens, les constructeurs dordinateurs et les programmeurs sont continuellement la recherche de nouvelles mthodes et techniques pour davantage de prcision des rsultats tout en diminuant le temps de calcul. Ce dfi de performance tait partag naturellement entre les mathmaticiens qui laborent les algorithmes et les programmeurs qui les implmentent dune part, et les constructeurs dordinateurs, principalement ceux des microprocesseurs, composants indispensables lexcution des programmes, dautre part. Toutefois, les attentes taient, souvent, tournes vers les fabricants qui promettaient de doubler la puissance des microprocesseurs tous les 18 mois, conformment la loi de Moore1 en doublant le nombre de transistors par circuit de mme taille, et avec le mme cot. Une aubaine pour les programmeurs qui voient ainsi leurs algorithmes acqurir plus de performance sans fournir deffort notable de leur part. Mais cette mthode a fini par atteindre ses limites : Laugmentation de frquence dun processeur ncessite laugmentation de la puissance lectrique fournie, et donc de lnergie thermique gnre, quil faut dissiper. Cest pour contourner cette limite que les constructeurs se sont tourns vers la fragmentation des puces et la construction de plusieurs curs dans le mme processeur, do la naissance des multi- curs 2.Cette nouvelle donne a pouss les mathmaticiens repenser leurs algorithmes ainsi que les programmeurs revoir leurs codes source, et ce, pour pouvoir exploiter pleinement les caractristiques de ces processeurs. Le sujet de ce rapport est justement de mettre la lumire sur cette pratique, en prenant comme exemples dapplications la rsolution de systmes linaires creux, car ils constituent une base essentielle pour le traitement numrique de nombreux problmes de calcul scientifique, dont nous pouvons citer quelques uns, titre dexemple : Le traitement des dchets nuclaires, Mto, etc. Ces systmes, qui apparaissent en particulier dans le cadre de la discrtisation par lments ou volumes finis, sont habituellement de trs grande taille, de lordre de plusieurs millions. Les cots opratoires et en mmoire induits sont tels que le paralllisme est alors une technique incontournable pour rsoudre ces trs grands systmes.
La loi de Moore, dicte en 1965 par Gordon E. Moore, cofondateur de la socit Intel, prvoyait que les performances des processeurs doubleraient tous les 12 mois. Cette loi a t rvise en 1975, portant le nombre de mois 18. 2 http://fr.wikipedia.org/wiki/Microprocesseur_multi-cur
9/90
Pourquoi faire de la programmation parallle? Depuis lapparition en 2001 du premier microprocesseur bi-cur dIBM, cette technologie rvolutionnaire sest rpandue dune manire foudroyante au point que mme les ordinateurs personnels en sont quips actuellement, et quon trouve sur le march grand public des bi-curs, 5 curs ou 8 curs, voire mme davantage. Il conviendrait cependant de noter quil y a, gnralement, confusion entre le calcul parallle et le calcul distribu. En effet, bien que ces deux concepts se ressemblent quant leur finalit, savoir l Acclration des calculs en utilisant plusieurs units de calcul , il y a, toutefois, une grande diffrence de fond. La premire partie traite cette diffrence et prsente quelques outils pour valuer lefficacit du paralllisme dun algorithme spcifique.
I Le
calcul
distribu
Le calcul distribu ou rparti ou encore partag, est l'action de rpartir un calcul ou un traitement sur plusieurs microprocesseurs et plus gnralement toute unit centrale informatique3 souvent structures autour dun serveur master qui rpartit et distribue le traitement aux autres units de calcul : les slaves . Cette structure sappelle un cluster et les units qui la composent sappellent des nuds. Rsultats
Entre
de
donnes
Master
Rseau
Messages
Nud
Nud
Mmoire
Mmoire
Figure 1. Modle Calcul distribu
Nud
Mmoire
Nud
Mmoire
Le systme de cluster est transparent pour lutilisateur, qui introduit les donnes et rcupre les rsultats comme sil sagissait dune seule machine. Chaque nud de lensemble a son propre microprocesseur et son propre espace mmoire, il na pas accs celui des autres. On parle ici dun accs mmoire distribue . Par consquent, la synchronisation et lchange de donnes entre les nuds sont la charge du programmeur qui implmente lalgorithme. Lune des bibliothques les plus utilises pour la programmation distribue est la bibliothque MPI (Message Passing Interface).
http://fr.wikipedia.org/wiki/Calcul_distribu
11/90
II Le
calcul
parallle
Le calcul parallle est le fait dexcuter un programme sur plusieurs microprocesseurs ou curs avec un accs une mmoire partage.
Entre
de
donnes
Rsultats
CPU
CPU
CPU
CPU
Mmoire
Figure 2. Modle Calcul parallle
Cette technique est base sur la cration des fils dexcution threads4 ; lapplication commence par la cration du fil principal qui cre, chaque section parallle, des fils enfant afin de partager le travail du code. Aussi, et du fait que les fils accdent au mme espace mmoire, le programmeur na pas se soucier de la communication entre eux, ce qui ne le dispense pas toutefois de lobligation de rester vigilant quant laccs concurrentiel des donnes lespace mmoire partag. On peut illustrer lexcution dun programme parallle comme suit : Dbut
Zone
squentielle
Zone
parallle
Zone
squentielle
Fin
Figure 3. Utilisation des threads dans la programmation parallle
12/90
La programmation parallle est de plus en plus accessible au programmeur, il suffit gnralement dajouter quelques directives au compilateur pour lui demander une version parallle du programme. Nanmoins, il ny a pas une mthode universelle pour convertir un algorithme squentiel en une autre version parallle optimise. Cela doit tre trait au cas par cas, et le codage devrait tre prcd par une phase danalyse pour dterminer les rgions susceptibles dtre excutes en parallle selon les particularits de chaque algorithme.
13/90
IV Mesures
de
performance
1 Acclration
(Speed
up)
:
Le gain en vitesse ou Acclration est le rapport des vitesses entre lalgorithme squentiel sur un seul processeur et lalgorithme parallle sur processeurs. (1) = ! ()
VOLUTIVIT (SCALABILITY) :
Un algorithme est dit volutif (scalable) si on obtient un gain en efficacit en utilisant plus de processeurs.
Loi dAMDAHL :
Supposons quun algorithme est constitu des zones squentielles et des zones paralllisables avec une amlioration potentielle de % sur le temps dexcution de la partie paralllisable. Et soit ! () le temps dexcution de la zone par curs. Donc ! = ! + ! Et ! ! = ! + ! = ! + ! () = 1 ! + Do lacclration : ! () 1 = = ! ! () 1 + Si on fait tendre vers linfini, on aura : !"# =
PFE de Adil Jaafar dirig par H. Allouche
!
1 1
14/90
!"# est la borne suprieure de lacclration quon peut esprer atteindre par la programmation parallle de cet algorithme. Cette borne sappelle la loi dAMDAHL5. La figure suivante prsente lacclration en fonction du nombre de curs. Partie
parallle
Nombre
de
curs
Acclration
Gene Myron Amdahl, amricain d'origine norvgienne, est un architecte d'ordinateur et un entrepreneur, principalement connu pour son travail sur les ordinateurs centraux chez IBM et plus tard dans ses propres entreprises, particulirement Amdahl Corporation.
15/90
Comment faire de la programmation parallle ? Pour mettre en uvre la programmation parallle, plusieurs choix nous sont disponibles. On a opt pour lAPI openMP, qui est intgre dans le compilateur C/C++ : gcc Dans cette partie, nous prsentons une description dopenMP et comment lutiliser.
16/90
I Introduction
OpenMP (Open Multi-Processing) est une API6 qui offre la possibilit de faire la programmation parallle mmoire partage laide dun ensemble de directives, dune bibliothque de fonctions et de variables denvironnement. Cette API est supporte sur de nombreuses plateformes dont Unix, Mac et Windows pour les langages de programmation C/C++ et Fortran. Un programme openMP est excut par un processus7 unique matre , ce dernier active dautres processus lgers (les threads) lentre dune rgion parallle. Une fois la partie parallle est termine, les threads se dtruisent et seul le processus matre continue lexcution jusqu rencontrer une autre rgion parallle. Dbut
Processus
matre
Cration
de
threads
(Fork)
Zone
parallle
Destruction
de
threads
(Join)
Zone
squentielle
Fin
Figure 5. Excution dun programme openMP (Fork-Join)
API : Application Programming Interface. Une Interface de programmation, un ensemble de fonctions qui peuvent tre intgres dans un programme. 7 Un processus est un conteneur compos dau moins un thread et a une pile dexcution (une zone mmoire ddie au processus pour stocker les appels aux fonctions, les donnes et les instructions)
17/90
II Principe
Dans le cadre de ce projet, on se limite la faon dcrire et dexcuter des programmes parallles avec openMP en langage C/C++. Pour utiliser les directives de lAPI, il faut inclure omp.h
#include <omp.h>
Inutile de chercher ce fichier, il est doffice intgr dans le compilateur gcc Pour utiliser une directive dopenMP, il faut commencer par la sentinelle #pragma suivie de la directive omp ainsi que les clauses dsires. Par exemple, une des faons pour dclarer une rgion parallle est la suivante :
#pragma omp parallel { /* ceci est une rgion parallle. */ }
La compilation du programme est effectue soit dans un environnement de dveloppement IDE, o directement partir dune ligne de commande :
gcc fopenmp o fichierDeSortie fichierSource.c
Si loption fopenmp est omise, le compilateur ignorera les directives omp, et crera ainsi une version squentielle du code. Pendant lexcution dune tche, une variable peut tre soit prive, cest dire accessible uniquement au thread qui excute la tche, ou partage et alors elle est accessible tous les threads. Dans lexemple suivant, les variables i et j sont dclares prives, tandis que a et b sont partages.
#pragma omp parallel private(i,j) shared(a,b) { /* ceci est une rgion parallle. Chaque thread a ses propres variables i et j Tous les threads partagent les mmes variables a et b */ }
18/90
Parallel for
Excuter une boucle par rpartition des itrations entre les tches ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #pragma omp parallel for private(i) for(l=0;l<NBm;l++){ //Itration } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Figure 6. Directive omp parallel for
Sections
Excuter plusieurs sections du code, mais une seule par tche ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #pragma omp parallel sections { #pragma omp section //Section 1 #pragma omp section //Section 2 #pragma omp section //Section 3 } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Figure 7. Directive omp parallel sections
Synchronisation
A la fin de chaque rgion parallle, les threads qui terminent leurs tches attendent les autres threads avant de mettre fin la rgion. Cest une barrire de synchronisation implicite. Ce comportement peut tre ignor par lajout de la clause NOWAIT la dclaration de la partie parallle. Alors, pour crer une barrire explicite, on utilise la directive : Une fiche contenant la liste exhaustive des directives, fonctions et variables denvironnement openMP est livre en annexe.
PFE de Adil Jaafar dirig par H. Allouche #pragma omp barrier
19/90
Pour juger lapport de la programmation parallle en termes de temps dexcution, nous proposons de coder des algorithmes de rsolution de systmes linaires et de comparer le temps de leur excution avec celui de la version parallle. Lobjectif est dtudier une mthode de rsolution de = (Systme de taille 2 + ) ne faisant intervenir que des rsolutions de systmes linaires de taille et .
I Contexte
On se propose la rsolution des systmes linaires = , o est une matrice carre, dfinie positive et de la forme :
! 0 ! !
0 ! ! !
! ! !
o ! et ! sont des matrices symtriques carres , ! et ! sont des matrices rectangulaires et ! une matrice symtrique carre . La matrice est alors 2 + (2 + ), les vecteurs et sont ainsi dans !!!! . On crira sous la forme :
est
symtrique
:
En effet, est symtrique :
! ! ! = 0 ! !
0 ! ! ! !
! ! ! ! ! ! ! !
! = 0 ! !
0 ! ! !
! ! !
21/90
2
Soit
On a : , =
! + ! ! + ! , ! ! ! + ! + !
est dfinie positive, donc , > 0 !!!! 0 en particulier pour = de mme pour =
! ! ! ! ! ! !
! ! = ! + ! , + ! + ! , + ! + ! + ! ,
et ! 0 on a : , = ! , > 0
et ! 0 on a : , = ! , > 0
Le systme quivalent :
! et ! sont dfinies positives, donc elles sont inversibles. En dveloppant le produit de la matrice et le vecteur solution, on trouve le systme quivalent suivant :
! = ! ! = ! =
! !! ! ! !! ! Avec = ! ! ! ! ! !! ! et = ! ! ! !! ! !
Valeur de :
La valeur de est la solution du systme = de taille . Il faut tout dabord ! !! ! !! calculer la valeur de = ! ! ! !! . Les termes ! et !! sont ! ! respectivement les solutions des deux systmes de taille : ! = et ! = . Puis ! ! ! ! calculer les produits matrices vecteurs ! et ! et finalement = ! ! Dans le calcul de , on peut rsoudre les systmes ! = et ! = et les ! ! produits ! et ! en parallle.
PFE de Adil Jaafar dirig par H. Allouche
22/90
Pour notre dmarche, il est ncessaire que soit symtrique et dfinie positive. En effet, ! = 3 1 1 1
Do est symtrique.
1 2 2 2 ! !! ! ! ! ! ! = ! ! ! ! ! !! ! ! ! ! ! !! ! = ! ! ! ! ! !! ! ! =
!!!! !! ! ! !!!! !! ! ! !
Et si on prend =
!!!! 0 , ! 0
On aura : !! !! , = ! ! ! + ! , ! ! + ! !! ! + ! , !! ! ! ! ! !! ! + ! ! ! ! !! ! + ! , !
Valeurs
de
et
:
Aprs le calcul de , et sont les solutions des deux systmes :
! = ! ! = !
23/90
Le but de cette mthode est de dterminer une valeur approche de la solution dune quation linaire du type = On note que la solution de ce systme est aussi lunique minimum de la fonction ! quadratique : = ! , , On utilise lalgorithme suivant, avec : une matrice symtrique dfinie positive ; un vecteur colonne de taille ; un seuil de tolrance. On choisit ! ! arbitraire, et on pose ! = ! Tant que ! > !!! = ! ! ! ! = ! , ! !!! = ! + ! !
24/90
Gradient conjugu :
La mthode du gradient conjugu fait partie des mthodes de descente, qui ont comme principe commun la recherche de la solution suivant le procd itratif : x! ! Arbitraire, x!!! = x! + ! p! Avec ! ! la direction de descente, et ! le pas de descente optimal qui minimise la fonction dans la direction ! . Cest--dire que : ! + ! ! = min ! + ! x! ! Valeur initiale ! = ! ! = ! Pour = 0 1 ! ! ! = ! , ! x!!! = x! + ! p! !!! = ! !!! ! ! = ! ! !!! = !!! + ! !
!!!
25/90
Les premires proccupations dun programmeur au moment de limplmentation dun algorithme sont loptimisation du stockage des donnes dans la mmoire et la rduction du temps dexcution. La 4me partie est ddie laspect pratique de ce projet. Durant toutes les tapes de programmation, une attention bien particulire a t prte pour rduire le temps dexcution et lespace mmoire utilis, et les algorithmes standard de produit matrice-vecteur ont t revus pour rpondre aux besoins de notre cas dtude.
Partie IV Implmentation
26/90
I Algorithme
1
1.1
! =
! ! = !
! =
! ! = !
Calcul
de
:
! !! ! ! ! ! !!
!
= ! !
Initialisation
de
Calcul
de
:
! !! ! ! ! ! ! ! !! !
!
! = !
! = !
! ! = !
! = !
! = !
! ! = !
! = !
= ! ! !
=
Calcul
de
:
! !! ! ! ! ! ! ! !! !
!
! = !
! = !
! ! = !
! = !
! = !
! ! = !
! = ! = ! ! !
27/90
! < , >
= +
OUI
>
Calcul de et ! = ! ! = ! ! = ! ! = ! ! = ! ! = !
Fin
Figure 8. Organigramme gradient pas optimal
28/90
2
2.1
Gradient
conjugu
:
Organigramme
:
Dbut
! =
! ! = !
! =
! ! = !
Calcul
de
:
! !! ! ! ! ! !!
!
= ! ! Initialisation de = = _! = , = 0
! = !
! = !
! ! = !
! = !
! = !
! ! = !
Calcul
de
:
! !! ! ! ! ! ! ! !! !
!
! = ! = ! ! ! _! ,
= + = _!!! = ,
29/90
_!!! _!
_! = _!!!
= +
= + 1
OUI
<
! = ! ! = ! ! = !
! = ! ! = ! ! = !
Calcul de et
Fin
Figure 9. Organigramme gradient conjugu
30/90
! =
! ! !(!!!)
En dautres termes, chacune des deux matrices sera stocke dans la mmoire dans des cases adjacentes, ligne aprs ligne.
1re ligne 2me ligne
nme ligne
! ! !!! ! !!!! !(!!!) !"!!
1.2
Les matrices , et :
A linstar de ! et ! , les matrices symtriques ! , ! et ! sont enregistres dans un tableau une seule dimension, sauf que lindexation des lments est diffrente :
! =
Avec qui reprsente le nombre de lignes/colonnes des matrices ! . Ce qui permet aux matrices symtriques ! de noccuper que la moiti de la taille mmoire dans des cases adjacentes.
1re ligne ( cases) 2me ligne ( 1 cases) me ligne (Une case)
! ! !!! ! !!!! ! !!! !!
!
PFE de Adil Jaafar dirig par H. Allouche
31/90
Pour excuter un programme, le processeur a besoin, principalement, de lire et dcrire des donnes partir et vers les registres et la mmoire, laccs cette dernire est coteux en terme de temps cause de la diffrence entre la vitesse de rponse des processeurs et celle des mmoires. Pour y remdier, le processeur copie certaines instructions et donnes dans sa mmoire cache pour un traitement plus rapide et renvoie le rsultat ensuite la mmoire. Le processeur suit deux logiques pour dcider quelles donnes ou instructions mettre dans le cache : la localit spatiale et la localit temporelle. Consquence, un programme qui prsente de bonnes caractristiques de localit, sera plus rapide.
2.1
Localit spatiale :
Lorsque le programme accde une donne ou une instruction, il accdera ensuite aux donnes ou instructions prsentes dans les cases mmoire situes juste ct.
2.2
Localit temporelle :
Lorsque le programme accde une donne ou une instruction, il y accdera encore plusieurs fois brves chances.
3
3.1
Dans la rsolution du systme = , il faut calculer les produits matrice- vecteur de la forme ! et !! .
Produit
:
Etant donn que les lments des matrices ! sont enregistrs dans la mmoire ligne aprs ligne, et donc adjacents, le code standard du produit matrice-vecteur prsente de bonnes localits spatiale et temporelle, et offre par consquent de meilleurs rsultats en terme de temps dexcution. La lecture du code ci-aprs permet dillustrer les propos prcits :
//Calcul de p=B.v for (i=0; i<n; i++){ p[i] = 0; for(j=i*m,k=0;k<m;j++,k++) p[i] += B[j]*v[k]; /* Localit spatiale : Accs aux lments successifs de B indexs par j Localit temporelle : Accs rcurrent la case p[i] */ }
32/90
Dans le cas du produit !! , au lieu de traiter la matrice !! ligne par ligne, qui sont des cases non adjacentes dans lespace mmoire, il est plus judicieux de traiter colonne par colonne, ce qui revient in fine traiter la matrice ! ligne par ligne, lesquelles sont adjacentes ce qui permet de raliser un gain de temps suite leur localit spatiale. Lillustration de ces assertions peut tre ralise par le code suivant :
//Calcul de p= ! . for (k=0; k<n; k++) p[k] = 0;
for (i=0; i<n; i++){ for(j=i*m,k=0;k<m;j++,k++){ p[k] += B[j]*w[i]; /* Localit spatiale : Accs aux lments successifs de B indexs par j, et ceux de p indexs par k Localit temporelle : Accs rcurrent la case w[i] */ }
3.2
Toujours la recherche de plus de localit spatiale et temporelle dans les codes des calculs, on propose de coder les produits des matrices ! , ! et ! par des vecteurs de deux manires :
Les
produits
et
:
Ces produits apparaissent dans des rgions parallles et sont donc calculs simultanment, et pour de meilleures performances, on value successivement lapport de chaque lment de la matrice dans le calcul de la somme, qui constitue les lments du rsultat. Le code illustrant ces affirmations est le suivant :
int tA = n*(n+1)/2;// tA : nombre dlments dans la matrice A int l,c;// l : indexe ligne, c : indexe colonne l=c=0; for(i=0;i<n;i++) p[i] = 0; for(i=0;i<tA;i++){ if(l==c){ p[l] += A[i]*v[c]; /* A[i] est dans la diagonale, il intervient uniquement dans le calcul de la l-me ligne de p */ }else{ p[l] += A[i]*v[c]; p[c] += A[i]*v[l]; /* A[i] intervient dans le calcul des lignes l et c de p */ } if(l==n-1){c++;l=c;} else{l++;} }
33/90
Le
produit
Pour le calcul du produit ! , un algorithme paralllisable est plus adapt la rsolution du systme. Cet algorithme doit comporter des itrations indpendantes les unes des autres.
for (i=0; i<m; i++) { p[i] = 0; for(j=0;j<m;j++){ if(j>i){ p[i] += A[i*m-i*(i+1)/2+j]*v[j]; }else{ p[i] += A[j*m-j*(j+1)/2+i]*v[j]; } } }
34/90
III
Codes
1
1.1
Pour valuer les codes raliss, il a fallu disposer de systmes tests dont on connat au pralable les solutions. Pour cette finalit, un module en C++ a t cr pour gnrer les matrices constituant le systme, et en choisissant comme solution le vecteur dont tous les lments sont 1. On calcule les vecteurs qui composent le second membre du systme. Puis, le tout est stock dans des fichiers binaires pour lesquels on a choisi lextension .m Selon les hypothses, la matrice globale devrait tre dfinie positive. Pour ce faire, une factorisation de Cholesky8 est effectue aprs la gnration alatoire des matrices ! , ! , ! , ! et ! . Au cours de cette factorisation, des modifications sont opres sur les lments des matrices ! pour permettre de mener la dite factorisation jusquau bout. Pour faciliter la manipulation des matrices et des vecteurs et avoir un code genre : Ou du genre :
U = M*X + N*Y; // M et N des matrices et X,Y et U des vecteurs
Ou bien encore
Le module comporte 3 classes : Matrice Symtrique, Matrice et Vecteur qui implmentent les oprations ncessaires pour les calculs, savoir : Le produit scalaire Vecteur-Vecteur La somme de deux vecteurs Le produit Matrice-Vecteur Le produit Matrice-Matrice De plus, les classes implmentent des fonctions supplmentaires comme la norme, la transpose dune matrice et le stockage du contenu dans un fichier binaire, et la rcupration des donnes depuis lesdits fichiers.
8
Factorisation de Cholesky : un procd qui permet, pour une matrice dfinie positive , de dterminer une matrice triangulaire infrieure , telle que = !
35/90
1.2
//Dclaration dune matrice symtrique de dimension 20 x 20 MatriceSymetrique M(20); //Affectation de 1.5 la case de ligne 1 et la colonne 4 //M(1,4) et M(4,1) pointent sur la mme case M(1,4) = 1.5; //Dclaration de deux vecteurs X et U dordre 20 Vecteur X(20), U(20); X(3) = 5; //Calcul du produit Matrice-Vecteur et affectation du vecteur rsultat U U = M*X; cout<<U; // Afficher U sur lecran FILE* f; f = open(M.m,wb); //ouverture du fichier M.m en mode criture binaire f<<M; // Stocker M dans le fichier M.m MatriceSymetique A(20); //Dclaration de la matrice FILE* f; F = open(A.m,rb); //ouverture de A.m en mode lecture binaire f>>A; // charger A.m dans A
Pour tirer des conclusions pertinentes propos de la rsolution du systme tudi = que ce soit par bloc ou en utilisant la programmation parallle, on propose de coder 3 programmes : (Les codes de ces programme se trouvent en annexe)
Gradient
conjugu
:
Rsolution
de
=
(globalement)
Rsolution de = par lalgorithme du gradient conjugu appliqu sur la totalit de la matrice . Les rsultats de son excution serviront de rfrence pour les comparaisons.
Gradient
pas
optimal
:
Rsolution
de
=
(par
bloc)
Rsolution de = par lalgorithme du gradient pas optimal appliqu sur les sous-systmes des blocs tudis plus haut. Puis compiler plusieurs versions squentielles et parallles sur 1, 2, 3 ou 4 curs.
Gradient
conjugu
:
Rsolution
de
=
(par
bloc)
De mme que pour lalgorithme du gradient pas optimal, plusieurs versions seront crees pour le programme implmentant lalgorithme du gradient conjugu.
36/90
IV Rsultats
et
comparaisons
1 Matriel
utilis
:
Les programmes cods sont tests sur une machine (ordinateur portable) de marque Lenovo comportant 4 curs. Systme dexploitation : Windows 7 Edition intgrale 32 bits Fabricant et modle : LENOVO 25371V7 BIOS : Ver 1.00PARTTBLx Processeur : Intel Core i5 CPU M 520 @ 2.40GHz (4 CPUs) Mmoire : 4096 MB RAM Disque dur : 300 Go
2
2.1
test.
28 24 20 14 10 7 5
Temps dexcution (s) 2039,314 915,612 229,056 20,218 0,274 0,156 0,031
37/90
2.2
Temps dexcution, en secondes, du 2me programme, rsolution par blocs du systme = par lalgorithme du gradient pas optimal appliqu sur les matrices de test.
28 24 20 14 10 7 5
SEQ : Excution squentielle - PAR : Excution parallle Labsence des temps dexcution sur le tableau est due la lenteur de convergence de la mthode gradient pas optimal pour les matrices de tests utilises.
38/90
2.3
Temps dexcution, en secondes, du 2me programme, rsolution par blocs du systme = par lalgorithme du gradient conjugu appliqu sur les matrices de test.
28 24 20 14 10 7 5
1 Cur SEQ 433,899 120,541 10,858 1,216 0,078 0,016 PAR 499,654 137,982 13,167 1,607 0,172 0,031
1076,917 1247,908 1076,527 713,951 1076,791 651,426 1077,604 610,445 433,619 287,041 433,822 264,982 433,681 248,369 120,386 10,811 1,170 0,078 0,016 80,605 8,518 1,092 0,172 0,078 120,432 10,764 1,138 0,078 0,016 74,163 8,330 1,155 0,234 0,094 120,308 10,702 1,139 0,078 0,016 70,137 8,252 1,233 0,280 0,094
39/90
Analyse de performance :
Les graphes prsents ci-aprs concernent les rsultats de limplmentation de lalgorithme gradient conjugu .
1200
1000
800
600
400
200
0
Seq1c
Seq2c
Seq3c
Seq4c
Figure 10. Temps dexcution du programme squentiel pour diffrentes tailles du systme
Le temps dexcution de la version squentielle du programme est peu influenc par le traitement sur plusieurs curs.
1400
1200
1000
800
600
400
200
0
Par1c
Par2c
Par3c
Par4c
4056
3048
2040
1028
510
207
105
Figure 11. Temps dexcution du programme parallle pour diffrentes tailles du systme
Le temps dexcution de la version parallle du programme est notablement diminu lors du calcul sur 2 curs, puis continue avec une lgrebaisse observeau- del de 3 curs.
40/90
Le programme prsente une bonne scalabilit pour les matrices dont la taille dpasse 1028.
2500
2000 GC global 1500 SequenJel par bloc Parallle 2 curs 1000 Parallle 3 curs Parallle 4 curs 500
Figure 13. Comparaison du temps dexcution de diffrents algorithmes en fonction de la taille du systme
Une augmentation trs rapide du temps dexcution, en fonction de la taille du systme, lors de lapplication de la mthode gradient conjugu sur toute la matrice. Cependant, cette augmentation est plus modre avec le traitement du systme par bloc (baisse denviron 50%) et plus modre encore avec les versions parallles sur 2, 3 et 4 curs (baisse denviron 75%).
41/90
Conclusion
Lanalyse des rsultats prsents sur les graphes prcits montre que la programmation parallle, combine avec un algorithme adapt, peut rduire considrablement le temps dexcution. Dans le cas de la matrice tudie, une autre amlioration peut encore tre apporte pour rduire davantage le temps dexcution, il sagit dune factorisation de Cholesky des matrices ! et ! pour rsoudre les systmes ! = et ! = qui apparaissent chaque itration des mthodes du gradient utilises. Tout au long de ce projet, le sujet consistait en ltude de la rsolution dun cas particulier des grands systmes linaires creux. Mais, en gnral, la plupart des algorithmes connus ne prsentent pas la particularit dtre paralllisables, et ne sont donc pas compatibles avec la tendance des fabricants de machines de calcul qui est oriente vers le multiprocessing, qui ne prsentent dintrt certain que lorsque les algorithmes quelles excutent sont parallles. Par consquent, les mathmaticiens et plus particulirement les chercheurs dans le domaine de lanalyse numrique sont invits simprgner, dans tous leurs travaux de recherches, du concept du calcul parallle. Ltape suivante, naturellement, est de se tourner vers le calcul distribu et son application dans la rsolution de trs grands systmes linaires en divisant le travail en plusieurs tches, relativement indpendantes les unes des autres, et distribuer leur excution sur plusieurs units de calcul avec une implmentation parallle.
42/90
Bibliographie/Webographie
COURS DANALYSE NUMERIQUE S5 2011/2012 H. ALLOUCHE UMI FACULTE DES SCIENCES MATRIX COMPUTATIONS Gene H. GOLUB, CHARLES F. VAN LOAN
http://openmp.org/wp/ http://www.idris.fr/ Institut du dveloppement et des ressources en informatique Scientifique http://intel-software-academic-program.com/courses/index.html Intel Software Acadimic Program http://www.top500.org/ SuperComputer Sites
43/90
ANNEXES
PFE de Adil Jaafar dirig par H. Allouche
44/90
Listing 2. Gnrateur de matrices test - Vecteur.cpp #include <iostream> #include <iomanip> #include "Vecteur.h" Vecteur::Vecteur(int dim){ this->dim = dim; this->data = newdouble[dim]; } Vecteur::~Vecteur(){ delete [] data; } double Vecteur::norme(){ //TODO: Norme !! return 1; } double& Vecteur::operator()(unsigned idx){ return data[idx-1]; } double Vecteur::operator()(unsigned idx) const{ return data[idx-1]; } doubleoperator*(Vecteur& U, Vecteur& V){ //TODO: verifier si U.dim == V.dim ? double p = 0; for (int i=1; i<=U.dim; i++) { p += U(i)*V(i); }
friend std::ostream&operator<<(std::ostream&, Vecteur&); friend std::istream&operator>>(std::istream&, Vecteur&); friend FILE* operator<<(FILE*, Vecteur&); friend FILE* operator>>(FILE*, Vecteur&); private: unsigned dim; double* data; }; #endif
45/90
Listing 3. Gnrateur de matrices test - Matrice.h #include "Vecteur.h" #ifndef J4_Matrice_h #define J4_Matrice_h class Matrice { public: Matrice(int nl=1, int nc=1); ~Matrice(); double norme(); Matrice transposee(); double& operator()(unsigned l, unsigned c); double operator()(unsigned l, unsigned c) const; friend Vecteur operator*(Matrice, Vecteur); friend Matrice operator*(Matrice, Matrice); friend std::ostream&operator<<(std::ostream&, Matrice&); friend std::istream&operator>>(std::istream&, Matrice&); friend FILE* operator<<(FILE*, Matrice&); friend FILE* operator>>(FILE*, Matrice&); private:
46/90
for(int i=1; i<=nl; i++) for(int j=1; j<=nc; j++) T(j,i) = data[(i-1)*nc+j-1]; return T; } double& Matrice::operator()(unsigned l, unsigned c){ return data[(l-1)*nc+c-1]; } double Matrice::operator()(unsigned l, unsigned c) const{ return data[(l-1)*nc+c-1]; } Vecteur operator*(Matrice M, Vecteur V){ //TODO: verifier si M.nc == V.dim Vecteur P(M.nl); for (int i=1; i<=M.nl; i++) { P(i) = 0; for(int j=1;j<=M.nc;j++) P(i) += M(i,j)*V(j); } return P; } Matrice operator*(Matrice M, Matrice N){ //TODO: verifier si M.nc == V.dim Matrice P(M.nl,N.nc); double Cij; for (int i=1; i<=M.nl; i++) { for(int j=1;j<=N.nc;j++){
47/90
Listing 5. Gnrateur de matrices test - MatriceSymetrique.h #include "Vecteur.h" #ifndef J4_MatriceSymetrique_h #define J4_MatriceSymetrique_h
class MatriceSymetrique{ public: MatriceSymetrique(int dim=1); ~MatriceSymetrique(); double norme(); double& operator()(unsigned l, unsigned c); double operator()(unsigned l, unsigned c) const; friend Vecteur operator*(MatriceSymetrique&, Vecteur&); friend MatriceSymetrique&operator*(MatriceSymetrique&, MatriceSymetrique&); friend std::ostream&operator<<(std::ostream&, MatriceSymetrique& ); friend std::istream&operator>>(std::istream&, MatriceSymetrique&); friend FILE* operator<<(FILE*, MatriceSymetrique&); friend FILE* operator>>(FILE*,
FILE* operator<<(FILE* f, Matrice& M){ fwrite(M.data, sizeof(double), M.nl*M.nc, f); return f; } FILE* operator>>(FILE* f, Matrice& M){ fread(M.data, sizeof(double), M.nl*M.nc, f); return f; }
PFE de Adil Jaafar dirig par H. Allouche
48/90
double& MatriceSymetrique::operator()(unsigned l, unsigned c){ if(c>l){ return data[(l-1)*dim-(l-1)*l/2+c-1]; }else{ return data[(c-1)*dim-(c-1)*c/2+l-1]; } } double MatriceSymetrique::operator()(unsigned l, unsigned c) const{ if(c>l){ return data[(l-1)*dim-(l-1)*l/2+c-1]; }else{ return data[(c-1)*dim-(c-1)*c/2+l-1]; } } Vecteur operator*(MatriceSymetrique& M, Vecteur& V){ //TODO: verifier si M.dim == V.dim Vecteur P(M.dim); for (int i=1; i<=M.dim; i++) { P(i) = 0; for(int j=1;j<=M.dim;j++) P(i) += M(i,j)*V(j); } return P; } std::ostream& operator<<(std::ostream& out, MatriceSymetrique& M ){ for(int i=1; i<=M.dim;i++){ for (int j=1; j<=M.dim; j++)
49/90
#include #include #include #include #include #include <iostream> <iomanip> <math.h> "Matrice.h" <vector> "MatriceSymetrique.h"
usingnamespace std; #define #define #define #define NBn 28 NBm 4000 randMIN .001 randMAX 2
int main(int argc, constchar * argv[]) { int trouvee, nessai = 0; MatriceSymetrique A1(NBn), A2(NBn), A3(NBm); Matrice B1(NBn,NBm), B2(NBn,NBm); Vecteur X(NBn), Y(NBn), Z(NBm); Vecteur U(NBn), V(NBn), W(NBm); Matrice L(2*NBn+NBm,2*NBn+NBm); double Aij; double S;
50/90
double r; /* Gnration des matrices A1 et A2 avec des valeurs dans les intervalles : -randMAX..-randMIN et randMIN..randMAX Affectation de la valeur 1 aux composantes des solutions X et Y */ for (int i=1; i<=NBn; i++){ X(i) = 1; Y(i) = 1; for(int j=i; j<=NBn;j++) { r = rand()/(double)RAND_MAX*2-1; if(r>=0) A1(i,j) = (double)((randMAX - randMIN) * r) + randMIN; if(r<0) A1(i,j) = (double)((randMAX - randMIN) * r) - randMIN; r = rand()/(double)RAND_MAX*2-1; if(r>=0) A2(i,j) = (double)((randMAX - randMIN) * r) + randMIN; if(r<0) A2(i,j) = (double)((randMAX - randMIN) * r) - randMIN; } } /* Gnration de la matrice A3 avec des valeurs dans les intervalles : -randMAX..-randMIN et randMIN..randMAX Affectation de la valeur 1 aux composantes de la solution Z */
for (int i=1; i<=NBm; i++){ Z(i) = 1; for(int j=i; j<=NBm;j++) { r = rand()/(double)RAND_MAX*2-1; if(r>=0) A3(i,j) = (double)((randMAX - randMIN) * r) + randMIN; if(r<0) A3(i,j) = (double)((randMAX - randMIN) * r) - randMIN; } } /* Gnration des matrices B1 et B2 avec des valeurs dans les intervalles : -randMAX..-randMIN et randMIN..randMAX */ for (int i=1; i<=NBn; i++){ for(int j=1; j<=NBm;j++) { r = rand()/(double)RAND_MAX*2-1; if(r>=0) B1(i,j) = (double)((randMAX - randMIN) * r) + randMIN; if(r<0) B1(i,j) = (double)((randMAX - randMIN) * r) - randMIN; r = rand()/(double)RAND_MAX*2-1; if(r>=0) B2(i,j) = (double)((randMAX - randMIN) * r) + randMIN; if(r<0) B2(i,j) = (double)((randMAX - randMIN) * r) - randMIN; } }
51/90
A2(j-NBn,j-NBn) = Aij; }else { A3(j-2*NBn,j-2*NBn) = Aij; } } L(j,j)=sqrt(Aij-S); for(int i=j+1;i<=2*NBn+NBm;i++){ S=0; for(int k=1;k<j;k++){ S+=L(i,k)*L(j,k); } if(j<=NBn){ if(i<=NBn){ Aij = A1(i,j); }elseif (i<=2*NBn) { Aij = 0; }else { Aij = B1(j,i-2*NBn); } }elseif (j<=2*NBn) { if (i<=2*NBn) { Aij = A2(i-NBn,j-NBn); }else { Aij = B2(j-NBn,i-2*NBn); } }else { Aij = A3(i-2*NBn,j-2*NBn); } L(i,j)=(Aij-S)/L(j,j); } }
52/90
f = fopen("Z.m", "wb"); f<<Z; f = fopen("U.m", "wb"); f<<U; f = fopen("V.m", "wb"); f<<V; f = fopen("W.m", "wb"); f<<W; cout<<"Systme gnr."; return0; }
53/90
#include #include #include #include #include #include <stdio.h> <stdlib.h> <time.h> <math.h> <assert.h> <string.h>
void remplir(char* input); void afficher(); void prod_A_v(double* Av, double* v, double* norme); int main(int argc, char **argv) { NBn = atoi(argv[2]); NBm = atoi(argv[3]); N = 2*NBn+NBm; double t1, t2, t; int k,l,i; printf("Dossier input : %s\nTaille n : %d\nTaille m : %d",argv[1],NBn,NBm); remplir(argv[1]); X = (double*) malloc(N * sizeof(double)); r = (double*) malloc(N * sizeof(double)); p = (double*) malloc(N * sizeof(double)); Ap = (double*) malloc(N * sizeof(double)); Ax = (double*) malloc(N * sizeof(double)); t1 = omp_get_wtime(); normeRk = 0; for(i=0;i<N;i++){ X[i] = 0; if(i<NBn){ p[i] = r[i] = U[i];
#include <omp.h> int NBn; int NBm; int N; double alpha, lambda, normeRk, normeRk1, norme2; double* A1; double* A2; double* A3; double* B1; double* B2; double* U; double* V; double* W; double* X; double* double* double* double* r; p; Ap; Ax;
54/90
printf("\nTemps CPU = %f\n",t); FILE* res; res = fopen("resultats-glb.txt","a"); fprintf(res,"global 4c %s : %f\n",argv[1],t); fclose(res); afficher();
for (i=0;i<=N; i++) { prod_A_v(Ap,p,&norme2); lambda = normeRk/norme2; normeRk1=0; for(l=0;l<N;l++){ X[l] += lambda*p[l]; r[l] -= lambda*Ap[l]; normeRk1 += r[l]*r[l]; } alpha = normeRk1/normeRk; normeRk = normeRk1; for(l=0;l<N;l++) p[l] = r[l] + alpha*p[l]; } t2 = omp_get_wtime(); t = t2-t1; return0; } void remplir(char* input){ printf("\nChargement des Matrices : A1, A2, A3, B1, B2 et les Vecteurs : U, V et W\n"); A1 = (double*) malloc(sizeof(double) * (NBn*(NBn+1)/2)); A2 = (double*) malloc(sizeof(double) * (NBn*(NBn+1)/2)); A3 = (double*) malloc(sizeof(double) * (NBm*(NBm+1)/2)); B1 = (double*) malloc(sizeof(double) * (NBn*NBm)); B2 = (double*) malloc(sizeof(double) * (NBn*NBm)); U = (double*) malloc(sizeof(double) * NBn); V = (double*) malloc(sizeof(double) * NBn); W = (double*) malloc(sizeof(double) * NBm);
55/90
strcat(chemin,input); strcat(chemin,"/B2.m"); f = fopen(chemin, "rb"); fread(B2, sizeof(double), NBn*NBm, f); printf("\nB2.m : OK"); chemin[0] = '\0'; strcat(chemin,input); strcat(chemin,"/U.m"); f = fopen(chemin, "rb"); fread(U, sizeof(double), NBn, f); printf("\nU.m : OK"); chemin[0] = '\0'; strcat(chemin,input); strcat(chemin,"/V.m"); f = fopen(chemin, "rb"); fread(V, sizeof(double), NBn, f); printf("\nV.m : OK"); chemin[0] = '\0'; strcat(chemin,input); strcat(chemin,"/W.m"); f = fopen(chemin, "rb"); fread(W, sizeof(double), NBm, f); printf("\nW.m : OK\n"); printf("\nFin du chargement, Calcul de la solution...\n"); } void afficher(){ int i; printf("\nX = \n");
56/90
k = i-NBn; for(j=0;j<NBn;j++){ if(j>k){ tmp += A2[k*NBnk*(k+1)/2+j]*v[j+NBn]; }else{ tmp += A2[j*NBnj*(j+1)/2+k]*v[j+NBn]; } } //B2 p for(j=k*NBm,l=2*NBn;l<2*NBn+NBm;j++,l++){ tmp += B2[j]*v[l]; } }else { k = i - 2*NBn; //B1(t) p for(j=0;j<NBn;j++){ tmp += B1[j*NBm+k]*v[j]; } //B2(t) p for(j=0;j<NBn;j++){ tmp += B2[j*NBm+k]*v[j+NBn]; } //A3 p for(j=0;j<NBm;j++){ if(j>k){ tmp += A3[k*NBmk*(k+1)/2+j]*v[j+2*NBn]; }else{ tmp += A3[j*NBm-
57/90
#include #include #include #include #include #include <stdio.h> <stdlib.h> <time.h> <math.h> <assert.h> <string.h>
#include <omp.h> int NBn; int NBm; double* A1; double* A2; double* A3; double* B1; double* B2; double* U; double* V; double* W; double* X; double* Y; double* Z; void remplir(char* input); void afficher(); void diff_V(double* R, double* V1, double* V2, int n);
58/90
void prod_Bv(double* Bv, double* B, double* v); void prod_tBv(double* tBv, double* B, double* v); void prod_A_V(double* P, double* A, double* T, int n, double* scalaire1, double* scalaire2); void prod_Av(double* Av, double* A, double* v,int n); void gc (double *A, double *x, double *b,int n ); int main(int argc, char **argv) { NBn = atoi(argv[2]); NBm = atoi(argv[3]); constint tailleNBn = NBn * sizeof(double); constint tailleNBm = NBm * sizeof(double); double t1, t2, t; int k,l,i; X = (double*) malloc(tailleNBn); Y = (double*) malloc(tailleNBn); Z = (double*) malloc(tailleNBm); // P1 = B1 * Zk et P2 = B2 * Zk double* P1 = (double*) malloc(tailleNBn); double* P2 = (double*) malloc(tailleNBn); printf("Dossier input : %s\nTaille n : %d\nTaille m : %d",argv[1],NBn,NBm); remplir(argv[1]); double* Q = (double*) malloc(tailleNBm);
C = (double*) malloc(tailleNBn); D = (double*) malloc(tailleNBn); V1 = (double*) malloc(tailleNBm); V2 = (double*) malloc(tailleNBm); V3 = (double*) malloc(tailleNBm);
//Calcul de Q = W - trans(B)*inv(A1)*U trans(B2)*inv(A2)*V printf("\nCalcul de Q..."); t1 = omp_get_wtime(); gc(A1,D,U,NBn); gc(A2,C,V,NBn); prod_tBv(V1,B1,D); prod_tBv(V2,B2,C); printf("\nQ..."); for(l=0;l<NBm;l++){ Q[l] = W[l] - V1[l] - V2[l]; } // Calcul de Z printf("\nCalcul de Z..."); double* r = (double*) malloc(tailleNBm); double* p = (double*) malloc(tailleNBm); double* Sp = (double*) malloc(tailleNBm); double alpha, lambda, normeRk, normeRk1, norme2;
59/90
r[l] -= lambda*Sp[l]; normeRk1 += r[l]*r[l]; } alpha = normeRk1/normeRk; normeRk = normeRk1; for(l=0;l<NBm;l++) p[l] = r[l] + alpha*p[l]; } // Solution : X et Y printf("\nCalcul de X et Y..."); prod_Bv(P1,B1,Z); prod_Bv(P2,B2,Z); diff_V(P1,U,P1,NBn); gc(A1,X,P1,NBn); diff_V(P2,V,P2,NBn); gc(A2,Y,P2,NBn); t2 = omp_get_wtime(); t = t2-t1; printf("\nTemps CPU = %f\n",t);
60/90
strcat(chemin,input); strcat(chemin,"/A1.m"); f = fopen(chemin, "rb"); fread(A1, sizeof(double), NBn*(NBn+1)/2, f); printf("\nA1.m : OK"); chemin[0] = '\0'; strcat(chemin,input); strcat(chemin,"/A2.m"); f = fopen(chemin, "rb"); fread(A2, sizeof(double), NBn*(NBn+1)/2, f); printf("\nA2.m : OK"); chemin[0] = '\0'; strcat(chemin,input); strcat(chemin,"/A3.m"); f = fopen(chemin, "rb"); fread(A3, sizeof(double), NBm*(NBm+1)/2, f); printf("\nA3.m : OK"); chemin[0] = '\0'; strcat(chemin,input); strcat(chemin,"/B1.m"); f = fopen(chemin, "rb"); fread(B1, sizeof(double), NBn*NBm, f); printf("\nB1.m : OK"); chemin[0] = '\0'; strcat(chemin,input); strcat(chemin,"/B2.m"); f = fopen(chemin, "rb"); fread(B2, sizeof(double), NBn*NBm, f); printf("\nB2.m : OK");
61/90
printf("\nZ = "); for(i=0;i<NBm;i++) printf("%f ",Z[i]); printf("\n"); } void diff_V(double* R, double* V1, double* V2, int n){ int i; for(i=0;i<n;i++) R[i] = V1[i] - V2[i]; } void prod_Bv(double* Bv, double* B, double* v){ int i,j,k,l,c; double tmp; for (i=0; i<NBn; i++) { tmp = 0; for(j=i*NBm,k=0;k<NBm;j++,k++){ tmp += B[j]*v[k]; } Bv[i] = tmp; } } void prod_tBv(double* tBv, double* B, double* v){ int i,j,k,l,c; double tmp; for(i=0;i<NBm;i++) tBv[i] = B[i]*v[0];
62/90
} } if(scalaire1!=NULL&& scalaire2==NULL){ for (i=0; i<n; i++) { s1 += T[i]*T[i]; } *scalaire1 = s1; } if(scalaire1==NULL&& scalaire2!=NULL){ for (i=0; i<n; i++) { s2 += P[i]*T[i]; } *scalaire2 = s2; } if(scalaire1!=NULL&& scalaire2!=NULL){ for (i=0; i<n; i++) { s1 += T[i]*T[i]; s2 += P[i]*T[i]; } *scalaire1 = s1; *scalaire2 = s2; } } void prod_Av(double* Av, double* A, double* v,int n){ int i,j; for (i=0; i<n; i++) { Av[i] = 0;
void prod_A_V(double* P, double* A, double* T, int n, double* scalaire1, double* scalaire2){ int i,j,l,c; int tA = n*(n+1)/2; double s1 = 0; double s2 = 0; l=c=0; for(i=0;i<n;i++) P[i] = 0; for(i=0;i<tA;i++){ if(l==c){ P[c] += A[i]*T[c]; }else{ P[l] += A[i]*T[c]; P[c] += A[i]*T[l]; } if(l==n-1){ c++; l=c; }else{ l++;
63/90
for(j=0;j<n;j++){ if(j>i){ Av[i] += A[i*n-i*(i+1)/2+j]*v[j]; }else{ Av[i] += A[j*n-j*(j+1)/2+i]*v[j]; } } } } void gc { double* double* double* double* (double *A, double *x, double *b,int n )
lambda = normeRk/norme2; normeRk1=0; for(l=0;l<n;l++){ x[l] += lambda*p[l]; r[l] -= lambda*Ap[l]; normeRk1 += r[l]*r[l]; } alpha = normeRk1/normeRk; normeRk = normeRk1; for(l=0;l<n;l++) p[l] = r[l] + alpha*p[l]; } }
r = (double*) malloc(n * sizeof(double)); p = (double*) malloc(n * sizeof(double)); Ap = (double*) malloc(n * sizeof(double)); Ax = (double*) malloc(n * sizeof(double));
double alpha, lambda, normeRk, normeRk1, norme2; int i,l; normeRk = 0; for(i=0;i<n;i++){ x[i] = 0; p[i] = r[i] = b[i]; normeRk += r[i]*r[i]; } if(normeRk==0) return; for (i=0;i<n; i++) { prod_A_V(Ap,A,p,n,NULL,&norme2);
64/90
#include #include #include #include #include #include <stdio.h> <stdlib.h> <time.h> <math.h> <assert.h> <string.h>
void prod_B_V(double* P, double* B, double* T, const trans mode); void prod_Bv(double* Bv, double* B, double* v); void prod_tBv(double* tBv, double* B, double* v); void prod_A_V(double* P, double* A, double* T, int n, double* scalaire1, double* scalaire2); void prod_Av(double* Av, double* A, double* v,int n); void gc (double *A, double *x, double *b,int n ); int main(int argc, char **argv) { //omp_set_num_threads(2); omp_set_nested(1); NBn = atoi(argv[2]); NBm = atoi(argv[3]); constint tailleNBn = NBn * sizeof(double); constint tailleNBm = NBm * sizeof(double); double t1, t2, t; int k,l,i; X = (double*) malloc(tailleNBn); Y = (double*) malloc(tailleNBn); Z = (double*) malloc(tailleNBm); // P1 = B1 * Zk et P2 = B2 * Zk double* P1 = (double*) malloc(tailleNBn); double* P2 = (double*) malloc(tailleNBn); printf("Dossier input : %s\nTaille n : %d\nTaille m : %d",argv[1],NBn,NBm);
#include <omp.h> int NBn; int NBm; double* A1; double* A2; double* A3; double* B1; double* B2; double* U; double* V; double* W; double* X; double* Y; double* Z; void remplir(char* input); void afficher(); void diff_V(double* R, double* V1, double* V2, int n);
65/90
#pragma omp parallel for schedule(dynamic) for(l=0;l<NBm;l++){ Q[l] = W[l] - V1[l] - V2[l]; } // Calcul de Z printf("\nCalcul de Z..."); double* r = (double*) malloc(tailleNBm); double* p = (double*) malloc(tailleNBm); double* Sp = (double*) malloc(tailleNBm); double alpha, lambda, normeRk, normeRk1, norme2; normeRk = 0;
//Calcul de Q = W - trans(B)*inv(A1)*U trans(B2)*inv(A2)*V printf("\nCalcul de Q..."); t1 = omp_get_wtime(); #pragma omp sections { #pragma omp section gc(A1,D,U,NBn); #pragma omp section gc(A2,C,V,NBn); } #pragma omp sections { #pragma omp section prod_tBv(V1,B1,D); #pragma omp section prod_tBv(V2,B2,C); } printf("\nQ...");
#pragma omp parallel for private(l) reduction(+:normeRk) for(i=0;i<NBm;i++){ Z[i] = 0; p[i] = r[i] = Q[i]; normeRk += r[i]*r[i]; } for (i=0;i<NBm; i++) { #pragma omp parallel sections { #pragma omp section prod_Bv(P1,B1,p); #pragma omp section prod_Bv(P2,B2,p); } #pragma omp parallel sections
66/90
normeRk1 += r[l]*r[l]; } alpha = normeRk1/normeRk; normeRk = normeRk1; #pragma omp parallel for private(l) for(l=0;l<NBm;l++) p[l] = r[l] + alpha*p[l]; } // Solution : X et Y printf("\nCalcul de X et Y..."); #pragma omp parallel sections { #pragma omp section prod_Bv(P1,B1,Z); #pragma omp section prod_Bv(P2,B2,Z); } #pragma omp parallel sections { #pragma omp section { diff_V(P1,U,P1,NBn); gc(A1,X,P1,NBn); } #pragma omp section { diff_V(P2,V,P2,NBn); gc(A2,Y,P2,NBn);
67/90
B2 = (double*) malloc(sizeof(double) * (NBn*NBm)); U = (double*) malloc(sizeof(double) * NBn); V = (double*) malloc(sizeof(double) * NBn); W = (double*) malloc(sizeof(double) * NBm); FILE* f; char chemin[80]; chemin[0] = '\0'; strcat(chemin,input); strcat(chemin,"/A1.m"); f = fopen(chemin, "rb"); fread(A1, sizeof(double), NBn*(NBn+1)/2, f); printf("\nA1.m : OK"); chemin[0] = '\0'; strcat(chemin,input); strcat(chemin,"/A2.m"); f = fopen(chemin, "rb"); fread(A2, sizeof(double), NBn*(NBn+1)/2, f); printf("\nA2.m : OK"); chemin[0] = '\0'; strcat(chemin,input); strcat(chemin,"/A3.m"); f = fopen(chemin, "rb"); fread(A3, sizeof(double), NBm*(NBm+1)/2, f); printf("\nA3.m : OK"); chemin[0] = '\0'; strcat(chemin,input);
68/90
solution...\n"); } void afficher(){ int i,j; double v; printf("\nX = "); for(i=0;i<NBn;i++) printf("%f ",X[i]); printf("\nY = "); for(i=0;i<NBn;i++) printf("%f ",Y[i]); printf("\nZ = "); for(i=0;i<NBm;i++) printf("%f ",Z[i]); printf("\n"); } void diff_V(double* R, double* V1, double* V2, int n){ int i; for(i=0;i<n;i++) R[i] = V1[i] - V2[i]; } void prod_Bv(double* Bv, double* B, double* v){ int i,j,k,l,c; double tmp; #pragma omp parallel for private(i,j,k,tmp) schedule(dynamic) for (i=0; i<NBn; i++) { tmp = 0;
69/90
l=c=0; for(i=0;i<n;i++) P[i] = 0; for(i=0;i<tA;i++){ if(l==c){ P[c] += A[i]*T[c]; }else{ P[l] += A[i]*T[c]; P[c] += A[i]*T[l]; } if(l==n-1){ c++; l=c; }else{ l++; } } if(scalaire1!=NULL&& scalaire2==NULL){ for (i=0; i<n; i++) { s1 += T[i]*T[i]; } *scalaire1 = s1; } if(scalaire1==NULL&& scalaire2!=NULL){ for (i=0; i<n; i++) { s2 += P[i]*T[i]; } *scalaire2 = s2; } if(scalaire1!=NULL&& scalaire2!=NULL){ for (i=0; i<n; i++) {
void prod_tBv(double* tBv, double* B, double* v){ int i,j,k,l,c; double tmp; for(i=0;i<NBm;i++) tBv[i] = B[i]*v[0]; #pragma omp parallel for private(l,c) schedule(static) for(i=NBm+1;i<NBm*NBn;i++){ l = i%NBm; c = i/NBm; tBv[l] += B[i]*v[c]; } } void prod_A_V(double* P, double* A, double* T, int n, double* scalaire1, double* scalaire2){ int i,j,l,c; int tA = n*(n+1)/2; double s1 = 0; double s2 = 0;
70/90
double* Ax = (double*) malloc(n * sizeof(double)); double alpha, lambda, normeRk, normeRk1, norme2; int i,l; normeRk = 0; for(i=0;i<n;i++){ x[i] = 0; p[i] = r[i] = b[i]; normeRk += r[i]*r[i]; } if(normeRk==0) return;
void prod_Av(double* Av, double* A, double* v,int n){ int i,j; #pragma omp parallel for private(i,j) schedule(dynamic) for (i=0; i<n; i++) { Av[i] = 0; for(j=0;j<n;j++){ if(j>i){ Av[i] += A[i*n-i*(i+1)/2+j]*v[j]; }else{ Av[i] += A[j*n-j*(j+1)/2+i]*v[j]; } } } } void gc { double* double* double* (double *A, double *x, double *b,int n ) r = (double*) malloc(n * sizeof(double)); p = (double*) malloc(n * sizeof(double)); Ap = (double*) malloc(n * sizeof(double));
for (i=0;i<n; i++) { prod_A_V(Ap,A,p,n,NULL,&norme2); lambda = normeRk/norme2; normeRk1=0; for(l=0;l<n;l++){ x[l] += lambda*p[l]; r[l] -= lambda*Ap[l]; normeRk1 += r[l]*r[l]; } alpha = normeRk1/normeRk; normeRk = normeRk1; for(l=0;l<n;l++) p[l] = r[l] + alpha*p[l];
71/90
#include #include #include #include #include #include <stdio.h> <stdlib.h> <time.h> <math.h> <assert.h> <string.h>
#include <omp.h> #define EPS 1e-1 int NBn; int NBm; double* A1; double* A2; double* A3; double* B1; double* B2; double* U; double* V; double* W; double* X; double* Y; double* Z; void remplir(char* input); void afficher();
72/90
void diff_V(double* R, double* V1, double* V2, int n); void prod_Bv(double* Bv, double* B, double* v); void prod_tBv(double* tBv, double* B, double* v); void prod_A_V(double* P, double* A, double* T, int n, double* scalaire1, double* scalaire2); void prod_Av(double* Av, double* A, double* v,int n); void gpo (double *A, double *R, double *T,int n ); int main(int argc, char **argv) { NBn = atoi(argv[2]); NBm = atoi(argv[3]); constint tailleNBn = NBn * sizeof(double); constint tailleNBm = NBm * sizeof(double); int k,l,i; X = (double*) malloc(tailleNBn); Y = (double*) malloc(tailleNBn); Z = (double*) malloc(tailleNBm); // P1 = B1 * Zk et P2 = B2 * Zk double* P1 = (double*) malloc(tailleNBn); double* P2 = (double*) malloc(tailleNBn); double* Pk = (double*) malloc(tailleNBm); double* SPk = (double*) malloc(tailleNBm); printf("(gpo2) Dossier input : %s\nTaille n : %d\nTaille m : %d",argv[1],NBn,NBm); remplir(argv[1]);
double t1, t2, t; double alpha, norme1, norme2; double* Q = (double*) malloc(tailleNBm); double* double* double* double* double* C = (double*) malloc(tailleNBn); D = (double*) malloc(tailleNBn); V1 = (double*) malloc(tailleNBm); V2 = (double*) malloc(tailleNBm); V3 = (double*) malloc(tailleNBm);
//Calcul de Q = W - trans(B)*inv(A1)*U trans(B2)*inv(A2)*V printf("\nCalcul de Q..."); t1 = omp_get_wtime(); gpo(A1,D,U,NBn); gpo(A2,C,V,NBn); prod_tBv(V1,B1,D); prod_tBv(V2,B2,C); printf("\nQ..."); for(l=0;l<NBm;l++){ Q[l] = W[l] - V1[l] - V2[l]; } // Calcul de Z printf("\nCalcul de Z..."); for (l=0; l<NBm; l++) { Z[l] = 0.5; }
73/90
norme2 += SPk[l]*Pk[l]; } alpha = norme1/norme2; for(l=0;l<NBm;l++) Z[l] += alpha*Pk[l]; } // Solution : X et Y printf("\nCalcul de X et Y..."); prod_Bv(P1,B1,Z); prod_Bv(P2,B2,Z); diff_V(P1,U,P1,NBn); diff_V(P2,V,P2,NBn); gpo(A1,X,P1,NBn); gpo(A2,Y,P2,NBn); t2 = omp_get_wtime(); t = t2-t1; printf("\nTemps CPU = %f\n",t); FILE* res; prod_Av(V1,A3,Pk,NBm); norme1 =0; norme2 =0; for(l=0;l<NBm;l++){ SPk[l] = V1[l] - V2[l] - V3[l]; norme1 += Pk[l]*Pk[l]; res = fopen("resultats-gpo_seq.txt","a"); fprintf(res,"seq %s : %f\n",argv[1],t); fclose(res); afficher();
for(l=0;l<NBm;l++) Pk[l] = Q[l] - V3[l] + V2[l] + V1[l]; prod_Bv(P1,B1,Pk); prod_Bv(P2,B2,Pk); gpo(A1,D,P1,NBn); gpo(A2,C,P2,NBn); prod_tBv(V2,B1,D); prod_tBv(V3,B2,C);
74/90
chemin[0] = '\0'; strcat(chemin,input); strcat(chemin,"/A2.m"); f = fopen(chemin, "rb"); fread(A2, sizeof(double), NBn*(NBn+1)/2, f); printf("\nA2.m : OK"); chemin[0] = '\0'; strcat(chemin,input); strcat(chemin,"/A3.m"); f = fopen(chemin, "rb"); fread(A3, sizeof(double), NBm*(NBm+1)/2, f); printf("\nA3.m : OK"); chemin[0] = '\0'; strcat(chemin,input); strcat(chemin,"/B1.m"); f = fopen(chemin, "rb"); fread(B1, sizeof(double), NBn*NBm, f); printf("\nB1.m : OK"); chemin[0] = '\0'; strcat(chemin,input); strcat(chemin,"/B2.m"); f = fopen(chemin, "rb"); fread(B2, sizeof(double), NBn*NBm, f); printf("\nB2.m : OK"); chemin[0] = '\0'; strcat(chemin,input); strcat(chemin,"/U.m"); f = fopen(chemin, "rb"); fread(U, sizeof(double), NBn, f);
75/90
} void diff_V(double* R, double* V1, double* V2, int n){ int i; for(i=0;i<n;i++) R[i] = V1[i] - V2[i]; } void prod_Bv(double* Bv, double* B, double* v){ int i,j,k,l,c; double tmp; for (i=0; i<NBn; i++) { tmp = 0; for(j=i*NBm,k=0;k<NBm;j++,k++){ tmp += B[j]*v[k]; } Bv[i] = tmp; } } void prod_tBv(double* tBv, double* B, double* v){ int i,j,k,l,c; double tmp; for(i=0;i<NBm;i++) tBv[i] = B[i]*v[0]; for(i=NBm+1;i<NBm*NBn;i++){ l = i%NBm; c = i/NBm; tBv[l] += B[i]*v[c]; }
76/90
if(l==c){ void prod_Av(double* Av, double* A, double* v,int n){ int i,j; for (i=0; i<n; i++) { Av[i] = 0; for(j=0;j<n;j++){ if(j>i){ Av[i] += A[i*n-i*(i+1)/2+j]*v[j]; }else{ Av[i] += A[j*n-j*(j+1)/2+i]*v[j]; } } } } void prod_A_V(double* P, double* A, double* T, int n, double* scalaire1, double* scalaire2){ int i,j,l,c; int tA = n*(n+1)/2; double s1 = 0; double s2 = 0; l=c=0; for(i=0;i<n;i++) P[i] = 0; for(i=0;i<tA;i++){ P[c] += A[i]*T[c]; }else{ P[l] += A[i]*T[c]; P[c] += A[i]*T[l]; } if(l==n-1){ c++; l=c; }else{ l++; } } if(scalaire1!=NULL&& scalaire2==NULL){ for (i=0; i<n; i++) { s1 += T[i]*T[i]; } *scalaire1 = s1; } if(scalaire1==NULL&& scalaire2!=NULL){ for (i=0; i<n; i++) { s2 += P[i]*T[i]; } *scalaire2 = s2; } if(scalaire1!=NULL&& scalaire2!=NULL){ for (i=0; i<n; i++) { s1 += T[i]*T[i]; s2 += P[i]*T[i]; } *scalaire1 = s1;
77/90
void gpo (double *A, double *x, double *b,int n ) { double* double* double* double* r = (double*) malloc(n * sizeof(double)); p = (double*) malloc(n * sizeof(double)); Ap = (double*) malloc(n * sizeof(double)); Ax = (double*) malloc(n * sizeof(double));
normeRk1=0; for(l=0;l<n;l++){ r[l] = b[l] - Ax[l]; normeRk1 += r[l]*r[l]; } alpha = normeRk1/normeRk; normeRk = normeRk1; for(l=0;l<n;l++) p[l] = r[l] + alpha*p[l]; }
double alpha, lambda, normeRk, normeRk1, norme2; int i,l; normeRk = 0; for(i=0;i<n;i++){ x[i] = 0; p[i] = r[i] = b[i]; normeRk += r[i]*r[i]; } if(normeRk==0) return; for (i=1;i<=n; i++) { prod_A_V(Ap,A,p,n,NULL,&norme2); lambda = normeRk/norme2; normeRk1=0;
78/90
#include #include #include #include #include #include <stdio.h> <stdlib.h> <time.h> <math.h> <assert.h> <string.h>
void diff_V(double* R, double* V1, double* V2, int n); void prod_Bv(double* Bv, double* B, double* v); void prod_tBv(double* tBv, double* B, double* v); void prod_A_V(double* P, double* A, double* T, int n, double* scalaire1, double* scalaire2); void prod_Av(double* Av, double* A, double* v,int n); void gpo (double *A, double *R, double *T,int n ); int main(int argc, char **argv) { //omp_set_num_threads(4); omp_set_nested(1); NBn = atoi(argv[2]); NBm = atoi(argv[3]); constint tailleNBn = NBn * sizeof(double); constint tailleNBm = NBm * sizeof(double); int k,l,i; X = (double*) malloc(tailleNBn); Y = (double*) malloc(tailleNBn); Z = (double*) malloc(tailleNBm); // P1 = B1 * Zk et P2 = B2 * Zk double* P1 = (double*) malloc(tailleNBn); double* P2 = (double*) malloc(tailleNBn); double* Pk = (double*) malloc(tailleNBm); double* SPk = (double*) malloc(tailleNBm); printf("(gpo2) Dossier input : %s\nTaille n : %d\nTaille m : %d",argv[1],NBn,NBm);
#include <omp.h> #define EPS 1e-1 int NBn; int NBm; double* A1; double* A2; double* A3; double* B1; double* B2; double* U; double* V; double* W; double* X; double* Y; double* Z; void remplir(char* input); void afficher();
79/90
} printf("\nQ..."); #pragma omp parallel for private(l) for(l=0;l<NBm;l++){ Q[l] = W[l] - V1[l] - V2[l]; } // Calcul de Z printf("\nCalcul de Z..."); #pragma omp parallel for private(l) for (l=0; l<NBm; l++) { Z[l] = 0.5; } norme1=1; for (k=0;norme1>=EPS*EPS;k++) { #pragma omp parallel sections { #pragma omp section prod_Bv(P1,B1,Z); #pragma omp section prod_Bv(P2,B2,Z); } #pragma omp parallel sections { #pragma omp section gpo(A1,D,P1,NBn); #pragma omp section gpo(A2,C,P2,NBn); }
//Calcul de Q = W - trans(B)*inv(A1)*U trans(B2)*inv(A2)*V printf("\nCalcul de Q..."); t1 = omp_get_wtime(); #pragma omp sections { #pragma omp section gpo(A1,D,U,NBn); #pragma omp section gpo(A2,C,V,NBn); } #pragma omp sections { #pragma omp section prod_tBv(V1,B1,D); #pragma omp section prod_tBv(V2,B2,C);
80/90
#pragma omp section prod_tBv(V3,B2,C); } prod_Av(V1,A3,Pk,NBm); norme1 =0; norme2 =0; #pragma omp parallel for private(l) reduction(+:norme1,norme2) for(l=0;l<NBm;l++){ SPk[l] = V1[l] - V2[l] - V3[l]; norme1 += Pk[l]*Pk[l]; norme2 += SPk[l]*Pk[l]; } alpha = norme1/norme2; #pragma omp parallel for private(l) for(l=0;l<NBm;l++) Z[l] += alpha*Pk[l]; } // Solution : X et Y printf("\nCalcul de X et Y..."); #pragma omp parallel sections { #pragma omp section prod_Bv(P1,B1,Z); #pragma omp section prod_Bv(P2,B2,Z); } #pragma omp parallel sections
#pragma omp parallel for private(l) for(l=0;l<NBm;l++) Pk[l] = Q[l] - V3[l] + V2[l] + V1[l]; #pragma omp parallel sections { #pragma omp section prod_Bv(P1,B1,Pk); #pragma omp section prod_Bv(P2,B2,Pk); } #pragma omp parallel sections { #pragma omp section gpo(A1,D,P1,NBn); #pragma omp section gpo(A2,C,P2,NBn); } #pragma omp parallel sections { #pragma omp section prod_tBv(V2,B1,D);
81/90
printf("\nChargement des Matrices : A1, A2, A3, B1, B2 et les Vecteurs : U, V et W\n"); A1 = (double*) malloc(sizeof(double) * (NBn*(NBn+1)/2)); A2 = (double*) malloc(sizeof(double) * (NBn*(NBn+1)/2)); A3 = (double*) malloc(sizeof(double) * (NBm*(NBm+1)/2)); B1 = (double*) malloc(sizeof(double) * (NBn*NBm)); B2 = (double*) malloc(sizeof(double) * (NBn*NBm)); U = (double*) malloc(sizeof(double) * NBn); V = (double*) malloc(sizeof(double) * NBn); W = (double*) malloc(sizeof(double) * NBm); FILE* f; char chemin[80]; chemin[0] = '\0'; strcat(chemin,input); strcat(chemin,"/A1.m"); f = fopen(chemin, "rb"); fread(A1, sizeof(double), NBn*(NBn+1)/2, f); printf("\nA1.m : OK"); chemin[0] = '\0'; strcat(chemin,input); strcat(chemin,"/A2.m"); f = fopen(chemin, "rb");
82/90
f = fopen(chemin, "rb"); fread(V, sizeof(double), NBn, f); printf("\nV.m : OK"); chemin[0] = '\0'; strcat(chemin,input); strcat(chemin,"/W.m"); f = fopen(chemin, "rb"); fread(W, sizeof(double), NBm, f); printf("\nW.m : OK\n"); printf("\nFin du chargement, Calcul de la solution...\n"); } void afficher(){ int i,j; double v; printf("\nX = "); for(i=0;i<NBn;i++) printf("%f ",X[i]); printf("\nY = "); for(i=0;i<NBn;i++) printf("%f ",Y[i]); printf("\nZ = "); for(i=0;i<NBm;i++) printf("%f ",Z[i]); printf("\n"); } void diff_V(double* R, double* V1, double* V2, int n){ int i;
83/90
} void prod_Av(double* Av, double* A, double* v,int n){ int i,j; #pragma omp parallel for private(i,j) schedule(dynamic) for (i=0; i<n; i++) { Av[i] = 0; for(j=0;j<n;j++){ if(j>i){ Av[i] += A[i*n-i*(i+1)/2+j]*v[j]; }else{ Av[i] += A[j*n-j*(j+1)/2+i]*v[j]; } } } } void prod_A_V(double* P, double* A, double* T, int n, double* scalaire1, double* scalaire2){ int i,j,l,c; int tA = n*(n+1)/2; double s1 = 0; double s2 = 0; l=c=0; for(i=0;i<n;i++) P[i] = 0;
void prod_tBv(double* tBv, double* B, double* v){ int i,j,k,l,c; double tmp; for(i=0;i<NBm;i++) tBv[i] = B[i]*v[0]; #pragma omp parallel for private(l,c) schedule(static) for(i=NBm+1;i<NBm*NBn;i++){ l = i%NBm; c = i/NBm; tBv[l] += B[i]*v[c]; }
84/90
*scalaire1 = s1; *scalaire2 = s2; } } void gpo (double *A, double *x, double *b,int n ) { double* double* double* double* r = (double*) malloc(n * sizeof(double)); p = (double*) malloc(n * sizeof(double)); Ap = (double*) malloc(n * sizeof(double)); Ax = (double*) malloc(n * sizeof(double));
double alpha, lambda, normeRk, normeRk1, norme2; int i,l; normeRk = 0; for(i=0;i<n;i++){ x[i] = 0; p[i] = r[i] = b[i]; normeRk += r[i]*r[i]; } if(normeRk==0) return; for (i=1;i<=n; i++) { prod_A_V(Ap,A,p,n,NULL,&norme2); lambda = normeRk/norme2; normeRk1=0;
85/90
86/90
87/90
88/90
89/90
90/90
http://goo.gl/qczIs
http://goo.gl/KB9bC
http://goo.gl/QOVmx