topomanager: check in file missed during prev commit
[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 XT3_TOPOLOGY
51   dimX = xt3tm.getDimX();
52   dimY = xt3tm.getDimY();
53   dimZ = xt3tm.getDimZ();
54
55   dimNX = xt3tm.getDimNX();
56   dimNY = xt3tm.getDimNY();
57   dimNZ = xt3tm.getDimNZ();
58   dimNT = xt3tm.getDimNT();
59
60   procsPerNode = xt3tm.getProcsPerNode();
61   int *torus;
62   torus = xt3tm.isTorus();
63   torusX = torus[0];
64   torusY = torus[1];
65   torusZ = torus[2];
66   torusT = torus[3];
67
68 #elif XT4_TOPOLOGY || XT5_TOPOLOGY
69   dimX = xttm.getDimX();
70   dimY = xttm.getDimY();
71   dimZ = xttm.getDimZ();
72
73   dimNX = xttm.getDimNX();
74   dimNY = xttm.getDimNY();
75   dimNZ = xttm.getDimNZ();
76   dimNT = xttm.getDimNT();
77
78   procsPerNode = xttm.getProcsPerNode();
79   int *torus;
80   torus = xttm.isTorus();
81   torusX = torus[0];
82   torusY = torus[1];
83   torusZ = torus[2];
84   torusT = torus[3];
85
86 #else
87   dimX = CkNumPes();
88   dimY = 1;
89   dimZ = 1;
90
91   dimNX = dimX;
92   dimNY = 1;
93   dimNZ = 1;
94
95   dimNT = procsPerNode = 1;
96   torusX = true;
97   torusY = true;
98   torusZ = true;
99   torusT = false;
100 #endif
101
102 #if CMK_BLUEGENE_CHARM
103   BgGetSize(&dimNX, &dimNY, &dimNZ);
104
105   dimNT = procsPerNode = BgGetNumWorkThread();
106   dimX = dimNX * procsPerNode;
107   dimY = dimNY;
108   dimZ = dimNZ;
109
110   torusX = true;
111   torusY = true;
112   torusZ = true;
113   torusT = false;
114 #endif
115 }
116
117 TopoManager::TopoManager(int NX, int NY, int NZ, int NT) : dimNX(NX), dimNY(NY), dimNZ(NZ), dimNT(NT) {
118   /* we rashly assume only one dimension is expanded */
119   procsPerNode = dimNT;
120   dimX = dimNX * dimNT;
121   dimY = dimNY;
122   dimZ = dimNZ;
123   torusX = true;
124   torusY = true;
125   torusZ = true;
126 }
127
128 int TopoManager::hasMultipleProcsPerNode() const {
129   if(procsPerNode == 1)
130     return 0;
131   else
132     return 1;
133 }
134
135 void TopoManager::rankToCoordinates(int pe, int &x, int &y, int &z) {
136 #if CMK_BLUEGENEL
137   bgltm.rankToCoordinates(pe, x, y, z);
138 #elif CMK_BLUEGENEP
139   bgptm.rankToCoordinates(pe, x, y, z);
140 #elif XT3_TOPOLOGY || XT4_TOPOLOGY || XT5_TOPOLOGY
141   CmiAbort("This function should not be called on Cray XT machines\n");
142 #else
143   if(dimY > 1){
144     // Assumed TXYZ
145     x = pe % dimX;
146     y = (pe % (dimX * dimY)) / dimX;
147     z = pe / (dimX * dimY);
148   }
149   else {
150     x = pe; 
151     y = 0; 
152     z = 0;
153   }
154 #endif
155
156 #if CMK_BLUEGENE_CHARM
157   if(dimY > 1){
158     // Assumed TXYZ
159     x = pe % dimX;
160     y = (pe % (dimX * dimY)) / dimX;
161     z = pe / (dimX * dimY);
162   }
163   else {
164     x = pe; 
165     y = 0; 
166     z = 0;
167   }
168 #endif
169 }
170
171 void TopoManager::rankToCoordinates(int pe, int &x, int &y, int &z, int &t) {
172 #if CMK_BLUEGENEL
173   bgltm.rankToCoordinates(pe, x, y, z, t);
174 #elif CMK_BLUEGENEP
175   bgptm.rankToCoordinates(pe, x, y, z, t);
176 #elif XT3_TOPOLOGY
177   xt3tm.rankToCoordinates(pe, x, y, z, t);
178 #elif XT4_TOPOLOGY || XT5_TOPOLOGY
179   xttm.rankToCoordinates(pe, x, y, z, t);
180 #else
181   if(dimNY > 1) {
182     t = pe % dimNT;
183     x = (pe % (dimNT*dimNX)) / dimNT;
184     y = (pe % (dimNT*dimNX*dimNY)) / (dimNT*dimNX);
185     z = pe / (dimNT*dimNX*dimNY);
186   } else {
187     t = pe % dimNT;
188     x = (pe % (dimNT*dimNX)) / dimNT;
189     y = 0;
190     z = 0;
191   }
192 #endif
193
194 #if CMK_BLUEGENE_CHARM
195   if(dimNY > 1) {
196     t = pe % dimNT;
197     x = (pe % (dimNT*dimNX)) / dimNT;
198     y = (pe % (dimNT*dimNX*dimNY)) / (dimNT*dimNX);
199     z = pe / (dimNT*dimNX*dimNY);
200   } else {
201     t = pe % dimNT;
202     x = (pe % (dimNT*dimNX)) / dimNT;
203     y = 0;
204     z = 0;
205   }
206 #endif
207 }
208
209 int TopoManager::coordinatesToRank(int x, int y, int z) {
210 #if CMK_BLUEGENE_CHARM
211   if(dimY > 1)
212     return x + y*dimX + z*dimX*dimY;
213   else
214     return x;
215 #endif
216
217 #if CMK_BLUEGENEL
218   return bgltm.coordinatesToRank(x, y, z);
219 #elif CMK_BLUEGENEP
220   return bgptm.coordinatesToRank(x, y, z);
221 #elif XT3_TOPOLOGY || XT4_TOPOLOGY || XT5_TOPOLOGY
222   CmiAbort("This function should not be called on Cray XT machines\n");
223 #else
224   if(dimY > 1)
225     return x + y*dimX + z*dimX*dimY;
226   else
227     return x;
228 #endif
229 }
230
231 int TopoManager::coordinatesToRank(int x, int y, int z, int t) {
232 #if CMK_BLUEGENE_CHARM
233   if(dimNY > 1)
234     return t + (x + (y + z*dimNY) * dimNX) * dimNT;
235   else
236     return t + x * dimNT;
237 #endif
238
239 #if CMK_BLUEGENEL
240   return bgltm.coordinatesToRank(x, y, z, t);
241 #elif CMK_BLUEGENEP
242   return bgptm.coordinatesToRank(x, y, z, t);
243 #elif XT3_TOPOLOGY
244   return xt3tm.coordinatesToRank(x, y, z, t);
245 #elif XT4_TOPOLOGY || XT5_TOPOLOGY
246   return xttm.coordinatesToRank(x, y, z, t);
247 #else
248   if(dimNY > 1)
249     return t + (x + (y + z*dimNY) * dimNX) * dimNT;
250   else
251     return t + x * dimNT;
252 #endif
253 }
254
255 int TopoManager::getHopsBetweenRanks(int pe1, int pe2) {
256   int x1, y1, z1, x2, y2, z2, t1, t2;
257   rankToCoordinates(pe1, x1, y1, z1, t1);
258   rankToCoordinates(pe2, x2, y2, z2, t2);
259   return (absX(x2-x1)+absY(y2-y1)+absZ(z2-z1));
260 }
261
262 void TopoManager::sortRanksByHops(int pe, int *pes, int *idx, int n) {
263   int minHops = getHopsBetweenRanks(pe, pes[0]);
264   int minIdx = 0;
265   int nowHops, tmp;
266   for(int i=0;i<n;i++)
267     idx[i] = i;
268   quicksort(pe, pes, idx, 0, n-1);
269 }
270
271 /*
272 int TopoManager::pickClosestRank(int mype, int *pes, int n) {
273 #if CMK_BLUEGENEL
274   return(bgltm->pickClosestRank(mype, pes, n));
275 #elif XT3_TOPOLOGY
276 #else 
277   return(pickClosestRank(mype,pes,n));
278 #endif
279 }
280 */
281
282 int TopoManager::pickClosestRank(int mype, int *pes, int n){
283   int minHops = getHopsBetweenRanks(mype, pes[0]);
284   int minIdx=0;
285   int nowHops; 
286   for(int i=1; i<n; i++) {
287     nowHops = getHopsBetweenRanks(mype, pes[i]);
288     if(nowHops < minHops) {
289       minHops = nowHops;
290       minIdx=i;
291     }
292   }
293   return minIdx;
294 }
295
296 int TopoManager::areNeighbors(int pe1, int pe2, int pe3, int distance) {
297   int pe1_x, pe1_y, pe1_z, pe1_t;
298   int pe2_x, pe2_y, pe2_z, pe2_t;
299   int pe3_x, pe3_y, pe3_z, pe3_t;
300
301   rankToCoordinates(pe1, pe1_x, pe1_y, pe1_z, pe1_t);
302   rankToCoordinates(pe2, pe2_x, pe2_y, pe2_z, pe2_t);
303   rankToCoordinates(pe3, pe3_x, pe3_y, pe3_z, pe3_t);
304
305   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 )
306     return 1;
307   else
308     return 0;
309 }
310
311 void TopoManager::quicksort(int pe, int *pes, int *arr, int left, int right) {
312   if(left<right) {
313     int split = partition(pe, pes, arr, left, right);
314     quicksort(pe, pes, arr, left, split);
315     quicksort(pe, pes, arr, split+1, right);
316   }
317 }
318
319 int TopoManager::partition(int pe, int *pes, int *idx, int left, int right) {
320   int val = getHopsBetweenRanks(pe, pes[idx[(left+right)/2]]);
321   int lm = left-1;
322   int rm = right+1;
323   for(;;) {
324     do
325       rm--;
326     while(getHopsBetweenRanks(pe, pes[idx[rm]]) > val);
327     do
328       lm++;
329     while(getHopsBetweenRanks(pe, pes[idx[lm]]) < val);
330     if(lm < rm) {
331       int tmp = idx[rm];
332       idx[rm] = idx[lm];
333       idx[lm] = tmp;
334     }
335     else
336       return rm;
337   }
338 }
339