fixing for ft
[charm.git] / src / conv-com / treerouter.C
1 /**
2    @addtogroup ConvComlibRouter
3    @{
4    @file 
5    @brief  Tree based converse level routing strategy 
6 */
7
8 #include "treerouter.h"
9 #define DEGREE 4
10 #define gmap(pe) (gpes ? gpes[pe] : pe)
11
12
13 /**The only communication op used. Modify this to use vector send. */
14 #if CMK_COMLIB_USE_VECTORIZE
15 #define TREESENDFN(kid, u, knewmsg, khndl, knextpe)  \
16         {if (knewmsg) {\
17           CmiSetHandler(knewmsg->msgs[0], khndl);\
18           CmiSyncVectorSendAndFree(knextpe, -knewmsg->count, knewmsg->sizes, knewmsg->msgs);\
19         }\
20         else {\
21           SendDummyMsg(kid, knextpe, u);\
22         }\
23 }
24 #else
25 #define TREESENDFN(kid, u, knewmsg, klen, khndl, knextpe)  \
26         {if (knewmsg) {\
27           CmiSetHandler(knewmsg, khndl);\
28           CmiSyncSendAndFree(knextpe, klen, knewmsg);\
29         }\
30         else {\
31           SendDummyMsg(kid, knextpe, u);\
32         }\
33 }
34 #endif
35
36
37
38
39 TreeRouter :: TreeRouter(int n, int me, Strategy *parent) : Router(parent)
40 {
41   int i;
42   MyPe=me;
43   NumPes=n;
44   gpes=NULL;
45
46   numChildren=0;
47   for (i=0;i<DEGREE;i++) {
48         if ((MyPe*DEGREE+i+1) < NumPes) numChildren++;
49   }
50
51   PeTree = new PeTable(NumPes);
52
53   recvExpected=1+numChildren;
54   InitVars();
55   //CmiPrintf("Tree with n=%d, me=%d\n", n, me);
56 }
57
58 TreeRouter :: ~TreeRouter()
59 {
60   delete PeTree;
61 }
62
63 void TreeRouter :: InitVars()
64 {
65   recvCount=0;
66 }
67
68
69 void TreeRouter::NumDeposits(comID , int num)
70 {
71 }
72
73 void TreeRouter::EachToAllMulticast(comID id, int size, void *msg, int more)
74 {
75   int npe=NumPes;
76   int * destpes=(int *)CmiAlloc(sizeof(int)*npe);
77   for (int i=0;i<npe;i++) destpes[i]=i;
78   EachToManyMulticast(id, size, msg, npe, destpes, more);
79 }
80
81 void TreeRouter::EachToManyMulticast(comID id, int size, void *msg, int numpes, int *destpes, int more)
82 {
83  //Create the message
84   if (size) {
85         PeTree->InsertMsgs(numpes, destpes, size, msg);
86   }
87
88   if (more >0) return;
89
90   //Hand it over to Recv. 
91   RecvManyMsg(id, NULL);
92 }
93
94 void TreeRouter :: RecvManyMsg(comID id, char *msg)
95 {
96   if (msg)
97         PeTree->UnpackAndInsert(msg);
98   recvCount++;
99   //CmiPrintf("%d Tree: recvCount=%d, recvExpected=%d\n",MyPe, recvCount, recvExpected);
100   if (recvCount == recvExpected) {
101         if (MyPe) {
102                 int len;
103                 int parent=(MyPe-1)/DEGREE;
104                 parent=gmap(parent);
105 #if CMK_COMLIB_USE_VECTORIZE
106                 PTvectorlist newmsg=SortBufferUp(id, 0);
107                 TREESENDFN(id, 0, newmsg, CkpvAccess(RouterRecvHandle), parent);
108 #else
109                 char *newmsg=SortBufferUp(id, 0, &len);
110                 TREESENDFN(id, 0, newmsg, len, CkpvAccess(RouterRecvHandle), parent);
111 #endif
112         }
113         else {
114                 DownStreamMsg(id);
115         }
116   }
117   if (recvCount > recvExpected) DownStreamMsg(id);
118 }
119
120 #if CMK_COMLIB_USE_VECTORIZE
121 PTvectorlist TreeRouter :: SortBufferUp(comID id, int ufield)
122 #else
123 char * TreeRouter :: SortBufferUp(comID id, int ufield, int *len)
124 #endif
125 {
126   int np=0, i;
127   int * pelst=(int *)CmiAlloc(sizeof(int)*NumPes);
128
129   for (i=0;i<NumPes;i++) {
130
131         //if (i==MyPe) continue;
132         int pe=i;
133         while (pe!=MyPe && pe>0) pe =(pe-1)/DEGREE;
134         if (pe == MyPe) continue;
135
136         pelst[np++]=i;
137   }
138 #if CMK_COMLIB_USE_VECTORIZE
139   PTvectorlist newmsg=PeTree->ExtractAndVectorize(id, ufield, np, pelst); 
140 #else
141   char *newmsg=PeTree->ExtractAndPack(id, ufield, np, pelst, len); 
142 #endif
143   CmiFree(pelst);
144   return(newmsg);
145 }
146   
147 #if CMK_COMLIB_USE_VECTORIZE
148 PTvectorlist TreeRouter :: SortBufferDown(comID id, int ufield, int s)
149 #else
150 char * TreeRouter :: SortBufferDown(comID id, int ufield, int *len, int s)
151 #endif
152 {
153   int np=0, i;
154   int * plist=(int *)CmiAlloc(sizeof(int)*NumPes);
155
156   for (i=0;i<NumPes;i++) {
157         if (i==MyPe) continue;
158         int pe=i;
159         int rep=MyPe*DEGREE+s;
160         while (pe!=rep && pe>0) pe =(pe-1)/DEGREE;
161         if (pe == rep) plist[np++]=i;
162   }
163
164 #if CMK_COMLIB_USE_VECTORIZE
165   PTvectorlist newmsg=PeTree->ExtractAndVectorize(id, ufield, np, plist); 
166 #else
167   char * newmsg=PeTree->ExtractAndPack(id, ufield, np, plist, len); 
168 #endif
169   CmiFree(plist);
170   return(newmsg);
171 }
172
173 void TreeRouter :: DownStreamMsg(comID id)
174 {
175   int deg=DEGREE;
176   if (NumPes < deg) deg=NumPes;
177
178   for (int i=0;i<deg;i++) {
179     int len;
180 #if CMK_COMLIB_USE_VECTORIZE
181     PTvectorlist newmsg=SortBufferDown(id, 0, i+1);
182 #else
183     char *newmsg=SortBufferDown(id, 0, &len, i+1);
184 #endif
185     int child=MyPe*DEGREE+i+1;
186     if (child >=NumPes || child==MyPe) break;
187     child=gmap(child);
188 #if CMK_COMLIB_USE_VECTORIZE
189     TREESENDFN(id, 0, newmsg, CkpvAccess(RouterRecvHandle), child);
190 #else
191     TREESENDFN(id, 0, newmsg, len, CkpvAccess(RouterRecvHandle), child);
192 #endif
193   }
194
195   LocalProcMsg(id);
196 }
197
198 void TreeRouter :: ProcManyMsg(comID id, char *m)
199 {
200   PeTree->UnpackAndInsert(m);
201   LocalProcMsg(id);
202 }
203
204 void TreeRouter:: LocalProcMsg(comID id)
205 {
206   PeTree->ExtractAndDeliverLocalMsgs(MyPe, container);
207   PeTree->Purge();
208   InitVars();
209   Done(id);
210 }
211
212 void TreeRouter :: DummyEP(comID id, int)
213 {
214   RecvManyMsg(id, NULL);
215 }
216
217 Router * newtreeobject(int n, int me, Strategy *strat)
218 {
219   Router * obj=new TreeRouter(n, me, strat);
220   return(obj);
221 }
222
223 void TreeRouter :: SetMap(int *pes)
224 {
225   gpes=pes;
226 }
227
228
229 /*@}*/