c95f70ed0438aedd5e6277d018784800d6c1f0a8
[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  private:
214
215     CkArrayID src_aid;  ///< Source Array ID
216     CkArrayID dest_aid; ///< Destination Array ID
217     
218     /**  Destination indices that are local to this PE 
219          (as determined by the bracketed counting scheme from a previous iteration)  
220     */
221     CkVec<CkArrayIndexMax> src_elements; 
222
223     /**  Destination indices that are currently being updated. 
224          At the beginning of the next iteration these will be 
225          moved into dest_elements by useNewDestinationList()
226     */
227     CkVec<CkArrayIndexMax> new_src_elements;
228
229     /**  Destination indices that are local to this PE 
230          (as determined by the bracketed counting scheme from a previous iteration)  
231     */
232     CkVec<CkArrayIndexMax> dest_elements; 
233
234     /**  Destination indices that are currently being updated. 
235          At the beginning of the next iteration these will be 
236          moved into dest_elements by useNewDestinationList()
237     */
238     CkVec<CkArrayIndexMax> new_dest_elements;
239
240     int isSrcArray;
241     int isDestArray;
242
243     bool isAllSrc; ///< if true then all the array is involved in the operation
244     int totalSrc; ///< The total number of src elements involved in the strategy
245     bool isAllDest; ///< if true then all the array is involved in the operation
246     int totalDest; ///< The total number of array elements involved in the strategy
247     
248  public:
249     ComlibArrayInfo();
250     //~ComlibArrayInfo();
251
252     /** Set the  source array used for this strategy. 
253         The list of array indices should be the whole portion of the array involved in the strategy.
254         The non-local array elements will be cleaned up inside purge() at migration of the strategy
255     */
256     void setSourceArray(CkArrayID aid, CkArrayIndexMax *e=0, int nind=0);
257     int isSourceArray(){return isSrcArray;}
258     CkArrayID getSourceArrayID() {return src_aid;}
259     const CkVec<CkArrayIndexMax> & getSourceElements() {return src_elements;}
260
261     /** Set the destination array used for this strategy. 
262         The list of array indices should be the whole portion of the array involved in the strategy.
263         The non-local array elements will be cleaned up inside purge() at migration of the strategy
264     */
265     void setDestinationArray(CkArrayID aid, CkArrayIndexMax *e=0, int nind=0);
266     int isDestinationArray(){return isDestArray;}
267     CkArrayID getDestinationArrayID() {return dest_aid;}
268     const CkVec<CkArrayIndexMax> & getDestinationElements() {return dest_elements;}
269
270     /// Get the number of source array elements
271     int getTotalSrc() {return totalSrc;}
272     int getLocalSrc() {return src_elements.size();}
273
274     /** Add a destination object that is local to this PE to list used in future iterations */
275     void addNewLocalDestination(const CkArrayIndexMax &e) {
276         CkAssert(e.nInts > 0);
277         new_dest_elements.push_back(e);
278     }
279
280     /** Add a source object that is local to this PE to list used in future iterations */
281     void addNewLocalSource(const CkArrayIndexMax &e) {
282         CkAssert(e.nInts > 0);
283         new_src_elements.push_back(e);
284     }
285   
286     /// Switch to using the new destination and source lists if the previous iteration found an error and constructed the new list
287     void useNewSourceAndDestinations() {
288       if(new_dest_elements.size() > 0) {
289         dest_elements.removeAll();
290         dest_elements = new_dest_elements;
291         CkAssert(dest_elements.size() == new_dest_elements.size());
292         new_dest_elements.removeAll();
293       }
294       if(new_src_elements.size() > 0) {
295         src_elements.removeAll();
296         src_elements = new_src_elements;
297         CkAssert(src_elements.size() == new_src_elements.size());
298         new_src_elements.removeAll();
299       }
300     }
301
302     int newDestinationListSize(){ return new_dest_elements.size(); }
303     int newSourceListSize(){ return new_src_elements.size(); }
304
305     int getTotalDest() {return totalDest;}
306     int getLocalDest() {return dest_elements.size();}
307
308     void newElement(CkArrayID &id, const CkArrayIndex &idx);
309
310     void localBroadcast(envelope *env);
311     static int localMulticast(CkVec<CkArrayIndexMax> *idx_vec,envelope *env);
312     static void deliver(envelope *env);
313
314     /// This routine is called only once at the beginning and will take the list
315     /// of source and destination elements and leave only those that have homePe
316     /// here.
317     void purge();
318
319     /// This routine returnes an array of size CkNumPes() where each element
320     /// follow the convention for bracketed strategies counts.
321     int *getCombinedCountList();
322
323     void printDestElementList();
324
325
326     void pup(PUP::er &p);
327 };
328
329 /** Implementation of CkLocIterator to get all the local elements from a
330     specified processor. Currently used by ComlibArrayInfo */
331 class ComlibElementIterator : public CkLocIterator {
332  public:
333   CkVec<CkArrayIndexMax> *list;
334
335   ComlibElementIterator(CkVec<CkArrayIndexMax> *l) : CkLocIterator() {
336     list = l;
337   }
338
339   virtual void addLocation (CkLocation &loc) {
340     list->push_back(loc.getIndex());
341   }
342 };
343
344
345
346 // forward declaration of wrapper for ComlibManager::registerArrayListener
347 void ComlibManagerRegisterArrayListener(CkArrayID, ComlibArrayInfo*);
348
349 /** All Charm++ communication library strategies should inherit from 
350     CharmStrategy, rather than inheriting from class Strategy (or one of its
351     subclasses). They should specify their object domain by setting
352     Strategy::type. They have three helpers predefined for them for node groups,
353     groups and arrays. */
354 class CharmStrategy {
355     
356  protected:
357   //int forwardOnMigration;
358     ComlibLearner *learner;
359     CmiBool mflag;    //Does this strategy handle point-to-point or 
360     CkCallback onFinish;
361
362
363     /** Deliver a message to a set of indices using the array manager. Indices can be local or remote. */
364     int deliverToIndices(void *msg, int numDestIdxs, const CkArrayIndexMax* indices );
365     
366     /** Deliver a message to a set of indices using the array manager. Indices can be local or remote. */
367     inline void deliverToIndices(void *msg, const CkVec< CkArrayIndexMax > &indices ){
368       deliverToIndices(msg, indices.size(), indices.getVec() );
369     }
370     
371     
372  public:
373     //int iterationNumber;
374     ComlibGroupInfo ginfo;
375     ComlibNodeGroupInfo nginfo;
376
377     /// The communication library array listener watches and monitors
378     /// the array elements belonging to ainfo.src_aid
379     ComlibArrayInfo ainfo;
380     
381     CharmStrategy() { //: Strategy() {
382       //setType(GROUP_STRATEGY); 
383       //forwardOnMigration = 0;
384       //iterationNumber = 0;
385       learner = NULL;
386       mflag = CmiFalse;
387     }
388
389     CharmStrategy(CkMigrateMessage *m) { //: Strategy(m){
390       learner = NULL;
391     }
392
393     //Set flag to optimize strategy for 
394     inline void setMulticast(){
395         mflag = CmiTrue;
396     }
397
398     //get the multicast flag
399     CmiBool getMulticast () {
400         return mflag;
401     }
402
403     inline void setOnFinish (CkCallback of) {
404       onFinish = of;
405     }
406
407     inline CkCallback getOnFinish () {
408       return onFinish;
409     }
410
411     
412     ComlibLearner *getLearner() {return learner;}
413     void setLearner(ComlibLearner *l) {learner = l;}
414     
415     virtual void pup(PUP::er &p);
416  
417 };
418
419 //API calls which will be valid when communication library is not linked
420 void ComlibNotifyMigrationDone();
421 //int ComlibGetLastKnown(CkArrayID aid, CkArrayIndexMax idx);
422
423
424 #endif
425
426 /*@}*/