bugfix
[charm.git] / src / conv-com / 3dgridrouter.C
1 /************************************************************
2  * File : D3Gridrouter.C
3  *
4  * Author : Sameer Kumar
5  *
6  * Grid (3d grid) based router
7  ***********************************************************/
8 #include <math.h>
9 #include "3dgridrouter.h"
10 //#define NULL 0
11
12 #define gmap(pe) {if (gpes) pe=gpes[pe];}
13
14 /**The only communication op used. Modify this to use
15  ** vector send */
16 #define GRIDSENDFN(kid, u1, u2, knpe, kpelist, khndl, knextpe)  \
17         {int len;\
18         char *newmsg;\
19         newmsg=PeGrid->ExtractAndPack(kid, u1, knpe, kpelist, &len);\
20         if (newmsg) {\
21           CmiSetHandler(newmsg, khndl);\
22           CmiSyncSendAndFree(knextpe, len, (char *)newmsg);\
23         }\
24         else {\
25           SendDummyMsg(kid, knextpe, u2);\
26         }\
27 }
28
29 #define ROWLEN COLLEN
30 #define NPLANES (int)ceil(((double)NumPes) / (ROWLEN * COLLEN))
31
32 #define RowLen(pe) ColLen3D(pe)
33 #define PELISTSIZE ((ROWLEN-1)/sizeof(int)+1)
34
35 double cubeRoot(double d) {
36   return pow(d,1.0/3.0);
37 }
38
39
40 inline int ColLen3D(int npes)
41 {
42     int len= (int)cubeRoot((double)npes);
43     //    ComlibPrintf("%d:collen len = %d\n", CkMyPe(), len);
44     if (npes > (len * len * len)) len++;
45     return(len);
46 }
47
48 inline int Expect1(int gpe, int gnpes)
49 {
50     int i, len=ColLen3D(gnpes);
51     int pe = gpe % (len * len);
52     
53     int npes = len * len;
54     if((gnpes - 1)/(len * len) == gpe / (len * len))
55         npes = ((gnpes - 1) % (len*len)) + 1;
56     
57     for (i=len-1;i>=0;i--) {
58         int myrow=pe/len;
59         int toprep=i*len;
60         int offset=pe-myrow*len;
61         if ((toprep+offset) <= (npes-1)) return(i+1);
62     }
63     return 0;
64     //return(len);
65 }
66
67 inline int Expect2(int gpe, int gnpes) {
68     int len=RowLen(gnpes);
69     int myplane = gpe / (len * len);
70     int lastplane = (gnpes - 1)/(len * len);
71     
72     if(myplane < lastplane)
73         return len;
74
75     int pe = gpe % (len * len);
76     int myrow = pe / len;
77     int lastrow = ((gnpes - 1) % (len * len)) / len;
78     
79     if (myrow < lastrow)
80         return len;
81     
82     int ret = ((gnpes - 1) % (len * len)) - myrow * len + 1;
83     if(ret < 0)
84         ret = 0;
85     return ret;
86 }
87     
88
89 inline int LPMsgExpect(int gpe, int gnpes)
90 {
91     int i;
92     int row = RowLen(gnpes);
93     int col = ColLen3D(gnpes);
94     int len = (int)ceil(((double)gnpes) / (row * col));
95
96     for (i=len-1;i>=0;i--) {
97         int myrow = (gpe%(row * col))/col;
98         int toprep=i*(row * col);
99         
100         if ((toprep + (gpe % (row * col))) <= (gnpes-1)) return(i+1);
101     }
102     return(len);
103 }
104
105 /****************************************************
106  * Preallocated memory=P ints + MAXNUMMSGS msgstructs
107  *****************************************************/
108 D3GridRouter::D3GridRouter(int n, int me)
109 {
110     ComlibPrintf("PE=%d me=%d NUMPES=%d\n", CkMyPe(), me, n);
111     
112     NumPes=n;
113     MyPe=me;
114     gpes=NULL;
115
116     COLLEN=ColLen3D(NumPes);
117
118     recvExpected[0] = 0;
119     recvExpected[1] = 0;
120     routerStage = 0;
121     
122     int myrow = (MyPe % (ROWLEN * COLLEN)) / COLLEN;
123     int myrep = myrow * COLLEN + MyPe - (MyPe % (ROWLEN * COLLEN));
124     int numunmappedpes=myrep+ROWLEN-NumPes;
125     int nummappedpes=ROWLEN;
126     
127     if (numunmappedpes >0) {
128         nummappedpes=NumPes-myrep;
129         int i=NumPes+MyPe-myrep;
130         while (i<myrep+ROWLEN) {
131             recvExpected[0] += Expect1(i, NumPes);
132             i+=nummappedpes;
133         }
134     }
135     
136     if((NumPes % (COLLEN * ROWLEN) != 0) && ((NumPes - 1)/(ROWLEN*COLLEN) - MyPe/(ROWLEN*COLLEN) == 1)){
137         if(myrep + ROWLEN * COLLEN >= NumPes) 
138             recvExpected[0] += Expect1(MyPe + ROWLEN*COLLEN, NumPes);
139         
140         if(MyPe + ROWLEN * COLLEN >= NumPes) 
141             recvExpected[1] += Expect2(MyPe + ROWLEN*COLLEN, NumPes);
142         ComlibPrintf("%d: here\n");
143     }
144
145     recvExpected[0] += Expect1(MyPe, NumPes);
146     recvExpected[1] += Expect2(MyPe, NumPes);
147
148     LPMsgExpected = LPMsgExpect(MyPe, NumPes);
149     //ComlibPrintf("%d LPMsgExpected=%d\n", MyPe, LPMsgExpected);
150     
151     PeGrid = new PeTable(/*CkNumPes()*/NumPes);
152     
153     oneplane = new int[NPLANES * ROWLEN];
154     zline = new int[NPLANES];
155     
156     InitVars();
157     ComlibPrintf("%d:%d:COLLEN=%d, ROWLEN=%d, recvexpected=%d,%d\n", CkMyPe(), MyPe, COLLEN, ROWLEN, recvExpected[0], recvExpected[1]);
158 }
159
160 D3GridRouter::~D3GridRouter()
161 {
162     delete PeGrid;
163     delete[] zline;
164     delete[] oneplane;
165 }
166
167 void D3GridRouter :: InitVars()
168 {
169     recvCount[0]=0;
170     recvCount[1]=0;
171     
172     LPMsgCount=0;
173 }
174
175 void D3GridRouter::NumDeposits(comID, int num)
176 {
177 }
178
179 void D3GridRouter::EachToAllMulticast(comID id, int size, void *msg, int more)
180 {
181     int npe=NumPes;
182     int * destpes=(int *)CmiAlloc(sizeof(int)*npe);
183     for (int i=0;i<npe;i++) destpes[i]=i;
184     EachToManyMulticast(id, size, msg, npe, destpes, more);
185 }
186
187 void D3GridRouter::EachToManyMulticast(comID id, int size, void *msg, int numpes, int *destpes, int more)
188 {
189     int i;
190     
191     //Buffer the message
192     if (size) {
193         PeGrid->InsertMsgs(numpes, destpes, size, msg);
194     }
195     
196     if (more) return;
197
198     routerStage = 0;
199     ComlibPrintf("All messages received %d %d\n", CkMyPe(), COLLEN);
200     
201     //Send the messages
202     int firstproc = MyPe - (MyPe % (ROWLEN * COLLEN));
203     for (i=0;i<COLLEN;i++) {
204         
205         ComlibPrintf("ROWLEN = %d, COLLEN =%d first proc = %d\n", ROWLEN, COLLEN, firstproc);
206         
207         int MYROW = (MyPe % (ROWLEN * COLLEN))/ROWLEN;
208         int nextrowrep = firstproc + i*ROWLEN;
209         
210         int nextpe = (MyPe % (ROWLEN * COLLEN)) % ROWLEN + nextrowrep;
211         int nummappedpes=NumPes-nextrowrep;
212         
213         if (nummappedpes <= 0) { // looks for nextpe in the previous plane
214             nextpe -= ROWLEN * COLLEN;
215             if(nextpe < 0)
216                 continue;
217         }
218
219         if (nextpe >= NumPes) {
220             int mm=(nextpe-NumPes) % nummappedpes;
221             nextpe=nextrowrep+mm;
222         }
223         
224         int nplanes = (int)ceil(((double)NumPes) / (ROWLEN * COLLEN));
225         int idx = 0;
226         
227         ComlibPrintf("%d->%d:(", MyPe, nextpe);
228         for (int j=0;j< ROWLEN;j++) 
229             for(int k = 0; k < nplanes; k++) {
230                 int dest = i * ROWLEN + j + ROWLEN * COLLEN * k;
231                 if(dest < NumPes) {
232                     oneplane[idx++] = dest;
233                     ComlibPrintf("%d,", oneplane[idx-1]);
234                 }
235                 else break;
236             }
237         ComlibPrintf(")\n");
238         
239         if (nextpe == MyPe) {
240             ComlibPrintf("%d calling recv directly\n", MyPe);
241             recvCount[0]++;
242             RecvManyMsg(id, NULL);
243             continue;
244         }
245         
246         ComlibPrintf("nummappedpes = %d, NumPes = %d, nextrowrep = %d, nextpe = %d, mype = %d\n", nummappedpes, NumPes, nextrowrep,  nextpe, MyPe);
247         
248         gmap(nextpe);
249         ComlibPrintf("sending to column %d and dest %d in %d\n", i, nextpe, CkMyPe());
250         GRIDSENDFN(id, 0, 0, idx, oneplane, CkpvAccess(RecvHandle), nextpe); 
251     }
252 }
253
254 void D3GridRouter::RecvManyMsg(comID id, char *msg)
255 {
256     ComlibPrintf("%d recvcount=%d,%d recvexpected = %d,%d\n", MyPe, recvCount[0],  recvCount[1], recvExpected[0],recvExpected[1]);
257     int stage = 0;
258     if (msg) {
259         stage = PeGrid->UnpackAndInsert(msg);
260         recvCount[stage]++;
261     }
262     
263     if ((recvCount[0] == recvExpected[0]) && (routerStage == 0)){
264         routerStage = 1;
265         int myrow = (MyPe % (ROWLEN * COLLEN)) / COLLEN;
266         int myrep = myrow*ROWLEN + MyPe - (MyPe % (ROWLEN * COLLEN));
267         for (int i=0;i<ROWLEN;i++) {
268             int nextpe = myrep + i;
269             
270             //if (nextpe >= NumPes || nextpe==MyPe) continue;
271             
272             if(nextpe == MyPe) {
273                 recvCount[1]++;
274                 RecvManyMsg(id, NULL);
275                 continue;
276             }
277             
278             if(nextpe >= NumPes) {
279                 nextpe -= ROWLEN * COLLEN;
280                 if(nextpe < 0)
281                     continue;
282             }
283
284             int *pelist = zline;
285             int nplanes = (int)ceil(((double)NumPes) / (ROWLEN * COLLEN));
286             int k = 0;
287             
288             ComlibPrintf("recv:myrow = %d, nplanes = %d\n", myrow, nplanes);
289             ComlibPrintf("recv:%d->%d:", MyPe, nextpe);
290             for(k = 0; k < nplanes; k++) {
291                 int dest = myrow * ROWLEN + i + ROWLEN * COLLEN * k;
292                 ComlibPrintf("%d,", dest);
293                 if(dest >= NumPes)
294                     break;
295                 zline[k] = dest;
296             }
297             ComlibPrintf(")\n");
298
299             ComlibPrintf("Before gmap %d\n", nextpe);
300             
301             gmap(nextpe);
302             
303             ComlibPrintf("After gmap %d\n", nextpe);
304             
305             ComlibPrintf("%d:sending recv message %d %d\n", MyPe, nextpe, myrep);
306             GRIDSENDFN(id, 1, 1, k, pelist, CkpvAccess(RecvHandle), nextpe);
307         }
308     }
309     
310     if((recvCount[1] == recvExpected[1]) && (routerStage == 1)){
311         routerStage = 2;
312         int nplanes = (int)ceil(((double)NumPes) / (ROWLEN * COLLEN));
313         for (int k=0; k < nplanes; k++) {
314             int nextpe = (MyPe % (ROWLEN * COLLEN)) + k * ROWLEN * COLLEN;
315
316             if (nextpe >= NumPes || nextpe==MyPe) continue;
317             
318             int gnextpe = nextpe;
319             int *pelist = &gnextpe;
320             
321             ComlibPrintf("Before gmap %d\n", nextpe);
322             
323             gmap(nextpe);
324             
325             ComlibPrintf("After gmap %d\n", nextpe);
326             
327             ComlibPrintf("%d:sending proc message %d %d\n", MyPe, nextpe, nplanes);
328             GRIDSENDFN(id, 2, 2, 1, pelist, CkpvAccess(ProcHandle), nextpe);
329         }
330         LocalProcMsg(id);
331     }
332 }
333
334 void D3GridRouter::DummyEP(comID id, int stage)
335 {
336     if (stage == 2) {
337         ComlibPrintf("%d dummy calling lp\n", MyPe);
338         LocalProcMsg(id);
339     }
340     else {
341         recvCount[stage]++;
342         ComlibPrintf("%d dummy calling recv\n", MyPe);
343         RecvManyMsg(id, NULL);
344     }
345 }
346
347 void D3GridRouter:: ProcManyMsg(comID id, char *m)
348 {
349     PeGrid->UnpackAndInsert(m);
350     ComlibPrintf("%d proc calling lp\n", MyPe);
351     LocalProcMsg(id);
352 }
353
354 void D3GridRouter:: LocalProcMsg(comID id)
355 {
356     ComlibPrintf("%d local procmsg called\n", MyPe);
357     
358     LPMsgCount++;
359     PeGrid->ExtractAndDeliverLocalMsgs(MyPe);
360     
361     if (LPMsgCount==LPMsgExpected) {
362         PeGrid->Purge();
363         InitVars();
364         routerStage = 0;
365         ComlibPrintf("%d:Round Done\n", CkMyPe());
366         Done(id);
367     }
368 }
369
370 void D3GridRouter :: SetMap(int *pes)
371 {
372     gpes=pes;
373     
374     //ComlibPrintf("%d:GPES[1] = %d\n", CkMyPe(), gpes[1]);
375     //gpes[1] = 4;
376 }
377