Did two optimizations:
authorChao Mei <chaomei2@illinois.edu>
Thu, 26 Jan 2012 23:12:51 +0000 (17:12 -0600)
committerChao Mei <chaomei2@illinois.edu>
Thu, 26 Jan 2012 23:12:51 +0000 (17:12 -0600)
1. Replaced the notification scheme with converse-level msg instead of a charm-level entry method.
2. Using gcc built-ins (atomic increment, compare_and_swap) to test whether the job finishes

NodeHelper.C
NodeHelper.h

index 0835d5b4d237ee23ebcd5672cd488adbb2aa58a4..4ca49ac0cc8bf61bf5f3ba4204d2ff3c29c895c8 100644 (file)
@@ -115,6 +115,11 @@ FuncNodeHelper::FuncNodeHelper(int mode_,int numThds_):
         numHelpers = CkMyNodeSize();
         helperArr = new CkChareID[numHelpers];
         helperPtr = new FuncSingleHelper *[numHelpers];
+        
+#if USE_CONVERSE_MSG
+        notifyMsgs = (ConverseNotifyMsg *)malloc(sizeof(ConverseNotifyMsg)*numHelpers);
+#endif        
+        
         int pestart = CkNodeFirst(CkMyNode());
         for (int i=0; i<numHelpers; i++) {
             CProxy_FuncSingleHelper::ckNew(thisgroup, &helperArr[i], pestart+i);
@@ -161,7 +166,7 @@ void FuncNodeHelper::parallelizeFunc(HelperFn func, int paramNum, void * param,
         CkPrintf("NodeHelper[%d]: WARNING! chunk is set to MAX_CHUNKS=%d\n", CmiMyPe(), MAX_CHUNKS);
         numChunks = MAX_CHUNKS;
     }
-    
+        
     Task **task = helperPtr[CkMyRank()]->getTasksMem();
 
     int first = lowerRange;
@@ -210,15 +215,23 @@ void FuncNodeHelper::parallelizeFunc(HelperFn func, int paramNum, void * param,
         stride = unit+1;
         for (int i=0; i<remainder; i++, first+=stride) {
             task[i]->init(func, first, first+stride-1, 0, CkMyRank(),paramNum, param);            
-            helperPtr[i%CkMyNodeSize()]->enqueueWork(task[i]);
+            helperPtr[i%numHelpers]->enqueueWork(task[i]);
         }
         
         stride = unit;
         for (int i=remainder; i<numChunks; i++, first+=stride) {
             task[i]->init(func, first, first+stride-1, 0, CkMyRank(),paramNum, param);            
-            helperPtr[i%CkMyNodeSize()]->enqueueWork(task[i]);
+            helperPtr[i%numHelpers]->enqueueWork(task[i]);
         }
         
+#if USE_CONVERSE_MSG
+        
+        for (int i=0; i<numHelpers; i++) {
+            if (i!=CkMyRank()) {
+                CmiPushPE(i, (void *)(notifyMsgs+i));
+            }
+        }
+#else
         CkEntryOptions entOpts;
         entOpts.setPriority(msgPriority);
 
@@ -227,13 +240,17 @@ void FuncNodeHelper::parallelizeFunc(HelperFn func, int paramNum, void * param,
                 CProxy_FuncSingleHelper helpProxy(helperArr[i]);                
                 helpProxy.processWork(0, &entOpts);
             }
-        }
+        }    
+#endif        
         helperPtr[CkMyRank()]->processWork(0);
         
         TRACE_BRACKET(20);
         
         TRACE_START(21);
-        waitDone(task,numChunks);
+                
+        while(!__sync_bool_compare_and_swap(&(helperPtr[CkMyRank()]->counter), numChunks, 0));
+        //waitDone(task,numChunks);
+        
         TRACE_BRACKET(21);
     }
 #else
@@ -340,6 +357,13 @@ void FuncNodeHelper::printMode(int mode) {
     }
 }
 
+#if USE_CONVERSE_MSG
+void NotifySingleHelper(ConverseNotifyMsg *msg){
+    FuncSingleHelper *h = msg->ptr;
+    h->processWork(0);
+}
+#endif
+
 //======================================================================//
 // Functions regarding helpers that parallelize a single function on a  //
 // single node (like OpenMP)                                            // 
@@ -355,22 +379,19 @@ void FuncSingleHelper::processWork(int filler) {
     one = (Task *)tmp;
     while (one) {
         (one->fnPtr)(one->first,one->last,(void *)(one->redBuf), one->paramNum, one->param);
-        int *partial = (int *)(one->redBuf);
+        //int *partial = (int *)(one->redBuf);
         //CkPrintf("SingleHelper[%d]: partial=%d\n", CkMyRank(), *partial);
-        one->setFlag();
+        
+        //one->setFlag();
+        __sync_add_and_fetch(&(thisNodeHelper->helperPtr[one->originRank]->counter), 1);
+        
+        
         CmiLock(reqLock);
         CqsDequeue(reqQ, &tmp);
         one = (Task *)tmp;
         CmiUnlock(reqLock);
     }
 }
-
-void FuncSingleHelper::reportCreated() {
-    //CkPrintf("Single helper %d is created on rank %d\n", CkMyPe(), CkMyRank());
-    CProxy_FuncNodeHelper fh(nodeHelperID);
-    CProxy_FuncSingleHelper thisproxy(thishandle);
-    fh[CkMyNode()].ckLocalBranch()->oneHelperCreated(CkMyRank(), thishandle, this);
-}
 //======================================================================//
 //   End of functions related with FuncSingleHelper                     //
 //======================================================================//
index 9d12f6c6fef2b4955ed0869ff92353b24a8cea9c..04f0c3f95117348c962110ae161bf31aa5fc0e9c 100644 (file)
@@ -8,6 +8,9 @@
 #include "NodeHelperAPI.h"
 #include "queueing.h"
 
+#define USE_CONVERSE_MSG 1
+
+/* The following only works on X86_64 platform */
 #define AtomicIncrement(someInt)  __asm__ __volatile__("lock incl (%0)" :: "r" (&(someInt)))
 
 
@@ -68,8 +71,20 @@ public:
 
 /* FuncNodeHelper is a nodegroup object */
 class FuncSingleHelper;
+#if USE_CONVERSE_MSG
+typedef struct converseNotifyMsg{
+    char core[CmiMsgHeaderSizeBytes];
+    FuncSingleHelper *ptr;
+}ConverseNotifyMsg;
+#endif
 
 class FuncNodeHelper : public CBase_FuncNodeHelper {
+    friend class FuncSingleHelper;
+private:
+#if USE_CONVERSE_MSG
+    ConverseNotifyMsg *notifyMsgs;         
+#endif
+
 public:
     static int MAX_CHUNKS;
     static void printMode(int mode);
@@ -85,12 +100,20 @@ public:
     
     ~FuncNodeHelper() {
         delete [] helperArr;
-        delete [] helperPtr;        
+        delete [] helperPtr;
+    #if USE_CONVERSE_MSG
+        delete [] notifyMsgs;
+    #endif
     }
 
-    void oneHelperCreated(int hid, CkChareID cid, FuncSingleHelper* cptr) {
+    /* handler is only useful when converse msg is used to initiate tasks on the pseudo-thread */
+    void oneHelperCreated(int hid, CkChareID cid, FuncSingleHelper* cptr, int handler=0) {
         helperArr[hid] = cid;
         helperPtr[hid] = cptr;
+#if USE_CONVERSE_MSG        
+        notifyMsgs[hid].ptr = cptr;
+        CmiSetHandler(&(notifyMsgs[hid]), handler);
+#endif
     }
 
 #if CMK_SMP
@@ -115,21 +138,26 @@ public:
     void reduce(Task **thisReq, void *redBuf, REDUCTION_TYPE type, int numChunks);
 };
 
+#if USE_CONVERSE_MSG
+void NotifySingleHelper(ConverseNotifyMsg *msg);
+#endif
+
 /* FuncSingleHelper is a chare located on every core of a node */
 class FuncSingleHelper: public CBase_FuncSingleHelper {
        friend class FuncNodeHelper;
-private:
+private: 
+    /* BE CAREFUL ABOUT THE FILEDS LAYOUT CONSIDERING CACHE EFFECTS */
+    volatile int counter;
+    int notifyHandler;
     CkGroupID nodeHelperID;
+    FuncNodeHelper *thisNodeHelper;
     Queue reqQ; /* The queue may be simplified for better performance */
     
     /* The following two vars are for usage of detecting completion in dynamic scheduling */
     CmiNodeLock reqLock;
-    int counter; 
-    
     /* To reuse such Task memory as each SingleHelper (i.e. a PE) will only
      * process one node-level parallelization at a time */
     Task **tasks; /* Note the Task type is a message */
-
 public:
     FuncSingleHelper(CkGroupID nid):nodeHelperID(nid) {
         reqQ = CqsCreate();
@@ -139,6 +167,15 @@ public:
         
         tasks = new Task *[FuncNodeHelper::MAX_CHUNKS];
         for(int i=0; i<FuncNodeHelper::MAX_CHUNKS; i++) tasks[i] = new (8*sizeof(int)) Task();
+        
+        CProxy_FuncNodeHelper fh(nodeHelperID);
+        thisNodeHelper = fh[CkMyNode()].ckLocalBranch();
+        CmiAssert(thisNodeHelper!=NULL);
+        
+        notifyHandler = 0;
+    #if USE_CONVERSE_MSG
+        notifyHandler = CmiRegisterHandler((CmiHandler)NotifySingleHelper);
+    #endif
     }
 
     ~FuncSingleHelper() {
@@ -159,7 +196,10 @@ public:
         CmiUnlock(reqLock);
     }
     void processWork(int filler); /* filler is here in order to use CkEntryOptions for setting msg priority */
-    void reportCreated();
+    void reportCreated() {
+        //CkPrintf("Single helper %d is created on rank %d\n", CkMyPe(), CkMyRank());        
+        thisNodeHelper->oneHelperCreated(CkMyRank(), thishandle, this, notifyHandler);
+    }
 };
 
 #endif