--- /dev/null
+#include <iostream>
+#include <list>
+#include <vector>
+#include <string>
+#include <fstream>
+#include <sstream>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <cmath>
+#include "msg/msg.h"
+#include "xbt/sysdep.h"
+#include "xbt/log.h"
+#include "xbt/asserts.h"
+
+using namespace std;
+
+typedef enum {Unique,Unite,AM,Local,Local2} Type_T; // types de politiques de transfert de charge
+
+double ALPHA=0.125; // poids de la dernière mesure d'intervalle d'attente d'équilibrage
+double BETA=0.125; // poids de la dernière mesure d'intervalle d'attente d'envois/réceptions
+int SEUIL_ENVOI=1; // nombre d'intervalles d'attente avant envoi d'infos
+double INTER=0.0; // intervalle de temps pour les tests d'équilibrages
+double SLEEP=0.0; // temps de mise en attente des processus
+double octetsTache=24.0; // en octets (3 doubles)
+double flopsTache=500.0; // en flops (500 opérations)
+int minNBT=1000,maxNBT=10000; // intervalle du nombre de tâches sur chaque proc
+int nbTerms=0; // nombre de procs ayant terminé leurs calculs
+int nbTI=0,nbTT=0; // nombres de tâches initiales et traitées
+double tGDMin=1e100,tGFMax=0; // temps globaux de début et fin
+int numUnique=-1; // numéro du processeur reçevant la charge en cas de charge unique
+vector<int> nbTaches; // tableau des nombres de tâches par proc
+double somVit=0; // somme des vitesses des procs du système
+double maxTC; // temps de calcul max sur répartition initiale
+double tempsOpt; // temps optimal de calcul des tâches sur le système
+int **nbIters=NULL,nbIt; // tableau des nombres d'itérations nécessaires pour la CV (simulée)
+ // et nb total itérations
+int minIt=1,maxIt=1; // bornes de l'intervalle du nombre d'itérations par tâche
+bool mutexTE,mutexTNE,mutexTR; // mutex pour la manipulation des listes de tâches
+vector<int> iterCumulees; // itérations locales cumulées par proc
+unsigned int variante=0; // indique les variantes éventuelles de l'algo d'équilibrage
+int nbArretEnvs=0; // nombre de procs ayant arrêté leur processus d'envois des infos/equs
+int nbArretRecs=0; // nombre de procs ayant arrêté leur processus de réception des infos/equs
+Type_T polit=AM; /* type de politique de transfert de charge :
+ Unique : transfert vers le moins chargé des voisins
+ Unite : transfert d'une unité de charge à chaque voisin moins chargé
+ AM : transfert selon règles données dans thèse AM
+ Local : répartition équilibrée sur voisins ayant moins de charge que
+ la moyenne de la source et des destinataires
+ */
+vector<int> valsAleat; // liste explicite de valeurs aléatoires (cross-plateforme)
+
+typedef enum {BASE=0,LL=1,CU=2,IL=4,IV=8,AB=16} Variante;
+/*
+ BASE = algo initial avec limite stricte de la charge locale restante sur l'émetteur
+ LL = léger dépassement de la limite de charge locale autorisé
+ CU = charge initiale unique sur un proc
+ IL = itérations liées (identiques entre les tâches)
+ IV = itérations réalisées sur tout le vecteur local
+ AB = processus d'apprentissage AdaBoost
+*/
+
+typedef vector<m_task_t> LTaches;
+typedef vector<m_host_t> LHotes;
+typedef struct {
+ double temps;
+ int nbT;
+} Charge;
+typedef struct {
+ Charge charge;
+ bool fini;
+ bool *connectes;
+ LHotes *voisins;
+ Charge *voCharges;
+ int icl;
+ double inter,*sleep;
+} Infos;
+typedef struct {
+ int pid;
+ Charge charge;
+ string nom;
+} Mess;
+typedef struct {
+ int nbT;
+ m_task_t *tab;
+} MessEqu;
+typedef struct {
+ string src;
+ int *dest,*icl;
+ LTaches *taches;
+ LTaches *recup;
+ LHotes *voisins;
+ bool fini;
+ double *sleep;
+} Equ;
+
+XBT_LOG_NEW_DEFAULT_CATEGORY(msg_test,"Messages specific to equil");
+
+int envInfos(int argc, char *argv[]);
+int recInfos(int argc, char *argv[]);
+int envEqu(int argc, char *argv[]);
+int recEqu(int argc, char *argv[]);
+int calculs(int argc, char *argv[]);
+double ordoOpt(m_host_t *listeHotes);
+bool lireListe(char *nom, vector<int> &valsAleat);
+int myRand();
+
+MSG_error_t test_all(const char *platform_file, const char *application_file);
+
+typedef enum {PORT_DON,PORT_EQU,MAX_CHANNEL} channel_t;
+
+// Fonction d'envoi des messages
+int envInfos(int argc, char *argv[])
+{
+ int pid;
+ m_task_t *enve = NULL;
+ m_process_t moi;
+ int i,j;
+ MSG_error_t err;
+ string nomHote;
+ Infos *denv=NULL;
+ stringstream sstr;
+ bool fini=false;
+ Charge chargePrec={-1.0,-1};
+ Mess *mess;
+ int compteur;
+
+ // Récupération de son processus
+ moi=MSG_process_self();
+
+ // Récupération nom machine
+ nomHote=string(MSG_host_get_name(MSG_host_self()));
+
+ // Récupération données
+ denv=(Infos *)MSG_process_get_data(moi);
+ denv->charge.temps=denv->icl*flopsTache/MSG_get_host_speed(MSG_host_self());
+
+ // Création tableau des messages d'envois
+ enve=new m_task_t[denv->voisins->size()];
+
+ // Affichage PID
+ pid=MSG_process_self_PID();
+ sstr.clear();
+ sstr << "Processus d'envoi des infos sur " << nomHote.c_str();
+ INFO1("\t* %s",sstr.str().c_str());
+ mess=new Mess;
+ mess->pid=pid;
+ mess->nom=nomHote;
+ compteur=0;
+
+ while(!fini){
+ if(compteur==SEUIL_ENVOI || chargePrec.temps!=denv->charge.temps || chargePrec.nbT!=denv->charge.nbT){
+ chargePrec=denv->charge;
+ // Envois bloquants des infos de charge
+ sstr.clear();
+ sstr.str("");
+ sstr << "Charge de " << mess->nom << " (" << pid << ")";
+ mess->charge=denv->charge;
+ for(i=0;i<denv->voisins->size();++i){
+ enve[i]=MSG_task_create(sstr.str().c_str(),0.0,(double)sizeof(Mess),(void *)mess);
+ err=MSG_task_put(enve[i],(*(denv->voisins))[i],PORT_DON);
+ if(err!=MSG_OK){
+ INFO2("\t* Pb à l'envoi des infos depuis %s vers %s",nomHote.c_str(),MSG_host_get_name((*(denv->voisins))[i]));
+ /*
+ switch(err){
+ case MSG_FATAL:
+ INFO1("\t* message mal initialisé sur %s",nomHote.c_str());
+ break;
+ case MSG_HOST_FAILURE:
+ INFO1("\t* hôte destination non joignable depuis %s",nomHote.c_str());
+ break;
+ case MSG_TRANSFER_FAILURE:
+ INFO1("\t* Erreur de transmission depuis %s",nomHote.c_str());
+ break;
+ }
+ */
+ MSG_task_destroy(enve[i]);
+ }else{
+ INFO1("\t* Envoi OK des infos depuis %s",nomHote.c_str());
+ }
+ }
+ sstr << " " << chargePrec.temps << " (" << chargePrec.nbT << ")";
+ INFO1("\t* %s",sstr.str().c_str());
+ compteur=0;
+ }else{
+ compteur++;
+ }
+ MSG_process_sleep(*(denv->sleep));
+ fini=denv->fini;
+ }
+ nbArretEnvs++;
+ INFO1("\t* Arrêt processus d'envois des infos sur %s",nomHote.c_str());
+
+ // Libérations mémoire
+ delete mess;
+ delete[] enve;
+}
+
+// Fonction de réception des messages
+int recInfos(int argc, char *argv[])
+{
+ Infos *drec;
+ m_process_t moi;
+ m_task_t recu=NULL;
+ string nomHote;
+ bool fini=false;
+ Mess *mess=NULL;
+ MSG_error_t err;
+ int i,pid;
+ stringstream sstr;
+ double tDeb,tFin;
+
+ // Récupération de son processus
+ moi=MSG_process_self();
+ nomHote=string(MSG_host_get_name(MSG_host_self()));
+
+ // Récupération données
+ drec=(Infos *)MSG_process_get_data(moi);
+
+ // Affichage infos
+ sstr.clear();
+ sstr << "Processus de réception des infos sur " << nomHote.c_str();
+ INFO1("\t\t# %s",sstr.str().c_str());
+
+ // Boucle de réception
+ tDeb=MSG_get_clock();
+ while(!fini){
+ pid=MSG_task_probe_from(PORT_DON);
+ if(pid>=0){
+ err=MSG_task_get(&recu,PORT_DON);
+ if(err!=MSG_OK){
+ INFO1("\t\t# Pb à la réception des infos sur %s",nomHote.c_str());
+ }else{
+ mess=(Mess *)MSG_task_get_data(recu);
+ drec->charge=mess->charge;
+ for(i=0;i<drec->voisins->size() && mess->nom!=MSG_host_get_name((*(drec->voisins))[i]);++i);
+ if(i<drec->voisins->size()){
+ drec->voCharges[i]=mess->charge;
+ drec->connectes[i]=true;
+ }
+ sstr.clear();
+ sstr.str("");
+ sstr << nomHote.c_str() << " a reçu l'info de charge " << drec->charge.temps << " (" << drec->charge.nbT << ") de " << mess->nom;
+ INFO1("\t\t# %s",sstr.str().c_str());
+ MSG_task_destroy(recu);
+ recu=NULL;
+ }
+ }else{
+ MSG_process_sleep(*(drec->sleep));
+ }
+ fini=drec->fini;
+ tFin=MSG_get_clock();
+ if(!fini && fabs(tFin-tDeb)>=drec->inter){
+ // réinitialisation de l'intervalle de temps
+ for(i=0;i<drec->voisins->size();++i){
+ drec->connectes[i]=false;
+ }
+ tDeb=tFin;
+ }
+ }
+ nbArretRecs++;
+ INFO1("\t\t# Arrêt processus de réceptions des infos sur %s",nomHote.c_str());
+}
+
+// Fonction d'envoi des données d'équilibrage
+int envEqu(int argc, char *argv[])
+{
+ string nomHote;
+ Equ *eenv=NULL;
+ bool fini=false;
+ MSG_error_t err=MSG_OK;
+ m_task_t tache=NULL;
+ int i,j;
+ MessEqu *mess=NULL;
+
+ // Récupération nom machine
+ nomHote=string(MSG_host_get_name(MSG_host_self()));
+
+ // Récupération données
+ eenv=(Equ *)MSG_process_get_data(MSG_process_self());
+
+ // Allocation du tableau des messages
+ mess=new MessEqu[(*(eenv->voisins)).size()];
+
+ // Affichage infos
+ INFO1("\t\t\t§ Processus d'envoi des équilibrages sur %s",nomHote.c_str());
+
+ // Boucle des envois
+ while(!fini){
+ for(i=0;i<(eenv->voisins)->size();++i){
+ if(eenv->dest[i]>0){
+ mess[i].nbT=eenv->dest[i];
+ mess[i].tab=new m_task_t[mess[i].nbT];
+ mutexTE=true;
+ for(j=0;j<mess[i].nbT;++j){
+ mess[i].tab[j]=(eenv->taches)->back();
+ *(eenv->icl)-=*((int *)MSG_task_get_data((eenv->taches)->back()));
+ (eenv->taches)->pop_back();
+ }
+ mutexTE=false;
+ tache=MSG_task_create("lot tâches",0.0,mess[i].nbT*octetsTache,(void *)(mess+i));
+ err=MSG_task_put(tache,(*(eenv->voisins))[i],PORT_EQU);
+ if(err!=MSG_OK){
+ INFO2("\t\t\t§ Pb à l'envoi d'équilibrage depuis %s vers %s",nomHote.c_str(),MSG_host_get_name((*(eenv->voisins))[i]));
+ mutexTNE=true;
+ for(j=0;j<mess[i].nbT;++j){
+ (eenv->recup)->push_back(mess[i].tab[j]);
+ *(eenv->icl)+=*((int *)MSG_task_get_data((eenv->recup)->back()));
+ }
+ mutexTNE=false;
+ delete[] mess[i].tab;
+ }else{
+ INFO3("\t\t\t§ Envoi OK de %d tâche(s) depuis %s vers %s",mess[i].nbT,nomHote.c_str(),MSG_host_get_name((*(eenv->voisins))[i]));
+ // (*(eenv->taches)).erase((*(eenv->taches)).end()-mess[i].nbT,(*(eenv->taches)).end());
+ }
+ eenv->dest[i]=0;
+ }
+ }
+ MSG_process_sleep(*(eenv->sleep));
+ fini=eenv->fini;
+ }
+ nbArretEnvs++;
+ INFO1("\t\t\t§ Arrêt processus d'envoi des équilibrages sur %s",nomHote.c_str());
+
+ // Libérations mémoire
+ delete[] mess;
+}
+
+// Fonction de réception des données d'équilibrage
+int recEqu(int argc, char *argv[])
+{
+ string nomHote,lt;
+ Equ *erec=NULL;
+ bool fini=false;
+ MSG_error_t err;
+ m_task_t tache=NULL;
+ m_host_t hsrc;
+ int i,pid;
+ MessEqu *mess;
+
+ // Récupération nom machine
+ nomHote=string(MSG_host_get_name(MSG_host_self()));
+
+ // Récupération données
+ erec=(Equ *)MSG_process_get_data(MSG_process_self());
+
+ // Affichage infos
+ INFO1("\t\t\t\t@ Processus de réception des équilibrages sur %s",nomHote.c_str());
+
+ // Boucle de réception
+ while(!fini){
+ pid=MSG_task_probe_from(PORT_EQU);
+ if(pid>=0){
+ err=MSG_task_get(&tache,PORT_EQU);
+ if(err!=MSG_OK){
+ INFO1("\t\t\t\t@ Pb à la réception d'un équilibrage sur %s",nomHote.c_str());
+ }else{
+ lt.clear();
+ mess=(MessEqu *)MSG_task_get_data(tache);
+ mutexTR=true;
+ lt=string(MSG_task_get_name(mess->tab[0]))+" oo "+string(MSG_task_get_name(mess->tab[mess->nbT-1]));
+ for(i=0;i<mess->nbT;++i){
+ (erec->taches)->push_back(mess->tab[i]);
+ *(erec->icl)+=*((int *)MSG_task_get_data((erec->taches)->back()));
+ // lt+=string(MSG_task_get_name(mess->tab[i]))+" ";
+ }
+ mutexTR=false;
+ delete[] mess->tab;
+ hsrc=MSG_task_get_source(tache);
+ for(i=0;i<erec->voisins->size() && hsrc!=(*(erec->voisins))[i];++i);
+ if(i<erec->voisins->size()){
+ erec->src=MSG_host_get_name((*(erec->voisins))[i]);
+ }
+ INFO3("\t\t\t\t@ %s a reçu %d tâche(s) de %s",nomHote.c_str(),mess->nbT,erec->src.c_str());
+ INFO2("\t\t\t\t@ %s %s",nomHote.c_str(),lt.c_str());
+ tache=NULL;
+ }
+ }
+ MSG_process_sleep(*(erec->sleep));
+ fini=erec->fini;
+ }
+ nbArretRecs++;
+ INFO1("\t\t\t\t@ Arrêt processus de réceptions des équilibrage sur %s",nomHote.c_str());
+}
+
+// Fonction d'équilibrage
+int calculs(int argc, char *argv[]) // Les paramètres sont : 0 = processus, 1,... = voisins
+{
+ m_host_t monHote=NULL,*listeHotes=NULL;
+ m_task_t mess=NULL,tvect=NULL;
+ LTaches listeT,listeTE,listeTR,listeTNE;
+ LHotes voisins;
+ int i,j;
+ MSG_error_t err;
+ int num;
+ string nomHote,nomTache,tmp;
+ stringstream sstr;
+ double tDeb,tFin;
+ m_process_t envi,reci,enve,rece;
+ Infos *denv,*drec;
+ Equ *eenv,*erec;
+ bool fini=false,fam=false,limite;
+ int indLim;
+ int indVM;
+ double diffMax;
+ int dtmp;
+ int nbTachesTraitees=0,nbCon;
+ double tCycD,tCycF,intervalle,*_sleep;
+ double tGlobalDeb, tGlobalFin,tempsCalc;
+ vector<Charge> diffs;
+ vector<int> indTries,tmpDest;
+ int tacheCrte,sommeTE;
+
+ // Récupération du nom de la machine courante
+ monHote = MSG_host_self();
+ nomHote=string(MSG_host_get_name(monHote));
+ // Récupération de la liste des machines
+ listeHotes=MSG_get_host_table();
+ // Récupération de la position de la machine courante dans la liste
+ for(num=0;num<MSG_get_host_number() && nomHote!=MSG_host_get_name(listeHotes[num]);++num);
+ num++;
+ // Récupération des voisins de la machine courante
+ for(i=0;i<MSG_get_host_number();++i){
+ tmp=string(MSG_host_get_name(listeHotes[i]));
+ for(j=1;j<argc && tmp!=argv[j];++j);
+ if(j<argc){
+ voisins.push_back(listeHotes[i]);
+ }
+ }
+ num--; // numérotation des procs à partir de 0
+ diffs.resize(voisins.size());
+
+ // Affichage infos
+ if(monHote==NULL){
+ INFO0("Unknown host... Stopping Now! ");
+ abort();
+ }else{
+ INFO3("Je suis %s et j'ai %d éléments / %d",nomHote.c_str(),nbTaches[num],nbTI);
+ }
+ sstr.str("");
+ for(i=0;i<voisins.size();++i){
+ sstr << MSG_host_get_name(voisins[i]) << " ";
+ }
+ INFO1("Mes voisins sont : %s",sstr.str().c_str());
+
+ // Allocation des infos de charge
+ _sleep=new double;
+ *_sleep=INTER;
+ denv=new Infos;
+ denv->fini=false;
+ denv->charge.temps=0;
+ denv->charge.nbT=nbTaches[num];
+ denv->voisins=&voisins;
+ denv->voCharges=NULL;
+ denv->icl=iterCumulees[num];
+ denv->inter=INTER;
+ denv->sleep=_sleep;
+ drec=new Infos;
+ drec->fini=false;
+ drec->connectes=new bool[voisins.size()];
+ for(i=0;i<voisins.size();++i){
+ drec->connectes[i]=false;
+ }
+ drec->voisins=&voisins;
+ drec->voCharges=new Charge[voisins.size()];
+ for(i=0;i<voisins.size();++i){
+ drec->voCharges[i].temps=1e100;
+ drec->voCharges[i].nbT=1<<30;
+ }
+ drec->inter=INTER;
+ drec->sleep=_sleep;
+
+ // Crée processus d'envois/réceptions des infos
+ envi=MSG_process_create("envInfos",&envInfos,(void *)denv,monHote);
+ reci=MSG_process_create("recInfos",&recInfos,(void *)drec,monHote);
+
+ // Allocation des messages d'équilibrage
+ eenv=new Equ;
+ eenv->src=nomHote;
+ eenv->dest=new int[voisins.size()];
+ for(i=0;i<voisins.size();++i){
+ eenv->dest[i]=0;
+ }
+ eenv->icl=&iterCumulees[num];
+ eenv->taches=&listeTE;
+ eenv->recup=&listeTNE;
+ eenv->voisins=&voisins;
+ eenv->fini=false;
+ eenv->sleep=_sleep;
+ erec=new Equ;
+ erec->icl=&iterCumulees[num];
+ erec->taches=&listeTR;
+ erec->voisins=&voisins;
+ erec->fini=false;
+ erec->sleep=_sleep;
+
+ mutexTE=mutexTNE=mutexTR=false;
+ tmpDest.resize(voisins.size(),0);
+
+ // Crée processus d'envois/réceptions des équilibrages
+ enve=MSG_process_create("envEqu",&envEqu,(void *)eenv,monHote);
+ rece=MSG_process_create("recEqu",&recEqu,(void *)erec,monHote);
+
+ // Création des tâches
+ nbCon=0;
+ for(i=0;i<num;++i){
+ nbCon+=nbTaches[i];
+ }
+ for(i=0;i<nbTaches[num];++i){
+ sstr.clear();
+ sstr.str("");
+ sstr << "T_" << i << "_" << num+1;
+ sstr >> nomTache;
+ listeT.push_back(MSG_task_create(nomTache.c_str(),flopsTache,octetsTache,(void *) nbIters[nbCon+i]));
+ }
+
+ // Exécution des itérations
+ tGlobalDeb=tCycD=MSG_get_clock();
+ tacheCrte=0;
+ while(!fini){
+
+ // Récupération des tâches non correctement envoyées précédemment
+ while(!mutexTNE && listeTNE.size()>0){
+ listeT.push_back(listeTNE.back());
+ listeTNE.pop_back();
+ }
+
+ // Récupération des tâches reçues d'un équilibrage
+ while(!mutexTR && listeTR.size()>0){
+ listeT.push_back(listeTR.back());
+ listeTR.pop_back();
+ }
+
+ // Calculs des tâches
+ if(listeT.size()>0){
+ // Mise à jour de l'état de terminaison globale si nécessaire
+ if(fam){
+ fam=false;
+ nbTerms--;
+ INFO1("%s reprends des calculs...",nomHote.c_str());
+ }
+
+ // Calcul seulement si tâche courante valide
+ if(tacheCrte>=listeT.size()){
+ tacheCrte=0;
+ }
+
+ // Affichage
+ if(!(variante & IV)){
+ INFO2("Nb tâches : %d\tTâche courante : %d",listeT.size(),tacheCrte);
+#if 0
+ nomTache.clear();
+ for(i=0;i<listeT.size();++i){
+ nomTache+=string(MSG_task_get_name(listeT[i]))+" ";
+ }
+ INFO2("!! %s %s",nomHote.c_str(),nomTache.c_str());
+#endif
+ INFO3("Exécution tâche %s (%d) sur proc %s",MSG_task_get_name(listeT[tacheCrte]),(*((int *) MSG_task_get_data(listeT[tacheCrte]))),nomHote.c_str());
+ }else{
+ INFO2("Exécution des %d tâches locales sur proc %s",listeT.size(),nomHote.c_str());
+ /*
+ nomTache.clear();
+ for(i=0;i<listeT.size();++i){
+ nomTache+=string(MSG_task_get_name(listeT[i]))+" (";
+ sstr.clear();
+ sstr.str("");
+ sstr << *((int *) MSG_task_get_data(listeT[i]));
+ nomTache+=sstr.str()+") ";
+ }
+ INFO2("!! %s %s",nomHote.c_str(),nomTache.c_str());
+ */
+ }
+
+ // Calculs
+ tDeb=MSG_get_clock();
+ if(variante & IV){
+ // Exécution des tâches du vecteur
+ tvect=MSG_task_create("Itération vecteur",flopsTache*listeT.size(),octetsTache*listeT.size(),NULL);
+ if(MSG_task_execute(tvect)!=MSG_OK){
+ INFO0("Pb d'exécution de l'itération sur le vecteur");
+ }
+ MSG_task_destroy(tvect);
+ tvect=NULL;
+
+ tFin=MSG_get_clock();
+ nbTachesTraitees+=listeT.size();
+ // Calcul charge restante et envoi
+ iterCumulees[num]-=listeT.size(); // Suppression des itérations que l'on vient de faire
+ denv->charge.temps=(tFin-tDeb)*iterCumulees[num];
+
+ // Décompte et suppression éventuelle de la tâche effectuée
+ for(tacheCrte=0;tacheCrte<listeT.size();){
+ (*((int *) MSG_task_get_data(listeT[tacheCrte])))--;
+ if(*((int *) MSG_task_get_data(listeT[tacheCrte]))==0){
+ delete ((int *) MSG_task_get_data(listeT[tacheCrte]));
+ MSG_task_destroy(listeT[tacheCrte]); // Vérifier si la destruction désalloue les data !!!
+ listeT.erase(listeT.begin()+tacheCrte);
+ INFO1("CONVERGENCE DE TACHE %d",tacheCrte);
+ }else{
+ tacheCrte++;
+ }
+ }
+
+ // Mise à jour nombre de tâches locales
+ denv->charge.nbT=listeT.size();
+
+ }else{
+
+ // Exécution tâche courante
+ if(MSG_task_execute(listeT[tacheCrte])!=MSG_OK){
+ INFO1("Pb d'exécution de la tâche %d",tacheCrte);
+ }
+ tFin=MSG_get_clock();
+ nbTachesTraitees++;
+
+ // Décompte et suppression éventuelle de la tâche effectuée
+ (*((int *) MSG_task_get_data(listeT[tacheCrte])))--;
+ if(*((int *) MSG_task_get_data(listeT[tacheCrte]))==0){
+ delete ((int *) MSG_task_get_data(listeT[tacheCrte]));
+ MSG_task_destroy(listeT[tacheCrte]); // Vérifier si la destruction désalloue les data !!!
+ listeT.erase(listeT.begin()+tacheCrte);
+ INFO1("CONVERGENCE DE TACHE %d",tacheCrte);
+ }else{
+ tacheCrte++;
+ }
+
+ // Calcul charge restante et envoi
+ iterCumulees[num]--; // Suppression de l'itération que l'on vient de faire
+ denv->charge.temps=(tFin-tDeb)*iterCumulees[num];
+ denv->charge.nbT=listeT.size();
+ }
+
+ }else{
+ if(listeTNE.size()==0 && listeTR.size()==0){
+ if(!fam){
+ fam=true;
+ nbTerms++;
+ }
+ if(nbTerms<MSG_get_host_number()){
+ INFO2("%s en attente de calculs... (%f)",nomHote.c_str(),*_sleep);
+ MSG_process_sleep(*_sleep);
+ }
+ }
+ }
+
+ // Décision équilibrage à intervalle régulier (temps discret)
+ tCycF=MSG_get_clock();
+ intervalle=fabs(tCycF-tCycD);
+ INFO4("-----------\t\t%f %f -> %f / %f",tCycD,tCycF,intervalle,drec->inter);
+ if(intervalle>=drec->inter){
+
+ // Affichage charges
+ sstr.clear();
+ sstr.str("");
+ nbCon=0;
+ sstr << nomHote << " : " << denv->charge.temps << " (" << denv->charge.nbT << ")\t";
+ for(i=0;i<voisins.size();++i){
+ sstr << drec->voCharges[i].temps << " (" << drec->voCharges[i].nbT << ") [";
+ if(drec->connectes[i]){ sstr << "X"; nbCon++; }else sstr << " ";
+ sstr << "] ";
+ }
+ INFO1("%s",sstr.str().c_str());
+
+ // Décision
+ if(listeT.size()>1){ // règles d'équilibrage
+ double somme=denv->charge.temps;
+ int nbTermes=1;
+
+ // Construction du tableau décroissant des diffs de charges
+ for(i=0;i<voisins.size();++i){
+ if(drec->connectes[i]
+ && eenv->dest[i]==0 // envoi de charge en cours pour le voisin i
+ && (!(variante & LL) || denv->charge.nbT>drec->voCharges[i].nbT)
+ && (denv->charge.temps-drec->voCharges[i].temps)*MSG_get_host_speed(monHote)>flopsTache){
+ diffs[i].temps=denv->charge.temps-drec->voCharges[i].temps;
+ diffs[i].nbT=denv->charge.nbT-drec->voCharges[i].nbT;
+ if(indTries.size()==0){
+ indTries.push_back(i);
+ }else{
+ for(j=0;j<indTries.size() && diffs[i].temps<diffs[indTries[j]].temps;++j);
+ indTries.insert(indTries.begin()+j,i);
+ }
+ somme+=drec->voCharges[i].temps;
+ nbTermes++;
+ }else{
+ diffs[i].temps=0;
+ diffs[i].nbT=0;
+ }
+ }
+ if(nbTermes>0 && polit==Local){
+ somme/=nbTermes;
+
+ // difficile de voir l'intérêt de la boucle sur topologies à degré <=2 !
+ bool fin=false;
+ do{
+ int nbTs=1;
+ double moyC=denv->charge.temps;
+ for(i=0;i<indTries.size() && drec->voCharges[indTries[i]].temps<somme;++i){
+ moyC+=drec->voCharges[indTries[i]].temps;
+ nbTs++;
+ }
+ if(i<indTries.size()){
+ indTries.resize(i);
+ }else{
+ fin=true;
+ }
+ nbTermes=nbTs;
+ somme=moyC/nbTermes;
+ }while(!fin);
+
+ }
+
+ INFO2("Temps = %lf\tTermes = %d",somme,nbTermes);
+
+ for(i=0;i<indTries.size();++i){
+ INFO5("Diff %s : %lf %d %e %e",MSG_host_get_name(voisins[indTries[i]]),diffs[indTries[i]].temps,diffs[indTries[i]].nbT,denv->charge.temps,drec->voCharges[indTries[i]].temps);
+ }
+
+ // Initialisation de la répartition des envois de charges
+ dtmp=0;
+ limite=false;
+ indLim=indTries.size();
+ sommeTE=0;
+
+ // Boucle de calcul de la répartition
+ for(i=0;i<indTries.size() && !limite;++i){
+ switch(polit){
+ case Unique:
+ dtmp+=(tmpDest[indTries[i]]=(int)rint(diffs[indTries[i]].nbT/2.0));
+ break;
+ case Unite:
+ dtmp+=(tmpDest[indTries[i]]=1);
+ break;
+ case AM:
+ dtmp+=(tmpDest[indTries[i]]=(int)rint(diffs[indTries[i]].nbT/(voisins.size()+1.0)));
+ break;
+ case Local:
+ if(drec->voCharges[indTries[i]].temps>0){
+ dtmp+=(tmpDest[indTries[i]]=(int)rint(drec->voCharges[indTries[i]].nbT*(somme-drec->voCharges[indTries[i]].temps)/drec->voCharges[indTries[i]].temps));//(int)rint(diffs[indTries[i]].nbT/2.0));//(voisins.size()+1.0)));
+ }else{
+ // On n'a pas l'info de temps restant sur le proc destination alors
+ // on n'a aucune idée de sa vitesse et donc du nombre de tâches à envoyer...
+ // Le plus raisonnable est de considérer la même vitesse que le proc source
+ dtmp+=(tmpDest[indTries[i]]=(int)rint(denv->charge.nbT*(somme-drec->voCharges[indTries[i]].temps)/denv->charge.temps));
+ }
+ break;
+ }
+ // Calcul de la somme des tâches à envoyer
+ if((polit==Unique && i>=1) ||
+ ((polit==Unite || polit==AM)
+ && denv->charge.nbT<dtmp+drec->voCharges[indTries[i]].nbT+tmpDest[indTries[i]]) ||
+ (polit==Local && drec->voCharges[indTries[i]].temps>=somme)
+ ){
+ limite=true;
+ indLim=i;
+ if(variante & LL){
+ indLim++;
+ sommeTE+=tmpDest[indTries[i]];
+ }
+ }else{
+ sommeTE+=tmpDest[indTries[i]];
+ }
+ }
+
+ INFO1("Somme TE = %d",sommeTE);
+
+ // Isolation des tâches à envoyer
+ if(sommeTE<listeT.size()){
+ for(i=0;i<sommeTE;++i){
+ listeTE.push_back(listeT.back());
+ listeT.pop_back();
+ }
+
+ // Activation de la répartition
+ for(i=0;i<indLim;++i){
+ eenv->dest[indTries[i]]=tmpDest[indTries[i]];
+ INFO2("EQU %s : %d",MSG_host_get_name(voisins[indTries[i]]),eenv->dest[indTries[i]]);
+ }
+ }
+ indTries.clear();
+ }
+ tCycD=tCycF;
+ }
+
+ // MAJ intervalle de temps de équilibrages
+ drec->inter=(1.0-ALPHA)*drec->inter+ALPHA*intervalle;
+ *_sleep=drec->inter;
+
+ // MAJ état de terminaison
+ fini=(listeT.size()==0 && listeTNE.size()==0 && listeTR.size()==0 && nbTerms==MSG_get_host_number());
+ }
+ tGlobalFin=MSG_get_clock();
+
+ // Calcul des temps min et max
+ if(tGlobalDeb<tGDMin){
+ tGDMin=tGlobalDeb;
+ }
+ if(tGlobalFin>tGFMax){
+ tGFMax=tGlobalFin;
+ }
+
+ // Affichage fin
+ INFO3("Fin calculs sur proc %s : %d (%d)",nomHote.c_str(),nbTachesTraitees,nbTaches[num]);
+ // INFO5("Fin calculs sur proc %s : %d %d %d %d",nomHote.c_str(),listeT.size(),listeTE.size(),listeTNE.size(),listeTR.size());
+ nbTT+=nbTachesTraitees;
+
+ // Indication terminaison des processus d'envois
+ denv->fini=true;
+ eenv->fini=true;
+ // Attente d'arrêt des comms d'équilibrage en cours
+ while(nbArretEnvs<2*MSG_get_host_number()){
+ // INFO1("Attente barrière envois sur %s",nomHote.c_str());
+ MSG_process_sleep(*_sleep);
+ }
+ // Indication terminaison des processus de réceptions
+ drec->fini=true;
+ erec->fini=true;
+ // Attente d'arrêt des comms d'infos en cours
+ while(nbArretRecs<2*MSG_get_host_number()){
+ // INFO1("Attente barrière réceptions sur %s",nomHote.c_str());
+ MSG_process_sleep(*_sleep);
+ }
+
+ // Calcul et affichage de la durée du calcul, de la distance à l'optimal et du gain
+ tempsCalc=tGFMax-tGDMin;
+ // tempsOpt=ceil((double)nbTT/MSG_get_host_number())*flopsTache*MSG_get_host_number()/somVit;
+ INFO3("Itérations effectuées : %d \tTotal itérations : %d \tSurcoût G : %.2f%%",nbTT,nbIt,100*(1.0-(maxTC-tempsCalc)/(maxTC-tempsOpt)));
+ INFO3("Temps de calcul : %f\tTemps optimal : %f\tSurcoût T : %.2f%%",tempsCalc,tempsOpt,100*(tempsCalc-tempsOpt)/tempsOpt);
+ INFO3("Temps initial : %f\tGain optimal : %.2f%% \tGain réel : %.2f%%",maxTC,100*(maxTC-tempsOpt)/maxTC,100*(maxTC-tempsCalc)/maxTC);
+
+ // Désallocation mémoire
+ delete _sleep;
+ listeT.clear();
+ voisins.clear();
+ diffs.clear();
+ indTries.clear();
+ iterCumulees.clear();
+ delete denv;
+ delete[] drec->connectes;
+ delete[] drec->voCharges;
+ delete drec;
+ delete[] eenv->dest;
+ delete eenv;
+ delete erec;
+
+ return 0;
+}/* end_of_receiver */
+
+
+/** Test function */
+MSG_error_t test_all(const char *platform_file,const char *application_file)
+{
+ MSG_error_t res = MSG_OK;
+ m_host_t *listeHotes=NULL;
+ double maxVit=0,minVit=1e100; // vitesses min et max des procs du système
+ double tempsCalc;
+ int i,j,k;
+
+ /* Simulation setting */
+ MSG_set_channel_number(MAX_CHANNEL);
+ // MSG_paje_output("equil.trace");
+ MSG_create_environment(platform_file);
+
+ // Allocation du tableau des tâches
+ nbTaches.resize(MSG_get_host_number());
+ // Calcul du nombre initial de tâches locales et comptage du nombre total
+ if(variante & CU){
+ if(numUnique<0){
+ // numUnique=(myRand()%MSG_get_host_number());
+ numUnique = 0; // On prend vraiment le pire cas
+ }
+ for(i=0;i<MSG_get_host_number();++i){
+ nbTaches[i]=0;
+ }
+ nbTaches[numUnique]=(myRand()%(maxNBT-minNBT+1))+minNBT;
+ nbTI+=nbTaches[numUnique];
+ }else{
+ int nbTG = (myRand()%(maxNBT-minNBT+1))+minNBT;
+ int nbTpP = nbTG / MSG_get_host_number(); // Répartition homogène des
+ // tâches sur les procs
+ int surplus = nbTG % MSG_get_host_number();
+ for(i=0 ; i<surplus ; ++i){
+ nbTaches[i] = nbTpP + 1;
+ nbTI += nbTaches[i];
+ }
+ for( ; i<MSG_get_host_number() ; ++i){
+ nbTaches[i] = nbTpP;
+ nbTI += nbTaches[i];
+ }
+ }
+
+ // Allocation et initialisation du tableau des itérations
+ nbIters=new int*[nbTI];
+ nbIt=0;
+ if(variante & AB){
+ /*
+ Répartition pour simuler u processus AdaBoost :
+ maxIt représente le nombre de classifieurs faibles utilisés
+ toutes les tâches prennent maxIt itérations sauf maxIt-1 qui
+ prennent respectivement de 1 à maxIt-1 itérations
+ */
+ for(i=0;i<nbTI;++i){
+ nbIters[i]=new int;
+ *(nbIters[i])=maxIt;
+ }
+ for(i=1;i<maxIt;++i){
+ int indit=myRand()%nbTI;
+ *(nbIters[indit])=i;
+ }
+ for(i=0;i<nbTI;++i){
+ nbIt+=*(nbIters[i]);
+ }
+ }else{
+ nbIters[0]=new int;
+ *(nbIters[0])=(myRand()%(maxIt-minIt+1))+minIt;
+ nbIt+=*(nbIters[0]);
+ for(i=1;i<nbTI;++i){
+ nbIters[i]=new int;
+ if(variante & IL){
+ *(nbIters[i])=*(nbIters[i-1]);
+ }else{
+ *(nbIters[i])=(myRand()%(maxIt-minIt+1))+minIt;
+ }
+ nbIt+=*(nbIters[i]);
+ }
+ }
+
+ // Allocation et calcul des itérations cumulées initiales par proc
+ iterCumulees.resize(MSG_get_host_number(),0);
+ k=0;
+ for(i=0;i<iterCumulees.size();++i){
+ for(j=0;j<nbTaches[i];++j){
+ iterCumulees[i]+=*(nbIters[k++]);
+ }
+ }
+
+ // Récupération vitesses des machines et temps max de calcul et réglages des tempos
+ listeHotes=MSG_get_host_table();
+ somVit=0;
+ for(i=0;i<MSG_get_host_number();++i){
+ somVit+=MSG_get_host_speed(listeHotes[i]);
+ if(MSG_get_host_speed(listeHotes[i])>maxVit){
+ maxVit=MSG_get_host_speed(listeHotes[i]);
+ }else
+ if(MSG_get_host_speed(listeHotes[i])<minVit){
+ minVit=MSG_get_host_speed(listeHotes[i]);
+ }
+ tempsCalc=iterCumulees[i]*flopsTache/MSG_get_host_speed(listeHotes[i]);
+ if(tempsCalc>maxTC){
+ maxTC=tempsCalc;
+ }
+ }
+ if(SLEEP==0.0){
+ SLEEP=flopsTache/(2*maxVit);
+ }
+ if(INTER==0.0){
+ INTER=0.99*flopsTache*MSG_get_host_number()/somVit; // Réglage délicat car influe sur la vitesse de simu !!!
+ }
+
+ // Calcul du temps optimal
+ tempsOpt=ordoOpt(listeHotes);
+
+ // Affichage des infos générales
+ INFO0("PARAMÈTRES GÉNÉRAUX");
+ INFO0("-------------------");
+ INFO1(" taille données : %f",octetsTache);
+ INFO1(" taille tâches : %f",flopsTache);
+ INFO1(" total itérations : %d",nbIt);
+ INFO1(" temps attentes : %lf",SLEEP);
+ INFO1("intervalle décision : %lf",INTER);
+ INFO1(" coef attente : %f",ALPHA);
+ INFO1(" limite stricte : %s",(variante & LL)?"inactive":"active");
+ INFO1(" charge unique : %s",(variante & CU)?"active":"inactive");
+ INFO1(" itérations liées : %s",(variante & IL)?"active":"inactive");
+ INFO1(" itération vecteur : %s",(variante & IV)?"active":"inactive");
+
+ /* Application deployment */
+ MSG_function_register("Calculs", calculs);
+ MSG_launch_application(application_file);
+
+ res = MSG_main();
+
+ nbTaches.clear();
+ delete[] nbIters;
+ return res;
+} /* end_of_test_all */
+
+
+/** Main function */
+int main(int argc, char *argv[])
+{
+ MSG_error_t res = MSG_OK;
+ int i,flags=0,graine;
+ char *nomPF,*nomDP;
+ MSG_global_init(&argc,argv);
+
+ graine=time(NULL);
+ for(i=0;i<argc;++i){
+ if(argv[i][0]=='-'){
+ switch(argv[i][1]){
+ case 'A':
+ variante |= AB;
+ break;
+ case 'a':
+ i++;
+ ALPHA=atof(argv[i]);
+ break;
+ case 'b':
+ i++;
+ BETA=atof(argv[i]);
+ break;
+ case 'c':
+ i++;
+ flopsTache=atof(argv[i]);
+ break;
+ case 'd':
+ i++;
+ nomDP=argv[i];
+ flags+=2;
+ break;
+ case 'f':
+ i++;
+ INTER=atof(argv[i]);
+ break;
+ case 'g':
+ i++;
+ graine=atoi(argv[i]);
+ break;
+ case 'G':
+ i++;
+ if(!lireListe(argv[i], valsAleat)){
+ CRITICAL1 ("Pb while reading random list: %s\n",argv[i]);
+ }
+ case 'i':
+ i++;
+ minIt=atoi(argv[i]);
+ break;
+ case 'I':
+ i++;
+ maxIt=atoi(argv[i]);
+ break;
+ case 'l':
+ variante|=IL;
+ break;
+ case 'L':
+ variante|=LL;
+ break;
+ case 'o':
+ i++;
+ octetsTache=atof(argv[i]);
+ break;
+ case 'p':
+ i++;
+ nomPF=argv[i];
+ flags+=1;
+ break;
+ case 's':
+ i++;
+ SLEEP=atof(argv[i]);
+ break;
+ case 't':
+ i++;
+ minNBT=atoi(argv[i]);
+ break;
+ case 'T':
+ i++;
+ maxNBT=atoi(argv[i]);
+ break;
+ case 'V':
+ variante|=IV;
+ break;
+ case 'u':
+ variante|=CU;
+ if(argc>i+1 && argv[i+1][0]!='-'){
+ i++;
+ numUnique=atoi(argv[i]);
+ }
+ break;
+ case 'z':
+ i++;
+ switch(argv[i][0]){
+ case 'U':
+ polit=Unique;
+ break;
+ case '1':
+ polit=Unite;
+ break;
+ case 'A':
+ polit=AM;
+ break;
+ case 'L':
+ polit=Local;
+ break;
+ case 'l':
+ polit=Local2;
+ break;
+ }
+ break;
+ }
+ }
+ }
+
+ if(flags!=3){
+ CRITICAL1 ("Usage : %s -p fichier_plateforme -d fichier_deploiement < options >\n",argv[0]);
+ CRITICAL0 (" -A : application AdaBoost");
+ CRITICAL0 (" -a réel : poids de la dernière mesure d'intervalle d'attente d'équilibrage");
+ CRITICAL0 (" -b réel : poids de la dernière mesure d'intervalle d'attente d'envois/réceptions");
+ CRITICAL0 (" -c entier : quantité de calculs par tâche (en flops)");
+ CRITICAL0 (" -f réel : intervalle de temps pour les tests d'équilibrages (en ms)");
+ CRITICAL0 (" -g entier : initialisation du générateur aléatoire");
+ CRITICAL0 (" -i entier : nombre minimal d'itérations par tâche");
+ CRITICAL0 (" -I entier : nombre maximal d'itérations par tâche");
+ CRITICAL0 (" -l : itérations liées (identiques entre les tâches)");
+ CRITICAL0 (" -L : léger dépassement autorisé de la limite de charge locale");
+ CRITICAL0 (" -o entier : taille des données relatives à une tâche (en octets)");
+ CRITICAL0 (" -s réel : temps de mise en attente des processus (en ms)");
+ CRITICAL0 (" -t entier : nombre minimal de tâches");
+ CRITICAL0 (" -T entier : nombre maximal de tâches");
+ CRITICAL0 (" -V : itérations réalisées sur tout le vecteur local");
+ CRITICAL0 (" -u : charge initiale uniquement sur un processeur");
+ CRITICAL0 (" -z [U 1 A L l] : politique de transfert de charge d'un noeud :");
+ CRITICAL0 (" U : transfert vers le moins chargé des voisins");
+ CRITICAL0 (" 1 : transfert d'une unité de charge à chaque voisin moins chargé");
+ CRITICAL0 (" A : transfert selon règles données dans thèse AM");
+ CRITICAL0 (" L : répartition équilibrée sur voisins ayant moins de charge");
+ CRITICAL0 (" que la moyenne de la source et des destinataires");
+ CRITICAL0 (" l : ?");
+ CRITICAL0 ("");
+ CRITICAL1 ("Exemple:\n\t%s -p platform_equil.xml -d deployment_ligne.xml -g 4 -t 1000 -T 100000 -i 250 -I 1000 -f 0.005 -a 0.5 -u -l -L -V\n",argv[0]);
+ exit(1);
+ }
+
+ srand(graine);
+ res = test_all(nomPF,nomDP);
+ INFO1("Total simulation time: %le", MSG_get_clock());
+ MSG_clean();
+
+ if(res==MSG_OK) return 0;
+ else return 1;
+} /* end_of_main */
+
+double ordoOpt(m_host_t *listeHotes)
+{
+ int i,j,nb=MSG_get_host_number();
+ vector<double> ordo;
+ int ind;
+ double min,tmp,ret=0;
+
+ ordo.resize(nb,0);
+
+ for(j=0;j<nbIt;++j){
+ min=ordo[0]+flopsTache/MSG_get_host_speed(listeHotes[0]);
+ ind=0;
+ for(i=1;i<nb;++i){
+ tmp=ordo[i]+flopsTache/MSG_get_host_speed(listeHotes[i]);
+ if(tmp<min){
+ min=tmp;
+ ind=i;
+ }
+ }
+ ordo[ind]=min;
+ if(ordo[ind]>ret){
+ ret=ordo[ind];
+ }
+ }
+
+ /*
+ for(i=0;i<nb;++i){
+ INFO3("Proc %d : %d %f",i+1,(int)rint(ordo[i]*MSG_get_host_speed(listeHotes[i])/flopsTache),ordo[i]);
+ }
+ */
+ ordo.clear();
+ return ret;
+}
+
+bool lireListe(char *nom, vector<int> &valsAleat)
+{
+ ifstream fic;
+ int i, nb;
+ bool ret = true;
+
+ fic.open(nom);
+ if(fic.good()){
+ fic >> nb;
+ valsAleat.resize(nb);
+ for(i=0; i<nb; ++i){
+ fic >> valsAleat[i];
+ }
+ fic.close();
+ }else{
+ ret = false;
+ }
+ return ret;
+}
+
+int myRand()
+{
+ static int indice = 0;
+
+ if(valsAleat.size() > 0){
+ int val = valsAleat[indice];
+ indice = (indice + 1) % valsAleat.size();
+ return val;
+ }else{
+ return rand();
+ }
+}
--- /dev/null
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <string>
+#include <vector>
+#include <cstdlib>
+#include <ctime>
+#include <unistd.h>
+
+using namespace std;
+
+void aide(char *prog);
+void genereLiensLigne(ofstream &fic, int nbNoeuds, int minB, int maxB, double minL, double maxL, bool liensDyns, double minP, double maxP, double intervalle);
+void genereLiensAnneau(ofstream &fic, int nbNoeuds, int minB, int maxB, double minL, double maxL, bool liensDyns, double minP, double maxP, double intervalle);
+void genereLiensComplet(ofstream &fic, int nbNoeuds, int minB, int maxB, double minL, double maxL, bool liensDyns, double minP, double maxP, double intervalle);
+void genereRoutesLigne(ofstream &fic, int nbNoeuds, bool lienUnique);
+void genereRoutesAnneau(ofstream &fic, int nbNoeuds, bool lienUnique);
+void genereRoutesComplet(ofstream &fic, int nbNoeuds, bool lienUnique);
+void genereDeploiementLigne(string &nom, int nbNoeuds);
+void genereDeploiementAnneau(string &nom, int nbNoeuds);
+void genereDeploiementComplet(string &nom, int nbNoeuds);
+
+int main(int argc, char **argv)
+{
+ int opt;
+ int nbNoeuds=10; // Taille du cluster
+ char topo='L'; // Ligne, Anneau ou Complet
+ int minV=98095000, maxV=98095000; // Vitesses min et max des procs
+ int minB=100000000, maxB=100000000; // Bandes passantes min et max
+ double minL=0.0001, maxL=0.0001; // Latences min et max
+ bool liensDyns=false; // Indique si les liens sont intermittants ou pas
+ double minP=0.001,maxP=1.0; // Intervalles de période pour les intermittences des liens
+ double intervalle=10.0; // Taille de l'intervalle de temps pour les traces dynamiques des liens
+ long graine=1; // Initialisation générateur aléatoire
+ ofstream ficP; // Fichiers Plateforme et Déploiement
+ string nomFicP,nomFicD; // Noms des fichiers
+ bool lienUnique=false; // Indique si tous les liens sont identiques
+
+ while ((opt = getopt(argc, argv, "a:b:B:dD:f:F:g:i:l:L:n:P:t:v:V:")) != -1) {
+ switch (opt) {
+ case 'a':
+ graine=time(NULL);
+ break;
+ case 'b':
+ minB=atoi(optarg);
+ break;
+ case 'B':
+ maxB=atoi(optarg);
+ break;
+ case 'd':
+ liensDyns=true;
+ break;
+ case 'D':
+ nomFicD=string(optarg);
+ break;
+ case 'f':
+ minP=atof(optarg);
+ break;
+ case 'F':
+ maxP=atof(optarg);
+ break;
+ case 'g':
+ graine=atoi(optarg);
+ break;
+ case 'i':
+ intervalle=atof(optarg);
+ break;
+ case 'l':
+ minL=atof(optarg);
+ break;
+ case 'L':
+ maxL=atof(optarg);
+ break;
+ case 'n':
+ nbNoeuds=atoi(optarg);
+ break;
+ case 'P':
+ nomFicP=string(optarg);
+ break;
+ case 't':
+ topo=*optarg;
+ break;
+ case 'v':
+ minV=atoi(optarg);
+ break;
+ case 'V':
+ maxV=atoi(optarg);
+ break;
+ default:
+ aide(argv[0]);
+ return 1;
+ }
+ }
+
+ // Vérification de la spécification du nom de fichier
+ if(nomFicP.size()==0 || nomFicD.size()==0){
+ aide(argv[0]);
+ return 1;
+ }else{
+ cout << "Paramètres de génération de la plateforme :" << endl;
+ cout << "-----------------------------------------" << endl;
+ cout << "\tGraine : " << graine << endl;
+ cout << endl;
+ cout << "\tNb noeuds : " << nbNoeuds << endl;
+ cout << "\tTopologie : " << ((topo=='L')?"Ligne":((topo=='A')?"Anneau":"Complet")) << endl;
+ cout << "\tVitesse min : " << minV << endl;
+ cout << "\tVitesse max : " << maxV << endl;
+ cout << "\tDébit min : " << minB << endl;
+ cout << "\tDébit max : " << maxB << endl;
+ cout << "\tLatence min : " << minL << endl;
+ cout << "\tLatence max : " << maxL << endl;
+ cout << "\tLiens dyns : " << ((liensDyns)?"oui":"non") << endl;
+ if(liensDyns){
+ cout << "\t\tPériode min : " << minP << endl;
+ cout << "\t\tPériode max : " << maxP << endl;
+ cout << "\t\tIntervalle : " << intervalle << endl;
+ }
+ cout << endl;
+ cout << "\tPlateforme : " << nomFicP << endl;
+ cout << "\tDéploiement : " << nomFicD << endl;
+ cout << "-----------------------------------------" << endl;
+ }
+
+ // Init générateur aléat
+ srand(graine);
+
+ // Génération du fichier de plateforme
+ ficP.open(nomFicP.c_str());
+ if(ficP.good()){
+ // En-tête
+ ficP << "<?xml version='1.0'?>" << endl;
+ ficP << "<!DOCTYPE platform SYSTEM \"simgrid.dtd\">" << endl;
+ ficP << "<platform version=\"2\">" << endl;
+ // Noeuds
+ if(minV!=maxV){
+ vector<int> puiss;
+ int i;
+ for(i=1;i<=nbNoeuds;++i){
+ int power=(int) (minV + (maxV - minV + 1.0) * rand() / (RAND_MAX + 1.0) );
+ puiss.push_back(power);
+ }
+ puiss[i = (rand() % nbNoeuds)] = maxV; // on force la présence des extremum
+ puiss[(i + ( rand() % nbNoeuds ) ) % nbNoeuds] = minV;
+ for(i=0;i<nbNoeuds;++i){
+ ficP << " <host id=\"" << i+1 << "\" power=\"" << puiss[i] << "\"/>" << endl;
+ }
+ puiss.clear();
+ }else{
+ for(int i=1;i<=nbNoeuds;++i){
+ ficP << " <host id=\"" << i << "\" power=\"" << maxV << "\"/>" << endl;
+ }
+ }
+ // Liens
+ if(minB==maxB && minL==maxL && !liensDyns){ // liens identiques partout et statiques
+ ficP << " <link id=\"unique\" bandwidth=\"" << maxB << "\" latency=\"" << minL << "\"/>" << endl;
+ lienUnique=true;
+ }else{
+ switch(topo){
+ case 'L':
+ genereLiensLigne(ficP, nbNoeuds, minB, maxB, minL, maxL, liensDyns, minP, maxP, intervalle);
+ break;
+ case 'A':
+ genereLiensAnneau(ficP, nbNoeuds, minB, maxB, minL, maxL, liensDyns, minP, maxP, intervalle);
+ break;
+ case 'C':
+ genereLiensComplet(ficP, nbNoeuds, minB, maxB, minL, maxL, liensDyns, minP, maxP, intervalle);
+ break;
+ }
+ }
+ // Routes
+ switch(topo){
+ case 'L':
+ genereRoutesLigne(ficP, nbNoeuds, lienUnique);
+ break;
+ case 'A':
+ genereRoutesAnneau(ficP, nbNoeuds, lienUnique);
+ break;
+ case 'C':
+ genereRoutesComplet(ficP, nbNoeuds, lienUnique);
+ break;
+ }
+ // Fin de description de plateforme
+ ficP << "</platform>" << endl;
+ // Fermeture du fichier
+ ficP.close();
+ }
+
+ // Génération du fichier de déploiement
+ switch(topo){
+ case 'L':
+ genereDeploiementLigne(nomFicD, nbNoeuds);
+ break;
+ case 'A':
+ genereDeploiementAnneau(nomFicD, nbNoeuds);
+ break;
+ case 'C':
+ genereDeploiementComplet(nomFicD, nbNoeuds);
+ break;
+ }
+
+ return 0;
+}
+
+void aide(char *prog)
+{
+ cout << "Usage : " << prog << " [options]" << endl
+ << "Options :" << endl
+ << " -b entier : bande passante min des liens" << endl
+ << " -B entier : bande passante max des liens" << endl
+ << " -d : liens dynamiques" << endl
+ << " -D fichier : nom du fichier de déploiement" << endl
+ << " -f réel : durée min d'intermittence des liens" << endl
+ << " -F réel : durée max d'intermittence des liens" << endl
+ << " -i réel : intervalle de temps des intermittences des liens" << endl
+ << " -l entier : latence min des liens" << endl
+ << " -L entier : latence max des liens" << endl
+ << " -n entier : nombre de procs" << endl
+ << " -P fichier : nom du fichier de plateforme" << endl
+ << " -t car : type de topologie (L, A, C)" << endl
+ << " -v entier : vitesse min des procs" << endl
+ << " -V entier : vitesse max des procs" << endl
+ << endl;
+}
+
+void genereLiensLigne(ofstream &fic, int nbNoeuds, int minB, int maxB, double minL, double maxL, bool liensDyns, double minP, double maxP, double intervalle)
+{
+ ofstream ficState;
+ stringstream nom;
+
+ for(int i=1; i<nbNoeuds; ++i){
+ // Sens i -> i+1
+ fic << " <link id=\"" << i << "-" << i+1 << "\"";
+ fic << " bandwidth=\"" << (int) (minB + (maxB - minB + 1.0) * rand() / (RAND_MAX + 1.0) ) << "\"";
+ fic << " latency=\"" << (minL + (maxL - minL) * rand() / RAND_MAX ) << "\"";
+ if(liensDyns){
+ // Spécification du fichier d'état dans la description du lien
+ nom.str("state_");
+ nom << i << "-" << i+1 << ".txt";
+ fic << " state_file=\"" << nom.str() << "\"";
+ // Écriture du fichier d'état
+ ficState.open(nom.str().c_str());
+ if(ficState.good()){
+ double somme=0.0;
+ bool etat = rand()%2;
+ ficState << "PERIODICITY " << (minP + (maxP - minP) * rand() / RAND_MAX ) << endl;
+ while(somme<intervalle){
+ double val = (minP + (maxP - minP) * rand() / RAND_MAX );
+ somme+=val;
+ ficState << somme << " " << ((etat==0)?1.0:-1.0) << endl;
+ etat = !etat;
+ }
+ ficState.close();
+ }
+ }
+ fic << "/>" << endl;
+ // Sens i+1 -> i
+ fic << " <link id=\"" << i+1 << "-" << i << "\"";
+ fic << " bandwidth=\"" << (int) (minB + (maxB - minB + 1.0) * rand() / (RAND_MAX + 1.0) ) << "\"";
+ fic << " latency=\"" << (minL + (maxL - minL) * rand() / RAND_MAX ) << "\"";
+ if(liensDyns){
+ // Spécification du fichier d'état dans la description du lien
+ fic << " state_file=\"" << nom.str() << "\"";
+ }
+ fic << "/>" << endl;
+ }
+}
+
+void genereLiensAnneau(ofstream &fic, int nbNoeuds, int minB, int maxB, double minL, double maxL, bool liensDyns, double minP, double maxP, double intervalle)
+{
+ ofstream ficState;
+ stringstream nom;
+
+ genereLiensLigne(fic, nbNoeuds, minB, maxB, minL, maxL, liensDyns, minP, maxP, intervalle);
+ // Sens dernier -> premier
+ fic << " <link id=\"" << nbNoeuds << "-" << 1 << "\"";
+ fic << " bandwidth=\"" << (int) (minB + (maxB - minB + 1.0) * rand() / (RAND_MAX + 1.0) ) << "\"";
+ fic << " latency=\"" << (minL + (maxL - minL) * rand() / RAND_MAX ) << "\"";
+ if(liensDyns){
+ // Spécification du fichier d'état dans la description du lien
+ nom.str("state_");
+ nom << nbNoeuds << "-" << 1 << ".txt";
+ fic << " state_file=\"" << nom.str() << "\"";
+ // Écriture du fichier d'état
+ ficState.open(nom.str().c_str());
+ if(ficState.good()){
+ double somme=0.0;
+ bool etat = rand()%2;
+ ficState << "PERIODICITY " << (minP + (maxP - minP) * rand() / RAND_MAX ) << endl;
+ while(somme<intervalle){
+ double val = (minP + (maxP - minP) * rand() / RAND_MAX );
+ somme+=val;
+ ficState << somme << " " << ((etat==0)?1.0:-1.0) << endl;
+ etat = !etat;
+ }
+ ficState.close();
+ }
+ }
+ fic << "/>" << endl;
+ // Sens premier -> dernier
+ fic << " <link id=\"" << 1 << "-" << nbNoeuds << "\"";
+ fic << " bandwidth=\"" << (int) (minB + (maxB - minB + 1.0) * rand() / (RAND_MAX + 1.0) ) << "\"";
+ fic << " latency=\"" << (minL + (maxL - minL) * rand() / RAND_MAX ) << "\"";
+ if(liensDyns){
+ // Spécification du fichier d'état dans la description du lien
+ fic << " state_file=\"" << nom.str() << "\"";
+ }
+ fic << "/>" << endl;
+}
+
+void genereLiensComplet(ofstream &fic, int nbNoeuds, int minB, int maxB, double minL, double maxL, bool liensDyns, double minP, double maxP, double intervalle)
+{
+ ofstream ficState;
+ stringstream nom;
+
+ for(int i=1; i<=nbNoeuds ; ++i){
+ for(int j=i+1; j<=nbNoeuds ; ++j){
+ // Sens i -> j
+ fic << " <link id=\"" << i << "-" << j << "\"";
+ fic << " bandwidth=\"" << (int) (minB + (maxB - minB + 1.0) * rand() / (RAND_MAX + 1.0) ) << "\"";
+ fic << " latency=\"" << (minL + (maxL - minL) * rand() / RAND_MAX ) << "\"";
+ if(liensDyns){
+ // Spécification du fichier d'état dans la description du lien
+ nom.str("state_");
+ nom << i << "-" << j << ".txt";
+ fic << " state_file=\"" << nom.str() << "\"";
+ // Écriture du fichier d'état
+ ficState.open(nom.str().c_str());
+ if(ficState.good()){
+ double somme=0.0;
+ bool etat = rand()%2;
+ ficState << "PERIODICITY " << (minP + (maxP - minP) * rand() / RAND_MAX ) << endl;
+ while(somme<intervalle){
+ double val = (minP + (maxP - minP) * rand() / RAND_MAX );
+ somme+=val;
+ ficState << somme << " " << ((etat==0)?1.0:-1.0) << endl;
+ etat = !etat;
+ }
+ ficState.close();
+ }
+ }
+ fic << "/>" << endl;
+ // Sens j -> i
+ fic << " <link id=\"" << j << "-" << i << "\"";
+ fic << " bandwidth=\"" << (int) (minB + (maxB - minB + 1.0) * rand() / (RAND_MAX + 1.0) ) << "\"";
+ fic << " latency=\"" << (minL + (maxL - minL) * rand() / RAND_MAX ) << "\"";
+ if(liensDyns){
+ // Spécification du fichier d'état dans la description du lien
+ fic << " state_file=\"" << nom.str() << "\"";
+ }
+ fic << "/>" << endl;
+ }
+ }
+}
+
+void genereRoutesLigne(ofstream &fic, int nbNoeuds, bool lienUnique)
+{
+ for(int i=1; i<nbNoeuds; ++i){
+ // Sens i -> i+1
+ fic << " <route src=\"" << i << "\" dst=\"" << i+1 << "\">" << endl;
+ if(lienUnique){
+ fic << " <link:ctn id=\"unique\"/>" << endl;
+ }else{
+ fic << " <link:ctn id=\"" << i << "-" << i+1 << "\"/>" << endl;
+ }
+ fic << " </route>" << endl;
+ // Sens i+1 -> i
+ fic << " <route src=\"" << i+1 << "\" dst=\"" << i << "\">" << endl;
+ if(lienUnique){
+ fic << " <link:ctn id=\"unique\"/>" << endl;
+ }else{
+ fic << " <link:ctn id=\"" << i+1 << "-" << i << "\"/>" << endl;
+ }
+ fic << " </route>" << endl;
+ }
+}
+
+void genereRoutesAnneau(ofstream &fic, int nbNoeuds, bool lienUnique)
+{
+ genereRoutesLigne(fic, nbNoeuds, lienUnique);
+ // Sens dernier -> premier
+ fic << " <route src=\"" << nbNoeuds << "\" dst=\"" << 1 << "\">" << endl;
+ if(lienUnique){
+ fic << " <link:ctn id=\"unique\"/>" << endl;
+ }else{
+ fic << " <link:ctn id=\"" << nbNoeuds << "-" << 1 << "\"/>" << endl;
+ }
+ fic << " </route>" << endl;
+ // Sens premier -> dernier
+ fic << " <route src=\"" << 1 << "\" dst=\"" << nbNoeuds << "\">" << endl;
+ if(lienUnique){
+ fic << " <link:ctn id=\"unique\"/>" << endl;
+ }else{
+ fic << " <link:ctn id=\"" << 1 << "-" << nbNoeuds << "\"/>" << endl;
+ }
+ fic << " </route>" << endl;
+}
+
+void genereRoutesComplet(ofstream &fic, int nbNoeuds, bool lienUnique)
+{
+ for(int i=1; i<=nbNoeuds ; ++i){
+ for(int j=i+1; j<=nbNoeuds ; ++j){
+ // Sens i -> j
+ fic << " <route src=\"" << i << "\" dst=\"" << j << "\">" << endl;
+ if(lienUnique){
+ fic << " <link:ctn id=\"unique\"/>" << endl;
+ }else{
+ fic << " <link:ctn id=\"" << i << "-" << j << "\"/>" << endl;
+ }
+ fic << " </route>" << endl;
+ // Sens j -> i
+ fic << " <route src=\"" << j << "\" dst=\"" << i << "\">" << endl;
+ if(lienUnique){
+ fic << " <link:ctn id=\"unique\"/>" << endl;
+ }else{
+ fic << " <link:ctn id=\"" << j << "-" << i << "\"/>" << endl;
+ }
+ fic << " </route>" << endl;
+ }
+ }
+}
+
+void genereDeploiementLigne(string &nom, int nbNoeuds)
+{
+ ofstream fic;
+
+ fic.open(nom.c_str());
+ if(fic.good()){
+ fic << "<?xml version='1.0'?>" << endl;
+ fic << "<!DOCTYPE platform SYSTEM \"simgrid.dtd\">" << endl;
+ fic << "<platform version=\"2\">" << endl;
+ for(int i=1; i<=nbNoeuds; ++i){
+ // Dépendances du proc i
+ fic << " <process host=\"" << i << "\" function=\"Calculs\">" << endl;
+ if(i>1)
+ fic << " <argument value=\"" << i-1 << "\"/>" << endl;
+ if(i<nbNoeuds)
+ fic << " <argument value=\"" << i+1 << "\"/>" << endl;
+ fic << " </process>" << endl;
+ }
+ fic << "</platform>" << endl;
+ fic.close();
+ }else{
+ cout << "Problème d'écriture du fichier de déploiement !" << endl;
+ }
+}
+
+void genereDeploiementAnneau(string &nom, int nbNoeuds)
+{
+ ofstream fic;
+
+ fic.open(nom.c_str());
+ if(fic.good()){
+ fic << "<?xml version='1.0'?>" << endl;
+ fic << "<!DOCTYPE platform SYSTEM \"simgrid.dtd\">" << endl;
+ fic << "<platform version=\"2\">" << endl;
+ for(int i=1; i<=nbNoeuds; ++i){
+ // Dépendances du proc i
+ fic << " <process host=\"" << i << "\" function=\"Calculs\">" << endl;
+ fic << " <argument value=\"" << 1+(i-1+nbNoeuds-1)%nbNoeuds << "\"/>" << endl;
+ fic << " <argument value=\"" << 1+(i%nbNoeuds) << "\"/>" << endl;
+ fic << " </process>" << endl;
+ }
+ fic << "</platform>" << endl;
+ fic.close();
+ }else{
+ cout << "Problème d'écriture du fichier de déploiement !" << endl;
+ }
+}
+
+void genereDeploiementComplet(string &nom, int nbNoeuds)
+{
+ ofstream fic;
+
+ fic.open(nom.c_str());
+ if(fic.good()){
+ fic << "<?xml version='1.0'?>" << endl;
+ fic << "<!DOCTYPE platform SYSTEM \"simgrid.dtd\">" << endl;
+ fic << "<platform version=\"2\">" << endl;
+ for(int i=1; i<=nbNoeuds; ++i){
+ // Dépendances du proc i
+ fic << " <process host=\"" << i << "\" function=\"Calculs\">" << endl;
+ for(int j=1; j<=nbNoeuds; ++j){
+ if(i!=j)
+ fic << " <argument value=\"" << j << "\"/>" << endl;
+ }
+ fic << " </process>" << endl;
+ }
+ fic << "</platform>" << endl;
+ fic.close();
+ }else{
+ cout << "Problème d'écriture du fichier de déploiement !" << endl;
+ }
+}