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