a better fix.
[charm.git] / src / ck-core / ckreduction.h
1 /*
2 Charm++ File: Reduction Library
3 added 3/27/2000 by Orion Sky Lawlor, olawlor@acm.org
4 modified 02/21/2003 by Sayantan Chakravorty
5
6
7 A reduction takes some sort of inputs (contributions)
8 from some set of objects scattered across all PE's,
9 and combines (reduces) all the contributions onto one
10 PE.  This library provides several different kinds of
11 combination routines (reducers), and various utilities
12 for supporting them.
13
14 The calls needed to use the reduction manager are:
15 -Create with CProxy_CkReduction::ckNew.
16
17 */
18 #ifndef _CKREDUCTION_H
19 #define _CKREDUCTION_H
20 #include "CkReduction.decl.h"
21 #include "cknodegroupreduction.h"
22
23 #include "CkArrayReductionMgr.decl.h"
24
25 class CkReductionMsg; //See definition below
26
27
28 //This message is sent between group objects on a single PE
29 // to let each know the other has been created.
30 class CkGroupCallbackMsg:public CMessage_CkGroupCallbackMsg {
31 public:
32         typedef void (*callbackType)(void *param);
33         CkGroupCallbackMsg(callbackType Ncallback,void *Nparam)
34                 {callback=Ncallback;param=Nparam;}
35         void call(void) {(*callback)(param);}
36 private:
37         callbackType callback;
38         void *param;
39 };
40
41 class CkGroupInitCallback : public IrrGroup {
42 public:
43         CkGroupInitCallback(void);
44         CkGroupInitCallback(CkMigrateMessage *m):IrrGroup(m) {}
45         void callMeBack(CkGroupCallbackMsg *m);
46         void pup(PUP::er& p){ IrrGroup::pup(p); }
47 };
48
49
50 class CkGroupReadyCallback : public IrrGroup {
51 private:
52   int _isReady;
53   CkQ<CkGroupCallbackMsg *> _msgs;
54   void callBuffered(void);
55 public:
56         CkGroupReadyCallback(void);
57         CkGroupReadyCallback(CkMigrateMessage *m):IrrGroup(m) {}
58         void callMeBack(CkGroupCallbackMsg *m);
59         int isReady(void) { return _isReady; }
60 protected:
61         void setReady(void) {_isReady = 1; callBuffered(); }
62         void setNotReady(void) {_isReady = 0; }
63 };
64
65 class CkReductionMsg;
66
67
68 class CkReductionNumberMsg:public CMessage_CkReductionNumberMsg {
69 public:
70   int num;
71   CkReductionNumberMsg(int n) {num=n;}
72 };
73
74
75 /**
76  * One CkReductionMgr runs a non-overlapping set of reductions.
77  * It collects messages from all local contributors, then sends
78  * the reduced message up the reduction tree to node zero, where
79  * they're passed to the user's client function.
80  */
81 class CkNodeReductionMgr;
82
83 class CProxy_CkArrayReductionMgr;
84 class CkReductionMgr : public CkGroupInitCallback {
85 public:
86         CProxy_CkReductionMgr thisProxy;
87
88 public:
89         CProxy_CkArrayReductionMgr nodeProxy; //holds the local branch of the nodegroup tree
90         CkReductionMgr(void);
91         CkReductionMgr(CkMigrateMessage *m);
92
93         typedef CkReductionClientFn clientFn;
94
95         /**
96          * Add the given client function.  Overwrites any previous client.
97          * This manager will dispose of the callback when replaced or done.
98          */
99         void ckSetReductionClient(CkCallback *cb);
100
101 //Contributors keep a copy of this structure:
102
103
104 //Contributor list maintainance:
105         //These just set and clear the "creating" flag to prevent
106         // reductions from finishing early because not all elements
107         // have been created.
108         void creatingContributors(void);
109         void doneCreatingContributors(void);
110         //Initializes a new contributor
111         void contributorStamped(contributorInfo *ci);//Increment global number
112         void contributorCreated(contributorInfo *ci);//Increment local number
113         void contributorDied(contributorInfo *ci);//Don't expect more contributions
114         //Migrating away
115         void contributorLeaving(contributorInfo *ci);
116         //Migrating in
117         void contributorArriving(contributorInfo *ci);
118
119 //Contribute-- the given msg can contain any data.  The reducerType
120 // field of the message must be valid.
121 // Each contributor must contribute exactly once to each reduction.
122         void contribute(contributorInfo *ci,CkReductionMsg *msg);
123
124 //Communication (library-private)
125         //Sent down the reduction tree (used by barren PEs)
126         void ReductionStarting(CkReductionNumberMsg *m);
127         //Sent to root of the reduction tree with late migrant data
128         void LateMigrantMsg(CkReductionMsg *m);
129         //A late migrating contributor will never contribute
130         void MigrantDied(CkReductionNumberMsg *m);
131
132         //Call back for using Node added by Sayantan
133         void ArrayReductionHandler(CkReductionMsg *m);
134         void endArrayReduction();
135
136         virtual CmiBool isReductionMgr(void){ return CmiTrue; }
137         virtual void flushStates();
138         /*FAULT_EVAC: used to get the gcount on a processor when 
139                 it is evacuated.
140                 TODO: It needs to be fixed as it should return the gcount
141                 and the adjustment information for objects that might have
142                 contributed and died.
143                 The current implementation lets us get by in the case
144                 when there are no gcount
145         */
146         int getGCount(){return gcount;};
147 private:
148
149
150 //Data members
151         //Stored callback function (may be NULL if none has been set)
152         CkCallback storedCallback;
153         // calback that came along with the contribute
154         CkCallback *secondaryStoredCallback;
155
156         int redNo;//Number of current reduction (incremented at end) to be deposited with NodeGroups
157         int completedRedNo;//Number of reduction Completed ie recieved callback from NodeGroups
158         CmiBool inProgress;//Is a reduction started, but not complete?
159         CmiBool creating;//Are elements still being created?
160         CmiBool startRequested;//Should we start the next reduction when creation finished?
161         int gcount;//=el't created here - el't deleted here
162         int lcount;//Number of local contributors
163         int maxStartRequest; // the highest future ReductionStarting message received
164
165         //Current local and remote contributions
166         int nContrib,nRemote;
167         //Contributions queued for the current reduction
168         CkMsgQ<CkReductionMsg> msgs;
169
170         //Contributions queued for future reductions (sent to us too early)
171         CkMsgQ<CkReductionMsg> futureMsgs;
172         //Remote messages queued for future reductions (sent to us too early)
173         CkMsgQ<CkReductionMsg> futureRemoteMsgs;
174
175         CkMsgQ<CkReductionMsg> finalMsgs;
176
177
178
179
180 //State:
181         void startReduction(int number,int srcPE);
182         void addContribution(CkReductionMsg *m);
183         void finishReduction(void);
184
185 /*//Reduction tree utilities
186         enum {TREE_WID=2};
187         int treeRoot(void);//Root PE
188         CmiBool hasParent(void);
189         int treeParent(void);//My parent PE
190         int firstKid(void);//My first child PE
191         int treeKids(void);//Number of children in tree*/
192
193         //Combine (& free) the current message vector.
194         CkReductionMsg *reduceMessages(void);
195
196         //Map reduction number to a time
197         CmiBool isPast(int num) const {return (CmiBool)(num<redNo);}
198         CmiBool isPresent(int num) const {return (CmiBool)(num==redNo);}
199         CmiBool isFuture(int num) const {return (CmiBool)(num>redNo);}
200
201
202         //This vector of adjustments is indexed by redNo,
203         // starting from the current redNo.
204         CkVec<countAdjustment> adjVec;
205         //Return the countAdjustment struct for the given redNo:
206         countAdjustment &adj(int number);
207         //Shift the list of countAdjustments down
208         void shiftAdjVec(void);
209
210 //Checkpointing utilities
211 public:
212         virtual void pup(PUP::er &p);
213         static int isIrreducible(){ return 0;}
214 };
215
216
217 //A CkReductionMsg is sent up the reduction tree-- it
218 // carries a contribution, or several reduced contributions.
219 class CkReductionMsg : public CMessage_CkReductionMsg
220 {
221         friend class CkReduction;
222         friend class CkReductionMgr;
223         friend class CkNodeReductionMgr;
224         friend class CkArrayReductionMgr;
225         friend class CkMulticastMgr;
226 public:
227
228 //Publically-accessible fields:
229         //"Constructor"-- builds and returns a new CkReductionMsg.
230         //  the "srcData" array you specify will be copied into this object (unless NULL).
231         static CkReductionMsg *buildNew(int NdataSize,const void *srcData,
232                 CkReduction::reducerType reducer=CkReduction::invalid,
233                 CkReductionMsg *buf = NULL);
234
235         inline int getLength(void) const {return dataSize;}
236         inline int getSize(void) const {return dataSize;}
237         inline void *getData(void) {return data;}
238         inline const void *getData(void) const {return data;}
239
240         inline int getGcount(void){return gcount;}
241         inline CkReduction::reducerType getReducer(void){return reducer;}
242         inline int getRedNo(void){return redNo;}
243
244         inline int getUserFlag(void) const {return userFlag;}
245         inline void setUserFlag(int f) { userFlag=f;}
246
247         inline void setCallback(const CkCallback &cb) { callback=cb; }
248
249         //Return true if this message came straight from a contribute call--
250         // if it didn't come from a previous reduction function.
251         inline int isFromUser(void) const {return sourceFlag==-1;}
252
253         inline bool isMigratableContributor(void) const {return migratableContributor;}
254         inline void setMigratableContributor(bool _mig){ migratableContributor = _mig;}
255
256         ~CkReductionMsg();
257
258 //Implementation-only fields (don't access these directly!)
259         //Msg runtime support
260         static void *alloc(int msgnum, size_t size, int *reqSize, int priobits);
261         static void *pack(CkReductionMsg *);
262         static CkReductionMsg *unpack(void *in);
263
264 private:
265         int dataSize;//Length of array below, in bytes
266         void *data;//Reduction data
267         int userFlag; //Some sort of identifying flag, for client use
268         CkCallback callback; //What to do when done
269         CkCallback secondaryCallback; // the group callback is piggybacked on the nodegrp reduction
270         bool migratableContributor; // are the contributors migratable
271
272         int sourceFlag;/*Flag:
273                 0 indicates this is a placeholder message (meaning: nothing to report)
274                 -1 indicates this is a single (non-reduced) contribution.
275                 >0 indicates this is a reduced contribution.
276         */
277         int nSources(void) {return sourceFlag<0?-sourceFlag:sourceFlag;}
278 private:
279         CkReduction::reducerType reducer;
280         contributorInfo *ci;//Source contributor, or NULL if none
281         int redNo;//The serial number of this reduction
282         int gcount;//Contribution to the global contributor count
283         // for section multicast/reduction library
284         CkSectionInfo sid;   // section cookie for multicast
285         char rebuilt;          // indicate if the multicast tree needs rebuilt
286         int nFrags;
287         int fragNo;      // fragment of a reduction msg (when pipelined)
288                          // value = 0 to nFrags-1
289         double dataStorage;//Start of data array (so it's double-aligned)
290
291         int no;
292         
293         //Default constructor is private so you must use "buildNew", above
294         CkReductionMsg();
295 };
296
297
298 //Define methods used to contribute to the given reduction type.
299 //  Data is copied, not deleted.
300 /*#define CK_REDUCTION_CONTRIBUTE_METHODS_DECL \
301   void contribute(int dataSize,const void *data,CkReduction::reducerType type, \
302         int userFlag=-1); \
303   void contribute(int dataSize,const void *data,CkReduction::reducerType type, \
304         const CkCallback &cb,int userFlag=-1); \
305   void contribute(CkReductionMsg *msg);\*/
306
307 #define CK_REDUCTION_CONTRIBUTE_METHODS_DEF(me,myRednMgr,myRednInfo,migratable) \
308 void me::contribute(int dataSize,const void *data,CkReduction::reducerType type,\
309         int userFlag)\
310 {\
311         CkReductionMsg *msg=CkReductionMsg::buildNew(dataSize,data,type);\
312         msg->setUserFlag(userFlag);\
313         msg->setMigratableContributor(migratable);\
314         myRednMgr->contribute(&myRednInfo,msg);\
315 }\
316 void me::contribute(int dataSize,const void *data,CkReduction::reducerType type,\
317         const CkCallback &cb,int userFlag)\
318 {\
319         CkReductionMsg *msg=CkReductionMsg::buildNew(dataSize,data,type);\
320         msg->setUserFlag(userFlag);\
321         msg->setCallback(cb);\
322         msg->setMigratableContributor(migratable);\
323         myRednMgr->contribute(&myRednInfo,msg);\
324 }\
325 void me::contribute(CkReductionMsg *msg) \
326         {\
327         msg->setMigratableContributor(migratable);\
328         myRednMgr->contribute(&myRednInfo,msg);\
329         }\
330
331
332 //A group that can contribute to reductions
333 class Group : public CkReductionMgr
334 {
335         contributorInfo reductionInfo;//My reduction information
336  public:
337         Group();
338         Group(CkMigrateMessage *msg);
339         virtual int isNodeGroup() { return 0; }
340         virtual void pup(PUP::er &p);
341         virtual void flushStates() {
342                 CkReductionMgr::flushStates();
343                 reductionInfo.redNo = 0;
344         }
345         virtual void CkAddThreadListeners(CthThread tid, void *msg);
346
347         CK_REDUCTION_CONTRIBUTE_METHODS_DECL
348 };
349
350
351
352
353
354 #endif //_CKREDUCTION_H