Removing assert statement that caused strategies only to work with 1d chare arrays.
[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       ComlibPrintf("[%d] useNewSourceAndDestinations previously had %d elements, now have %d elements\n", CkMyPe(), dest_elements.size(), new_src_elements.size() );
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       src_elements.removeAll();
294       src_elements = new_src_elements;
295       CkAssert(src_elements.size() == new_src_elements.size());
296       new_src_elements.removeAll();
297       if(com_debug)
298         printDestElementList();
299     }
300
301     int newDestinationListSize(){ return new_dest_elements.size(); }
302     int newSourceListSize(){ return new_src_elements.size(); }
303
304     int getTotalDest() {return totalDest;}
305     int getLocalDest() {return dest_elements.size();}
306
307     void newElement(CkArrayID &id, const CkArrayIndex &idx);
308
309     void localBroadcast(envelope *env);
310     static int localMulticast(CkVec<CkArrayIndexMax> *idx_vec,envelope *env);
311     static void deliver(envelope *env);
312
313     /// This routine is called only once at the beginning and will take the list
314     /// of source and destination elements and leave only those that have homePe
315     /// here.
316     void purge();
317
318     /// This routine returnes an array of size CkNumPes() where each element
319     /// follow the convention for bracketed strategies counts.
320     int *getCombinedCountList();
321
322     void printDestElementList();
323
324
325     void pup(PUP::er &p);
326 };
327
328 /** Implementation of CkLocIterator to get all the local elements from a
329     specified processor. Currently used by ComlibArrayInfo */
330 class ComlibElementIterator : public CkLocIterator {
331  public:
332   CkVec<CkArrayIndexMax> *list;
333
334   ComlibElementIterator(CkVec<CkArrayIndexMax> *l) : CkLocIterator() {
335     list = l;
336   }
337
338   virtual void addLocation (CkLocation &loc) {
339     list->push_back(loc.getIndex());
340   }
341 };
342
343
344
345 // forward declaration of wrapper for ComlibManager::registerArrayListener
346 void ComlibManagerRegisterArrayListener(CkArrayID, ComlibArrayInfo*);
347
348 /** All Charm++ communication library strategies should inherit from 
349     CharmStrategy, rather than inheriting from class Strategy (or one of its
350     subclasses). They should specify their object domain by setting
351     Strategy::type. They have three helpers predefined for them for node groups,
352     groups and arrays. */
353 class CharmStrategy {
354     
355  protected:
356   //int forwardOnMigration;
357     ComlibLearner *learner;
358     CmiBool mflag;    //Does this strategy handle point-to-point or 
359     CkCallback onFinish;
360
361
362     /** Deliver a message to a set of indices using the array manager. Indices can be local or remote. */
363     int deliverToIndices(void *msg, int numDestIdxs, const CkArrayIndexMax* indices );
364     
365     /** Deliver a message to a set of indices using the array manager. Indices can be local or remote. */
366     inline void deliverToIndices(void *msg, const CkVec< CkArrayIndexMax > &indices ){
367       deliverToIndices(msg, indices.size(), indices.getVec() );
368     }
369     
370     
371  public:
372     //int iterationNumber;
373     ComlibGroupInfo ginfo;
374     ComlibNodeGroupInfo nginfo;
375
376     /// The communication library array listener watches and monitors
377     /// the array elements belonging to ainfo.src_aid
378     ComlibArrayInfo ainfo;
379     
380     CharmStrategy() { //: Strategy() {
381       //setType(GROUP_STRATEGY); 
382       //forwardOnMigration = 0;
383       //iterationNumber = 0;
384       learner = NULL;
385       mflag = CmiFalse;
386     }
387
388     CharmStrategy(CkMigrateMessage *m) { //: Strategy(m){
389       learner = NULL;
390     }
391
392     //Set flag to optimize strategy for 
393     inline void setMulticast(){
394         mflag = CmiTrue;
395     }
396
397     //get the multicast flag
398     CmiBool getMulticast () {
399         return mflag;
400     }
401
402     inline void setOnFinish (CkCallback of) {
403       onFinish = of;
404     }
405
406     inline CkCallback getOnFinish () {
407       return onFinish;
408     }
409
410     
411     ComlibLearner *getLearner() {return learner;}
412     void setLearner(ComlibLearner *l) {learner = l;}
413     
414     virtual void pup(PUP::er &p);
415  
416 };
417
418 //API calls which will be valid when communication library is not linked
419 void ComlibNotifyMigrationDone();
420 //int ComlibGetLastKnown(CkArrayID aid, CkArrayIndexMax idx);
421
422
423 #endif
424
425 /*@}*/