root/ompi/mca/topo/treematch/treematch/tm_topology.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tm_set_numbering
  2. tm_get_numbering
  3. tgt_to_tm
  4. nb_processing_units
  5. topo_nb_proc
  6. link_cost
  7. topology_to_arch
  8. symetric
  9. build_process_tab_id
  10. hwloc_to_tm
  11. tm_get_local_topology_with_hwloc
  12. tm_free_topology
  13. tm_load_topology
  14. tm_display_topology
  15. tm_display_arity
  16. int_cmp_inc
  17. topo_check_constraints
  18. tm_topology_set_binding_constraints_cpy
  19. tm_topology_set_binding_constraints
  20. tm_topology_add_binding_constraints
  21. topology_numbering_cpy
  22. topology_arity_cpy
  23. topology_constraints_cpy
  24. topology_cost_cpy
  25. optimize_arity
  26. tm_optimize_topology
  27. tm_build_synthetic_topology
  28. build_synthetic_proc_id
  29. tm_enable_oversubscribing

   1 #include <hwloc.h>
   2 #include <hwloc/helper.h>
   3 #include "tm_tree.h"
   4 #include "tm_mapping.h"
   5 #include <ctype.h>
   6 #include "tm_verbose.h"
   7 #include "tm_solution.h"
   8 
   9 
  10 tm_topology_t* tm_get_local_topo_with_hwloc(void);
  11 tm_topology_t* hwloc_to_tm(char *filename);
  12 int int_cmp_inc(const void* x1,const void* x2);
  13 void optimize_arity(int **arity, double **cost, int *nb_levels,int n);
  14 int symetric(hwloc_topology_t topology);
  15 tm_topology_t * tgt_to_tm(char *filename);
  16 void tm_display_arity(tm_topology_t *topology);
  17 void tm_display_topology(tm_topology_t *topology);
  18 void tm_free_topology(tm_topology_t *topology);
  19 tm_topology_t *tm_load_topology(char *arch_filename, tm_file_type_t arch_file_type);
  20 void tm_optimize_topology(tm_topology_t **topology);
  21 int  tm_topology_add_binding_constraints(char *constraints_filename, tm_topology_t *topology);
  22 int topo_nb_proc(hwloc_topology_t topology,int N);
  23 void topology_arity_cpy(tm_topology_t *topology,int **arity,int *nb_levels);
  24 void topology_constraints_cpy(tm_topology_t *topology,int **constraints,int *nb_constraints);
  25 void topology_cost_cpy(tm_topology_t *topology,double **cost);
  26 void topology_numbering_cpy(tm_topology_t *topology,int **numbering,int *nb_nodes);
  27 double ** topology_to_arch(hwloc_topology_t topology);
  28 void   build_synthetic_proc_id(tm_topology_t *topology);
  29 tm_topology_t  *tm_build_synthetic_topology(int *arity, double *cost, int nb_levels, int *core_numbering, int nb_core_per_nodes);
  30 void            tm_set_numbering(tm_numbering_t new_val); /* TM_NUMBERING_LOGICAL or TM_NUMBERING_PHYSICAL */
  31 
  32 
  33 #define LINE_SIZE (1000000)
  34 
  35 
  36 static tm_numbering_t numbering = TM_NUMBERING_LOGICAL;
  37 
  38 void            tm_set_numbering(tm_numbering_t new_val){
  39   numbering = new_val;
  40 }
  41 
  42 tm_numbering_t  tm_get_numbering(){
  43   return numbering;
  44 }
  45 
  46 
  47 
  48 /* transform a tgt scotch file into a topology file*/
  49 tm_topology_t * tgt_to_tm(char *filename)
  50 {
  51   tm_topology_t *topology = NULL;
  52   FILE *pf = NULL;
  53   char line[1024];
  54   char *s = NULL;
  55   double *cost = NULL;
  56   int i;
  57 
  58 
  59 
  60   pf = fopen(filename,"r");
  61   if(!pf){
  62     if(tm_get_verbose_level() >= CRITICAL)
  63       fprintf(stderr,"Cannot open %s\n",filename);
  64     exit(-1);
  65   }
  66 
  67   if(tm_get_verbose_level() >= INFO)
  68     printf("Reading TGT file: %s\n",filename);
  69 
  70 
  71   fgets(line,1024,pf);
  72   fclose(pf);
  73 
  74   s = strstr(line,"tleaf");
  75   if(!s){
  76     if(tm_get_verbose_level() >= CRITICAL)
  77       fprintf(stderr,"Syntax error! %s is not a tleaf file\n",filename);
  78     exit(-1);
  79   }
  80 
  81   s += 5;
  82   while(isspace(*s))
  83     s++;
  84 
  85   topology                 = (tm_topology_t*)MALLOC(sizeof(tm_topology_t));
  86   topology->nb_constraints = 0;
  87   topology->oversub_fact   = 1;
  88   topology->constraints    = NULL;
  89   topology->nb_levels      = atoi(strtok(s," "))+1;
  90   topology->arity          = (int*)MALLOC(sizeof(int)*topology->nb_levels);
  91 
  92   cost = (double*)CALLOC(topology->nb_levels,sizeof(double));
  93 
  94   for( i = 0 ; i < topology->nb_levels-1 ; i++ ){
  95     topology->arity[i] = atoi(strtok(NULL," "));
  96     cost[i] = atoi(strtok(NULL," "));
  97   }
  98 
  99   topology->arity[topology->nb_levels-1] = 0;
 100   /* cost[topology->nb_levels-1]=0; */
 101 
 102   /*aggregate costs*/
 103   for( i = topology->nb_levels-2 ; i >= 0 ; i-- )
 104     cost[i] += cost[i+1];
 105 
 106   build_synthetic_proc_id(topology);
 107 
 108   if(tm_get_verbose_level() >= INFO)
 109     printf("Topology built from %s!\n",filename);
 110 
 111   topology->cost=cost;
 112 
 113 
 114   return topology;
 115 }
 116 
 117 
 118 
 119 int nb_processing_units(tm_topology_t *topology)
 120 {
 121   return topology->nb_proc_units;
 122 }
 123 
 124 int topo_nb_proc(hwloc_topology_t topology,int N)
 125 {
 126   hwloc_obj_t *objs = NULL;
 127   int nb_proc;
 128 
 129   objs = (hwloc_obj_t*)MALLOC(sizeof(hwloc_obj_t)*N);
 130   objs[0] = hwloc_get_next_obj_by_type(topology,HWLOC_OBJ_PU,NULL);
 131   nb_proc = 1 + hwloc_get_closest_objs(topology,objs[0],objs+1,N-1);
 132   FREE(objs);
 133   return nb_proc;
 134 }
 135 
 136 
 137 static double link_cost(int depth)
 138 {
 139   /*
 140     Bertha values
 141     double tab[5]={21,9,4.5,2.5,0.001};
 142     double tab[5]={1,1,1,1,1};
 143     double tab[6]={100000,10000,1000,500,100,10};
 144   */
 145   double tab[11] = {1024,512,256,128,64,32,16,8,4,2,1};
 146 
 147   return tab[depth];
 148   /*
 149    return 10*log(depth+2);
 150    return (depth+1);
 151    return (long int)pow(100,depth);
 152   */
 153 }
 154 
 155 double ** topology_to_arch(hwloc_topology_t topology)
 156 {
 157   int nb_proc,i,j;
 158   hwloc_obj_t obj_proc1,obj_proc2,obj_res;
 159   double **arch = NULL;
 160 
 161   nb_proc = hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_PU);
 162   arch = (double**)MALLOC(sizeof(double*)*nb_proc);
 163   for( i = 0 ; i < nb_proc ; i++ ){
 164     obj_proc1 = hwloc_get_obj_by_type(topology,HWLOC_OBJ_PU,i);
 165     arch[obj_proc1->os_index] = (double*)MALLOC(sizeof(double)*nb_proc);
 166     for( j = 0 ; j < nb_proc ; j++ ){
 167       obj_proc2 = hwloc_get_obj_by_type(topology,HWLOC_OBJ_PU,j);
 168       obj_res = hwloc_get_common_ancestor_obj(topology,obj_proc1,obj_proc2);
 169       /* printf("arch[%d][%d] <- %ld\n",obj_proc1->os_index,obj_proc2->os_index,*((long int*)(obj_res->userdatab))); */
 170       arch[obj_proc1->os_index][obj_proc2->os_index]=link_cost(obj_res->depth+1);
 171     }
 172   }
 173   return arch;
 174 }
 175 
 176 int symetric(hwloc_topology_t topology)
 177 {
 178    int depth,i,topodepth = hwloc_topology_get_depth(topology);
 179    unsigned int arity;
 180    hwloc_obj_t obj;
 181    for ( depth = 0; depth < topodepth-1 ; depth++ ) {
 182     int N = hwloc_get_nbobjs_by_depth(topology, depth);
 183     obj = hwloc_get_next_obj_by_depth (topology,depth,NULL);
 184     arity = obj->arity;
 185 
 186     /* printf("Depth=%d, N=%d, Arity:%d\n",depth,N,arity); */
 187     for (i = 1; i < N; i++ ){
 188       obj = hwloc_get_next_obj_by_depth (topology,depth,obj);
 189       if( obj->arity != arity){
 190         /* printf("[%d]: obj->arity=%d, arity=%d\n",i,obj->arity,arity); */
 191         return 0;
 192       }
 193     }
 194    }
 195    return 1;
 196 }
 197 
 198 static void build_process_tab_id(tm_topology_t *topology,  hwloc_obj_t *objs, char* filename){
 199   unsigned int i,j;
 200   unsigned int nb_nodes = topology->nb_proc_units; 
 201   int vl = tm_get_verbose_level();
 202   
 203   /* Build process id tab */
 204   if(numbering == TM_NUMBERING_LOGICAL){
 205     for (i = 0; i < nb_nodes; i++){
 206       topology->node_id[i] = i;
 207       topology->node_rank[i] = i;
 208     }
 209   }else if(numbering == TM_NUMBERING_PHYSICAL){
 210     for (i = 0; i < nb_nodes; i++){
 211       if(objs[i]->os_index > nb_nodes){
 212         if(vl >= CRITICAL){
 213           fprintf(stderr, "Cannot use forced physical numbering!\n\tIndex of PU %d is %d and larger than number of nodes : %d\n",
 214                   i, objs[i]->os_index, nb_nodes);
 215         }
 216         exit(-1);
 217       }
 218       for(j = 0; j < i; j++){
 219         if((unsigned int)topology->node_id[j] == objs[i]->os_index){
 220           if(vl >= CRITICAL){
 221             fprintf(stderr, "Cannot use forced physical numbering!\n\tDuplicated physical number of some PUs in %s.\n\tPU %d and PU %d have the same physical number: (os_index[%d] = %d) == (os_index[%d] = %d)\n", filename, j, i, j, objs[j]->os_index, i, objs[i]->os_index);
 222           }
 223           exit(-1);
 224         }
 225       }
 226       topology->node_id[i] = objs[i]->os_index;
 227       topology->node_rank[objs[i]->os_index] = i;
 228     }
 229   }else{
 230     if(vl >= CRITICAL){
 231       fprintf(stderr, "Unknown numbering %d\n", (int)numbering);
 232     }
 233     exit(-1);
 234   }
 235 }
 236 
 237 
 238 tm_topology_t* hwloc_to_tm(char *filename)
 239 {
 240   hwloc_topology_t topology;
 241   tm_topology_t *res = NULL;
 242   hwloc_obj_t *objs = NULL;
 243   unsigned topodepth,depth;
 244   unsigned int nb_nodes;
 245   double *cost;
 246   int err, l;
 247   int vl = tm_get_verbose_level();
 248 
 249   /* Build the topology */
 250   hwloc_topology_init(&topology);
 251   err = hwloc_topology_set_xml(topology, filename);
 252   if(err == -1){
 253     if(vl >= CRITICAL)
 254       fprintf(stderr,"Error: %s is a bad xml topology file!\n",filename);
 255     exit(-1);
 256   }
 257 
 258 #if HWLOC_API_VERSION < 0x20000
 259   hwloc_topology_ignore_all_keep_structure(topology);
 260 #else
 261   hwloc_topology_set_all_types_filter(topology, HWLOC_TYPE_FILTER_KEEP_STRUCTURE);
 262 #endif
 263 
 264   err = hwloc_topology_load(topology);
 265   if(err == -1){
 266     if(vl >= CRITICAL)
 267       fprintf(stderr,"Error: the content of the xml topology file %s is not compatible with the version installed on this machine.\nPlease use compatible versions to generate the file and to use it!\n",filename);
 268     exit(-1);
 269   }
 270 
 271 
 272   /* Test if symetric */
 273   if(!symetric(topology)){
 274     if(vl >= CRITICAL)
 275       fprintf(stderr,"%s not symetric!\n",filename);
 276     exit(-1);
 277   }
 278 
 279   /* work on depth */
 280   topodepth = hwloc_topology_get_depth(topology);
 281   
 282   res                   = (tm_topology_t*)MALLOC(sizeof(tm_topology_t));
 283   res->oversub_fact      = 1;
 284   res->nb_constraints   = 0;
 285   res->constraints      = NULL;
 286   res->nb_levels        = topodepth;
 287   res->nb_nodes         = (size_t*)MALLOC(sizeof(size_t)*res->nb_levels);
 288   res->arity            = (int*)MALLOC(sizeof(int)*res->nb_levels);
 289 
 290   if(vl >= INFO)
 291       printf("topodepth = %d\n",topodepth);
 292 
 293   /* Build TreeMatch topology */
 294   for( depth = 0 ; depth < topodepth ; depth++ ){
 295     nb_nodes = hwloc_get_nbobjs_by_depth(topology, depth);
 296     res->nb_nodes[depth] = nb_nodes;
 297 
 298     objs    = (hwloc_obj_t*)MALLOC(sizeof(hwloc_obj_t)*nb_nodes);
 299     objs[0] = hwloc_get_next_obj_by_depth(topology, depth, NULL);
 300     hwloc_get_closest_objs(topology, objs[0], objs+1, nb_nodes-1);
 301     res->arity[depth] = objs[0]->arity;
 302     
 303     if(vl >= DEBUG)
 304       printf("\n--%d(%d) **%d**:--\n",res->arity[depth],nb_nodes,res->arity[0]);
 305 
 306     
 307     if (depth == topodepth -1){
 308       res->nb_constraints = nb_nodes;
 309       res->nb_proc_units  = nb_nodes;
 310       res->node_id        = (int*)MALLOC(sizeof(int)*nb_nodes);
 311       res->node_rank      = (int*)MALLOC(sizeof(int)*nb_nodes);
 312    
 313       build_process_tab_id(res, objs, filename);
 314      
 315     }
 316     FREE(objs);
 317 
 318 
 319   }
 320 
 321   cost = (double*)CALLOC(res->nb_levels,sizeof(double));
 322   for(l=0; l<res->nb_levels; l++){
 323     cost[l] = link_cost(l);
 324   }
 325   res->cost = cost;
 326 
 327 
 328   /* Destroy topology object. */
 329   hwloc_topology_destroy(topology);
 330   if(tm_get_verbose_level() >= INFO)
 331     printf("\n");
 332 
 333 
 334 
 335   return res;
 336 }
 337 
 338 tm_topology_t* tm_get_local_topology_with_hwloc(void)
 339 {
 340   hwloc_topology_t topology;
 341   tm_topology_t *res = NULL;
 342   hwloc_obj_t *objs = NULL;
 343   unsigned topodepth,depth;
 344   int nb_nodes;
 345 
 346   /* Build the topology */
 347   hwloc_topology_init(&topology);
 348 
 349 #if HWLOC_API_VERSION < 0x20000
 350   hwloc_topology_ignore_all_keep_structure(topology);
 351 #else
 352   hwloc_topology_set_all_types_filter(topology, HWLOC_TYPE_FILTER_KEEP_STRUCTURE);
 353 #endif
 354 
 355   hwloc_topology_load(topology);
 356 
 357   /* Test if symetric */
 358   if(!symetric(topology)){
 359     if(tm_get_verbose_level() >= CRITICAL)
 360       fprintf(stderr,"Local toplogy not symetric!\n");
 361     exit(-1);
 362   }
 363 
 364   /* work on depth */
 365   topodepth = hwloc_topology_get_depth(topology);
 366 
 367   res                  = (tm_topology_t*)MALLOC(sizeof(tm_topology_t));
 368   res->nb_constraints  = 0;
 369   res->constraints     = NULL;
 370   res->nb_levels       = topodepth;
 371   res->nb_nodes        = (size_t*)MALLOC(sizeof(size_t)*res->nb_levels);
 372   res->arity           = (int*)MALLOC(sizeof(int)*res->nb_levels);
 373   res->oversub_fact    = 1; //defaut
 374   res->cost            = NULL; 
 375 
 376   /* Build TreeMatch topology */
 377   for( depth = 0 ; depth < topodepth ; depth++ ){
 378     nb_nodes = hwloc_get_nbobjs_by_depth(topology, depth);
 379     res->nb_nodes[depth] = nb_nodes;
 380 
 381     objs = (hwloc_obj_t*)MALLOC(sizeof(hwloc_obj_t)*nb_nodes);
 382     objs[0] = hwloc_get_next_obj_by_depth(topology,depth,NULL);
 383     hwloc_get_closest_objs(topology,objs[0],objs+1,nb_nodes-1);
 384     res->arity[depth] = objs[0]->arity;
 385 
 386     if (depth == topodepth -1){
 387       res->nb_constraints = nb_nodes;
 388       res->nb_proc_units  = nb_nodes;
 389       res->node_id        = (int*)MALLOC(sizeof(int)*nb_nodes);
 390       res->node_rank      = (int*)MALLOC(sizeof(int)*nb_nodes);
 391     /* printf("%d:",res->arity[depth]); */
 392 
 393       /* Build process id tab */
 394 
 395       build_process_tab_id(res, objs, "Local node topology");
 396     }
 397     FREE(objs);
 398   }
 399 
 400 
 401 
 402   /* Destroy HWLOC topology object. */
 403   hwloc_topology_destroy(topology);
 404 
 405   /* printf("\n"); */
 406   return res;
 407 }
 408 
 409 
 410 void tm_free_topology(tm_topology_t *topology)
 411 {
 412   FREE(topology->node_id);
 413   FREE(topology->node_rank);
 414   FREE(topology->constraints);
 415   FREE(topology->nb_nodes);
 416   FREE(topology->arity);
 417   FREE(topology->cost);
 418   FREE(topology);
 419 }
 420 
 421 tm_topology_t *tm_load_topology(char *arch_filename, tm_file_type_t arch_file_type){
 422   switch(arch_file_type){
 423   case   TM_FILE_TYPE_TGT:
 424     return  tgt_to_tm(arch_filename);
 425   case TM_FILE_TYPE_XML:
 426     return hwloc_to_tm(arch_filename);
 427   default:
 428     if(tm_get_verbose_level() >= ERROR){
 429       fprintf(stderr,"Error loading topology. Filetype %d unknown\n", arch_file_type);
 430     }
 431     exit(-1);
 432   }
 433 }
 434 
 435 
 436 void tm_display_topology(tm_topology_t *topology)
 437 {
 438   int i;
 439   unsigned long  id;
 440   for( i = 0 ; i < topology->nb_levels ; i++ ){
 441     printf("Level %d with arity %d ", i, topology->arity[i]); 
 442     printf("\n");
 443   }
 444 
 445   printf("Last level: ");
 446   for(id = 0; id < topology->nb_nodes[topology->nb_levels-1]/topology->oversub_fact; id++)
 447     printf("%d ",topology->node_rank[id]);
 448   printf("\n");
 449 
 450 
 451   if(topology->constraints){
 452     printf("Constraints: ");
 453     for(i = 0; i < topology->nb_constraints; i++)
 454       printf("%d ",topology->constraints[i]);
 455     printf("\n");
 456   }
 457 
 458   printf("\tnb_levels=%d\n\tnb_constraints=%d\n\toversub_fact=%d\n\tnb proc units=%d\n\n",
 459          topology->nb_levels, topology->nb_constraints, topology->oversub_fact, topology->nb_proc_units);
 460 
 461 }
 462 
 463 
 464 void tm_display_arity(tm_topology_t *topology){
 465   int depth;
 466   for(depth=0; depth < topology->nb_levels; depth++){
 467     printf("%d",topology->arity[depth]);
 468     if(topology->cost) 
 469       printf("(%lf)",topology->cost[depth]); 
 470     else 
 471       printf(":"); 
 472   }
 473   printf("\n");
 474 }
 475 
 476 int int_cmp_inc(const void* x1,const void* x2)
 477 {
 478   return *((int *)x1) < *((int *)x2) ? -1 : 1;
 479 }
 480 
 481 
 482 static int topo_check_constraints(tm_topology_t *topology){
 483   int n = topology->nb_constraints;
 484   int i;
 485   int depth = topology->nb_levels-1;
 486   for (i=0;i<n;i++){
 487     if(!in_tab(topology->node_id, topology->nb_nodes[depth], topology->constraints[i])){
 488       if(tm_get_verbose_level() >= CRITICAL){
 489         fprintf(stderr,"Error! Incompatible constraint with the topology: rank %d in the constraints is not a valid id of any nodes of the topology.\n",topology->constraints[i]);
 490       }
 491       return 0;
 492     }
 493   }
 494   return 1;
 495 }
 496 
 497 
 498 
 499 
 500 /* cpy flag tells if we need to copy the array.
 501    Set to 1 when called from the application level and 0 when called from inside the library*/
 502 static int tm_topology_set_binding_constraints_cpy(int *constraints, int nb_constraints, tm_topology_t *topology, int cpy_flag){
 503 
 504   topology -> nb_constraints = nb_constraints;
 505   if(cpy_flag){
 506     topology -> constraints    =  (int*)MALLOC(nb_constraints*sizeof(int));
 507     memcpy(topology -> constraints, constraints, nb_constraints*sizeof(int));
 508   }else{
 509     topology -> constraints    = constraints;
 510   }
 511 
 512   return topo_check_constraints(topology);
 513 }
 514 
 515 int tm_topology_set_binding_constraints(int *constraints, int nb_constraints, tm_topology_t *topology){
 516   return tm_topology_set_binding_constraints_cpy(constraints, nb_constraints, topology, 1);
 517 }
 518 
 519 int  tm_topology_add_binding_constraints(char *constraints_filename, tm_topology_t *topology)
 520 {
 521   int *tab = NULL;
 522   FILE *pf = NULL;
 523   char  line[LINE_SIZE],*l = NULL;
 524   char *ptr = NULL;
 525   int i,n;
 526   unsigned int vl = tm_get_verbose_level();
 527 
 528 
 529   if (!(pf = fopen(constraints_filename,"r"))) {
 530     if(vl >= CRITICAL)
 531       fprintf(stderr,"Cannot open %s\n",constraints_filename);
 532     exit(-1);
 533   }
 534 
 535   /* compute the size of the array to store the constraints*/
 536   n = 0;
 537   fgets(line, LINE_SIZE, pf);
 538   l = line;
 539   while((ptr=strtok(l," \t"))){
 540     l = NULL;
 541     if((ptr[0] != '\n') && ( !isspace(ptr[0])) && (*ptr) && (ptr))
 542       n++;
 543   }
 544 
 545   tab = (int*)MALLOC(n*sizeof(int));
 546 
 547   rewind(pf);
 548   fgets(line, LINE_SIZE, pf);
 549   fclose(pf);
 550   l = line;
 551   i = 0;
 552   while((ptr=strtok(l," \t"))){
 553     l = NULL;
 554     if((ptr[0] != '\n') && ( !isspace(ptr[0])) && (*ptr) && (ptr)){
 555       if(i < n)
 556         tab[i] = atoi(ptr);
 557       else{
 558         if(vl >= CRITICAL)
 559           fprintf(stderr, "More than %d entries in %s\n", n, constraints_filename);
 560         exit(-1);
 561       }
 562       i++;
 563     }
 564   }
 565 
 566   if( i != n ){
 567     if(vl >= CRITICAL)
 568       fprintf(stderr, "Read %d entries while expecting %d ones\n", i, n);
 569     exit(-1);
 570   }
 571 
 572   qsort(tab,n,sizeof(int),int_cmp_inc);
 573 
 574   return tm_topology_set_binding_constraints_cpy(tab, n, topology, 0);
 575 }
 576 
 577 
 578 void topology_numbering_cpy(tm_topology_t *topology,int **numbering,int *nb_nodes)
 579 {
 580   int nb_levels;
 581   unsigned int vl = tm_get_verbose_level();
 582 
 583   nb_levels = topology->nb_levels;
 584   *nb_nodes = topology->nb_nodes[nb_levels-1];
 585   if(vl >= INFO)
 586     printf("nb_nodes=%d\n",*nb_nodes);
 587   *numbering = (int*)MALLOC(sizeof(int)*(*nb_nodes));
 588   memcpy(*numbering,topology->node_id,sizeof(int)*(*nb_nodes));
 589 }
 590 
 591 void topology_arity_cpy(tm_topology_t *topology,int **arity,int *nb_levels)
 592 {
 593   *nb_levels = topology->nb_levels;
 594   *arity = (int*)MALLOC(sizeof(int)*(*nb_levels));
 595   memcpy(*arity,topology->arity,sizeof(int)*(*nb_levels));
 596 }
 597 
 598 void topology_constraints_cpy(tm_topology_t *topology,int **constraints,int *nb_constraints)
 599 {
 600   *nb_constraints = topology->nb_constraints;
 601   if(topology->constraints){
 602     *constraints = (int*)MALLOC(sizeof(int)*(*nb_constraints));
 603     memcpy(*constraints,topology->constraints,sizeof(int)*(*nb_constraints));
 604   }else{
 605     *constraints = NULL;
 606   }
 607 }
 608 
 609 void topology_cost_cpy(tm_topology_t *topology,double **cost)
 610 {
 611   *cost = (double*)MALLOC(sizeof(double)*(topology->nb_levels));
 612   memcpy(*cost,topology->cost,sizeof(double)*(topology->nb_levels));
 613 }
 614 
 615 void optimize_arity(int **arity, double **cost, int *nb_levels,int n)
 616 {
 617   int a,i;
 618   int *new_arity = NULL;
 619   double *new_cost = NULL;
 620 
 621   if( n < 0 )
 622     return;
 623   /*   printf("n=%d\tnb_levels=%d\n",n,*nb_levels); */
 624   /*   for(i=0;i<*nb_levels;i++) */
 625   /*     printf("%d:",(*arity)[i]); */
 626   /*   printf("\n");   */
 627   /* if(n==(*nb_levels)-3) */
 628   /*  exit(-1); */
 629   a = (*arity)[n];
 630   if( (a%3 == 0) && (a > 3) ){
 631     /*
 632     check if the arity of level n devides 3
 633     If this is the case:
 634     Add a level
 635     */
 636     (*nb_levels)++;
 637     /* Build a new arity and cost arrays  */
 638     new_arity = (int*)MALLOC(sizeof(int)*(*nb_levels));
 639     new_cost  = (double*)MALLOC(sizeof(double)*(*nb_levels));
 640     /*  Copy the begining if the old arrays */
 641     for( i = 0 ; i < n ; i++){
 642       new_arity[i] = (*arity)[i];
 643       new_cost[i] = (*cost)[i];
 644     }
 645     /* set the nth level to arity 3  */
 646     new_arity[n] = 3;
 647     /* copy the cost to this level*/
 648     new_cost[n] = (*cost)[n];;
 649     /* printf("a=%d\n",a); */
 650     /* Set the (n+1) level to arity a/3 */
 651     new_arity[n+1] = a/3;
 652     /*Dupliacte the cost as it is the same level originally*/
 653     new_cost[n+1] = (*cost)[n];
 654     /* Copy the end of the arrays */
 655     for( i = n+2 ; i < *nb_levels ; i++){
 656       new_arity[i] = (*arity)[i-1];
 657       new_cost[i] = (*cost)[i-1];
 658     }
 659     FREE(*arity);
 660     FREE(*cost);
 661     /* if a/3 =3 then go to the next level */
 662     if(new_arity[n+1] == 3)
 663       optimize_arity(&new_arity,&new_cost,nb_levels,n);
 664     else /* continue to this level (remember we just add a new level */
 665       optimize_arity(&new_arity,&new_cost,nb_levels,n+1);
 666     *arity=new_arity;
 667     *cost=new_cost;
 668   }else if( (a%2==0) && (a>2) ){/* same as above but for arity == 2 instead of 3 */
 669     (*nb_levels)++;
 670     new_arity = (int*)MALLOC(sizeof(int)*(*nb_levels));
 671     new_cost  = (double*)MALLOC(sizeof(double)*(*nb_levels));
 672     for( i = 0 ; i < n ; i++ ){
 673       new_arity[i] = (*arity)[i];
 674       new_cost[i] = (*cost)[i];
 675     }
 676     new_arity[n] = 2;
 677     new_cost[n] = (*cost)[n];;
 678     /* printf("a=%d\n",a); */
 679     new_arity[n+1] = a/2;
 680     new_cost[n+1] = (*cost)[n];
 681     for( i = n+2 ; i < *nb_levels ; i++ ){
 682       new_arity[i] = (*arity)[i-1];
 683       new_cost[i] = (*cost)[i-1];
 684     }
 685    FREE(*arity);
 686     FREE(*cost);
 687     if(new_arity[n+1] == 2)
 688       optimize_arity(&new_arity, &new_cost, nb_levels, n);
 689     else
 690       optimize_arity(&new_arity, &new_cost, nb_levels, n+1);
 691     *arity = new_arity;
 692     *cost= new_cost;
 693   }else /* if nothing works go to next level.  */
 694     optimize_arity(arity, cost, nb_levels,n-1);
 695 }
 696 
 697 
 698 
 699 
 700 void tm_optimize_topology(tm_topology_t **topology){
 701   int *arity = NULL,nb_levels;
 702   int *numbering = NULL,nb_nodes;
 703   tm_topology_t *new_topo;
 704   double *cost;
 705   unsigned int vl = tm_get_verbose_level();
 706   int *constraints = NULL, nb_constraints;
 707   int i;
 708 
 709   if(vl >= DEBUG)
 710     tm_display_arity(*topology);
 711 
 712   topology_arity_cpy(*topology,&arity,&nb_levels);
 713   topology_numbering_cpy(*topology,&numbering,&nb_nodes);
 714   topology_constraints_cpy(*topology,&constraints,&nb_constraints);
 715   topology_cost_cpy(*topology,&cost);
 716 
 717 
 718   optimize_arity(&arity,&cost,&nb_levels,nb_levels-2);
 719   new_topo = tm_build_synthetic_topology(arity, NULL, nb_levels,numbering,nb_nodes);
 720   new_topo->cost = cost;
 721   new_topo->constraints    = constraints;
 722   new_topo->nb_constraints = nb_constraints;
 723   new_topo->nb_proc_units  = (*topology)->nb_proc_units;
 724   new_topo->oversub_fact   = (*topology)->oversub_fact;
 725 
 726 
 727 
 728   if(vl >= DEBUG){
 729     if(constraints){
 730       printf("Constraints: ");
 731       for(i=0;i<nb_constraints;i++)
 732         printf("%d - ",constraints[i]);
 733       printf("\n");
 734     }
 735 
 736     tm_display_arity(new_topo);
 737   }
 738   FREE(arity);
 739   FREE(numbering);
 740   tm_free_topology(*topology);
 741 
 742   *topology = new_topo;
 743   /*  exit(-1); */
 744 
 745 
 746 }
 747 
 748 
 749 
 750 /*
 751    Build a synthetic balanced topology
 752 
 753    arity : array of arity of the first nb_level (of size nb_levels)
 754    cost : array of costs between the levels (of size nb_levels)
 755    core_numbering: numbering of the core by the system. Array of size nb_core_per_node
 756 
 757    nb_core_per_nodes: number of cores of a given node size of the array core_numbering
 758 
 759    The numbering of the cores is done in round robin fashion after a width traversal of the topology.
 760    for example:
 761        {0,1,2,3} becomes 0,1,2,3,4,5,6,7...
 762    and
 763        {0,2,1,3} becomes 0,2,1,3,4,6,5,7,...
 764  */
 765 
 766 tm_topology_t  *tm_build_synthetic_topology(int *arity, double *cost, int nb_levels, int *core_numbering, int nb_core_per_nodes)
 767 {
 768   tm_topology_t *topology = NULL;
 769   int i,j,n;
 770 
 771 
 772   topology                 = (tm_topology_t*)MALLOC(sizeof(tm_topology_t));
 773   topology->nb_constraints = 0;
 774   topology->oversub_fact   = 1;
 775   topology->constraints    = NULL;
 776   topology->nb_levels      = nb_levels;
 777   topology->arity          = (int*)MALLOC(sizeof(int)*topology->nb_levels);
 778   topology->nb_nodes       = (size_t *)MALLOC(sizeof(size_t)*topology->nb_levels);
 779   if(cost)
 780     topology->cost         = (double*)CALLOC(topology->nb_levels,sizeof(double));
 781   else
 782     topology->cost         = NULL;
 783 
 784   memcpy(topology->arity, arity, sizeof(int)*nb_levels);
 785   if(cost)
 786     memcpy(topology->cost, cost, sizeof(double)*nb_levels);
 787 
 788   n = 1;
 789   for( i = 0 ; i < topology->nb_levels ; i++ ){
 790     topology->nb_nodes[i] = n;
 791     if (i == topology->nb_levels-1){
 792       topology->node_id        = (int*)MALLOC(sizeof(int)*n);
 793       topology->node_rank      = (int*)MALLOC(sizeof(int)*n);
 794       topology->nb_constraints = n;
 795       topology->nb_proc_units  = n;
 796       for( j = 0 ; j < n ; j++ ){
 797         int id = core_numbering[j%nb_core_per_nodes] + (nb_core_per_nodes)*(j/nb_core_per_nodes);
 798         topology->node_id[j]    = id;
 799         topology->node_rank[id] = j;
 800       }
 801     }
 802     n *= topology->arity[i];
 803   }
 804   if(cost){
 805     /*aggregate costs*/
 806     for( i = topology->nb_levels-2 ; i >= 0 ; i-- )
 807       topology->cost[i] += topology->cost[i+1];
 808   }
 809 
 810   return topology;
 811 }
 812 
 813 
 814 void   build_synthetic_proc_id(tm_topology_t *topology)
 815 {
 816   int i;
 817   size_t j,n = 1;
 818 
 819   topology->nb_nodes  = (size_t*) MALLOC(sizeof(size_t)*topology->nb_levels);
 820 
 821   for( i = 0 ; i < topology->nb_levels ; i++ ){
 822     /* printf("n= %lld, arity := %d\n",n, topology->arity[i]); */
 823     topology->nb_nodes[i] = n;
 824    
 825     if (i == topology->nb_levels-1){
 826       topology->node_rank      = (int*)MALLOC(sizeof(int)*n);
 827       topology->node_id        = (int*)MALLOC(sizeof(int)*n);
 828       if ( !topology->node_id ){
 829         if(tm_get_verbose_level() >= CRITICAL)
 830           fprintf(stderr,"Cannot allocate last level (of size %ld) of the topology\n", (unsigned long int)n);
 831         exit(-1);
 832       }
 833       
 834       topology->nb_constraints = n;
 835       topology->nb_proc_units = n;
 836       
 837       for( j = 0 ; j < n ; j++ ){
 838         topology->node_id[j]   = j;
 839         topology->node_rank[j] = j;
 840       }
 841     }
 842 
 843     n *= topology->arity[i];
 844   }
 845 
 846 }
 847 
 848 
 849 
 850 void tm_enable_oversubscribing(tm_topology_t *topology, unsigned int oversub_fact){
 851 {
 852   int i,j,n;
 853   int *node_id, *node_rank;
 854 
 855   if(oversub_fact <=1)
 856     return;
 857 
 858   topology -> nb_levels ++;
 859   topology -> arity        = (int*)    REALLOC(topology->arity, sizeof(int)*topology->nb_levels);
 860   topology -> cost         = (double*) REALLOC(topology->cost, sizeof(double)*topology->nb_levels);
 861   topology -> nb_nodes     = (size_t *)REALLOC(topology->nb_nodes, sizeof(size_t)*topology->nb_levels);
 862   topology -> oversub_fact = oversub_fact;
 863 
 864   i = topology->nb_levels - 1;
 865   n = topology->nb_nodes[i-1] * oversub_fact;
 866   topology->arity[i-1] = oversub_fact;
 867   topology->cost[i-1] = 0;
 868   node_id = (int*)MALLOC(sizeof(int)*n);
 869   node_rank = (int*)MALLOC(sizeof(int)*n);
 870   topology->nb_nodes[i] = n;
 871 
 872   for( j = 0 ; j < n ; j++ ){
 873     int id = topology->node_id[j/oversub_fact];
 874     node_id[j]    = id;
 875     node_rank[id] = j;
 876   }
 877   FREE(topology->node_id);
 878   FREE(topology->node_rank);
 879   topology->node_id   = node_id;  
 880   topology->node_rank = node_rank;  
 881  }
 882 
 883 }

/* [<][>][^][v][top][bottom][index][help] */