This source file includes following definitions.
- tm_set_numbering
- tm_get_numbering
- tgt_to_tm
- nb_processing_units
- topo_nb_proc
- link_cost
- topology_to_arch
- symetric
- build_process_tab_id
- hwloc_to_tm
- tm_get_local_topology_with_hwloc
- tm_free_topology
- tm_load_topology
- tm_display_topology
- tm_display_arity
- int_cmp_inc
- topo_check_constraints
- tm_topology_set_binding_constraints_cpy
- tm_topology_set_binding_constraints
- tm_topology_add_binding_constraints
- topology_numbering_cpy
- topology_arity_cpy
- topology_constraints_cpy
- topology_cost_cpy
- optimize_arity
- tm_optimize_topology
- tm_build_synthetic_topology
- build_synthetic_proc_id
- 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);
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
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
101
102
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
141
142
143
144
145 double tab[11] = {1024,512,256,128,64,32,16,8,4,2,1};
146
147 return tab[depth];
148
149
150
151
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
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
187 for (i = 1; i < N; i++ ){
188 obj = hwloc_get_next_obj_by_depth (topology,depth,obj);
189 if( obj->arity != arity){
190
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
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
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
273 if(!symetric(topology)){
274 if(vl >= CRITICAL)
275 fprintf(stderr,"%s not symetric!\n",filename);
276 exit(-1);
277 }
278
279
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
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
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
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
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
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;
374 res->cost = NULL;
375
376
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
392
393
394
395 build_process_tab_id(res, objs, "Local node topology");
396 }
397 FREE(objs);
398 }
399
400
401
402
403 hwloc_topology_destroy(topology);
404
405
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
501
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
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
624
625
626
627
628
629 a = (*arity)[n];
630 if( (a%3 == 0) && (a > 3) ){
631
632
633
634
635
636 (*nb_levels)++;
637
638 new_arity = (int*)MALLOC(sizeof(int)*(*nb_levels));
639 new_cost = (double*)MALLOC(sizeof(double)*(*nb_levels));
640
641 for( i = 0 ; i < n ; i++){
642 new_arity[i] = (*arity)[i];
643 new_cost[i] = (*cost)[i];
644 }
645
646 new_arity[n] = 3;
647
648 new_cost[n] = (*cost)[n];;
649
650
651 new_arity[n+1] = a/3;
652
653 new_cost[n+1] = (*cost)[n];
654
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
662 if(new_arity[n+1] == 3)
663 optimize_arity(&new_arity,&new_cost,nb_levels,n);
664 else
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) ){
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
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
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
744
745
746 }
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
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
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
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 }