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