Make notifyMsg local to each helper instead of being local to the node helper
[charm.git] / NodeHelper.h
1 #ifndef _NODEHELPER_H
2 #define _NODEHELPER_H
3 #include <assert.h>
4
5 #include "charm++.h"
6 #include "NodeHelperAPI.h"
7
8 #define USE_TREE_BROADCAST_THRESHOLD 8
9 #define TREE_BCAST_BRANCH (4)
10 #define CACHE_LINE_SIZE 64
11
12 class FuncSingleHelper;
13
14 class CurLoopInfo{
15     friend class FuncSingleHelper;
16     
17 private:
18     volatile int curChunkIdx;
19     int numChunks;
20     HelperFn fnPtr;
21     int lowerIndex;
22     int upperIndex;
23     int paramNum;
24     void *param;
25     //limitation: only allow single variable reduction of size numChunks!!!
26     void **redBufs;
27         char *bufSpace;
28
29     volatile int finishFlag;
30     
31     //a tag to indicate whether the task for this new loop has been inited
32     //this tag is needed to prevent other helpers to run the old task
33     int inited;
34     
35 public:    
36     CurLoopInfo(int maxChunks):numChunks(0),fnPtr(NULL), lowerIndex(-1), upperIndex(0), 
37     paramNum(0), param(NULL), curChunkIdx(-1), finishFlag(0), redBufs(NULL), bufSpace(NULL), inited(0) 
38         {
39                 redBufs = new void *[maxChunks];
40                 bufSpace = new char[maxChunks * CACHE_LINE_SIZE];
41         for(int i=0; i<maxChunks; i++) redBufs[i] = (void *)(bufSpace+i*CACHE_LINE_SIZE);
42         }
43     
44     ~CurLoopInfo() { 
45                 delete [] redBufs; 
46                 delete [] bufSpace;
47         }
48     
49     void set(int nc, HelperFn f, int lIdx, int uIdx, int numParams, void *p){        
50         numChunks = nc;
51         fnPtr = f;
52         lowerIndex = lIdx;
53         upperIndex = uIdx;
54         paramNum = numParams;
55         param = p;
56         curChunkIdx = -1;
57         finishFlag = 0;
58         //needs to be set last
59         inited = 1;
60     }
61       
62     void waitLoopDone(){
63         while(!__sync_bool_compare_and_swap(&finishFlag, numChunks, 0));
64         inited = 0;
65     }
66     int getNextChunkIdx(){
67         return __sync_add_and_fetch(&curChunkIdx, 1);
68     }
69     void reportFinished(){
70         __sync_add_and_fetch(&finishFlag, 1);
71     }
72     
73         void **getRedBufs() { return redBufs; }
74         
75     void stealWork();
76 };
77
78 /* FuncNodeHelper is a nodegroup object */
79
80 typedef struct converseNotifyMsg{
81     char core[CmiMsgHeaderSizeBytes];
82     int srcRank;
83     void *ptr;
84 }ConverseNotifyMsg;
85
86 class FuncNodeHelper : public CBase_FuncNodeHelper {
87     friend class FuncSingleHelper;
88         
89 public:
90     static int MAX_CHUNKS;
91 private:    
92     int numHelpers;    
93     FuncSingleHelper **helperPtr; /* ptrs to the FuncSingleHelpers it manages */
94         int useTreeBcast;
95     
96 public:
97         FuncNodeHelper();
98     ~FuncNodeHelper() {
99         delete [] helperPtr;
100     }
101
102     /* handler is only useful when converse msg is used to initiate tasks on the pseudo-thread */
103     void oneHelperCreated(int hid, FuncSingleHelper* cptr) {
104         helperPtr[hid] = cptr;
105     }
106     
107     void parallelizeFunc(HelperFn func, /* the function that finishes a partial work on another thread */
108                         int paramNum, void * param, /* the input parameters for the above func */
109                         int msgPriority, /* the priority of the intra-node msg, and node-level msg */
110                         int numChunks, /* number of chunks to be partitioned */
111                         int lowerRange, int upperRange, /* the loop-like parallelization happens in [lowerRange, upperRange] */                        
112                         void *redResult=NULL, REDUCTION_TYPE type=NODEHELPER_NONE /* the reduction result, ONLY SUPPORT SINGLE VAR of TYPE int/float/double */
113                         );
114     void reduce(void **redBufs, void *redBuf, REDUCTION_TYPE type, int numChunks);
115 };
116
117 void SingleHelperStealWork(ConverseNotifyMsg *msg);
118
119 /* FuncSingleHelper is a chare located on every core of a node */
120 class FuncSingleHelper: public CBase_FuncSingleHelper {
121         friend class FuncNodeHelper;
122 private: 
123     FuncNodeHelper *thisNodeHelper;
124     ConverseNotifyMsg *notifyMsg;
125     CurLoopInfo *curLoop; /* Points to the current loop that is being processed */
126     
127 public:
128     FuncSingleHelper(CkGroupID nid) {        
129         CProxy_FuncNodeHelper fh(nid);
130         thisNodeHelper = fh[CkMyNode()].ckLocalBranch();
131         CmiAssert(thisNodeHelper!=NULL);        
132         int stealWorkHandler = CmiRegisterHandler((CmiHandler)SingleHelperStealWork);
133         curLoop = new CurLoopInfo(FuncNodeHelper::MAX_CHUNKS);
134         
135         notifyMsg = (ConverseNotifyMsg *)malloc(sizeof(ConverseNotifyMsg));
136         if(thisNodeHelper->useTreeBcast){
137             notifyMsg->srcRank = CmiMyRank();
138         }else{
139             notifyMsg->srcRank = -1;
140         }
141         notifyMsg->ptr = (void *)curLoop;
142         CmiSetHandler(notifyMsg, stealWorkHandler);
143     }
144
145     ~FuncSingleHelper() {
146         delete curLoop;
147         delete notifyMsg;
148     }
149     
150     FuncSingleHelper(CkMigrateMessage *m) {}
151                 
152     void reportCreated() {
153         //CkPrintf("Single helper %d is created on rank %d\n", CkMyPe(), CkMyRank());
154                 thisNodeHelper->oneHelperCreated(CkMyRank(), this);
155     }    
156 };
157
158 #endif