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