00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "de.h"
00015
00016 #define gmap(pe) {if (gpes) pe=gpes[pe];}
00017
00018
00019
00023 #if CMK_COMMLIB_USE_VECTORIZE
00024 #define HCUBESENDFN(kid, u1, u2, knpe, kpelist, khndl, knextpe, pehcube) \
00025 {int len;\
00026 PTvectorlist newmsg;\
00027 newmsg=pehcube->ExtractAndVectorize(kid, u1, knpe, kpelist);\
00028 if (newmsg) {\
00029 CmiSetHandler(newmsg->msgs[0], khndl);\
00030 CmiSyncVectorSendAndFree(knextpe, -newmsg->count, newmsg->sizes, newmsg->msgs);\
00031 }\
00032 else {\
00033 SendDummyMsg(kid, knextpe, u2);\
00034 }\
00035 }
00036 #else
00037 #define HCUBESENDFN(kid, u1, u2, knpe, kpelist, khndl, knextpe, pehcube) \
00038 {int len;\
00039 char *newmsg;\
00040 newmsg=pehcube->ExtractAndPack(kid, u1, knpe, kpelist, &len);\
00041 if (newmsg) {\
00042 CmiSetHandler(newmsg, khndl);\
00043 CmiSyncSendAndFree(knextpe, len, newmsg);\
00044 }\
00045 else {\
00046 SendDummyMsg(kid, knextpe, u2);\
00047 }\
00048 }
00049 #endif
00050
00051 inline int maxdim(int n)
00052 {
00053 int maxpes=1, dim=0;
00054
00055 while (maxpes< n) {
00056 maxpes *=2;
00057 dim++;
00058 }
00059 if (maxpes==n) return(dim);
00060 else return(dim-1);
00061 }
00062
00063 inline int neighbor(int pe, int dim)
00064 {
00065 return(pe ^ (1<<dim));
00066 }
00067
00068 inline int adjust(int dim, int pe)
00069 {
00070 int mymax=1<<dim;
00071 if (pe >= mymax) return(neighbor(pe, dim));
00072 else return(pe);
00073 }
00074
00075 inline int setIC(int dim, int pe, int N)
00076 {
00077 int mymax= 1<< dim;
00078 int initCounter=1, myneighb;
00079 if (mymax < N) {
00080 myneighb= neighbor(pe, dim);
00081 if (myneighb < N && myneighb >= mymax) {
00082 initCounter=0;
00083 }
00084 }
00085 if (pe >= mymax) initCounter = -1;
00086 return(initCounter);
00087 }
00088
00089
00090
00091
00092 DimexRouter::DimexRouter(int n, int me, int ndirect)
00093 {
00094 int i;
00095
00096
00097 numDirectSteps = ndirect;
00098
00099 two_pow_ndirect = 1;
00100 for(int count = 0; count < ndirect; count ++)
00101 two_pow_ndirect *= 2;
00102
00103
00104 NumPes=n;
00105 MyPe=me;
00106 gpes=NULL;
00107
00108
00109 Dim=maxdim(NumPes);
00110
00111 PeHcube=new PeTable(NumPes);
00112 PeHcube1 = new PeTable(NumPes);
00113
00114 InitVars();
00115
00116
00117 buffer=new int[Dim+1];
00118 next= new int* [Dim];
00119 for (i=0;i<Dim;i++) {
00120 next[i]=new int[NumPes];
00121 buffer[i]=0;
00122 for (int j=0;j<NumPes;j++) next[i][j]=-1;
00123 }
00124 buffer[Dim]=0;
00125
00126
00127 penum=new int[NumPes];
00128 int *dp=new int[NumPes];
00129 for (i=0;i<NumPes;i++) {
00130 penum[i]=0;
00131 dp[i]=i;
00132 }
00133
00134 CreateStageTable(NumPes, dp);
00135 delete [] dp;
00136
00137
00138
00139 if(numDirectSteps > Dim - 1)
00140 numDirectSteps = Dim - 1;
00141 }
00142
00143 DimexRouter :: ~DimexRouter()
00144 {
00145 int i;
00146 delete PeHcube;
00147 delete PeHcube1;
00148 delete buffer;
00149 for (i=0;i<Dim;i++) {
00150 delete next[i];
00151 }
00152 delete next;
00153 delete penum;
00154 }
00155
00156 void DimexRouter :: SetMap(int *pes)
00157 {
00158 gpes=pes;
00159 }
00160
00161 void DimexRouter :: InitVars()
00162 {
00163 stage=Dim-1;
00164 InitCounter=setIC(Dim, MyPe, NumPes);
00165 procMsgCount = 0;
00166 }
00167
00168 void DimexRouter::EachToAllMulticast(comID id, int size, void *msg, int more)
00169 {
00170 int npe=NumPes;
00171 int * destpes=(int *)CmiAlloc(sizeof(int)*npe);
00172 for (int i=0;i<npe;i++) destpes[i]=i;
00173 EachToManyMulticast(id, size, msg, npe, destpes, more);
00174 CmiFree(destpes);
00175 }
00176
00177 void DimexRouter::NumDeposits(comID, int num)
00178 {
00179
00180 }
00181
00182 void DimexRouter::EachToManyMulticast(comID id, int size, void *msg, int numpes, int *destpes, int more)
00183 {
00184
00185 SetID(id);
00186
00187
00188 if (msg && size) {
00189 PeHcube->InsertMsgs(numpes, destpes, size, msg);
00190 }
00191
00192 if (more) return;
00193 start_hcube(id);
00194 }
00195
00196 void DimexRouter::EachToManyMulticastQ(comID id, CkQ<MessageHolder *> &msgq) {
00197 SetID(id);
00198
00199 int count = 0;
00200 int length = msgq.length();
00201
00202 for(count = 0; count < length; count ++) {
00203 MessageHolder *mhdl = msgq.deq();
00204 PeHcube->InsertMsgs(mhdl->npes, mhdl->pelist, mhdl->size,
00205 mhdl->getMessage());
00206 delete mhdl;
00207 }
00208
00209 start_hcube(id);
00210 }
00211
00212 void DimexRouter::start_hcube(comID id) {
00213
00214 if (InitCounter <0) {
00215 ComlibPrintf("%d Sending to the lower hypercube\n", MyPe);
00216 int nextpe=neighbor(MyPe, Dim);
00217 int * pelist=(int *)CmiAlloc(NumPes*sizeof(int));
00218 for (int i=0;i<NumPes;i++) {
00219 pelist[i]=i;
00220 }
00221
00222 ComlibPrintf("Before Gmap %d\n", nextpe);
00223 gmap(nextpe);
00224 ComlibPrintf("%d: EachToMany Sending to %d\n", MyPe, nextpe);
00225 HCUBESENDFN(id, Dim, Dim, NumPes, pelist, CkpvAccess(RecvHandle), nextpe, PeHcube);
00226 CmiFree(pelist);
00227 return;
00228 }
00229
00230
00231 if (stage <0) {
00232
00233 LocalProcMsg(id);
00234 return;
00235 }
00236
00237 InitCounter++;
00238 RecvManyMsg(id,NULL);
00239 }
00240
00241
00242
00243 void DimexRouter::RecvManyMsg(comID id, char *msg)
00244 {
00245 ComlibPrintf("%d recvmanymsg called\n", MyPe);
00246 int msgstage;
00247 if (msg) {
00248 msgstage=PeHcube->UnpackAndInsert(msg);
00249
00250 if (msgstage == Dim) InitCounter++;
00251 else buffer[msgstage]=1;
00252 }
00253
00254
00255 while ((InitCounter==2) || (stage >=numDirectSteps && buffer[stage+1])) {
00256 InitCounter=setIC(Dim, MyPe, NumPes);
00257 if (InitCounter != 2) {
00258 buffer[stage+1]=0;
00259 }
00260
00261
00262 int nextpe=neighbor(MyPe, stage);
00263
00264 ComlibPrintf("Before Gmap %d\n", nextpe);
00265 gmap(nextpe);
00266 ComlibPrintf("%d RecvManyMsg Sending to %d\n", MyPe, nextpe);
00267 HCUBESENDFN(id, stage, stage, penum[stage], next[stage], CkpvAccess(RecvHandle), nextpe, PeHcube);
00268
00269
00270 stage--;
00271 }
00272
00273 if (stage < numDirectSteps && buffer[numDirectSteps]) {
00274
00275 InitCounter=setIC(Dim, MyPe, NumPes);
00276
00277
00278
00279 if(InitCounter >= 0 && numDirectSteps > 0) {
00280
00281
00282
00283 #if CMK_COMMLIB_USE_VECTORIZE
00284 PTvectorlist newmsg;
00285 newmsg=PeHcube->ExtractAndVectorizeAll(id, stage);
00286 if (newmsg) {
00287 CmiSetHandler(newmsg->msgs[0], CkpvAccess(ProcHandle));
00288 for (int count=0; count<two_pow_ndirect; ++count) {
00289 int nextpe = count ^ MyPe;
00290 gmap(nextpe);
00291 ComlibPrintf("%d Sending to %d\n", MyPe, nextpe);
00292 CmiSyncVectorSend(nextpe, -newmsg->count, newmsg->sizes, newmsg->msgs);
00293 }
00294 for(int i=0;i<newmsg->count;i++) CmiFree(newmsg->msgs[i]);
00295 CmiFree(newmsg->sizes);
00296 CmiFree(newmsg->msgs);
00297 }
00298 #else
00299 int *pelist = (int *)CmiAlloc(two_pow_ndirect * sizeof(int));
00300 for(int count = 0; count < two_pow_ndirect; count ++){
00301 int nextpe = count ^ MyPe;
00302 gmap(nextpe);
00303
00304 ComlibPrintf("%d Sending to %d\n", MyPe, nextpe);
00305 pelist[count] = nextpe;
00306 }
00307
00308 int len;
00309 char *newmsg;
00310 newmsg=PeHcube->ExtractAndPackAll(id, stage, &len);
00311 if (newmsg) {
00312 CmiSetHandler(newmsg, CkpvAccess(ProcHandle));
00313 CmiSyncListSendAndFree(two_pow_ndirect, pelist, len, newmsg);
00314 }
00315 CmiFree(pelist);
00316 #endif
00317
00318 stage -= numDirectSteps;
00319
00320
00321
00322 }
00323 else if(numDirectSteps == 0) {
00324 LocalProcMsg(id);
00325 ComlibPrintf("Calling local proc msg %d\n",
00326 buffer[numDirectSteps]);
00327 }
00328
00329 buffer[numDirectSteps]=0;
00330 }
00331 }
00332
00333 void DimexRouter :: ProcManyMsg(comID id, char *m)
00334 {
00335 ComlibPrintf("%d: In procmanymsg\n", MyPe);
00336 InitCounter=setIC(Dim, MyPe, NumPes);
00337 if(id.isAllToAll) {
00338 int pe_list[2];
00339 int npes = 2;
00340
00341 if(InitCounter > 0)
00342 npes = 1;
00343
00344 pe_list[0] = MyPe;
00345 pe_list[1] = neighbor(MyPe, Dim);
00346
00347 PeHcube1->UnpackAndInsertAll(m, npes, pe_list);
00348 }
00349 else
00350 PeHcube->UnpackAndInsert(m);
00351
00352 procMsgCount ++;
00353
00354 if(InitCounter >= 0){
00355 if((procMsgCount == two_pow_ndirect) && stage < 0) {
00356 ComlibPrintf("%d Calling lp %d %d\n", MyPe,
00357 procMsgCount, stage);
00358 LocalProcMsg(id);
00359 }
00360 }
00361 else
00362
00363 LocalProcMsg(id);
00364 }
00365
00366 void DimexRouter:: LocalProcMsg(comID id)
00367 {
00368
00369
00370 int mynext=neighbor(MyPe, Dim);
00371 int mymax=1<<Dim;
00372
00373 if (mynext >=mymax && mynext < NumPes) {
00374 ComlibPrintf("Before Gmap %d\n", mynext);
00375 int pelist[1];
00376 pelist[0] = mynext;
00377 ComlibPrintf("%d Sending to upper hypercube %d\n", MyPe, mynext);
00378
00379 if(id.isAllToAll){
00380 gmap(mynext);
00381 HCUBESENDFN(id, Dim, -1, 1, pelist, CkpvAccess(ProcHandle), mynext, PeHcube1);
00382 }
00383 else {
00384 gmap(mynext);
00385 HCUBESENDFN(id, Dim, -1, 1, pelist, CkpvAccess(ProcHandle), mynext, PeHcube);
00386 }
00387 }
00388
00389 if(id.isAllToAll)
00390 PeHcube1->ExtractAndDeliverLocalMsgs(MyPe);
00391 else
00392 PeHcube->ExtractAndDeliverLocalMsgs(MyPe);
00393
00394 PeHcube->Purge();
00395 PeHcube1->Purge();
00396 InitVars();
00397 Done(id);
00398 }
00399
00400 void DimexRouter::DummyEP(comID id, int msgstage)
00401 {
00402 if (msgstage >= 0) {
00403 buffer[msgstage]=1;
00404 RecvManyMsg(id, NULL);
00405 }
00406 else {
00407
00408 LocalProcMsg(id);
00409 }
00410 }
00411
00412 void DimexRouter::CreateStageTable(int numpes, int *destpes)
00413 {
00414 int *dir=new int[numpes];
00415 int nextdim, j, i;
00416 for (i=0;i<numpes;i++) {
00417 dir[i]=MyPe ^ adjust(Dim, destpes[i]);
00418 }
00419 for (nextdim=Dim-1; nextdim>=0; nextdim--) {
00420 int mask=1<<nextdim;
00421 for (i=0;i<numpes;i++) {
00422 if (dir[i] & mask) {
00423 dir[i]=0;
00424 for (j=0;(j<penum[nextdim]) && (destpes[i]!=next[nextdim][j]);j++);
00425 if (destpes[i]==next[nextdim][j]) {
00426
00427 continue;
00428 }
00429 next[nextdim][penum[nextdim]]=destpes[i];
00430 penum[nextdim]+=1;
00431
00432 }
00433 }
00434 }
00435 delete [] dir;
00436 return;
00437 }
00438
00439 Router * newhcubeobject(int n, int me)
00440 {
00441 Router *obj=new DimexRouter(n, me);
00442 return(obj);
00443 }
00444
00445
00446 void DimexRouter::SetID(comID id) {
00447
00448 if(id.isAllToAll) {
00449 numDirectSteps = 2;
00450 two_pow_ndirect = 1;
00451 for(int count = 0; count < numDirectSteps; count ++)
00452 two_pow_ndirect *= 2;
00453 }
00454 }