Switching to use SYNCLISTSENDANDFREE.
[charm.git] / src / ck-com / OneTimeMulticastStrategy.C
1 /**
2    @addtogroup ComlibCharmStrategy
3    @{
4    @file
5
6 */
7
8
9 #include "OneTimeMulticastStrategy.h"
10 #include <string>
11 #include <set>
12 #include <vector>
13 #include <list>
14
15 //#define DEBUG 1
16
17 using std::list;
18 using std::set;
19 using std::vector;
20
21
22 /// @note: There is some bug that is preventing us from using CmiSyncListSend. 
23 #define SYNCLISTSENDANDFREE 1
24
25
26 CkpvExtern(CkGroupID, cmgrID);
27
28 OneTimeMulticastStrategy::OneTimeMulticastStrategy()
29   : Strategy(), CharmStrategy() {
30   //  ComlibPrintf("OneTimeMulticastStrategy constructor\n");
31   setType(ARRAY_STRATEGY);
32 }
33
34 OneTimeMulticastStrategy::~OneTimeMulticastStrategy() {
35 }
36
37 void OneTimeMulticastStrategy::pup(PUP::er &p){
38   Strategy::pup(p);
39   CharmStrategy::pup(p);
40 }
41
42
43 /** Called when the user invokes the entry method on the delegated proxy. */
44 void OneTimeMulticastStrategy::insertMessage(CharmMessageHolder *cmsg){
45 #if DEBUG
46   CkPrintf("[%d] OneTimeMulticastStrategy::insertMessage\n", CkMyPe());
47   fflush(stdout);
48 #endif 
49
50   if(cmsg->dest_proc != IS_SECTION_MULTICAST && cmsg->sec_id == NULL) { 
51     CkAbort("OneTimeMulticastStrategy can only be used with an array section proxy");
52   }
53     
54
55   envelope *env = UsrToEnv(cmsg->getCharmMessage());
56   int npes = 1;
57   int pes[1] = {0};
58   _TRACE_CREATION_MULTICAST(env, npes, pes);
59
60 #if DEBUG
61   CkPrintf("[%d] after TRACE_CREATION_MULTICAST menv->event=%d\n", CkMyPe(), (int)env->getEvent());  
62 #endif
63   
64   // Create a multicast message containing all information about remote destination objects 
65   ComlibMulticastMsg * multMsg = sinfo.getNewMulticastMessage(cmsg, 0, getInstance());
66
67
68 #if DEBUG
69     CkPrintf("[%d] after TRACE_CREATION_MULTICAST multMsg->event=%d\n", CkMyPe(), (int)( UsrToEnv(multMsg)->getEvent() ) );  
70 #endif
71
72   // The remote multicast method will send the message to the remote PEs, as specified in multMsg
73   remoteMulticast(multMsg, true);
74
75   // local multicast will re-extract a list of local destination objects (FIXME to make this more efficient)
76   localMulticast(cmsg);
77
78   delete cmsg;    
79 }
80
81
82
83 /** Deliver the message to the local elements. */
84 void OneTimeMulticastStrategy::localMulticast(CharmMessageHolder *cmsg) {
85   double start = CmiWallTimer();
86   CkSectionID *sec_id = cmsg->sec_id;
87   CkVec< CkArrayIndexMax > localIndices;
88   sinfo.getLocalIndices(sec_id->_nElems, sec_id->_elems, sec_id->_cookie.aid, localIndices);
89   deliverToIndices(cmsg->getCharmMessage(), localIndices );
90   traceUserBracketEvent(10000, start, CmiWallTimer());
91 }
92
93
94
95
96
97 /** 
98     Forward multicast message to our successor processors in the spanning tree. 
99     Uses CmiSyncListSend for delivery to this strategy's OneTimeMulticastStrategy::handleMessage method.
100 */
101 void OneTimeMulticastStrategy::remoteMulticast(ComlibMulticastMsg * multMsg, bool rootPE) {
102   double start = CmiWallTimer();
103
104   envelope *env = UsrToEnv(multMsg);
105     
106   
107   /// The index into the PE list in the message
108   int myIndex = -10000; 
109   const int totalDestPEs = multMsg->nPes;
110   const int myPe = CkMyPe();
111   
112   // Find my index in the list of all destination PEs
113   if(rootPE){
114     CkAssert(CkMyPe() == multMsg->_cookie.pe);
115     myIndex = -1;
116   } else {
117     for (int i=0; i<totalDestPEs; ++i) {
118       if(multMsg->indicesCount[i].pe == myPe){
119         myIndex = i;
120         break;
121       }
122     }
123   }
124   
125   if(myIndex == -10000)
126     CkAbort("My PE was not found in the list of destination PEs in the ComlibMulticastMsg");
127   
128   int npes;
129   int *pelist = NULL;
130
131   if(totalDestPEs > 0)
132     determineNextHopPEs(totalDestPEs, multMsg->indicesCount, myIndex, multMsg->_cookie.pe, pelist, npes );
133   else {
134     npes = 0;
135   }
136
137   if(npes == 0) {
138 #if DEBUG
139     CkPrintf("[%d] OneTimeMulticastStrategy::remoteMulticast is not forwarding to any other PEs\n", CkMyPe());
140 #endif
141     traceUserBracketEvent(10001, start, CmiWallTimer());
142     CmiFree(env);
143     return;
144   }
145   
146   //Collect Multicast Statistics
147   RECORD_SENDM_STATS(getInstance(), env->getTotalsize(), pelist, npes);
148   
149
150   CmiSetHandler(env, CkpvAccess(comlib_handler));
151   ((CmiMsgHeaderBasic *) env)->stratid = getInstance();  
152   CkPackMessage(&env);
153
154   double middle = CmiWallTimer();
155
156   
157   // CkPrintf("[%d] before CmiSyncListSendAndFree env->event=%d\n", CkMyPe(), (int)env->getEvent());
158
159 #if SYNCLISTSENDANDFREE
160   CmiSyncListSendAndFree(npes, pelist, env->getTotalsize(), (char*)env);
161 #else
162
163   CkAssert(npes > 0);
164   CmiSyncListSend(npes, pelist, env->getTotalsize(), (char*)env);
165   
166   delete[] pelist;
167 #endif
168
169   double end = CmiWallTimer();
170   traceUserBracketEvent(10001, start, middle);
171   traceUserBracketEvent(10002, middle, end);
172   
173 }
174
175
176
177 /** 
178     Receive an incoming multicast message(sent from OneTimeMulticastStrategy::remoteMulticast).
179     Deliver the message to all local elements 
180 */
181 void OneTimeMulticastStrategy::handleMessage(void *msg){
182 #if DEBUG
183   //  CkPrintf("[%d] OneTimeMulticastStrategy::handleMessage\n", CkMyPe());
184 #endif
185   envelope *env = (envelope *)msg;
186   CkUnpackMessage(&env);
187   ComlibMulticastMsg* multMsg = (ComlibMulticastMsg*)EnvToUsr(env);
188   
189   // Don't use msg after this point. Instead use the unpacked env
190   
191   RECORD_RECV_STATS(getInstance(), env->getTotalsize(), env->getSrcPe()); // DOESN'T DO ANYTHING IN NEW COMLIB
192   
193   // Deliver to objects marked as local in the message
194   int localElems;
195   envelope *newenv;
196   CkArrayIndexMax *local_idx_list;  
197   sinfo.unpack(env, localElems, local_idx_list, newenv);
198   ComlibMulticastMsg *newmsg = (ComlibMulticastMsg *)EnvToUsr(newenv);  
199
200   //  CkPrintf("[%d] in OneTimeMulticastStrategy::handleMessage before  deliverToIndices newenv->event=%d\n", CkMyPe(), (int)newenv->getEvent());
201
202
203 #if SYNCLISTSENDANDFREE
204
205   // Deliver locally
206   deliverToIndices(newmsg, localElems, local_idx_list );
207   
208   // Forward on to other processors if necessary
209   remoteMulticast(multMsg, false);
210  
211 #else
212
213   // Forward on to other processors if necessary
214   remoteMulticast(multMsg, false);
215
216   // Deliver locally
217   deliverToIndices(newmsg, localElems, local_idx_list );
218   
219   // Finally delete the reference counted message because remoteMulticast does not do this.
220   CmiFree(multMsg);
221
222 #endif
223   
224 }
225
226
227
228
229 void OneTimeMulticastStrategy::determineNextHopPEs(const int totalDestPEs, const ComlibMulticastIndexCount* destPEs, const int myIndex, const int rootPE, int * &pelist, int &npes) {
230   if(myIndex==-1){
231     // We are at a root node of the spanning tree. 
232     // We will forward the message to all other PEs in the destination list.
233     npes = totalDestPEs;
234     
235     pelist = new int[npes];
236     for (int i=0; i<npes; ++i) {
237       pelist[i] = destPEs[i].pe;
238     }
239   } else {
240     // We are at a leaf node of the spanning tree. 
241     npes = 0;
242   }
243   
244 }
245
246
247 void OneTimeRingMulticastStrategy::determineNextHopPEs(const int totalDestPEs, const ComlibMulticastIndexCount* destPEs, const int myIndex, const int rootPE, int * &pelist, int &npes) {
248   const int myPe = CkMyPe();
249
250   if(myIndex == totalDestPEs-1){
251     // Final PE won't send to anyone
252     npes = 0;
253     return;
254   } else {
255     // All non-final PEs will send to next PE in list
256     npes = 1;
257     pelist = new int[1];
258     pelist[0] = destPEs[myIndex+1].pe;
259   }
260
261 }
262
263
264 void OneTimeTreeMulticastStrategy::determineNextHopPEs(const int totalDestPEs, const ComlibMulticastIndexCount* destPEs, const int myIndex, const int rootPE, int * &pelist, int &npes){
265   const int myPe = CkMyPe();
266   
267   // The logical indices start at 0 = root node. Logical index i corresponds to the entry i+1 in the array of PEs in the message
268   
269   int sendLogicalIndexStart = degree*(myIndex+1) + 1;       // inclusive
270   int sendLogicalIndexEnd = sendLogicalIndexStart + degree - 1;   // inclusive
271   
272   if(sendLogicalIndexEnd-1 >= totalDestPEs){
273     sendLogicalIndexEnd = totalDestPEs;
274   }
275
276   int numSend = sendLogicalIndexEnd - sendLogicalIndexStart + 1;
277   if(numSend <= 0){
278     npes = 0;
279     return;
280   }
281  
282 #if DEBUG
283   if(numSend > 0)
284     CkPrintf("Tree logical index %d sending to logical %d to %d (totalDestPEs excluding root=%d)  numSend=%d\n",
285              myIndex+1, sendLogicalIndexStart, sendLogicalIndexEnd, totalDestPEs, numSend);
286 #endif
287
288   npes = numSend;
289   pelist = new int[npes];
290   
291   for(int i=0;i<numSend;i++){
292     CkAssert(sendLogicalIndexStart-1+i < totalDestPEs);
293     pelist[i] = destPEs[sendLogicalIndexStart-1+i].pe;
294 #if DEBUG
295     CkPrintf("Tree logical index %d sending to PE %d\n", myIndex+1, pelist[i]);
296 #endif
297     CkAssert(pelist[i] < CkNumPes());
298   }
299   
300 }
301
302
303 /** Find a unique representative PE for a node containing pe, with the restriction that the returned PE is in the list destPEs. */
304 int getFirstPeOnPhysicalNodeFromList(int pe, const int totalDestPEs, const ComlibMulticastIndexCount* destPEs){
305   int num;
306   int *nodePeList;
307   CmiGetPesOnPhysicalNode(pe, &nodePeList, &num);
308   
309   for(int i=0;i<num;i++){
310     // Scan destPEs for the pe
311     int p = nodePeList[i];
312     
313     for(int j=0;j<totalDestPEs;j++){
314       if(p == destPEs[j].pe){
315         // found the representative PE for the node that is in the destPEs list
316         return p;
317       }
318     }
319   }
320   
321   CkAbort("ERROR: Could not find an entry for pe in destPEs list.\n");
322   return -1;
323 }
324
325
326 /** Find a unique representative PE for a node containing pe, with the restriction that the returned PE is in the list destPEs. */
327 int getNthPeOnPhysicalNodeFromList(int n, int pe, const int totalDestPEs, const ComlibMulticastIndexCount* destPEs){
328   int num;
329   int *nodePeList;
330   CmiGetPesOnPhysicalNode(pe, &nodePeList, &num);
331   
332   int count = 0;
333   int lastFound = -1;
334   
335   // Foreach PE on this physical node
336   for(int i=0;i<num;i++){
337     int p = nodePeList[i];
338     
339     // Scan destPEs for the pe
340     for(int j=0;j<totalDestPEs;j++){
341       if(p == destPEs[j].pe){
342         lastFound = p;
343         if(count==n)
344           return p;
345         count++;
346       }
347     }
348   }
349   
350   if(lastFound != -1)
351     return lastFound;
352
353   CkAbort("ERROR: Could not find an entry for pe in destPEs list.\n");
354   return -1;
355 }
356
357
358 /** List all the PEs from the list that share the physical node */ 
359 vector<int> getPesOnPhysicalNodeFromList(int pe, const int totalDestPEs, const ComlibMulticastIndexCount* destPEs){ 
360    
361   vector<int> result; 
362  
363   int num; 
364   int *nodePeList; 
365   CmiGetPesOnPhysicalNode(pe, &nodePeList, &num); 
366   
367   for(int i=0;i<num;i++){ 
368     // Scan destPEs for the pe 
369     int p = nodePeList[i]; 
370     for(int j=0;j<totalDestPEs;j++){ 
371       if(p == destPEs[j].pe){ 
372         // found the representative PE for the node that is in the
373         // destPEs list 
374         result.push_back(p); 
375         break; 
376       } 
377     } 
378   } 
379   
380   return result; 
381 }
382
383
384
385 /** List all the other PEs from the list that share the physical node */
386 vector<int> getOtherPesOnPhysicalNodeFromList(int pe, const int totalDestPEs, const ComlibMulticastIndexCount* destPEs){
387   
388   vector<int> result;
389
390   int num;
391   int *nodePeList;
392   CmiGetPesOnPhysicalNode(pe, &nodePeList, &num);
393   
394   for(int i=0;i<num;i++){
395     // Scan destPEs for the pe
396     int p = nodePeList[i];
397     if(p != pe){
398       for(int j=0;j<totalDestPEs;j++){
399         if(p == destPEs[j].pe){
400           // found the representative PE for the node that is in the destPEs list
401           result.push_back(p);
402           break;
403         }
404       }
405     }
406   }
407   
408   return result;
409 }
410
411
412 void OneTimeNodeTreeMulticastStrategy::determineNextHopPEs(const int totalDestPEs, const ComlibMulticastIndexCount* destPEs, const int myIndex, const int rootPE, int * &pelist, int &npes){
413   const int myPe = CkMyPe();
414
415   set<int> nodePERepresentatives;
416   
417   // create a list of PEs, with one for each node to which the message must be sent
418   for(int i=0; i<totalDestPEs; i++){
419     int pe = destPEs[i].pe;
420     int representative = getFirstPeOnPhysicalNodeFromList(pe, totalDestPEs, destPEs);
421     nodePERepresentatives.insert(representative);    
422   }
423   
424   // Create an ordered list of PEs to send to, based upon the rootPE
425   // This should distribute load more evenly than the sorted list previously used
426   set<int>::iterator splitter = nodePERepresentatives.upper_bound(rootPE);
427   vector<int> nodePERepresentativesOrdered;
428   for(set<int>::iterator iter = splitter; iter!=nodePERepresentatives.end(); ++iter){
429     nodePERepresentativesOrdered.push_back(*iter);
430   }
431   for(set<int>::iterator iter = nodePERepresentatives.begin(); iter!=splitter; ++iter){
432     nodePERepresentativesOrdered.push_back(*iter);
433   }
434
435   CkAssert(nodePERepresentativesOrdered.size() == nodePERepresentatives.size());
436     
437   int numRepresentativePEs = nodePERepresentatives.size();
438   
439   int repForMyPe=-1;
440   if(myIndex != -1)
441     repForMyPe = getFirstPeOnPhysicalNodeFromList(CkMyPe(), totalDestPEs, destPEs);
442   
443 #if DEBUG
444   CkPrintf("[%d] Multicasting to %d PEs on %d physical nodes  repForMyPe=%d\n", CkMyPe(), totalDestPEs, numRepresentativePEs, repForMyPe);
445   fflush(stdout);
446 #endif
447   
448   // If this PE is part of the multicast tree, then it should forward the message along
449   if(CkMyPe() == repForMyPe || myIndex == -1){
450     // I am an internal node in the multicast tree
451     
452     // flatten the nodePERepresentativesOrdered data structure
453     int *repPeList = new int[numRepresentativePEs];
454     int myRepIndex = -1;
455     int p=0;
456     for(vector<int>::iterator iter=nodePERepresentativesOrdered.begin(); iter != nodePERepresentativesOrdered.end(); iter++){
457       repPeList[p] = *iter;
458       if(*iter == repForMyPe)
459         myRepIndex = p;
460       p++;
461     }
462     CkAssert(myRepIndex >=0 || myIndex==-1);
463       
464     // The logical indices start at 0 = root node. Logical index i corresponds to the entry i+1 in the array of PEs in the message
465     int sendLogicalIndexStart = degree*(myRepIndex+1) + 1;       // inclusive
466     int sendLogicalIndexEnd = sendLogicalIndexStart + degree - 1;   // inclusive
467     
468     if(sendLogicalIndexEnd-1 >= numRepresentativePEs){
469       sendLogicalIndexEnd = numRepresentativePEs;
470     }
471     
472     int numSendTree = sendLogicalIndexEnd - sendLogicalIndexStart + 1;
473     if(numSendTree < 0)
474       numSendTree = 0;
475     
476     vector<int> otherLocalPes = getOtherPesOnPhysicalNodeFromList(CkMyPe(), totalDestPEs, destPEs);
477     int numSendLocal;
478     if(myIndex == -1)
479       numSendLocal = 0;
480     else 
481       numSendLocal = otherLocalPes.size();
482     
483     
484
485 #if DEBUG
486     CkPrintf("[%d] numSendTree=%d numSendLocal=%d sendLogicalIndexStart=%d sendLogicalIndexEnd=%d\n", CkMyPe(), numSendTree, numSendLocal,  sendLogicalIndexStart, sendLogicalIndexEnd);
487     fflush(stdout);
488 #endif
489
490     int numSend = numSendTree + numSendLocal;
491     if(numSend <= 0){
492       npes = 0;
493       return;
494     }
495     
496     npes = numSend;
497     pelist = new int[npes];
498   
499     for(int i=0;i<numSendTree;i++){
500       CkAssert(sendLogicalIndexStart-1+i < numRepresentativePEs);
501       pelist[i] = repPeList[sendLogicalIndexStart-1+i];
502       CkAssert(pelist[i] < CkNumPes() && pelist[i] >= 0);
503     }
504     
505     delete[] repPeList;
506     repPeList = NULL;
507
508     for(int i=0;i<numSendLocal;i++){
509       pelist[i+numSendTree] = otherLocalPes[i];
510       CkAssert(pelist[i] < CkNumPes() && pelist[i] >= 0);
511     }
512     
513     
514 #if DEBUG
515     char buf[1024];
516     sprintf(buf, "PE %d is sending to Remote Node PEs: ", CkMyPe() );
517     for(int i=0;i<numSend;i++){
518       if(i==numSendTree)
519         sprintf(buf+strlen(buf), " and Local To Node PEs: ", pelist[i]);
520
521       sprintf(buf+strlen(buf), "%d ", pelist[i]);
522     }    
523     CkPrintf("%s\n", buf);
524     fflush(stdout);
525 #endif
526         
527   } else {
528     // We are a leaf PE
529     npes = 0;
530     return;
531   }
532
533   
534   
535 }
536
537
538 void OneTimeNodeTreeRingMulticastStrategy::determineNextHopPEs(const int totalDestPEs, const ComlibMulticastIndexCount* destPEs, const int myIndex, const int rootPE, int * &pelist, int &npes){
539   const int myPe = CkMyPe();
540
541   set<int> nodePERepresentatives;
542   
543   // create a list of PEs, with one for each node to which the message must be sent
544   for(int i=0; i<totalDestPEs; i++){
545     int pe = destPEs[i].pe;
546     int representative = getFirstPeOnPhysicalNodeFromList(pe, totalDestPEs, destPEs);
547     nodePERepresentatives.insert(representative);    
548   }
549
550    // Create an ordered list of PEs to send to, based upon the rootPE
551   // This should distribute load more evenly than the sorted list previously used
552   set<int>::iterator splitter = nodePERepresentatives.upper_bound(rootPE);
553   vector<int> nodePERepresentativesOrdered;
554   for(set<int>::iterator iter = splitter; iter!=nodePERepresentatives.end(); ++iter){
555     nodePERepresentativesOrdered.push_back(*iter);
556   }
557   for(set<int>::iterator iter = nodePERepresentatives.begin(); iter!=splitter; ++iter){
558     nodePERepresentativesOrdered.push_back(*iter);
559   }
560
561   CkAssert(nodePERepresentativesOrdered.size() == nodePERepresentatives.size());
562   int numRepresentativePEs = nodePERepresentatives.size();
563   
564   int repForMyPe=-1;
565   if(myIndex != -1)
566     repForMyPe = getFirstPeOnPhysicalNodeFromList(CkMyPe(), totalDestPEs, destPEs);
567   
568 #if DEBUG
569   CkPrintf("[%d] Multicasting to %d PEs on %d physical nodes  repForMyPe=%d\n", CkMyPe(), totalDestPEs, numRepresentativePEs, repForMyPe);
570   fflush(stdout);
571 #endif
572   
573   // If this PE is part of the multicast tree, then it should forward the message along
574   if(CkMyPe() == repForMyPe || myIndex == -1){
575     // I am an internal node in the multicast tree
576     
577     // flatten the data structure for nodePERepresentatives
578     int *repPeList = new int[numRepresentativePEs];
579     int myRepIndex = -1;
580     int p=0;
581     for(vector<int>::iterator iter=nodePERepresentativesOrdered.begin(); iter != nodePERepresentativesOrdered.end(); iter++){
582       repPeList[p] = *iter;
583       if(*iter == repForMyPe)
584         myRepIndex = p;
585       p++;
586     }
587     CkAssert(myRepIndex >=0 || myIndex==-1);
588       
589     // The logical indices start at 0 = root node. Logical index i corresponds to the entry i+1 in the array of PEs in the message
590     int sendLogicalIndexStart = degree*(myRepIndex+1) + 1;       // inclusive
591     int sendLogicalIndexEnd = sendLogicalIndexStart + degree - 1;   // inclusive
592     
593     if(sendLogicalIndexEnd-1 >= numRepresentativePEs){
594       sendLogicalIndexEnd = numRepresentativePEs;
595     }
596     
597     int numSendTree = sendLogicalIndexEnd - sendLogicalIndexStart + 1;
598     if(numSendTree < 0)
599       numSendTree = 0;
600
601
602     // Send in a ring to the PEs on this node
603     vector<int> otherLocalPes = getOtherPesOnPhysicalNodeFromList(CkMyPe(), totalDestPEs, destPEs);
604     int numSendLocal = 0;
605     if(myIndex == -1)
606       numSendLocal = 0;
607     else {
608       if(otherLocalPes.size() > 0)
609         numSendLocal = 1;
610       else
611         numSendLocal = 0;
612     }
613     
614
615 #if DEBUG
616     CkPrintf("[%d] numSendTree=%d numSendLocal=%d sendLogicalIndexStart=%d sendLogicalIndexEnd=%d\n", CkMyPe(), numSendTree, numSendLocal,  sendLogicalIndexStart, sendLogicalIndexEnd);
617     fflush(stdout);
618 #endif
619
620     int numSend = numSendTree + numSendLocal;
621     if(numSend <= 0){
622       npes = 0;
623       return;
624     }
625     
626     npes = numSend;
627     pelist = new int[npes];
628   
629     for(int i=0;i<numSendTree;i++){
630       CkAssert(sendLogicalIndexStart-1+i < numRepresentativePEs);
631       pelist[i] = repPeList[sendLogicalIndexStart-1+i];
632       CkAssert(pelist[i] < CkNumPes() && pelist[i] >= 0);
633     }
634     
635     delete[] repPeList;
636     repPeList = NULL;
637
638     for(int i=0;i<numSendLocal;i++){
639       pelist[i+numSendTree] = otherLocalPes[i];
640       CkAssert(pelist[i] < CkNumPes() && pelist[i] >= 0);
641     }
642     
643     
644 #if DEBUG
645     char buf[1024];
646     sprintf(buf, "PE %d is sending to Remote Node PEs: ", CkMyPe() );
647     for(int i=0;i<numSend;i++){
648       if(i==numSendTree)
649         sprintf(buf+strlen(buf), " and Local To Node PEs: ", pelist[i]);
650
651       sprintf(buf+strlen(buf), "%d ", pelist[i]);
652     }    
653     CkPrintf("%s\n", buf);
654     fflush(stdout);
655 #endif
656         
657   } else {
658     // We are a leaf PE, so forward in a ring to the PEs on this node
659     const vector<int> otherLocalPes = getPesOnPhysicalNodeFromList(CkMyPe(), totalDestPEs, destPEs);
660     
661     npes = 0;
662     pelist = new int[1];
663     
664     //    CkPrintf("[%d] otherLocalPes.size=%d\n", CkMyPe(), otherLocalPes.size() ); 
665     const int numOthers = otherLocalPes.size() ;
666     
667     for(int i=0;i<numOthers;i++){
668       if(otherLocalPes[i] == CkMyPe()){
669         // found me in the PE list for this node
670         if(i+1<otherLocalPes.size()){
671           // If we have a successor in the ring
672           pelist[0] = otherLocalPes[i+1];
673           npes = 1;
674         }
675       }
676     }
677     
678     
679 #if DEBUG
680     if(npes==0)
681       CkPrintf("[%d] At end of ring\n", CkMyPe() );
682     else
683       CkPrintf("[%d] sending along ring to %d\n", CkMyPe(), pelist[0] );
684     
685     fflush(stdout);
686 #endif
687     
688     
689   }
690   
691   
692   
693 }
694
695
696
697
698
699
700
701
702 void OneTimeDimensionOrderedMulticastStrategy::determineNextHopPEs(const int totalDestPEs, const ComlibMulticastIndexCount* destPEs, const int myIndex, const int rootPE, int * &pelist, int &npes){
703  //  const int myPe = CkMyPe();
704
705 //   set<int> nodePERepresentatives;
706   
707 //   // create a list of PEs, with one for each node to which the message must be sent
708 //   for(int i=0; i<totalDestPEs; i++){
709 //     int pe = destPEs[i].pe;
710 //     int representative = getFirstPeOnPhysicalNodeFromList(pe, totalDestPEs, destPEs);
711 //     nodePERepresentatives.insert(representative);    
712 //   }
713   
714 //   int numRepresentativePEs = nodePERepresentatives.size();
715   
716 //   int repForMyPe=-1;
717 //   if(myIndex != -1)
718 //     repForMyPe = getFirstPeOnPhysicalNodeFromList(CkMyPe(), totalDestPEs, destPEs);
719   
720 // #if DEBUG
721 //   CkPrintf("[%d] Multicasting to %d PEs on %d physical nodes  repForMyPe=%d\n", CkMyPe(), totalDestPEs, numRepresentativePEs, repForMyPe);
722 //   fflush(stdout);
723 // #endif
724   
725 //   // If this PE is part of the multicast tree, then it should forward the message along
726 //   if(CkMyPe() == repForMyPe || myIndex == -1){
727 //     // I am an internal node in the multicast tree
728
729 //     TopoManager tmgr;
730     
731 //     // flatten the data structure for nodePERepresentatives
732 //     int *repPeList = new int[numRepresentativePEs];
733 //     bool *inTreeYet = new bool[numRepresentativePEs];
734 //     int *repPeTopoX = new int[numRepresentativePEs];
735 //     int *repPeTopoY = new int[numRepresentativePEs];
736 //     int *repPeTopoZ = new int[numRepresentativePEs];
737
738 //     set<int> xcoords;
739
740 //     int myX, myY, myZ, myT;
741 //     int rootX, rootY, rootZ, rootT;
742 //     tmgr->rankToCoordinates(CkMyPe(), myX, myY, myZ, myT);        
743 //     tmgr->rankToCoordinates(CkMyPe(), rootX, rootY, rootZ, rootT);        
744
745 //     int myRepIndex = -1;
746 //     set<int>::iterator iter;
747 //     int p=0;
748 //     for(iter=nodePERepresentatives.begin(); iter != nodePERepresentatives.end(); iter++){
749 //       int pe =  *iter;
750 //       repPeList[p] = pe;
751 //       inTreeYet[p] = false;
752 //       int t; // ignore the 't' dimension (which PE on the node)
753 //       tmgr->rankToCoordinates(pe, repPeTopoX[p], repPeTopoY[p], repPeTopoZ[p], t);     
754 //       xcoords.insert(repPeTopoX[p]);
755 //       if(*iter == repForMyPe)
756 //      myRepIndex = p;
757 //       p++;
758 //     }
759 //     CkAssert(myRepIndex >=0 || myIndex==-1);
760     
761
762 //     // Holds the spanning tree as we build it. It maps from index in the repPeList to sets of indices for repPeList
763 //     map<int, set<int> > spanningTreeChildren;
764
765 //     //---------------------------------------------------------------------------------------------
766 //     // Determine the children of the root of the multicast tree
767  
768 //     int nearestXp = 100000;
769 //     int nearestXpidx = -1;
770 //     int nearestXm = -100000;
771 //     int nearestXmidx = -1;
772
773 //     for(int i=0; i<numRepresentativePEs; i++){
774 //       // Find the nearest +x neighbor
775 //       if(repPeTopoX[i] > rootX && repPeTopoX[i] < nearestXp){
776 //      nearestXp = repPeTopoX[i] ;
777 //      nearestXpidx = i;
778 //       }
779       
780 //       // Find the nearest -x neighbor
781 //       if(repPeTopoX[i] < rootX && repPeTopoX[i] > nearestXm){
782 //      nearestXm = repPeTopoX[i] ;
783 //      nearestXmidx = i;
784 //       }    
785       
786 //     //   // send to some destinations with same X coordinate (just one per Y coordinate)
787 // //       if(repPeTopoX == rootX){
788 // //   set<int>::iterator iter;
789 // //   bool found = false;
790 // //   for(iter = spanningTreeChildren[-1].begin(); iter != spanningTreeChildren[-1].end(); ++iter){
791 // //     iterYcoord = repPeTopoY[*iter];
792 // //     if(iterYcoord == repPeTopoY[i]){
793 // //       found = true;
794 // //       break;
795 // //     } 
796 // //   }
797 // //   if(! found) {
798 // //     // haven't seen this Y coordinate yet
799 // //     spanningTreeChildren[-1].insert(i);
800 // //     inTreeYet[i] = true;
801 // //   }
802 // //       }
803 //     }
804     
805     
806 //     // The root sends to nearest +x neighbor
807 //     if(nearestXpidx != -1){
808 //       spanningTreeChildren[-1].insert(nearestXpidx);
809 //       inTreeYet[nearestXpidx] = true;
810 //     }
811     
812     
813 //     // The root sends to nearest -x neighbor
814 //     if(nearestXpidx != -1){
815 //       spanningTreeChildren[-1].insert(nearestXpidx);
816 //       inTreeYet[nearestXpidx] = true;
817 //     }
818     
819     
820 //     //---------------------------------------------------------------------------------------------
821 //     // Make sure we span all X coordinates 
822     
823     
824     
825     
826
827
828
829
830
831     
832     
833    
834 //     int numSendTree = 1;
835 //     if(numSendTree < 0)
836 //       numSendTree = 0;
837     
838 //     vector<int> otherLocalPes = getOtherPesOnPhysicalNodeFromList(CkMyPe(), totalDestPEs, destPEs);
839 //     int numSendLocal;
840 //     if(myIndex == -1)
841 //       numSendLocal = 0;
842 //     else 
843 //       numSendLocal = otherLocalPes.size();
844     
845 //     int numSend = numSendTree + numSendLocal;
846 //     if(numSend <= 0){
847 //       npes = 0;
848 //       return;
849 //     }
850     
851 //     npes = numSend;
852 //     pelist = new int[npes];
853   
854 //     for(int i=0;i<numSendTree;i++){
855 //       CkAssert(sendLogicalIndexStart-1+i < numRepresentativePEs);
856 //       pelist[i] = repPeList[sendLogicalIndexStart-1+i];
857 //       CkAssert(pelist[i] < CkNumPes() && pelist[i] >= 0);
858 //     }
859     
860 //     delete[] repPeList;
861 //     delete[] repPeTopoX;
862 //     delete[] repPeTopoY;
863 //     delete[] repPeTopoZ;
864 //     repPeList = NULL;
865
866 //     for(int i=0;i<numSendLocal;i++){
867 //       pelist[i+numSendTree] = otherLocalPes[i];
868 //       CkAssert(pelist[i] < CkNumPes() && pelist[i] >= 0);
869 //     }
870     
871 // #if 1
872 //     char buf[1024];
873 //     sprintf(buf, "PE %d is sending to Remote Node PEs: ", CkMyPe() );
874 //     for(int i=0;i<numSend;i++){
875 //       if(i==numSendTree)
876 //      sprintf(buf+strlen(buf), " and Local To Node PEs: ", pelist[i]);
877
878 //       sprintf(buf+strlen(buf), "%d ", pelist[i]);
879 //     }    
880 //     CkPrintf("%s\n", buf);
881 //     fflush(stdout);
882 // #endif
883         
884 //   } else {
885 //     // We are a leaf PE
886 //     npes = 0;
887 //     return;
888 //   }
889
890   
891   
892 }
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907 /*@}*/