added filename to printTopo
[charm.git] / src / util / TopoManager.C
1 /** \file TopoManager.C
2  *  Author: Abhinav S Bhatele
3  *  Date Created: March 19th, 2007
4  *
5  *  This would be the top level interface for all topology managers we
6  *  will write for different machines (cray, bg/l ... for tori, meshes ...)
7  *  Current plan is to have functionality for Blue Gene/L, Cray XT3,
8  *  BigSim and non-topo machines.
9  */
10
11 #include "TopoManager.h"
12
13 TopoManager::TopoManager() {
14 #if CMK_BLUEGENEL
15   dimX = bgltm.getDimX();
16   dimY = bgltm.getDimY();
17   dimZ = bgltm.getDimZ();
18
19   dimNX = bgltm.getDimNX();
20   dimNY = bgltm.getDimNY();
21   dimNZ = bgltm.getDimNZ();
22   dimNT = bgltm.getDimNT();
23
24   procsPerNode = bgltm.getProcsPerNode();
25   int *torus;
26   torus = bgltm.isTorus();
27   torusX = torus[0];
28   torusY = torus[1];
29   torusZ = torus[2];
30   torusT = torus[3];
31
32 #elif CMK_BLUEGENEP
33   dimX = bgptm.getDimX();
34   dimY = bgptm.getDimY();
35   dimZ = bgptm.getDimZ();
36
37   dimNX = bgptm.getDimNX();
38   dimNY = bgptm.getDimNY();
39   dimNZ = bgptm.getDimNZ();
40   dimNT = bgptm.getDimNT();
41
42   procsPerNode = bgptm.getProcsPerNode();
43   int *torus;
44   torus = bgptm.isTorus();
45   torusX = torus[0];
46   torusY = torus[1];
47   torusZ = torus[2];
48   torusT = torus[3];
49
50 #elif CMK_BLUEGENEQ
51   dimX = bgqtm.getDimX();
52   dimY = bgqtm.getDimY();
53   dimZ = bgqtm.getDimZ();
54
55   dimNX = bgqtm.getDimNX();
56   dimNY = bgqtm.getDimNY();
57   dimNZ = bgqtm.getDimNZ();
58   dimNT = bgqtm.getDimNT();
59
60   procsPerNode = bgqtm.getProcsPerNode();
61   int *torus;
62   torus = bgqtm.isTorus();
63   torusA = torus[0];
64   torusB = torus[1];
65   torusC = torus[2]; 
66   torusD = torus[3];
67   torusE = torus[4];
68
69 #elif XT3_TOPOLOGY
70   dimX = xt3tm.getDimX();
71   dimY = xt3tm.getDimY();
72   dimZ = xt3tm.getDimZ();
73
74   dimNX = xt3tm.getDimNX();
75   dimNY = xt3tm.getDimNY();
76   dimNZ = xt3tm.getDimNZ();
77   dimNT = xt3tm.getDimNT();
78
79   procsPerNode = xt3tm.getProcsPerNode();
80   int *torus;
81   torus = xt3tm.isTorus();
82   torusX = torus[0];
83   torusY = torus[1];
84   torusZ = torus[2];
85   torusT = torus[3];
86
87 #elif XT4_TOPOLOGY || XT5_TOPOLOGY || XE6_TOPOLOGY
88   dimX = xttm.getDimX();
89   dimY = xttm.getDimY();
90   dimZ = xttm.getDimZ();
91
92   dimNX = xttm.getDimNX();
93   dimNY = xttm.getDimNY();
94   dimNZ = xttm.getDimNZ();
95   dimNT = xttm.getDimNT();
96
97   procsPerNode = xttm.getProcsPerNode();
98   int *torus;
99   torus = xttm.isTorus();
100   torusX = torus[0];
101   torusY = torus[1];
102   torusZ = torus[2];
103   torusT = torus[3];
104
105 #else
106   dimX = CmiNumPes();
107   dimY = 1;
108   dimZ = 1;
109
110   dimNX = dimX;
111   dimNY = 1;
112   dimNZ = 1;
113
114   dimNT = procsPerNode = 1;
115   torusX = true;
116   torusY = true;
117   torusZ = true;
118   torusT = false;
119 #endif
120
121 #if CMK_BIGSIM_CHARM
122   BgGetSize(&dimNX, &dimNY, &dimNZ);
123
124   dimNT = procsPerNode = BgGetNumWorkThread();
125   dimX = dimNX * procsPerNode;
126   dimY = dimNY;
127   dimZ = dimNZ;
128
129   torusX = true;
130   torusY = true;
131   torusZ = true;
132   torusT = false;
133 #endif
134
135   numPes = CmiNumPes();
136 }
137
138 TopoManager::TopoManager(int NX, int NY, int NZ, int NT) : dimNX(NX), dimNY(NY), dimNZ(NZ), dimNT(NT) {
139   /* we rashly assume only one dimension is expanded */
140   procsPerNode = dimNT;
141   dimX = dimNX * dimNT;
142   dimY = dimNY;
143   dimZ = dimNZ;
144   torusX = true;
145   torusY = true;
146   torusZ = true;
147 #if CMK_BLUEGENEQ
148   torusA = true;
149   torusB = true;
150   torusC = true;
151   torusD = true;
152   torusE = true;
153 #endif
154   numPes = dimNX * dimNY * dimNZ * dimNT;
155 }
156
157 int TopoManager::hasMultipleProcsPerNode() const {
158   if(procsPerNode == 1)
159     return 0;
160   else
161     return 1;
162 }
163
164 void TopoManager::rankToCoordinates(int pe, int &x, int &y, int &z) {
165   CmiAssert( pe >= 0 && pe < numPes );
166 #if CMK_BLUEGENEL
167   bgltm.rankToCoordinates(pe, x, y, z);
168 #elif CMK_BLUEGENEP
169   bgptm.rankToCoordinates(pe, x, y, z);
170 #elif XT3_TOPOLOGY || XT4_TOPOLOGY || XT5_TOPOLOGY || XE6_TOPOLOGY
171         int t;
172   xttm.rankToCoordinates(pe, x, y, z, t);
173 #else
174   if(dimY > 1){
175     // Assumed TXYZ
176     x = pe % dimX;
177     y = (pe % (dimX * dimY)) / dimX;
178     z = pe / (dimX * dimY);
179   }
180   else {
181     x = pe; 
182     y = 0; 
183     z = 0;
184   }
185 #endif
186
187 #if CMK_BIGSIM_CHARM
188   if(dimY > 1){
189     // Assumed TXYZ
190     x = pe % dimX;
191     y = (pe % (dimX * dimY)) / dimX;
192     z = pe / (dimX * dimY);
193   }
194   else {
195     x = pe; 
196     y = 0; 
197     z = 0;
198   }
199 #endif
200 }
201
202 void TopoManager::rankToCoordinates(int pe, int &x, int &y, int &z, int &t) {
203   CmiAssert( pe >= 0 && pe < numPes );
204 #if CMK_BLUEGENEL
205   bgltm.rankToCoordinates(pe, x, y, z, t);
206 #elif CMK_BLUEGENEP
207   bgptm.rankToCoordinates(pe, x, y, z, t);
208 #elif CMK_BLUEGENEQ
209   bgqtm.rankToCoordinates(pe, x, y, z, t);
210 #elif XT3_TOPOLOGY
211   xt3tm.rankToCoordinates(pe, x, y, z, t);
212 #elif XT4_TOPOLOGY || XT5_TOPOLOGY || XE6_TOPOLOGY
213   xttm.rankToCoordinates(pe, x, y, z, t);
214 #else
215   if(dimNY > 1) {
216     t = pe % dimNT;
217     x = (pe % (dimNT*dimNX)) / dimNT;
218     y = (pe % (dimNT*dimNX*dimNY)) / (dimNT*dimNX);
219     z = pe / (dimNT*dimNX*dimNY);
220   } else {
221     t = pe % dimNT;
222     x = (pe % (dimNT*dimNX)) / dimNT;
223     y = 0;
224     z = 0;
225   }
226 #endif
227
228 #if CMK_BIGSIM_CHARM
229   if(dimNY > 1) {
230     t = pe % dimNT;
231     x = (pe % (dimNT*dimNX)) / dimNT;
232     y = (pe % (dimNT*dimNX*dimNY)) / (dimNT*dimNX);
233     z = pe / (dimNT*dimNX*dimNY);
234   } else {
235     t = pe % dimNT;
236     x = (pe % (dimNT*dimNX)) / dimNT;
237     y = 0;
238     z = 0;
239   }
240 #endif
241 }
242
243 #if CMK_BLUEGENEQ
244 void TopoManager::rankToCoordinates(int pe, int &a, int &b, int &c, int &d, int &e, int &t) {
245   CmiAssert( pe >= 0 && pe < numPes );
246   bgqtm.rankToCoordinates(pe, a, b, c, d, e, t);
247 }
248 #endif
249
250 int TopoManager::coordinatesToRank(int x, int y, int z) {
251   CmiAssert( x>=0 && x<dimX && y>=0 && y<dimY && z>=0 && z<dimZ );
252 #if CMK_BIGSIM_CHARM
253   if(dimY > 1)
254     return x + y*dimX + z*dimX*dimY;
255   else
256     return x;
257 #endif
258
259 #if CMK_BLUEGENEL
260   return bgltm.coordinatesToRank(x, y, z);
261 #elif CMK_BLUEGENEP
262   return bgptm.coordinatesToRank(x, y, z);
263 #elif XT3_TOPOLOGY || XT4_TOPOLOGY || XT5_TOPOLOGY || XE6_TOPOLOGY
264   return xttm.coordinatesToRank(x, y, z, 0);
265 #else
266   if(dimY > 1)
267     return x + y*dimX + z*dimX*dimY;
268   else
269     return x;
270 #endif
271 }
272
273 int TopoManager::coordinatesToRank(int x, int y, int z, int t) {
274   CmiAssert( x>=0 && x<dimNX && y>=0 && y<dimNY && z>=0 && z<dimNZ && t>=0 && t<dimNT );
275 #if CMK_BIGSIM_CHARM
276   if(dimNY > 1)
277     return t + (x + (y + z*dimNY) * dimNX) * dimNT;
278   else
279     return t + x * dimNT;
280 #endif
281
282 #if CMK_BLUEGENEL
283   return bgltm.coordinatesToRank(x, y, z, t);
284 #elif CMK_BLUEGENEP
285   return bgptm.coordinatesToRank(x, y, z, t);
286 #elif CMK_BLUEGENEQ
287   return bgqtm.coordinatesToRank(x, y, z, t);
288 #elif XT3_TOPOLOGY
289   return xt3tm.coordinatesToRank(x, y, z, t);
290 #elif XT4_TOPOLOGY || XT5_TOPOLOGY || XE6_TOPOLOGY
291   return xttm.coordinatesToRank(x, y, z, t);
292 #else
293   if(dimNY > 1)
294     return t + (x + (y + z*dimNY) * dimNX) * dimNT;
295   else
296     return t + x * dimNT;
297 #endif
298 }
299
300 #if CMK_BLUEGENEQ
301 int TopoManager::coordinatesToRank(int a, int b, int c, int d, int e, int t) {
302   CmiAssert( a>=0 && x<dimNA && b>=0 && b<dimNB && c>=0 && c<dimNC && d>=0 && d<dimND && e>=0 && e<dimNE && t>=0 && t<dimNT );
303   return bgqtm.coordinatesToRank(a, b, c, d, e, t);
304 }
305 #endif
306
307 int TopoManager::getHopsBetweenRanks(int pe1, int pe2) {
308   CmiAssert( pe1 >= 0 && pe1 < numPes );
309   CmiAssert( pe2 >= 0 && pe2 < numPes );
310 #if CMK_BLUEGENEQ
311   int a1, b1, c1, d1, e1, t1, a2, b2, c2, d2, e2, t2; 
312   rankToCoordinates(pe1, a1, b1, c1, d1, e1, t1);
313   rankToCoordinates(pe2, a2, b2, c2, d2, e2, t2);
314   return (absA(a2-a1)+absB(b2-b1)+absC(c2-c1)+absD(d2-d1)+absE(e2-e1));  
315 #else
316   int x1, y1, z1, x2, y2, z2, t1, t2;
317   rankToCoordinates(pe1, x1, y1, z1, t1);
318   rankToCoordinates(pe2, x2, y2, z2, t2);
319   return (absX(x2-x1)+absY(y2-y1)+absZ(z2-z1));
320 #endif
321 }
322
323 void TopoManager::sortRanksByHops(int pe, int *pes, int *idx, int n) {
324   /* The next three lines appear to do nothing other than waste time.
325      int minHops = getHopsBetweenRanks(pe, pes[0]);
326      int minIdx = 0;
327      int nowHops, tmp;
328   */
329   for(int i=0;i<n;i++)
330     idx[i] = i;
331   quicksort(pe, pes, idx, 0, n-1);
332 }
333
334 /*
335 int TopoManager::pickClosestRank(int mype, int *pes, int n) {
336 #if CMK_BLUEGENEL
337   return(bgltm->pickClosestRank(mype, pes, n));
338 #elif XT3_TOPOLOGY
339 #else 
340   return(pickClosestRank(mype,pes,n));
341 #endif
342 }
343 */
344
345 int TopoManager::pickClosestRank(int mype, int *pes, int n){
346   int minHops = getHopsBetweenRanks(mype, pes[0]);
347   int minIdx=0;
348   int nowHops; 
349   for(int i=1; i<n; i++) {
350     nowHops = getHopsBetweenRanks(mype, pes[i]);
351     if(nowHops < minHops) {
352       minHops = nowHops;
353       minIdx=i;
354     }
355   }
356   return minIdx;
357 }
358
359 int TopoManager::areNeighbors(int pe1, int pe2, int pe3, int distance) {
360 #if CMK_BLUEGENEQ
361   int pe1_a, pe1_b, pe1_c, pe1_d, pe1_e, pe1_t;
362   int pe2_a, pe2_b, pe2_c, pe2_d, pe2_e, pe2_t;
363   int pe3_a, pe3_b, pe3_c, pe3_d, pe3_e, pe3_t;
364   rankToCoordinates(pe1, pe1_a, pe1_b, pe1_c, pe1_d, pe1_e, pe1_t);
365   rankToCoordinates(pe2, pe2_a, pe2_b, pe2_c, pe2_d, pe2_e, pe2_t);
366   rankToCoordinates(pe3, pe3_a, pe3_b, pe3_c, pe3_d, pe3_e, pe3_t);
367
368   if ( (absA(pe1_a - (pe2_a+pe3_a)/2) + absB(pe1_b - (pe2_b+pe3_b)/2)+absC(pe1_c - (pe2_c+pe3_c)/2)+absD(pe1_d - (pe2_d+pe3_d)/2)+absE(pe1_e - (pe2_e+pe3_e)/2)) <= distance )
369     return 1;
370   else
371     return 0;
372 #else
373   int pe1_x, pe1_y, pe1_z, pe1_t;
374   int pe2_x, pe2_y, pe2_z, pe2_t;
375   int pe3_x, pe3_y, pe3_z, pe3_t;
376
377   rankToCoordinates(pe1, pe1_x, pe1_y, pe1_z, pe1_t);
378   rankToCoordinates(pe2, pe2_x, pe2_y, pe2_z, pe2_t);
379   rankToCoordinates(pe3, pe3_x, pe3_y, pe3_z, pe3_t);
380
381   if ( (absX(pe1_x - (pe2_x+pe3_x)/2) + absY(pe1_y - (pe2_y+pe3_y)/2) + absZ(pe1_z - (pe2_z+pe3_z)/2)) <= distance )
382     return 1;
383   else
384     return 0;
385 #endif
386 }
387
388 void TopoManager::quicksort(int pe, int *pes, int *arr, int left, int right) {
389   if(left<right) {
390     int split = partition(pe, pes, arr, left, right);
391     quicksort(pe, pes, arr, left, split);
392     quicksort(pe, pes, arr, split+1, right);
393   }
394 }
395
396 int TopoManager::partition(int pe, int *pes, int *idx, int left, int right) {
397   int val = getHopsBetweenRanks(pe, pes[idx[(left+right)/2]]);
398   int lm = left-1;
399   int rm = right+1;
400   for(;;) {
401     do
402       rm--;
403     while(getHopsBetweenRanks(pe, pes[idx[rm]]) > val);
404     do
405       lm++;
406     while(getHopsBetweenRanks(pe, pes[idx[lm]]) < val);
407     if(lm < rm) {
408       int tmp = idx[rm];
409       idx[rm] = idx[lm];
410       idx[lm] = tmp;
411     }
412     else
413       return rm;
414   }
415 }
416
417 void TopoManager::printAllocation(FILE *fp)
418 {
419         int i,x,y,z,t;
420         fprintf(fp, "Topology Info-\n");
421         fprintf(fp, "NumPes -  %d\n", numPes);
422         fprintf(fp, "Dims - %d %d %d\n",dimNX,dimNY,dimNZ);
423         fprintf(fp, "Rank - x y z t\n");
424         for(i=0; i<numPes; i++) {
425                 rankToCoordinates(i,x,y,z,t);
426                 fprintf(fp, "%d - %d %d %d %d\n",i,x,y,z,t);
427         }
428 }
429