Evolution #308
parallélisation d'Herezh
Ajouté par Gérard Rio il y a environ 3 ans. Mis à jour il y a 4 mois.
90%
Description
Objectif: introduire la possibilité d'utiliser plusieurs processeur.
Travail réalisé:
- petite étude biblio:
. dans le cas d'Herezh, une version multi-thread pose des pb d'accès simultané à des mêmes zones mémoires. On peut résoudre (a priori) les pb, mais cela risque d'être complexe et avec un gros risque de conflit.
. L'utilisation de la bibliothèque MPI parait plus adapté: c'est le choix retenu.
. 2 bibliothèques open-source sont a priori dispo: MPICH ou OPENMPI. Pour les ordres courants, les syntaxes sont a priori identiques. Les deux bib sont dispo sur linux et osx donc OK.
@suivre
Fichiers
cube0_temps.cpu (1,53 ko) cube0_temps.cpu | le cpu maître | Gérard Rio, 29/03/2022 09:34 | |
cube1_temps.cpu (1,54 ko) cube1_temps.cpu | Gérard Rio, 29/03/2022 09:34 | ||
cube2_temps.cpu (1,54 ko) cube2_temps.cpu | Gérard Rio, 29/03/2022 09:34 | ||
cube3_temps.cpu (1,54 ko) cube3_temps.cpu | Gérard Rio, 29/03/2022 09:34 | ||
cube_temps.cpu_lapack (1,4 ko) cube_temps.cpu_lapack | cas mono-proc avec résolution // | Gérard Rio, 29/03/2022 09:34 | |
cube_temps.cpu (1,41 ko) cube_temps.cpu | cas sans aucune parallèlisation | Gérard Rio, 29/03/2022 10:17 | |
tube.info (4,27 ko) tube.info | Gérard Rio, 04/09/2023 11:47 | ||
clipboard-202407260941-maasa.png (91,1 ko) clipboard-202407260941-maasa.png | Gérard Rio, 26/07/2024 09:41 |
Mis à jour par Frank Petitjean il y a environ 3 ans
Bonjour Gérard,
Je ne savais pas que tu comptais t'attaquer à ce vaste et complexe chantier de la parallélisation d'Herezh. Je t'en remercie et t'encourage avec ferveur :-) !
Frank, un gros de CPU
Mis à jour par Gérard Rio il y a presque 3 ans
- Statut changé de Nouveau à En cours
- % réalisé changé de 0 à 10
- mise en place des bib open mpi et mpich : a priori pour avoir accès aux wrapper il faut installer les bib à partir des sources officielles: c'est ok pour osX
- test de fonctionnement sur un exe c et c++ de base: en mono processeur ok via xcode, en multiprocesseur (4 sur un portable) : ok en ligne de commande
- mise en place de boost mpi : a priori nécessite une installation à partir des sources (par exemple n'est pas installer par défaut avec macport, mais il semblerait que l'on peut avec homebrew ?) , c'est ok sur osX
- test de fonctionnement sur un exe de base c et c++ en utilisant la syntaxe et les outils boost mpi ok via xcode, en multiprocesseur (4 sur un portable) : ok en ligne de commande (mais ça n'a pas été simple au niveau des PATH et directives de compilation !!) ... mais ça marche !
prochaine étape: intégration dans herezh avec l'opération de lecture pour plusieurs process
à suivre...
Mis à jour par Gérard Rio il y a presque 3 ans
- % réalisé changé de 10 à 20
- compilation d'un test C++ en MPI avec xcode
- debuggage de deux processus test C++ en parallèle avec xcode: et ben... un parcours de combattant mais ça à l'air de fonctionner !!
à suivre
Mis à jour par Gérard Rio il y a presque 3 ans
- debug de deux Herezh en // , ce n'est pas pratique mais c'est ok
- mise en place de deux nouvelles versions d'Herezh:
HZppD_Vn-1_MPI pour le debug en non fast
HZpp_Vn-1_MPI pour l'execution en non fast
les compilations sont différentiées via des variables de pré-compilation
- lecture initiale d'un .info
. pour éviter de passer toute la structure de données entre les différents proc, je fais le choix de lire successivement le .info par chaque processeur. On aura donc n fois le temps de lecture, mais cela permet à chaque processeur de créer la bonne structure de données.
. mise en place et ... a priori c'est ok
Mis à jour par Gérard Rio il y a presque 3 ans
- introduction de la classe Distribution_CPU qui a pour objectif de calculer le partitionnement des maillages en vue de distribuer de manière équilibrée les calculs sur les CPU autres que 0
. mise en place de la sérialisation de cette distribution via le standard de boost : pas facile mais cela à l'air d'être ok, nécessaire pour la transmission inter-CPU
. calcul d'un équilibrage initial et transmission de la distribution à tous les CPU : à vérifier que ça fonctionne
- initialisation différenciée des matrices initiales de raideur globale suivant que c'est le CPU 0 ou non
- à suivre directement : extension aux matrices masses et à la mise à jour de toutes les matrices ...
Mis à jour par Gérard Rio il y a plus de 2 ans
- % réalisé changé de 20 à 30
- introduction d'une sérialisation des types vecteur et matglobale
- fin modif du calcul différencié des raideur et second membre en fonction du cpu
- introduction de plusieurs petites méthodes particulières relatives aux transferts de données
- algo > AlgoriNonDyna: modification des méthodes d'initialisation, d'exécution ...
. mise en place des dialogues entre cpu maître et cpu satellites
- test et mise au point sur le calcul d'un maillage d'un seul hexaèdre en traction pour une élongation de 30%
avec 6 incréments et plusieurs itérations au premier incrément
===> ça fonctionne en // avec 2 proc : c-a-d : un proc qui calcule les matrices élémentaires et l'autre qui est le maître et exécute l'assemblage et la résolution globale.
a priori, on obtient les mêmes résultats qu'avec un seul proc
bon... l'implantation mpi est au final bien intrusive et il reste en perspective pas mal de travail mais... j'ai enfin quelque chose qui commence à fonctionner !!
affaire à suivre !
Mis à jour par Gérard Rio il y a plus de 2 ans
suite des premiers tests et correction de bug
> fonctionne maintenant avec plusieurs éléments et plusieurs cpurésultats (test de traction sur hexaèdres linéaires) avec la version non fast :
avec 64 éléments (calcul sur portable) (résultats avec time)
------------------------------------------------------------
mono cpu
150.651u 0.643s 2:31.57 99.8% 0+0k 0+0io 0pf+0w
2 cpu
342.505u 1.426s 2:52.45 199.4% 0+0k 0+0io 2054pf+0w
4 cpu
458.176u 2.397s 1:55.85 397.5% 0+0k 0+0io 2056pf+0w
On voit que l'on gagne environ 30% par rapport au mono cpu, avec 4 cpu, c-a-d 3 qui calculent les matrices élémentaires et le dernier qui est le maître et fait la résolution. Dans le cas présent de calcul la résolution est mono. Il faut que je fasse également le test avec une résolution globale en //
> a priori on obtient exactement les mêmes résultats au niveau de l'affichage durant le déroulement (convergence et résidu)Il faut maintenant que je regarde plus en détail les différents temps pour analyser les déroulements.
Mis à jour par Frank Petitjean il y a plus de 2 ans
Bravo, c'est encourageant. A voir si ce gain se poursuit avec d'avantage de cpu.
As-tu prévu de pouvoir choisir le nombre de cpu engagés ? Il faudrait pas qu'Herezh prenne toute les ressources machine !
Frank
Mis à jour par Gérard Rio il y a plus de 2 ans
oui, au moment du lancement on choisit le nombre de cpu.
Par exemple pour mon test je lance:
mpirun -n 4 HZpp_Vn-1_MPI -f cube
et à la place de 4 tu mets ce que tu veux. Par contre tu ne peux pas dépasser (en tout cas je ne sais pas comment faire) le nombre physique de cpu que tu as sur ta machine.
Mis à jour par Gérard Rio il y a plus de 2 ans
Mise en place du calcul des temps cpu dédiés aux transferts d'info inter-process, et sortie d'info pour tous les temps cpu par process.
Bilan:
- on retrouve bien les différents temps cohérents entre eux,
- les temps de transfert représentent sur mon cas test :
. 32% pour le cpu maître
. 69% pour les cpu dédiés aux calculs élémentaires
Donc on voit bien où il faut maintenant travailler !
Mis à jour par Gérard Rio il y a plus de 2 ans
compte tenu des temps passés en transfert l'idée a été d'éviter de sérialiser, opération très pratique mais très couteuse car successivement:
- on transforme les données en un gros tableau de caractères (de taille variable)
- on transfère les infos
- on désérialise: tableau de caractère transformé en données
C'est ok pour des transferts complexes occasionnels, mais c'est très couteux pour des transferts fréquents et de tailles variables.
MPI ne propose des transferts natifs efficaces que sur les types simples ou des structures simples de type un gros tableau ou des tranches d'un gros tableau.
Du coup l'idée est d'utiliser directement ces types natifs.
Pour cela:
- on modifie le mode de stockage des vecteurs en introduisant la possibilité d'utiliser des vecteurs = une tranche d'un gros vecteur. Ces vecteurs particuliers ne sont accessibles que pour des classes friend. En fonction d'un indicateur certaines méthodes de Vecteur sont adaptées.
- on modifie le mode de stockage des matrices rectangulaire Mat_pleine, le stockage initial (un tableau de vecteur) est transformé en:
. un gros vecteur
. un tableau de pointeur de vecteurs secondaires, chacun = une ligne de la matrice
- on adapte toutes les méthodes de Mat_pleine qui utilisent directement le stockage interne (beaucoup de méthodes ...)
- on introduit les méthodes de transfert natif de MPI: send, recp, isend et irecp sur le stockage de base des vecteurs et matrices, via les méthodes
void Envoi_MPI(..,void Recup_MPI(.., mpi::request Ienvoi_MPI(.. et mpi::request Irecup_MPI(..
- on garde cependant les méthodes utilisant la sérialisation pour des transferts occasionnels
-> après compil et debug, a priori les résultats obtenus en calcul // avec les nouveaux types de stockage (avec sérialisation) sont identiques aux précédents calculs... ouf !
à suivre: la modification d'Algori::RaidSmEner(... qui gère le calcul // des vecteurs et matrices locales et qui fait l'assemblage, en introduisant l'utilisation des nouvelles méthodes Envoi_MPI, Recup_MPI tout d'abord puis les méthodes non bloquantes Ienvoi_MPI et Irecup_MPI
Mis à jour par Gérard Rio il y a plus de 2 ans
- Fichier cube0_temps.cpu cube0_temps.cpu ajouté
- Fichier cube1_temps.cpu cube1_temps.cpu ajouté
- Fichier cube2_temps.cpu cube2_temps.cpu ajouté
- Fichier cube3_temps.cpu cube3_temps.cpu ajouté
- Fichier cube_temps.cpu_lapack cube_temps.cpu_lapack ajouté
- Fichier cube_temps.cpu cube_temps.cpu ajouté
- % réalisé changé de 30 à 40
- modification de Algori::RaidSmEner( pour prendre en compte les nouveaux types de stockage
- mise au point, tests
On considère un maillage de 8x8x8 hexaèdres quadratiques avec 27 pt d'intégration (4913 noeuds).
Toujours la même sollicitation très simple d'un déplacement imposé sur une facette et un blocage isostatique.
4 processeurs -> 3 qui calculent les matrices locales, 1 qui résout globalement
Les calculs sont effectués en version non-optimisée (donc beaucoup de vérifs qui sont supprimés dans la version rapide)
Temps utilisateurs globaux:
1) tout mono processeur avec la résolution par défaut -> 52:59 : vraiment très très long
2) matrices locales mono-processeur, résolution lapack // -> 7:29 : déjà beaucoup plus rapide
3) tout // (résolution lapack //) -> 3:35 c-a-d 208% plus rapide que 2)
Pour ce calcul, la partie résolution ne prend pas beaucoup de temps comparativement aux calculs locaux.
Globalement avec 3 proc qui travaillent on est 2 fois plus rapide ce qui est pas trop mal à mon avis.
Pour info je mets les fichiers des temps cpu, généré par chacun des proc.
- mono-proc et lapack: partie résolution 30158, matrices locales 354674, > au total : 389899 tout // : cpu 0 résolution 35027 un peu plus longue (?),
0) le cpu 0 attend -> 129806, normal car il ne calcule pas les matrices locales, et avec l'assemblage -> 136824, ce qui semble cohérent et montre que la boucle d'assemblage prend très peu de temps
1) le cpu 1 : matrices locales + transfert: 137758, X3 c'est beaucoup plus long que le cas mono proc ?? je ne sais pas trop pourquoi car le temps de transfert (non bloqué) est faible (7000),
tps__transfert_long_inter_cpu ( 18.57 % ) 35029 : correspond au transfert du vecteur solution (taille 15000 double) du cpu 0 -> les autres cpu : loin d'être négligeable, utilise un transfert natif MPI donc a priori performant, utilise également un broadcast ce qui synchronise (et bloque) tous les cpu... pour l'instant je garde cette option (j'ai aussi essayer avec une boucle de transfert non bloquant... approximativement le même temps! )
et les autres cpu du même type que le 1)
NB:
- les transfert_court sont relatifs aux vecteurs locaux, le transfert long est relatif au vecteur solution
- les calculs des temps cpu sont effectués par Herezh via boost, avec un temps cpu induit sans doute pas totalement négligeable. Dans la version optimisée, peut-être que je supprimerai ces mesures de temps ??
Suite prévue:
- transfert des cpu de calcul vers le cpu 0 des grandeurs: énergies diverses, volumes divers, intégrales, > globalisation dans cpu 0 transfert du cpu 0 vers cpu de calcul des grandeurs globales de manière à pouvoir utiliser des fct nd par exemple
- extension de ce qui a été fait pour l'implicite (Algori::RaidSmEner) au cas explicite (Algori::SecondMembreEnerg)
- regarder ce qui pourrait être envisagé pour l'algorithme de relaxation dynamique: partie vecteurs locaux...
Mis à jour par Gérard Rio il y a plus de 2 ans
Début de la mise en place d'une version simplifiée (uniquement les vecteurs locaux des éléments) MPI en relaxation dynamique, en suivant une méthodologie analogue au cas implicite.
Mis à jour par Gérard Rio il y a environ un an
- % réalisé changé de 40 à 50
V 7.018
- fin mise en place calcul parallèle (MPI) dans algo RD
- idem pour le calcul des second membres (Algori)
- idem pour le chargement pression en explicite
- tests ok pour calcul MPI en RD avec pression
- introduction d'une mesure des 3 temps de transfert long, court, et attente, différenciée:
. pour l'algo général (ex RD)
. pour le calcul des matrices et vecteur locaux
. pour le chargement
. pour le contact (pour l'instant ne mesure rien)
Ces mesures permettent d'y voir plus clair dans les différents temps passés par les CPU.
- au niveau des CPU qui calculent les chargements, intro d'un tableau de conteneurs de passage (dimension = nb CPU, mais c'est arbitraire) ce qui permet aux différents cpu de calculer plusieurs éléments de chargement de manière asynchrone par rapport à l'assemblage global effectué par le CPU 0
Remarque:
Dans les tests que j'ai effectués, j'utilise au maximum 4 CPU dont 1 CPU maître et 3 cpu qui calculent les grandeurs locales.
J'obtiens par rapport à 1 CPU, un gain maximum de 2 et des poussières. Mais le gain n'est pas toujours constant ce qui m'étonne ??? certaine fois le gain n'est que de 1.5 ?
Je remarque que le gain s'améliore à mesure que je fais tourner le même test ? comme si la première fois servait à mettre en place les tuyaux !
Je remarque que le CPU 0 attend beaucoup ...alors que les CPU de calcul travaillent pratiquement en continue de manière équilibrées du coup peut-être qu'avec plus de CPU cela permettrait de charger plus le CPU 0 et donc d'être plus efficace ...
bref le fct en MPI n'est pas vraiment simple !
à suivre !
rappel si besoin: les sources actuelles V 7.018 sont dispo sur le site d'Herezh.git
https://gitcdr.univ-ubs.fr/rio/Herezh_dev/src/branch/V_7.018
en cliquant sur ce2d011450 on peut voir les modifs et ajouts
Mis à jour par Gérard Rio il y a environ un an
les prochaines étapes:
- j’ai mis en place la parallélisation du chargement en explicite pour la pression, reste tous les autres chargements et les cas implicites ! ceci étant, normalement je suivrai le même modèle et en particulier pour le proc 0 la structure doit normalement être ok
- il y a aussi le contact à paralléliser. Normalement je commence à maîtriser certains des schémas de fct en MPI, donc je pars confiant, mais à voir !
- en enfin il faut que je m’occupe de toutes les variables globales
àsuivre...
Mis à jour par Gérard Rio il y a environ un an
test avec un maillage plus grand: 5000 triangle, 3329 itérations,
1)utilisation des versions fast
mono processeur: 284179 ms
4 proc : 126613 ms (donc 1 proc qui résoud le global, et assemble, et 3 proc qui calculent les vecteurs élémentaires)
j'ai l'impression que c'est correct
2) utilisation des versions debug
mono processeur : 746160 ms
4 proc: 408117 ms
pour info je mets le fichier .info et les résultats en cpu pour la version fast
==========================================================================
Herezh++ : (CPU 0) bilan temps cpu pour l'algorithme: dynamique_relaxation_dynam
==========================================================================
version 7.019 (version la plus rapide )
--------------- temps_locaux_cpu_en_milliseconde: ---------
---> tps_total_algo (126613.27 )
tps_InitAlgo ( 3.28 % ) 4147
tps_MiseAJourAlgo ( 0.00 % ) 0
tps_CalEquilibre ( 96.72 % ) 122465
tps_MatSmLoc .( 0.00 % ) 0
tps_SmLoc .( 47.52 % ) 60166
tps_lois_comp ..( 0.00 % ) 0
tps_metrique_KSM ...( 0.00 % ) 0
tps_chargement .( 7.14 % ) 9037
tps_rech_contact .( 0.00 % ) 0
tps_contactMatSmLoc .( 0.00 % ) 0
tps_contactSmLoc .( 0.00 % ) 0
tps_CL .( 0.35 % ) 439
tps_CLL .( 0.00 % ) 0
tps_ResSystLineaire ( 0.03 % ) 32
tps_Sauvegarde ( 0.00 % ) 0
tps_SortieFilCalcul ( 0.00 % ) 0
--------- dialogue inter cpu ---------
tps__transfert_court_Algo ( 0.01 % ) 14
tps__transfert_long_Algo ( 0.06 % ) 74
tps__attente_Algo ( 0.00 % ) 0
tps__transfert_court-Mat-Smloc ( 43.09 % ) 54562
tps__transfert_long-Mat-Smloc ( 4.85 % ) 6144
tps__attente-Mat-Smloc ( 0.00 % ) 2
tps__transfert_court_charge ( 14.84 % ) 18795
tps__transfert_long_charge ( 5.58 % ) 7067
tps__attente_charge ( 0.00 % ) 0
tps__transfert_court_contact ( 0.00 % ) 0
tps__transfert_long_contact ( 0.00 % ) 0
tps__attente_contact ( 0.00 % ) 0
--------------- partie specifique aux lois de comportement ---------
---> tps_total_loi (3848.22 )
tps_loi: ISOELAS2D_C (100.00 % ) 3848
--------------- temps_mise_en_donnees_en_milliseconde: ---------
tps_de la mise en donnees 127
------- temps globaux jour/heure:minute:seconde:centieme ------
temps_user: cpu 0 0/00:02:06.83 system:0/00:00:00.29 reel:0/00:02:07.33
==========================================================================
Herezh++ : (CPU 1) bilan temps cpu pour l'algorithme: dynamique_relaxation_dynam
==========================================================================
version 7.019 (version la plus rapide )
--------------- temps_locaux_cpu_en_milliseconde: ---------
---> tps_total_algo (121348.08 )
tps_InitAlgo ( 3.38 % ) 4100
tps_MiseAJourAlgo ( 0.00 % ) 0
tps_CalEquilibre ( 96.62 % ) 117247
tps_MatSmLoc .( 0.00 % ) 0
tps_SmLoc .( 96.89 % ) 117569
tps_lois_comp ..( 50.15 % ) 60850
tps_metrique_KSM ...( 37.21 % ) 45157
tps_chargement .( 25.42 % ) 30848
tps_rech_contact .( 0.00 % ) 0
tps_contactMatSmLoc .( 0.00 % ) 0
tps_contactSmLoc .( 0.00 % ) 0
tps_CL .( 0.00 % ) 0
tps_CLL .( 0.00 % ) 0
tps_ResSystLineaire ( 0.00 % ) 0
tps_Sauvegarde ( 0.00 % ) 0
tps_SortieFilCalcul ( 0.00 % ) 0
--------- dialogue inter cpu ---------
tps__transfert_court_Algo ( 4.64 % ) 5632
tps__transfert_long_Algo ( 0.07 % ) 90
tps__attente_Algo ( 0.00 % ) 0
tps__transfert_court-Mat-Smloc ( 1.67 % ) 2025
tps__transfert_long-Mat-Smloc ( 1.60 % ) 1938
tps__attente-Mat-Smloc ( 0.58 % ) 705
tps__transfert_court_charge ( 1.97 % ) 2386
tps__transfert_long_charge ( 1.42 % ) 1723
tps__attente_charge ( 1.28 % ) 1556
tps__transfert_court_contact ( 0.00 % ) 0
tps__transfert_long_contact ( 0.00 % ) 0
tps__attente_contact ( 0.00 % ) 0
--------------- partie specifique aux lois de comportement ---------
---> tps_total_loi (60844.99 )
tps_loi: ISOELAS2D_C (100.00 % ) 60844
--------------- temps_mise_en_donnees_en_milliseconde: ---------
tps_de la mise en donnees 123
------- temps globaux jour/heure:minute:seconde:centieme ------
temps_user: cpu 1 0/00:02:06.88 system:0/00:00:00.24 reel:0/00:02:07.33
==========================================================================
Herezh++ : bilan temps cpu pour l'algorithme: dynamique_relaxation_dynam
==========================================================================
version 7.017 (version la plus rapide )
--------------- temps_locaux_cpu_en_milliseconde: ---------
---> tps_total_algo (284179.07 )
tps_InitAlgo ( 1.09 % ) 3095
tps_MiseAJourAlgo ( 0.00 % ) 0
tps_CalEquilibre ( 97.31 % ) 276523
tps_MatSmLoc .( 0.00 % ) 0
tps_SmLoc .( 62.83 % ) 178539
tps_lois_comp ..( 60.02 % ) 170571
tps_metrique_KSM ...( 44.55 % ) 126599
tps_chargement .( 31.13 % ) 88473
tps_rech_contact .( 0.00 % ) 0
tps_contactMatSmLoc .( 0.00 % ) 0
tps_contactSmLoc .( 0.00 % ) 0
tps_CL .( 0.15 % ) 412
tps_CLL .( 0.00 % ) 0
tps_ResSystLineaire ( 0.01 % ) 30
tps_Sauvegarde ( 1.56 % ) 4437
tps_SortieFilCalcul ( 0.04 % ) 122
--------------- partie specifique aux lois de comportement ---------
---> tps_total_loi (174038.01 )
tps_loi: ISOELAS2D_C (100.00 % ) 174038
--------------- temps_mise_en_donnees_en_milliseconde: ---------
tps_de la mise en donnees 94
------- temps globaux jour/heure:minute:seconde:centieme ------
temps_user:0/00:04:39.72 system:0/00:00:01.25 reel:0/00:04:43.72
Mis à jour par Gérard Rio il y a environ un an
- % réalisé changé de 50 à 60
fin implantation de tous les cas de chargement en MPI:
. explicite
. implicite,
suivant la stratégie précédemment testée... ouf !!
Mis à jour par Gérard Rio il y a environ un an
Remarque:
- alors qu'avec de petits maillages, j'obtiens des résultats sur les vitesses de calcul, qui varient de plusieurs dizaines de %, quand j'utilise un maillage assez important les résultats ne varient plus (ex: 126613ms, 126750ms, 126244ms) on a toujours environ un gain de 2.24 sur mon test RD (5000 triangle, 3329 itérations)
ça me rassure !! sur l'intérêt du MPI et sur la précision des indicateurs de mesure que j'ai mis en place !
rappel: les sources mise à jour : V 7.019 sont dispo à :
https://gitcdr.univ-ubs.fr/rio/Herezh_dev/src/branch/V_7.019
Mis à jour par Gérard Rio il y a 11 mois
version 7.020: intégration partielle de la parallélisation MPI pour le contact
(sources avec modifs :
https://gitcdr.univ-ubs.fr/rio/Herezh_dev/commit/b670e8f9b8ebec4638fac9f473bfd48bc88a7d93#diff-17d294911e297ee7382df53b9f62a0955740ee2c
c-a-d v 7.020)
à suivre
Mis à jour par Gérard Rio il y a 9 mois
version 7.024 ==> execution parallele (MPI)
- première version qui fonctionne avec du contact en implicite et pour le cas d'un test bulge axi volumique.
Pour l'instant:
. fonctionne avec 2 à 4 proc,
. donne sensiblement le même résultat qu'en mono processeur, mais pas exactement le même !! : c'est étrange je vais chercher une explication,
NB: par rapport à la version // sans contact, le contact a nécessité la mise en place de nombreux échanges de données entre les proc i et le proc 0. Le fonctionnement actuel est une première validation du fonctionnement de ses échanges de données.
à suivre ...
Mis à jour par Gérard Rio il y a 8 mois
- % réalisé changé de 60 à 70
fin mise en place de la première version MPI en implicite avec contact
- plusieurs modifs et correctifs
test bulge axi volumique:
- augmentation de la finesse du maillage de la pièce: on passe d'un maillage de 20x2 à un maillage de 120x3
- versions // avec 2, 3 et 4 proc donnent exactement les mêmes résultats qu'en mono processeur
- temps de calcul:
mono proc en version fast: 89571.15 ms
4 proc (1 maître et 3 qui calculent ) : 47701.03 ms donc en gros un speed up de 1.9
.... suite prévue avec un algo RD et le test bulge avec membrane et 2 surfaces maîtres de contact
Mis à jour par Gérard Rio il y a 8 mois
- % réalisé changé de 70 à 80
première mise en place de la version MPI avec la relaxation dynamique et du contact.
- ventilation du contact sur les différents proc
- parallélisation du calcul de la matrice masse
- beaucoup de passage d'info inter proc...
- en comparaison avec le mono-processeur:
. on obtient approximativement les mêmes résultats ... mais pas exactement. Peut-être que c'est dû à la ventilation du contact ?
. toujours avec 4 proc (1 maître et 3 qui calculent) on a un speed up de plus de 2 sur le gonflement d'une membrane en bulge axi avec 2 solides en contact
entre autres: vue pendant le test: à faire: dans le cas de non-convergence, il faut gérer les exceptions de manière différente qu'en mono
à suivre
Mis à jour par Gérard Rio il y a 8 mois
- % réalisé changé de 80 à 90
Mise en place des versions linux, validation du fct en // en MPI sur deux machines linux.
Bilan actuel:
. une première version // en MPI fonctionne avec le contact:
-> pour un calcul implicite statique en Newton Raphson
* distribution du calcul des matrices et seconds membres locaux
* // de l’assemblage avec prise en compte des interruptions qui apparaissent au niveau du calcul des matrices et seconds membres locaux
* parallélisation des chargements
* ordonnancement et résolution par le proc 0
* prise en compte du contact: implémentation compliquée due au fait que les contacts apparaissent pendant le calcul (contrairement aux éléments qui sont définis dès le départ)
. distribution de la recherche de contact
. distribution du calcul des matrices et seconds membres issus des contacts
. // de l’assemblage
* test sur le bulge test axi volumique
-> pour un calcul en RD, en + de l’implicite on a
* parallélisation spécifique du calcul des vecteurs locaux
* idem pour le chargement (donc en explicite)
* parallélisation du calcul de la matrice de pseudo masse
* prise en compte du contact
* test sur le bulge test axi: membrane + 2 outils volumiques
Au niveau os:
. implémentation pour osX: ok sur portable et station multicoeurs (4 et 6)
. implémentation sur linux: ok sur portable et station multicoeurs (4 et 6) via virtualbox
. doc d’implémentation en cours
. mise en place d’un environnement de développement ad hoc avec CodeBlocks (compilation, debug, exécutable autonome)
. mise à jour des sources (git)
. ajout dans les sources (répertoire linux) des fichiers de paramétrage pour l’environnement de développement (CodeBlocks + sources directement opérationnelles)
* fichier Herezh.cbp : pour le calcul et l'édition de lien des versions debug et fast
* fichier Herezh_MPI.cbp : version debug MPI (permet de "rattacher" le débugger à chaque processus, il est nécessaire d'intervenir avec le debugger pour démarrer l'exécution, cf. Herezh.cc ) et version debug MPI en fonctionnement autonome (classique)
* Herezhfast_MPI.cbp : seule la cible "release" dans codeblocks est à considérer, et produit la version fast MPI
l'ensemble est dans la version V.028 (rappel: dispo à l'URL https://gitcdr.univ-ubs.fr/rio/Herezh_dev )
Mis à jour par Gérard Rio il y a 7 mois
Mise à jour sur le serveur git V 7.029:
-----------------------------------------
version 7.029: (par rapport à la 7.028)
- modification du calcul des normales sur les facettes et sur les frontières, à l'initialisation et lors des mises à jour
- optimisation sur la l'ajout de grandeurs quelconque aux noeuds:
. les anciennes versions étaient fonctionnelles, mais introduisaient un stockage important. Avec la nouvelle version, on économise 500M0 sur 2 Go !!
Nouveau test avec un grand nombre d'éléments et en RD, sur qq itérations:
resultats mpi/mono sur une mise en données initiale transmise par Frank,
-------------------------------------------------------------------------
. 27090 NOEUDS et 31524 ELEMENTS
. PRECISION 0.95 -> convergence en 22 itérations en RD , on se restreint au au premier pas
histoire que le calcul ne soit pas trop long
. calculs effectués en version fast (mono et MPI)
-> à convergence en monno ->
max puissance exterieure = 53.112847
max puissance interieurs = 184.19868
max des reactions = 1.7057188
max du residu total = 149.22726
E_cinetique = 53360.223
E_ext = -56462.418
E_int = 3151.8073
- E_cinetique/E_statique_ET_Res/Reac_et_Fext --> 0.94505735
-> avec 4 proc:
max puissance exterieure = 53.112847
max puissance interieurs = 184.19868
max des reactions = 1.7057188
max du residu total = 149.22726
E_cinetique = 53360.223
E_ext = -56462.418
E_int = 3151.8073 - E_cinetique/E_statique_ET_Res/Reac_et_Fext --> 0.94505735
donc exactement les mêmes chiffres.
2) temps cpu:
total mono: ---> tps_total_algo (111075.05 )
4 proc: proc 0: ---> tps_total_algo (58252.70 )
donc ici on a un speedup de 1.9068
plus précisémment:
a - calcul de la matrice masse:
. mono: 25154,
. proc 1: 10490, proc 2: 10571, proc 3: 6010
b - calcul des forces généralisées locales (SmLoc):
. mono: 48584
. proc 1: 21265, proc 2: 21590, proc 3: 12759
c - chargement:
. mono: 29886
. proc 1: 12885, proc 2: 12992, proc 3: 7348
(i) donc on a bien une ventilation des calculs sur les proc i,
(ii) ici le proc 0 fait essentiellement de l'ordonnancement contrairement au cas implicite
(iii) on voit que le proc 3 est moins chargé que les 2 autres, cela provient (a priori) du type de partitionnement implanté:
. les éléments de surfaces sont définis au début du fichier ballon.her, et les éléments 1D (POUT BIE1) sont définis en fin de fichier. Du coup les 2 premiers proc travaillent avec des quadrangles et le dernier avec les éléments 1D. On voit ici l'intérêt d'un rééquilibrage en fonction des temps de calcul constatés.
Mis à jour par Gérard Rio il y a 5 mois
Mise en place d'une stratégie pour utiliser des entrées/sorties en MPI_IO:
Intérêts de MPI_IO:
- permet de bonnes performances pour des I/O bufferisés de grandes tailles
- permet des I/O collectifs ou non,
- possibilité d'avoir des offsets différents pour chaque proc avec positionnements positifs ou négatifs
...
Difficultés:
- chaque i/o nécessite de connaître la taille avant transfert des buffers à transférer, du coup il faut pouvoir stocker les tailles de buffer.
Méthode:
- l'idée est d'utiliser le plus possible des buffers intermédiaires avec redirection à certaines étapes des flux i/o C++ dans ces buffers.
- nécessite :
. une gestion individualisée des offsets pour chaque proc (tous interviennent sur le même fichier à des offsets différents, plusieurs offsets par proc pour chaque incrément)
. l'écriture s'effectue en deux étapes: a) toutes les sorties sont bufferisées et stockées, b) puis après calcul et gestion des offsets écriture de tous les buffers (avec sauvegarde des tailles des buffers)
. manip inverse à la lecture
Implémentation au niveau des méthodes Ecriture_base_info et Lecture_base_info au niveau de tous les algos , de ParaGlob et VariablesExporter. Partiellement pour les Maillages (la structure est en place, mais on attend la validation de la méthode pour finaliser).
Le prochain objectif est de tester le fonctionnement I/O sur le .BI au niveau des algos pour valider la méthode.
Mis à jour par Gérard Rio il y a 4 mois
- validation de la stratégie initiale: on récupère bien un début de fichier .BI contenant les infos pour l'algo et paraglob, donc on étend au cas des maillages
- implantation des méthodes entrées/sorties en MPI_IO pour LesMaillages et Maillage:
. utilisation d'un offset spécifique pour chaque élément ce qui permet
- en écriture pour chaque proc i de sauvegardé les éléments le concernant, parallèlement avec les autres proc
- en lecture d'utiliser un nombre de proc quelconque ,indépendamment du nombre de proc utilisés en écriture.
- validation de l'écriture des maillages dans le .BI
. on compare le fichier .BI obtenu en mono processeur et le fichier obtenu avec 2 à 4 processeurs: concernant l'algo et les maillages (noeuds et éléments avec toutes les infos associées: loi de comportement, etc.) pour tous les tests, on obtient les mêmes infos. En MPI, on sauvegarde également les offsets ce qui permet de faire de l'adressage direct en lecture.
- validation du calcul des offsets et de leur lecture.
- la validation de la lecture intégrant les maillages est en cours ...
NB: J'ai l'impression que l'opération d'écriture en MPI est plus rapide que celle initiale, mais c'est à confirmer.
(environ dans le même rapport que le calcul ?)
Mis à jour par Gérard Rio il y a 4 mois
Validation de la lecture en MPI_IO sur un test d'un cube en traction avec 3 et 64 hexa quadratique complet:
- écriture et lecture en restart puis poursuite du calcul OK,
quelque soit le nombre de proc en lecture et écriture avec éventuellement un nombre différent en lecture par rapport à l'écriture
- extension de l'implantation pour les classes principales: LesCourbes1D, LesReferences, LesFonctions_nD
-> validation en cours sur un algo RD
Mis à jour par Gérard Rio il y a 4 mois
- fin de l'extension de l'implantation pour les classes principales : LesLoisDeComp, DiversStockage, Charge, LesCondLim, LesContacts, Resultats,
- validation (écriture restart) sur :
. le test du cube en newton raphson
. un test de gonflement (sans contact) en RD
. le test de gonflement d'une membrane axi en RD avec contact avec 2 solides.
A priori ça à l'air de bien fonctionner ...
Ce qui est prévu pour la suite :
- Actuellement seul un calcul // peut redémarrer avec une sauvegarde effectuée en calcul //. Mais en // on ne peut pas post-traiter les résultats obtenus au pti car seul le cpu 0 est pour l'instant en charge de la sortie des fichiers de post traitement.
L'idée est de pouvoir relire le .BI en mono proc et ainsi de pouvoir post-traiter toutes les infos disponibles dans le .BI
Pour cela il faut qu'un calcul en mono proc soit capable de relire un fichier .BI réalisé par un calcul multi-proc. Or ce dernier comporte plus d'informations que celui obtenu en mono proc (il s'agit des offsets utilisés en MPI I/O pour l'adressage direct, qui n'existent pas en flux séquentiel).
Du coup, la prochaine étape est de modifier la lecture en mono proc pour passer la lecture des offsets.
- il s'agira ensuite de voir si tout fonctionne également en Linux. Pour l'instant tous les développements sont réalisés sur OSX sur un portable. Avant on regardera si c'est tout d'abord ok sur une tour osX avec 6 proc.
à suivre ....
Mis à jour par Gérard Rio il y a 4 mois
- Fichier clipboard-202407260941-maasa.png clipboard-202407260941-maasa.png ajouté
- implantation d'une méthode pour relire avec un mono-proc un .BI issue d'un calcul //. La méthode doit fonctionner également dans le cas classique d'un .BI issue d'un calcul non //
- test d'utilisation d'un mono-proc pour post-traiter les résultats d'un calcul // Il s'agit du test de gonflement d'une membrane axi en RD avec contact avec 2 solides.
Le calcul // sauvegarde 20 incréments sur .BI
En mono proc:
- on fait un restart au 20 ième incrément,
- on fait un petit incrément supplémentaire pour qu'Herezh crée l'ensemble des conteneurs, convergence très rapide,
(TEMPSFIN 0.2 passé à 0.2001)
- on sort les contraintes de Mises sur les 20 incréments pour une visualisation avec gmsh: Herezh relit chaque incrément du .BI
- on vérifie sur gmsh
sur le test le processus fonctionne. On peut enfin post-traiter le calcul //
NB:
. il ne faut pas regarder les valeurs car j'ai mis une précision très grossière (0.05) pour que le calcul soit rapide,
. pour rappel sur mon portable, pour un incrément avec 4 proc (restart à 2 et calcul jusqu'à l'incrément 3) on a un speed up supérieur à 2