Adding some user events to trace the multicasts.
[charm.git] / src / ck-com / ComlibStrategy.h
1 /**
2    @addtogroup CharmComlib
3    @{
4    @file
5
6    @brief Defines CharmStrategy and CharmMessageHolder.
7 */
8
9 #ifndef COMLIBSTRATEGY_H
10 #define COMLIBSTRATEGY_H
11
12 #include "charm++.h"
13 #include "ckhashtable.h"
14 #include "convcomlibstrategy.h"
15 #include "ComlibLearner.h"
16 #include "envelope.h"
17
18 CkpvExtern(int, migrationDoneHandlerID);
19
20
21 /// Defines labels for distinguishing between types of sends in a CharmMessageHolder
22 enum CmhMessageType { CMH_ARRAYSEND, 
23                       CMH_GROUPSEND, 
24                       CMH_ARRAYBROADCAST, 
25                       CMH_ARRAYSECTIONSEND, 
26                       CMH_GROUPBROADCAST     };
27
28
29
30 /// Class managing Charm++ messages in the communication library.
31 /// It is aware of envelopes, arrays, etc
32 class CharmMessageHolder : public MessageHolder{
33  public:
34     /// An unused, and probably unnecessary array that was used to avoid a memory corruption that clobbers members in this class. The bug has likely been fixed.
35
36 #define BUGTRAPSIZE 5000
37
38     int bug_trap[BUGTRAPSIZE];
39
40     /// The section information for an enqueued multicast message
41     CkSectionID *sec_id;
42
43     /// Saves a copy of the CkSectionID sec_id when enqueing a multicast message
44     CkSectionID *copy_of_sec_id;  
45
46     CkArrayID array_id; 
47
48     /// Type of message we are buffering
49     CmhMessageType type; 
50     
51  CharmMessageHolder(char * msg, int proc, CmhMessageType t) : 
52     MessageHolder((char *)UsrToEnv(msg), UsrToEnv(msg)->getTotalsize(), proc){
53       type = t;
54       sec_id = NULL;
55       copy_of_sec_id = NULL;
56       for(int i=0;i<BUGTRAPSIZE;i++){
57         bug_trap[i] = 0;
58       }
59       
60       checkme();
61     }
62     
63     /// Verfiy that the bug_trap array has not been corrupted. Noone should ever write to that array.
64     void checkme() {
65         for(int i=0;i<BUGTRAPSIZE;i++){
66           if(bug_trap[i] != 0){
67             CkPrintf("bug_trap[%d]=%d (should be 0) bug_trap[%d] is at %p\n", i, bug_trap[i], i, &bug_trap[i]);
68             CkAbort("Corruption of CharmMessageHolder has occured\n");
69           }
70         }
71     }
72
73
74     CharmMessageHolder(CkMigrateMessage *m) : MessageHolder(m) {
75       for(int i=0;i<BUGTRAPSIZE;i++){
76         bug_trap[i] = 0;
77       }
78       checkme();
79     }
80     
81
82
83     ~CharmMessageHolder(){
84       checkme();
85     }
86
87     inline char * getCharmMessage() {
88         return (char *)EnvToUsr((envelope *) data);
89         checkme();
90     }
91     
92     /// Store a local copy of the sec_id, so I can use it later.
93     inline void saveCopyOf_sec_id(){
94       ComlibPrintf("[%d] saveCopyOf_sec_id sec_id=%p NULL=%d\n", CkMyPe(), sec_id, NULL);
95
96       checkme();
97
98       if(sec_id!=NULL){
99
100         ComlibPrintf("Original has values: _nElems=%d, npes=%d\n", sec_id->_nElems, sec_id->npes );
101         CkAssert(sec_id->_nElems>=0);
102         CkAssert(sec_id->npes>=0);
103
104
105         // Create a new CkSectionID, allocating its members
106         copy_of_sec_id = new CkSectionID();
107         copy_of_sec_id->_elems = new CkArrayIndexMax[sec_id->_nElems];
108         copy_of_sec_id->pelist = new int[sec_id->npes];
109         
110         // Copy in the values
111         copy_of_sec_id->_cookie = sec_id->_cookie;
112         copy_of_sec_id->_nElems = sec_id->_nElems;
113         copy_of_sec_id->npes = sec_id->npes;
114         ComlibPrintf("Copy has values: _nElems=%d, npes=%d\n", copy_of_sec_id->_nElems, copy_of_sec_id->npes );
115         for(int i=0; i<sec_id->_nElems; i++){
116           copy_of_sec_id->_elems[i] = sec_id->_elems[i];
117         }
118         for(int i=0; i<sec_id->npes; i++){
119           copy_of_sec_id->pelist[i] = sec_id->pelist[i];
120         }
121
122         // change local pointer to the new copy of the CkSectionID
123         ComlibPrintf("saving copy of sec_id into %p\n", copy_of_sec_id);
124       }
125
126       checkme();
127
128     }
129
130     inline void freeCopyOf_sec_id(){
131     /*   if(copy_of_sec_id != NULL){ */
132 /*      CkPrintf("delete %p\n", sec_id); */
133 /*      delete[] copy_of_sec_id->_elems; */
134 /*      delete[] copy_of_sec_id->pelist; */
135 /*      delete copy_of_sec_id; */
136 /*      copy_of_sec_id = NULL; */
137 /*       } */
138
139       checkme();
140
141     }
142
143
144     virtual void pup(PUP::er &p);
145     PUPable_decl(CharmMessageHolder);
146 };
147
148
149
150 // Info classes that help bracketed streategies manage objects.
151 // Each info class points to a list of source (or destination) objects.
152 // ArrayInfo also access the array listener interface
153
154 class ComlibNodeGroupInfo {
155  protected:
156     CkNodeGroupID ngid;
157     int isNodeGroup;
158
159  public:
160     ComlibNodeGroupInfo();
161
162     void setSourceNodeGroup(CkNodeGroupID gid) {
163         ngid = gid;
164         isNodeGroup = 1;
165     }
166
167     int isSourceNodeGroup(){return isNodeGroup;}
168     CkNodeGroupID getSourceNodeGroup();
169
170     void pup(PUP::er &p);
171 };
172
173 class ComlibGroupInfo {
174  protected:
175     CkGroupID sgid, dgid;
176     int *srcpelist, nsrcpes; //src processors for the elements
177     int *destpelist, ndestpes;
178     int isSrcGroup;   
179     int isDestGroup;
180
181  public:
182     ComlibGroupInfo();
183     ~ComlibGroupInfo();
184
185     int isSourceGroup(){return isSrcGroup;}
186     int isDestinationGroup(){return isDestGroup;}
187
188     void setSourceGroup(CkGroupID gid, int *srcpelist=0, int nsrcpes=0);    
189     void getSourceGroup(CkGroupID &gid);
190     void getSourceGroup(CkGroupID &gid, int *&pelist, int &npes);
191
192     void setDestinationGroup(CkGroupID sgid,int *destpelist=0,int ndestpes=0);
193     void getDestinationGroup(CkGroupID &gid);
194     void getDestinationGroup(CkGroupID &dgid,int *&destpelist, int &ndestpes);
195
196     /// This routine returnes an array of size CkNumPes() where each element
197     /// follow the convention for bracketed strategies counts.
198     int *getCombinedCountList();
199     //void getCombinedPeList(int *&pelist, int &npes);
200     void pup(PUP::er &p);
201 };
202
203 class ComlibMulticastMsg;
204
205 /** Array strategy helper class.
206    Stores the source and destination arrays.
207    Computes most recent processor maps of source and destinaton arrays.
208    
209    Array section helper functions, make use of sections easier for the
210    communication library.
211 */
212 class ComlibArrayInfo {
213  protected:
214     CkArrayID src_aid;  ///< Source Array ID
215     CkVec<CkArrayIndexMax> src_elements;     ///< local source array elements
216     int isSrcArray;
217     int isAllSrc; ///< if true then all the array is involved in the operation
218     int totalSrc; ///< The total number of src elements involved in the strategy
219
220     CkArrayID dest_aid;
221     CkVec<CkArrayIndexMax> dest_elements; ///< destination indices
222     int isDestArray;
223     int isAllDest; ///< if true then all the array is involved in the operation
224     int totalDest; ///< The total number of array elements involved in the strategy
225     
226  public:
227     ComlibArrayInfo();
228     //~ComlibArrayInfo();
229
230     void setSourceArray(CkArrayID aid, CkArrayIndexMax *e=0, int nind=0);
231     int isSourceArray(){return isSrcArray;}
232     void getSourceArray(CkArrayID &aid, CkArrayIndexMax *&e, int &nind);
233     /// This operation leaks memory is the index vector is not retrieved before!
234     void resetSource() {new (&src_elements) CkVec<CkArrayIndexMax>();};
235     void addSource(CkArrayIndexMax &e) {
236         src_elements.push_back(e);
237 //      ComlibPrintf("[%d] src_elements.push_back(%d)  now contains %d\n", CkMyPe(), e.data()[0], src_elements.size());
238     }
239
240     /// Get the number of source array elements
241     int getTotalSrc() {return totalSrc;}
242     int getLocalSrc() {return src_elements.size();}
243
244     void setDestinationArray(CkArrayID aid, CkArrayIndexMax *e=0, int nind=0);
245     int isDestinationArray(){return isDestArray;}
246     void getDestinationArray(CkArrayID &aid, CkArrayIndexMax *&e, int &nind);
247     /// This operation leaks memory is the index vector is not retrieved before!
248     void resetDestination() {new (&dest_elements) CkVec<CkArrayIndexMax>();};
249     void addDestination(CkArrayIndexMax &e) {
250         dest_elements.push_back(e);
251         ComlibPrintf("[%d] dest_elements.push_back(%d)  now contains %d\n", CkMyPe(), e.data()[0], dest_elements.size());       
252     }
253     int getTotalDest() {return totalDest;}
254     int getLocalDest() {return dest_elements.size();}
255
256     void newElement(CkArrayID &id, const CkArrayIndex &idx);
257
258     void localBroadcast(envelope *env);
259     static int localMulticast(CkVec<CkArrayIndexMax> *idx_vec,envelope *env);
260     static void deliver(envelope *env);
261
262     /// This routine is called only once at the beginning and will take the list
263     /// of source and destination elements and leave only those that have homePe
264     /// here.
265     void purge();
266
267     /// This routine returnes an array of size CkNumPes() where each element
268     /// follow the convention for bracketed strategies counts.
269     int *getCombinedCountList();
270     //void getSourcePeList(int *&pelist, int &npes);
271     //void getDestinationPeList(int *&pelist, int &npes);
272     //void getCombinedPeList(int *&pelist, int &npes);
273     
274     void pup(PUP::er &p);
275 };
276
277 /** Implementation of CkLocIterator to get all the local elements from a
278     specified processor. Currently used by ComlibArrayInfo */
279 class ComlibElementIterator : public CkLocIterator {
280  public:
281   CkVec<CkArrayIndexMax> *list;
282
283   ComlibElementIterator(CkVec<CkArrayIndexMax> *l) : CkLocIterator() {
284     list = l;
285   }
286
287   virtual void addLocation (CkLocation &loc) {
288     list->push_back(loc.getIndex());
289   }
290 };
291
292
293
294 // forward declaration of wrapper for ComlibManager::registerArrayListener
295 void ComlibManagerRegisterArrayListener(CkArrayID, ComlibArrayInfo*);
296
297 /** All Charm++ communication library strategies should inherit from 
298     CharmStrategy, rather than inheriting from class Strategy (or one of its
299     subclasses). They should specify their object domain by setting
300     Strategy::type. They have three helpers predefined for them for node groups,
301     groups and arrays. */
302 class CharmStrategy {
303     
304  protected:
305   //int forwardOnMigration;
306     ComlibLearner *learner;
307     CmiBool mflag;    //Does this strategy handle point-to-point or 
308     CkCallback onFinish;
309
310
311     /** Deliver a message to a set of indices using the array manager. Indices can be local or remote. */
312     void deliverToIndices(void *msg, int numDestIdxs, const CkArrayIndexMax* indices );
313     
314     /** Deliver a message to a set of indices using the array manager. Indices can be local or remote. */
315     inline void deliverToIndices(void *msg, const CkVec< CkArrayIndexMax > &indices ){
316       deliverToIndices(msg, indices.size(), indices.getVec() );
317     }
318     
319     
320  public:
321     //int iterationNumber;
322     ComlibGroupInfo ginfo;
323     ComlibNodeGroupInfo nginfo;
324
325     /// The communication library array listener watches and monitors
326     /// the array elements belonging to ainfo.src_aid
327     ComlibArrayInfo ainfo;
328     
329     CharmStrategy() { //: Strategy() {
330       //setType(GROUP_STRATEGY); 
331       //forwardOnMigration = 0;
332       //iterationNumber = 0;
333       learner = NULL;
334       mflag = CmiFalse;
335     }
336
337     CharmStrategy(CkMigrateMessage *m) { //: Strategy(m){
338       learner = NULL;
339     }
340
341     //Set flag to optimize strategy for 
342     inline void setMulticast(){
343         mflag = CmiTrue;
344     }
345
346     //get the multicast flag
347     CmiBool getMulticast () {
348         return mflag;
349     }
350
351     inline void setOnFinish (CkCallback of) {
352       onFinish = of;
353     }
354
355     inline CkCallback getOnFinish () {
356       return onFinish;
357     }
358
359     
360     ComlibLearner *getLearner() {return learner;}
361     void setLearner(ComlibLearner *l) {learner = l;}
362     
363     virtual void pup(PUP::er &p);
364  
365 };
366
367 //API calls which will be valid when communication library is not linked
368 void ComlibNotifyMigrationDone();
369 //int ComlibGetLastKnown(CkArrayID aid, CkArrayIndexMax idx);
370
371
372 #endif
373
374 /*@}*/