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