merging with main branch
[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       /*
57       for(int i=0;i<BUGTRAPSIZE;i++){
58         bug_trap[i] = 0;
59       }
60       
61       checkme();
62       */
63     }
64     
65     /// Verfiy that the bug_trap array has not been corrupted. Noone should ever write to that array.
66     /*
67     void checkme() {
68         for(int i=0;i<BUGTRAPSIZE;i++){
69           if(bug_trap[i] != 0){
70             CkPrintf("bug_trap[%d]=%d (should be 0) bug_trap[%d] is at %p\n", i, bug_trap[i], i, &bug_trap[i]);
71             CkAbort("Corruption of CharmMessageHolder has occured\n");
72           }
73         }
74     }
75     */
76
77     CharmMessageHolder(CkMigrateMessage *m) : MessageHolder(m) {
78       /*
79       for(int i=0;i<BUGTRAPSIZE;i++){
80         bug_trap[i] = 0;
81       }
82       checkme();
83       */
84     }
85     
86
87
88     ~CharmMessageHolder(){
89       //      checkme();
90     }
91
92     inline char * getCharmMessage() {
93         return (char *)EnvToUsr((envelope *) data);
94     }
95     
96     /// Store a local copy of the sec_id, so I can use it later.
97     inline void saveCopyOf_sec_id(){
98       //      ComlibPrintf("[%d] saveCopyOf_sec_id sec_id=%p NULL=%d\n", CkMyPe(), sec_id, NULL);
99
100       //      checkme();
101
102       if(sec_id!=NULL){
103
104         //ComlibPrintf("Original has values: _nElems=%d, npes=%d\n", sec_id->_nElems, sec_id->npes );
105         CkAssert(sec_id->_nElems>=0);
106         CkAssert(sec_id->npes>=0);
107
108
109         // Create a new CkSectionID, allocating its members
110         copy_of_sec_id = new CkSectionID();
111         copy_of_sec_id->_elems = new CkArrayIndex[sec_id->_nElems];
112         copy_of_sec_id->pelist = new int[sec_id->npes];
113         
114         // Copy in the values
115         copy_of_sec_id->_cookie = sec_id->_cookie;
116         copy_of_sec_id->_nElems = sec_id->_nElems;
117         copy_of_sec_id->npes = sec_id->npes;
118         //      ComlibPrintf("Copy has values: _nElems=%d, npes=%d\n", copy_of_sec_id->_nElems, copy_of_sec_id->npes );
119         for(int i=0; i<sec_id->_nElems; i++){
120           copy_of_sec_id->_elems[i] = sec_id->_elems[i];
121         }
122         for(int i=0; i<sec_id->npes; i++){
123           copy_of_sec_id->pelist[i] = sec_id->pelist[i];
124         }
125
126         // change local pointer to the new copy of the CkSectionID
127         //      ComlibPrintf("saving copy of sec_id into %p\n", copy_of_sec_id);
128       }
129
130       //      checkme();
131
132     }
133
134     inline void freeCopyOf_sec_id(){
135     /*   if(copy_of_sec_id != NULL){ */
136 /*      CkPrintf("delete %p\n", sec_id); */
137 /*      delete[] copy_of_sec_id->_elems; */
138 /*      delete[] copy_of_sec_id->pelist; */
139 /*      delete copy_of_sec_id; */
140 /*      copy_of_sec_id = NULL; */
141 /*       } */
142
143 //      checkme();
144
145     }
146
147
148     virtual void pup(PUP::er &p);
149     PUPable_decl(CharmMessageHolder);
150 };
151
152
153
154 // Info classes that help bracketed streategies manage objects.
155 // Each info class points to a list of source (or destination) objects.
156 // ArrayInfo also access the array listener interface
157
158 class ComlibNodeGroupInfo {
159  protected:
160     CkNodeGroupID ngid;
161     int isNodeGroup;
162
163  public:
164     ComlibNodeGroupInfo();
165
166     void setSourceNodeGroup(CkNodeGroupID gid) {
167         ngid = gid;
168         isNodeGroup = 1;
169     }
170
171     int isSourceNodeGroup(){return isNodeGroup;}
172     CkNodeGroupID getSourceNodeGroup();
173
174     void pup(PUP::er &p);
175 };
176
177 class ComlibGroupInfo {
178  protected:
179     CkGroupID sgid, dgid;
180     int *srcpelist, nsrcpes; //src processors for the elements
181     int *destpelist, ndestpes;
182     int isSrcGroup;   
183     int isDestGroup;
184
185  public:
186     ComlibGroupInfo();
187     ~ComlibGroupInfo();
188
189     int isSourceGroup(){return isSrcGroup;}
190     int isDestinationGroup(){return isDestGroup;}
191
192     void setSourceGroup(CkGroupID gid, int *srcpelist=0, int nsrcpes=0);    
193     void getSourceGroup(CkGroupID &gid);
194     void getSourceGroup(CkGroupID &gid, int *&pelist, int &npes);
195
196     void setDestinationGroup(CkGroupID sgid,int *destpelist=0,int ndestpes=0);
197     void getDestinationGroup(CkGroupID &gid);
198     void getDestinationGroup(CkGroupID &dgid,int *&destpelist, int &ndestpes);
199
200     /// This routine returnes an array of size CkNumPes() where each element
201     /// follow the convention for bracketed strategies counts.
202     int *getCombinedCountList();
203     //void getCombinedPeList(int *&pelist, int &npes);
204     void pup(PUP::er &p);
205 };
206
207 class ComlibMulticastMsg;
208
209 /** Array strategy helper class.
210    Stores the source and destination arrays.
211    Computes most recent processor maps of source and destinaton arrays.
212    
213    Array section helper functions, make use of sections easier for the
214    communication library.
215 */
216 class ComlibArrayInfo {
217  private:
218
219     CkArrayID src_aid;  ///< Source Array ID
220     CkArrayID dest_aid; ///< Destination Array ID
221     
222     /**  Destination indices that are local to this PE 
223          (as determined by the bracketed counting scheme from a previous iteration)  
224     */
225     CkVec<CkArrayIndex> src_elements; 
226
227     /**  Destination indices that are currently being updated. 
228          At the beginning of the next iteration these will be 
229          moved into dest_elements by useNewDestinationList()
230     */
231     CkVec<CkArrayIndex> new_src_elements;
232
233     /**  Destination indices that are local to this PE 
234          (as determined by the bracketed counting scheme from a previous iteration)  
235     */
236     CkVec<CkArrayIndex> dest_elements; 
237
238     /**  Destination indices that are currently being updated. 
239          At the beginning of the next iteration these will be 
240          moved into dest_elements by useNewDestinationList()
241     */
242     CkVec<CkArrayIndex> new_dest_elements;
243
244     int isSrcArray;
245     int isDestArray;
246
247     bool isAllSrc; ///< if true then all the array is involved in the operation
248     int totalSrc; ///< The total number of src elements involved in the strategy
249     bool isAllDest; ///< if true then all the array is involved in the operation
250     int totalDest; ///< The total number of array elements involved in the strategy
251     
252  public:
253     ComlibArrayInfo();
254     //~ComlibArrayInfo();
255
256     /** Set the  source array used for this strategy. 
257         The list of array indices should be the whole portion of the array involved in the strategy.
258         The non-local array elements will be cleaned up inside purge() at migration of the strategy
259     */
260     void setSourceArray(CkArrayID aid, CkArrayIndex *e=0, int nind=0);
261     int isSourceArray(){return isSrcArray;}
262     CkArrayID getSourceArrayID() {return src_aid;}
263     const CkVec<CkArrayIndex> & getSourceElements() {return src_elements;}
264
265     /** Set the destination array used for this strategy. 
266         The list of array indices should be the whole portion of the array involved in the strategy.
267         The non-local array elements will be cleaned up inside purge() at migration of the strategy
268     */
269     void setDestinationArray(CkArrayID aid, CkArrayIndex *e=0, int nind=0);
270     int isDestinationArray(){return isDestArray;}
271     CkArrayID getDestinationArrayID() {return dest_aid;}
272     const CkVec<CkArrayIndex> & getDestinationElements() {return dest_elements;}
273
274     /// Get the number of source array elements
275     int getTotalSrc() {return totalSrc;}
276     int getLocalSrc() {return src_elements.size();}
277
278     /** Add a destination object that is local to this PE to list used in future iterations */
279     void addNewLocalDestination(const CkArrayIndex &e) {
280         CkAssert(e.nInts > 0);
281         new_dest_elements.push_back(e);
282     }
283
284     /** Add a source object that is local to this PE to list used in future iterations */
285     void addNewLocalSource(const CkArrayIndex &e) {
286         CkAssert(e.nInts > 0);
287         new_src_elements.push_back(e);
288     }
289   
290     /// Switch to using the new destination and source lists if the previous iteration found an error and constructed the new list
291     void useNewSourceAndDestinations() {
292       ComlibPrintf("[%d] useNewSourceAndDestinations previously had %d elements, now have %d elements\n", CkMyPe(), dest_elements.size(), new_src_elements.size() );
293       dest_elements.removeAll();
294       dest_elements = new_dest_elements;
295       CkAssert(dest_elements.size() == new_dest_elements.size());
296       new_dest_elements.removeAll();
297       src_elements.removeAll();
298       src_elements = new_src_elements;
299       CkAssert(src_elements.size() == new_src_elements.size());
300       new_src_elements.removeAll();
301       if(com_debug)
302         printDestElementList();
303     }
304
305     int newDestinationListSize(){ return new_dest_elements.size(); }
306     int newSourceListSize(){ return new_src_elements.size(); }
307
308     int getTotalDest() {return totalDest;}
309     int getLocalDest() {return dest_elements.size();}
310
311     void newElement(CkArrayID &id, const CkArrayIndex &idx);
312
313     void localBroadcast(envelope *env);
314     static int localMulticast(CkVec<CkArrayIndex> *idx_vec,envelope *env);
315     static void deliver(envelope *env);
316
317     /// This routine is called only once at the beginning and will take the list
318     /// of source and destination elements and leave only those that have homePe
319     /// here.
320     void purge();
321
322     /// This routine returnes an array of size CkNumPes() where each element
323     /// follow the convention for bracketed strategies counts.
324     int *getCombinedCountList();
325
326     void printDestElementList();
327
328
329     void pup(PUP::er &p);
330 };
331
332 /** Implementation of CkLocIterator to get all the local elements from a
333     specified processor. Currently used by ComlibArrayInfo */
334 class ComlibElementIterator : public CkLocIterator {
335  public:
336   CkVec<CkArrayIndex> *list;
337
338   ComlibElementIterator(CkVec<CkArrayIndex> *l) : CkLocIterator() {
339     list = l;
340   }
341
342   virtual void addLocation (CkLocation &loc) {
343     list->push_back(loc.getIndex());
344   }
345 };
346
347
348
349 // forward declaration of wrapper for ComlibManager::registerArrayListener
350 void ComlibManagerRegisterArrayListener(CkArrayID, ComlibArrayInfo*);
351
352 /** All Charm++ communication library strategies should inherit from 
353     CharmStrategy, rather than inheriting from class Strategy (or one of its
354     subclasses). They should specify their object domain by setting
355     Strategy::type. They have three helpers predefined for them for node groups,
356     groups and arrays. */
357 class CharmStrategy {
358     
359  protected:
360   //int forwardOnMigration;
361     ComlibLearner *learner;
362     CmiBool mflag;    //Does this strategy handle point-to-point or 
363     CkCallback onFinish;
364
365
366     /** Deliver a message to a set of indices using the array manager. Indices can be local or remote. */
367     int deliverToIndices(void *msg, int numDestIdxs, const CkArrayIndex* indices );
368     
369     /** Deliver a message to a set of indices using the array manager. Indices can be local or remote. */
370     inline void deliverToIndices(void *msg, const CkVec< CkArrayIndex > &indices ){
371       deliverToIndices(msg, indices.size(), indices.getVec() );
372     }
373     
374     
375  public:
376     //int iterationNumber;
377     ComlibGroupInfo ginfo;
378     ComlibNodeGroupInfo nginfo;
379
380     /// The communication library array listener watches and monitors
381     /// the array elements belonging to ainfo.src_aid
382     ComlibArrayInfo ainfo;
383     
384     CharmStrategy() { //: Strategy() {
385       //setType(GROUP_STRATEGY); 
386       //forwardOnMigration = 0;
387       //iterationNumber = 0;
388       learner = NULL;
389       mflag = CmiFalse;
390     }
391
392     CharmStrategy(CkMigrateMessage *m) { //: Strategy(m){
393       learner = NULL;
394     }
395
396     //Set flag to optimize strategy for 
397     inline void setMulticast(){
398         mflag = CmiTrue;
399     }
400
401     //get the multicast flag
402     CmiBool getMulticast () {
403         return mflag;
404     }
405
406     inline void setOnFinish (CkCallback of) {
407       onFinish = of;
408     }
409
410     inline CkCallback getOnFinish () {
411       return onFinish;
412     }
413
414     
415     ComlibLearner *getLearner() {return learner;}
416     void setLearner(ComlibLearner *l) {learner = l;}
417     
418     virtual void pup(PUP::er &p);
419  
420 };
421
422 //API calls which will be valid when communication library is not linked
423 void ComlibNotifyMigrationDone();
424 //int ComlibGetLastKnown(CkArrayID aid, CkArrayIndex idx);
425
426
427 #endif
428
429 /*@}*/