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