Adding communication library in src/ck-com and src/conv-com
[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       ComlibPrintf("%d: before gmap sending to %d of column %d\n",
200                    MyPe, nextpe, i);
201       gmap(nextpe);
202       ComlibPrintf("%d:sending to %d of column %d\n", MyPe, nextpe, i);
203       
204       GRIDSENDFN(id, 0, 0, length, onerow, CkpvAccess(RecvHandle), nextpe); 
205   }
206   RecvManyMsg(id, NULL);
207 }
208
209 void GridRouter::RecvManyMsg(comID id, char *msg)
210 {
211   if (msg) {  
212       if(id.isAllToAll)
213           PeMesh1->UnpackAndInsertAll(msg, 1, &MyPe);
214       else
215           PeMesh->UnpackAndInsert(msg);
216   }
217
218   recvCount++;
219   if (recvCount == recvExpected) {
220       ComlibPrintf("%d recvcount=%d recvexpected = %d\n", MyPe, recvCount, recvExpected);
221       
222       int myrow=MyPe/COLLEN;
223       int mycol=MyPe%COLLEN;
224       
225       char *a2amsg;
226       int a2a_len;
227       if(id.isAllToAll) {
228           a2amsg = PeMesh1->ExtractAndPackAll(id, 1, &a2a_len);
229           CmiSetHandler(a2amsg, CkpvAccess(ProcHandle));
230           CmiReference(a2amsg);
231           CmiSyncListSendAndFree(cvecSize, gcolVector, a2a_len, a2amsg);   
232           ProcManyMsg(id, a2amsg);
233           return;
234       }
235
236       for (int rowcount=0; rowcount < cvecSize; rowcount++) {
237           int nextpe = colVector[rowcount];
238                     
239           int gnextpe = nextpe;
240           int *pelist=&gnextpe;
241           
242           ComlibPrintf("Before gmap %d\n", nextpe);
243           
244           gmap(nextpe);
245
246           ComlibPrintf("After gmap %d\n", nextpe);
247           
248           ComlibPrintf("%d:sending message to %d of row %d\n", MyPe, nextpe, 
249                        rowcount);
250           
251           GRIDSENDFN(id, 0, 1, 1, pelist, CkpvAccess(ProcHandle), nextpe);
252       }
253       
254       LocalProcMsg(id);
255   }
256 }
257
258 void GridRouter::DummyEP(comID id, int magic)
259 {
260   if (magic == 1) {
261         //ComlibPrintf("%d dummy calling lp\n", MyPe);
262         LocalProcMsg(id);
263   }
264   else {
265         //ComlibPrintf("%d dummy calling recv\n", MyPe);
266         RecvManyMsg(id, NULL);
267   }
268 }
269
270 void GridRouter:: ProcManyMsg(comID id, char *m)
271 {
272     if(id.isAllToAll)
273         PeMesh2->UnpackAndInsertAll(m, 1, &MyPe);
274     else
275         PeMesh->UnpackAndInsert(m);
276     //ComlibPrintf("%d proc calling lp\n");
277     
278     LocalProcMsg(id);
279 }
280
281 void GridRouter:: LocalProcMsg(comID id)
282 {
283     LPMsgCount++;
284     PeMesh->ExtractAndDeliverLocalMsgs(MyPe);
285     PeMesh2->ExtractAndDeliverLocalMsgs(MyPe);
286     
287     ComlibPrintf("%d local procmsg called\n", MyPe);
288     if (LPMsgCount==LPMsgExpected) {
289         PeMesh->Purge();
290         PeMesh2->Purge();
291         
292         InitVars();
293         Done(id);
294     }
295 }
296
297 Router * newgridobject(int n, int me)
298 {
299   Router *obj=new GridRouter(n, me);
300   return(obj);
301 }
302
303 void GridRouter :: SetMap(int *pes)
304 {
305     
306   gpes=pes;
307   
308   if(!gpes)
309       return;
310
311   int count = 0;
312
313   for(count = 0; count < rvecSize; count ++)
314       growVector[count] = gpes[rowVector[count]];
315   
316   for(count = 0; count < cvecSize; count ++)
317       gcolVector[count] = gpes[colVector[count]];
318 }
319