modified the registration of the converse handlers for propagate and propagate_frag.
[charm.git] / src / conv-com / gridrouter.C
1 /*****************************************************************************
2  * $Source$
3  * $Author$
4  * $Date$
5  * $Revision$
6  *****************************************************************************/
7
8 /************************************************************
9  * File : gridrouter.C
10  *
11  * Author : Krishnan V.
12  *
13  * Grid (mesh) based router
14  ***********************************************************/
15
16 #include "gridrouter.h"
17
18 #define gmap(pe) {if (gpes) pe=gpes[pe];}
19
20 /**The only communication op used. Modify this to use
21  ** vector send */
22 #define GRIDSENDFN(kid, u1, u2, knpe, kpelist, khndl, knextpe)  \
23         {int len;\
24         char *newmsg;\
25         newmsg=PeMesh->ExtractAndPack(kid, u1, knpe, kpelist, &len);\
26         if (newmsg) {\
27           CmiSetHandler(newmsg, khndl);\
28           CmiSyncSendAndFree(knextpe, len, newmsg);\
29         }\
30         else {\
31           SendDummyMsg(kid, knextpe, u2);\
32         }\
33 }
34
35 /****************************************************
36  * Preallocated memory=P ints + MAXNUMMSGS msgstructs
37  *****************************************************/
38 GridRouter::GridRouter(int n, int me)
39 {
40   //CmiPrintf("PE=%d me=%d NUMPES=%d\n", MyPe, me, n);
41   
42   NumPes=n;
43   MyPe=me;
44   gpes=NULL;
45   COLLEN=ColLen(NumPes);
46   LPMsgExpected = Expect(MyPe, NumPes);
47   recvExpected = 0;
48
49   myrow=MyPe/COLLEN;
50   mycol=MyPe%COLLEN;  
51   int lastrow = (NumPes - 1)/COLLEN;
52   
53   if(myrow < lastrow) 
54       recvExpected = ROWLEN;
55   else
56       recvExpected = (NumPes - 1)%ROWLEN + 1;
57
58   if(lastrow * COLLEN + mycol > NumPes - 1) {
59       //We have a hole in the lastrow
60       if(lastrow * COLLEN + myrow <= NumPes - 1) 
61           //We have a processor which wants to send data to that hole
62           recvExpected ++;
63       
64       if((myrow == 0) && (NumPes == ROWLEN*(COLLEN-1) - 1))
65           //Special case with one hole only
66           recvExpected ++;      
67   }
68   
69   ComlibPrintf("%d LPMsgExpected=%d\n", MyPe, LPMsgExpected);
70
71   PeMesh = new PeTable(NumPes);
72   PeMesh1 = new PeTable(NumPes);
73   PeMesh2 = new PeTable(NumPes);
74
75   onerow=(int *)CmiAlloc(ROWLEN*sizeof(int));
76
77   rowVector = (int *)CmiAlloc(ROWLEN*sizeof(int));
78   colVector = (int *)CmiAlloc(COLLEN*sizeof(int));
79
80   int myrep=myrow*COLLEN;
81   int count = 0;
82   int pos = 0;
83
84   for(count = mycol; count < ROWLEN+mycol; count ++){
85       int nextpe= myrep + count%ROWLEN;
86       
87       if (nextpe >= NumPes) {
88           int new_row = mycol % (myrow+1);
89           
90           if(new_row >= myrow)
91               new_row = 0;
92           
93           nextpe = COLLEN * new_row + count%ROWLEN;
94       }
95       
96       if(nextpe == MyPe)
97           continue;
98
99       ComlibPrintf("Row[%d] = %d\n", MyPe, nextpe);
100
101       rowVector[pos ++] = nextpe;
102   }
103   rvecSize = pos;
104
105   pos = 0;
106   for(count = myrow; count < COLLEN+myrow; count ++){
107       int nextrowrep = (count % COLLEN) *COLLEN;
108       int nextpe = nextrowrep+mycol;
109       
110       if(nextpe < NumPes && nextpe != MyPe)
111           colVector[pos ++] = nextpe;
112   }
113   
114   cvecSize = pos;
115
116   growVector = new int[rvecSize];
117   gcolVector = new int[cvecSize];
118
119   for(count = 0; count < rvecSize; count ++)
120       growVector[count] = rowVector[count];
121   
122   for(count = 0; count < cvecSize; count ++)
123       gcolVector[count] = colVector[count];
124   
125
126   InitVars();
127   ComlibPrintf("%d:COLLEN=%d, ROWLEN=%d, recvexpected=%d\n", MyPe, COLLEN, ROWLEN, recvExpected);
128 }
129
130 GridRouter::~GridRouter()
131 {
132   delete PeMesh;
133   delete PeMesh1;
134   delete PeMesh2;
135     
136   CmiFree(onerow);
137 }
138
139 void GridRouter :: InitVars()
140 {
141   recvCount=0;
142   LPMsgCount=0;
143 }
144
145 void GridRouter::NumDeposits(comID, int num)
146 {
147 }
148
149 void GridRouter::EachToAllMulticast(comID id, int size, void *msg, int more)
150 {
151   int npe=NumPes;
152   int * destpes=(int *)CmiAlloc(sizeof(int)*npe);
153   for (int i=0;i<npe;i++) destpes[i]=i;
154   EachToManyMulticast(id, size, msg, npe, destpes, more);
155 }
156
157 extern void CmiReference(void *blk);
158
159 void GridRouter::EachToManyMulticast(comID id, int size, void *msg, int numpes, int *destpes, int more)
160 {
161   if(id.isAllToAll)
162       PeMesh->InsertMsgs(1, &MyPe, size, msg);
163   else
164       PeMesh->InsertMsgs(numpes, destpes, size, msg);
165   
166   if (more) return;
167
168   ComlibPrintf("All messages received %d %d %d\n", MyPe, COLLEN,id.isAllToAll);
169   sendRow(id);
170 }
171
172 void GridRouter::EachToManyMulticastQ(comID id, CkQ<MessageHolder *> &msgq) {
173    
174     ComlibPrintf("Grid Router :: EachToManyQ\n");
175  
176     int count = 0;
177     int length = msgq.length();
178     if(id.isAllToAll) {
179         for(count = 0; count < length; count ++) {
180             MessageHolder *mhdl = msgq.deq();
181             PeMesh->InsertMsgs(1, &MyPe, mhdl->size, mhdl->getMessage());
182             delete mhdl;
183         }
184     }
185     else {
186         for(count = 0; count < length; count ++) {
187             MessageHolder *mhdl = msgq.deq();
188             PeMesh->InsertMsgs(mhdl->npes, mhdl->pelist, mhdl->size, 
189                                mhdl->getMessage());
190             delete mhdl;
191         }
192     }
193     
194     sendRow(id);
195 }
196
197
198 void GridRouter::sendRow(comID id) {
199
200     int i=0;
201     char *a2amsg = NULL;
202     int a2a_len;
203     if(id.isAllToAll) {
204         ComlibPrintf("ALL to ALL flag set\n");
205         
206         a2amsg = PeMesh->ExtractAndPackAll(id, 0, &a2a_len);
207         CmiSetHandler(a2amsg, CkpvAccess(RecvHandle));
208         CmiReference(a2amsg);
209         CmiSyncListSendAndFree(rvecSize, growVector, a2a_len, a2amsg);      
210         RecvManyMsg(id, a2amsg);
211         return;
212     }
213     
214     //Send the messages
215     //int MYROW  =MyPe/COLLEN;
216     //int MYCOL = MyPe%COLLEN;
217     int myrep= myrow*COLLEN; 
218     int maxlength = (NumPes - 1)/COLLEN + 1;
219     
220     for (int colcount = 0; colcount < rvecSize; ++colcount) {
221         int nextpe = rowVector[colcount];
222         i = nextpe % COLLEN;
223         
224         int length = maxlength;
225         if((length - 1)* COLLEN + i >= NumPes)
226             length --;
227         
228         for (int j = 0; j < length; j++) {
229             onerow[j]=j * COLLEN + i;
230         }
231         
232         ComlibPrintf("%d: before gmap sending to %d of column %d for %d procs,  %d,%d,%d,%d\n",
233                      MyPe, nextpe, i, length, onerow[0], onerow[1], onerow[2], onerow[3]);
234         
235         gmap(nextpe);
236         
237         GRIDSENDFN(id, 0, 0,length, onerow, CkpvAccess(RecvHandle), nextpe); 
238         ComlibPrintf("%d:sending to %d of column %d\n", MyPe, nextpe, i);
239     }
240     RecvManyMsg(id, NULL);
241 }
242
243 void GridRouter::RecvManyMsg(comID id, char *msg)
244 {
245   if (msg) {  
246       if(id.isAllToAll)
247           PeMesh1->UnpackAndInsertAll(msg, 1, &MyPe);
248       else
249           PeMesh->UnpackAndInsert(msg);
250   }
251
252   recvCount++;
253
254   ComlibPrintf("%d recvcount=%d recvexpected = %d\n", MyPe, recvCount, recvExpected);
255
256   if (recvCount == recvExpected) {
257       
258       char *a2amsg;
259       int a2a_len;
260       if(id.isAllToAll) {
261           a2amsg = PeMesh1->ExtractAndPackAll(id, 1, &a2a_len);
262           CmiSetHandler(a2amsg, CkpvAccess(ProcHandle));
263           CmiReference(a2amsg);
264           CmiSyncListSendAndFree(cvecSize, gcolVector, a2a_len, a2amsg);   
265           ProcManyMsg(id, a2amsg);
266           return;
267       }
268
269       for (int rowcount=0; rowcount < cvecSize; rowcount++) {
270           int nextpe = colVector[rowcount];
271                     
272           int gnextpe = nextpe;
273           int *pelist=&gnextpe;
274           
275           ComlibPrintf("Before gmap %d\n", nextpe);
276           
277           gmap(nextpe);
278
279           ComlibPrintf("After gmap %d\n", nextpe);
280           
281           ComlibPrintf("%d:sending message to %d of row %d\n", MyPe, nextpe, 
282                        rowcount);
283           
284           GRIDSENDFN(id, 0, 1, 1, pelist, CkpvAccess(ProcHandle), nextpe);
285       }
286       
287       LocalProcMsg(id);
288   }
289 }
290
291 void GridRouter::DummyEP(comID id, int magic)
292 {
293   if (magic == 1) {
294         //ComlibPrintf("%d dummy calling lp\n", MyPe);
295         LocalProcMsg(id);
296   }
297   else {
298         //ComlibPrintf("%d dummy calling recv\n", MyPe);
299         RecvManyMsg(id, NULL);
300   }
301 }
302
303 void GridRouter:: ProcManyMsg(comID id, char *m)
304 {
305     ComlibPrintf("%d: ProcManyMsg\n", MyPe);
306     
307     if(id.isAllToAll)
308         PeMesh2->UnpackAndInsertAll(m, 1, &MyPe);
309     else
310         PeMesh->UnpackAndInsert(m);
311     //ComlibPrintf("%d proc calling lp\n");
312     
313     LocalProcMsg(id);
314 }
315
316 void GridRouter:: LocalProcMsg(comID id)
317 {
318     LPMsgCount++;
319     PeMesh->ExtractAndDeliverLocalMsgs(MyPe);
320     if(id.isAllToAll)
321         PeMesh2->ExtractAndDeliverLocalMsgs(MyPe);
322     
323     ComlibPrintf("%d local procmsg called, %d, %d\n", MyPe, 
324                  LPMsgCount, LPMsgExpected);
325     if (LPMsgCount==LPMsgExpected) {
326         PeMesh->Purge();
327         if(id.isAllToAll)
328             PeMesh2->Purge();
329         
330         InitVars();
331         Done(id);
332     }
333 }
334
335 Router * newgridobject(int n, int me)
336 {
337   Router *obj=new GridRouter(n, me);
338   return(obj);
339 }
340
341 void GridRouter :: SetMap(int *pes)
342 {
343     
344   gpes=pes;
345   
346   if(!gpes)
347       return;
348
349   int count = 0;
350
351   for(count = 0; count < rvecSize; count ++)
352       growVector[count] = gpes[rowVector[count]];
353   
354   for(count = 0; count < cvecSize; count ++)
355       gcolVector[count] = gpes[colVector[count]];
356 }
357