Adding some user events to trace the multicasts.
[charm.git] / src / ck-com / OneTimeMulticastStrategy.C
index bd28b5ab9a677b1caa2f5ed4958d34d2278ff5d7..19b93ae65ab10bcb996feb5a45f11b2eb3eddd3d 100644 (file)
@@ -11,7 +11,6 @@
 
 CkpvExtern(CkGroupID, cmgrID);
 
-
 OneTimeMulticastStrategy::OneTimeMulticastStrategy()
   : Strategy(), CharmStrategy() {
   //  ComlibPrintf("OneTimeMulticastStrategy constructor\n");
@@ -41,7 +40,7 @@ void OneTimeMulticastStrategy::insertMessage(CharmMessageHolder *cmsg){
   localMulticast(cmsg);
   
   // The remote multicast method will send the message to the remote PEs, as specified in multMsg
-  remoteMulticast(multMsg);
+  remoteMulticast(multMsg, true);
    
   delete cmsg;    
 }
@@ -50,54 +49,78 @@ void OneTimeMulticastStrategy::insertMessage(CharmMessageHolder *cmsg){
 
 /** Deliver the message to the local elements. */
 void OneTimeMulticastStrategy::localMulticast(CharmMessageHolder *cmsg) {
+  double start = CmiWallTimer();
   CkSectionID *sec_id = cmsg->sec_id;
   CkVec< CkArrayIndexMax > localIndices;
   sinfo.getLocalIndices(sec_id->_nElems, sec_id->_elems, sec_id->_cookie.aid, localIndices);
   deliverToIndices(cmsg->getCharmMessage(), localIndices );
+  traceUserBracketEvent(10000, start, CmiWallTimer());
 }
 
 
 
+
+
 /** 
-    Forward multicast message to all other processors containing destination objects
+    Forward multicast message to our successor processors in the spanning tree
     Uses CmiSyncListSendAndFree for delivery to this strategy's OneTimeMulticastStrategy::handleMessage method.
 */
-void OneTimeMulticastStrategy::remoteMulticast(ComlibMulticastMsg * multMsg) {
-  envelope *env = UsrToEnv(multMsg);
-
-  // double StartTime = CmiWallTimer();
+void OneTimeMulticastStrategy::remoteMulticast(ComlibMulticastMsg * multMsg, bool rootPE) {
+  double start = CmiWallTimer();
 
-  int npes = multMsg->nPes;
+  envelope *env = UsrToEnv(multMsg);
+    
+  int npes;
+  int *pelist;   
+  
+  /// The index into the PE list in the message
+  int myIndex = -10000; 
+  const int totalDestPEs = multMsg->nPes;
+  const int myPe = CkMyPe();
+  
+  // Find my index in the list of all destination PEs
+  if(rootPE){
+    myIndex = -1;
+  } else {
+    for (int i=0; i<totalDestPEs; ++i) {
+      if(multMsg->indicesCount[i].pe == myPe){
+       myIndex = i;
+       break;
+      }
+    }
+  }
+  
+  CkAssert(myIndex != -10000); // Sanity check
+  
+  determineNextHopPEs(totalDestPEs, multMsg->indicesCount, myIndex, pelist, npes );
   
   if(npes == 0) {
+    traceUserBracketEvent(10001, start, CmiWallTimer());
     CmiFree(env);
-    return;    
-  }
-
-  // ComlibPrintf("[%d] remoteMulticast Sending to %d PEs: \n", CkMyPe(), npes);
-  int *pelist = new int[npes];
-  for (int i=0; i<npes; ++i) {
-    pelist[i] = multMsg->indicesCount[i].pe;
-    //  ComlibPrintf("[%d]   %d messages to pe %d\n", CkMyPe(), multMsg->indicesCount[i].count, multMsg->indicesCount[i].pe);
+    return;
   }
   
   CmiSetHandler(env, CkpvAccess(comlib_handler));
-
-  ((CmiMsgHeaderBasic *) env)->stratid = getInstance();
+  ((CmiMsgHeaderBasic *) env)->stratid = getInstance();  
+  CkPackMessage(&env);
 
   //Collect Multicast Statistics
   RECORD_SENDM_STATS(getInstance(), env->getTotalsize(), pelist, npes);
-    
-  CkPackMessage(&env);
-     
-  CmiSyncListSendAndFree(npes, pelist, env->getTotalsize(), (char*)env);
-  //CmiSyncBroadcastAndFree(env->getTotalsize(), (char*)env);
+  
 
-  //   traceUserBracketEvent( 2201, StartTime, CmiWallTimer()); 
+#if DEBUG
+  for(int i=0;i<npes;i++){
+    CkPrintf("[%d] Multicast to %d  rootPE=%d\n", CkMyPe(), pelist[i], (int)rootPE);
+  }
+#endif
 
-}
+  //  if(npes > 0)
+  CmiSyncListSendAndFree(npes, pelist, env->getTotalsize(), (char*)env);
+  
+  delete[] pelist;
+  traceUserBracketEvent(10001, start, CmiWallTimer());
 
+}
 
 
 
@@ -106,26 +129,103 @@ void OneTimeMulticastStrategy::remoteMulticast(ComlibMulticastMsg * multMsg) {
     Deliver the message to all local elements 
 */
 void OneTimeMulticastStrategy::handleMessage(void *msg){
-  // ComlibPrintf("[%d] In handleMulticastMessage\n", CkMyPe());
-
-  //   double StartTime = CmiWallTimer();
-  
   envelope *env = (envelope *)msg;
+  CkUnpackMessage(&env);
+  
+  ComlibMulticastMsg* multMsg = (ComlibMulticastMsg*)EnvToUsr(env);
+  
+  // Don't use msg after this point. Instead use the unpacked env
+  
   RECORD_RECV_STATS(getInstance(), env->getTotalsize(), env->getSrcPe());
   
-  // Extract the list of elements to be delivered locally
-
+  // Deliver to objects marked as local in the message
   int localElems;
   envelope *newenv;
-  CkArrayIndexMax *local_idx_list;    
-    
-  CkUnpackMessage(&env);
+  CkArrayIndexMax *local_idx_list;  
   sinfo.unpack(env, localElems, local_idx_list, newenv);
-
   ComlibMulticastMsg *newmsg = (ComlibMulticastMsg *)EnvToUsr(newenv);  
-
   deliverToIndices(newmsg, localElems, local_idx_list );
+  
+  // Forward on to other processors if necessary
+  remoteMulticast( multMsg, false);
+
+}
+
+
+
+
+void OneTimeMulticastStrategy::determineNextHopPEs(const int totalDestPEs, const ComlibMulticastIndexCount* destPEs, const int myIndex, int * &pelist, int &npes) {
+  if(myIndex==-1){
+    // We are at a root node of the spanning tree. 
+    // We will forward the message to all other PEs in the destination list.
+    npes = totalDestPEs;
     
+    pelist = new int[npes];
+    for (int i=0; i<npes; ++i) {
+      pelist[i] = destPEs[i].pe;
+    }
+  } else {
+    // We are at a leaf node of the spanning tree. 
+    npes = 0;
+  }
+  
+}
+
+
+void OneTimeRingMulticastStrategy::determineNextHopPEs(const int totalDestPEs, const ComlibMulticastIndexCount* destPEs, const int myIndex, int * &pelist, int &npes) {
+  const int myPe = CkMyPe();
+
+  if(myIndex == totalDestPEs-1){
+    // Final PE won't send to anyone
+    npes = 0;
+    return;
+  } else {
+    // All non-final PEs will send to next PE in list
+    npes = 1;
+    pelist = new int[1];
+    pelist[0] = destPEs[myIndex+1].pe;
+  }
+
+}
+
+
+void OneTimeTreeMulticastStrategy::determineNextHopPEs(const int totalDestPEs, const ComlibMulticastIndexCount* destPEs, const int myIndex, int * &pelist, int &npes){
+  const int myPe = CkMyPe();
+  
+  // 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
+  
+  // All non-final PEs will send to next PE in list
+  int sendLogicalIndexStart = degree*(myIndex+1) + 1;       // inclusive
+  int sendLogicalIndexEnd = sendLogicalIndexStart + degree - 1;   // inclusive
+  
+  if(sendLogicalIndexEnd-1 >= totalDestPEs){
+    sendLogicalIndexEnd = totalDestPEs;
+  }
+
+  int numSend = sendLogicalIndexEnd - sendLogicalIndexStart + 1;
+  if(numSend <= 0){
+    npes = 0;
+    return;
+  }
+#if DEBUG
+  if(numSend > 0)
+    CkPrintf("Tree logical index %d sending to logical %d to %d (totalDestPEs excluding root=%d)  numSend=%d\n",
+            myIndex+1, sendLogicalIndexStart, sendLogicalIndexEnd, totalDestPEs, numSend);
+#endif
+
+  npes = numSend;
+  pelist = new int[npes];
+  
+  for(int i=0;i<numSend;i++){
+    CkAssert(sendLogicalIndexStart-1+i < totalDestPEs);
+    pelist[i] = destPEs[sendLogicalIndexStart-1+i].pe;
+#if DEBUG
+    CkPrintf("Tree logical index %d sending to PE %d\n", myIndex+1, pelist[i]);
+#endif
+    CkAssert(pelist[i] < CkNumPes());
+  }
+  
 }