use rca_get_max_dimension to find dimension
[charm.git] / src / util / CrayNid.c
1 /** \file CrayNid.c
2  *  Author: Abhinav S Bhatele
3  *  Date created: October 10th, 2007  
4  *  
5  *  This file is needed because including the cnos_mpi_os.h in a C++ leads 
6  *  to a compiler error. Hence we have defined a wrapper function here which
7  *  can be called from C++ files
8  */
9
10 #include <stdlib.h>
11 #include "converse.h"
12
13 #if CMK_CRAYXT || CMK_CRAYXE
14
15 #if XT3_TOPOLOGY
16 #include <catamount/cnos_mpi_os.h>
17
18 #else   /* if it is a XT4/5 or XE */
19 #include <pmi.h>
20 #endif
21
22 CmiNodeLock  cray_lock, cray_lock2;
23
24 /** \function getXTNodeID
25  *  returns nodeID corresponding to the MPI rank (possibly obtained
26  *  from CmiMyNode()/CmiNodeOf(pe)) passed to it
27  */
28 int getXTNodeID(int mpirank, int nummpiranks) {
29   int nid = -1;
30
31 #if XT3_TOPOLOGY
32   cnos_nidpid_map_t *nidpid; 
33   int ierr;
34   
35   nidpid = (cnos_nidpid_map_t *)malloc(sizeof(cnos_nidpid_map_t) * nummpiranks);
36
37   ierr = cnos_get_nidpid_map(&nidpid);
38   nid = nidpid[mpirank].nid;
39   free(nidpid); 
40
41 #elif CMK_HAS_PMI_GET_NID       /* if it is a XT4/5 or XE */
42   PMI_Get_nid(mpirank, &nid);
43 #else
44 #error "Cannot get network topology information on a Cray build. Swap current module xt-mpt with xt-mpt/5.0.0 or higher and xt-asyncpe with xt-asyncpe/4.0 or higher and then rebuild"
45 #endif
46
47   return nid;
48 }
49
50 #endif /* CMK_CRAYXT || CMK_CRAYXE */
51
52 #if XT3_TOPOLOGY || XT4_TOPOLOGY || XT5_TOPOLOGY || XE6_TOPOLOGY
53
54 #if !CMK_HAS_RCALIB
55 #error "The Cray rca library is not available. Try 'module load rca' and rebuild"
56 #endif
57
58 #include <rca_lib.h>
59
60 /*
61         #if XT3_TOPOLOGY
62         #define MAXNID 2784
63         #define TDIM 2
64
65   #elif XT4_TOPOLOGY
66   #define MAXNID 14000
67   #define TDIM 4
68
69   #elif XT5_TOPOLOGY
70   #define MAXNID 22020
71   #define TDIM 12
72
73   #elif XE6_TOPOLOGY
74     // hopper 
75   #define MAXNID 6384
76   #define TDIM 24
77 #if 0
78     // titan
79   #define MAXNID 9600
80 #define TDIM 16
81     // ESS 
82   #define MAXNID 4608
83   #define TDIM 32
84     // JYC
85   #define MAXNID 97
86   #define TDIM 32
87 #endif
88   #endif
89 */
90
91 int *pid2nid = NULL;            /* rank to node ID */
92 int maxX = -1;
93 int maxY = -1;
94 int maxZ = -1;
95 int maxNID = -1;
96 #if CMK_HAS_RCALIB
97 rca_mesh_coord_t  *coords = NULL;
98 #endif
99
100 void getDimension(int *maxnid, int *xdim, int *ydim, int *zdim);
101
102 /** \function getMeshCoord
103  *  wrapper function for rca_get_meshcoord
104  *  0: success,   -1: failure
105  */
106 int getMeshCoord(int nid, int *x, int *y, int *z) {
107 #if CMK_HAS_RCALIB
108   if (coords == NULL) {
109   rca_mesh_coord_t xyz;
110   int ret = -1;
111   ret = rca_get_meshcoord(nid, &xyz);
112   if (ret == -1) return -1;
113   *x = xyz.mesh_x;
114   *y = xyz.mesh_y;
115   *z = xyz.mesh_z;
116   return ret;
117   }
118   else {
119   *x = coords[nid].mesh_x;
120   *y = coords[nid].mesh_y;
121   *z = coords[nid].mesh_z;
122   return *x==-1?-1:0;
123   }
124 #else
125   CmiAbort("rca_get_meshcoord not exist");
126   return -1;
127 #endif
128 }
129
130 /** \function pidtonid
131  *  finds nids for pids 1 to CmiNumPes and stores them in an array
132  *  correspondingly also creates an array for nids to pids
133  */
134 void pidtonid(int numpes) {
135   CmiLock(cray_lock);
136   if (pid2nid != NULL) {
137       CmiUnlock(cray_lock);
138       return;          /* did once already */
139   }
140
141   getDimension(&maxNID,&maxX,&maxY,&maxZ);
142   int numCores = CmiNumCores();
143   
144   pid2nid = (int *)malloc(sizeof(int) * numpes);
145
146 #if XT3_TOPOLOGY
147   cnos_nidpid_map_t *nidpid; 
148   int ierr, i, nid;
149         int *nid2pid;
150         
151   nid2pid = (int*)malloc(maxNID*2*sizeof(int));
152   nidpid = (cnos_nidpid_map_t *)malloc(sizeof(cnos_nidpid_map_t) * numpes);
153
154   for(i=0; i<maxNID; i++) {
155     nid2pid[2*i+0] = -1;
156     nid2pid[2*i+1] = -1;
157   }
158       
159   ierr = cnos_get_nidpid_map(&nidpid);
160   for(i=0; i<numpes; i++) {
161     nid = nidpid[i].nid;
162     pid2nid[i] = nid;
163     
164     /* if the first position on the node is not filled */
165     /* put it there (0) else at (1) */
166     if (nid2pid[2*nid+0] == -1)
167       nid2pid[2*nid+0] = i;
168     else
169       nid2pid[2*nid+1] = i;
170   }
171
172   /* CORRECTION FOR MPICH_RANK_REORDER_METHOD */
173
174   int k = -1;
175   for(i=0; i<maxNID; i++) {
176     if(nid2pid[2*i+0] != -1) {
177       nid2pid[2*i+0] = k++;
178       pid2nid[k] = i;
179       nid2pid[2*i+1] = k++;
180       pid2nid[k] = i;
181     }
182   }
183         free(nidpid);
184         free(nid2pid);
185
186 #elif XT4_TOPOLOGY || XT5_TOPOLOGY || XE6_TOPOLOGY
187   int i, nid, ret;
188   CmiAssert(coords == NULL);
189   coords = (rca_mesh_coord_t *)malloc(sizeof(rca_mesh_coord_t)*(maxNID+1));
190   for (i=0; i<maxNID; i++) {
191     coords[i].mesh_x = coords[i].mesh_y = coords[i].mesh_z = -1;
192   }
193   for (i=0; i<numpes; i++) {
194     PMI_Get_nid(CmiNodeOf(i), &nid);
195     pid2nid[i] = nid;
196     CmiAssert(nid < maxNID);
197     ret = rca_get_meshcoord(nid, &coords[nid]);
198     CmiAssert(ret != -1);
199   }
200 #endif
201   CmiUnlock(cray_lock);
202 }
203
204 /* get size and dimension for XE machine */
205 void getDimension(int *maxnid, int *xdim, int *ydim, int *zdim)
206 {
207   int i = 0, ret;
208   rca_mesh_coord_t dimsize;
209
210   CmiLock(cray_lock2);
211
212   if(maxNID != -1) {
213         *xdim = maxX;
214         *ydim = maxY;
215         *zdim = maxZ;
216         *maxnid = maxNID;
217         CmiUnlock(cray_lock2);
218         return;
219   }
220
221 #if CMK_HAS_RCA_MAX_DIMENSION
222   // rca_get_meshtopology(&mnid);
223   rca_get_max_dimension(&dimsize);
224   *xdim = dimsize.mesh_x+1;
225   *ydim = dimsize.mesh_y+1;
226   *zdim = dimsize.mesh_z+1;
227   *maxnid = *xdim * *ydim * *zdim * 2;
228
229 #else
230
231   *xdim = *ydim = *zdim = 0;
232     /* loop until fails to find the max */ 
233   do {
234       int x, y, z;
235       ret = getMeshCoord(i, &x, &y, &z);
236       if (ret == -1) {
237 #if CMK_CRAY_MAXNID
238           if (i<=CMK_CRAY_MAXNID) {
239               i++;
240               ret = 0;
241               continue;
242           }
243 #endif
244           break;
245       }
246       if (x>*xdim) *xdim = x;
247       if (y>*ydim) *ydim = y;
248       if (z>*zdim) *zdim = z;
249       i++;
250   } while (ret == 0);
251   maxNID = *maxnid = i;
252   maxX = *xdim = *xdim+1;
253   maxY = *ydim = *ydim+1;
254   maxZ = *zdim = *zdim+1;
255 #endif
256
257   CmiUnlock(cray_lock2);
258
259   /* printf("%d %d %d %d\n", *maxnid, *xdim, *ydim, *zdim); */
260 }
261
262 void craynid_init()
263 {
264   if (CmiMyRank()==0) {
265     cray_lock = CmiCreateLock();
266     cray_lock2 = CmiCreateLock();
267
268     pidtonid(CmiNumPes());
269   }
270 }
271
272 #endif /* XT3_TOPOLOGY || XT4_TOPOLOGY || XT5_TOPOLOGY || XE6_TOPOLOGY */