Add a flag to provide timer for the case of no objs in Meta-Balancer
[charm.git] / src / libs / ck-libs / cache / CkCache.h
1 #ifndef __CACHEMANAGER_H__
2 #define __CACHEMANAGER_H__
3
4 #include <sys/types.h>
5 #include <vector>
6 #include <map>
7 #include <set>
8 #include "charm++.h"
9 #include "envelope.h"
10
11 #if COSMO_STATS > 0
12 #include <fstream>
13 #endif
14
15 /** NodeCacheEntry represents the entry for a remote 
16 node that is requested by the chares 
17 on a processor.
18 It stores the index of the remote chare from 
19 which node is to be requested and the local
20 chares that request it.***/
21
22 typedef CmiUInt8 CkCacheKey;
23
24 typedef struct _CkCacheUserData {
25   CmiUInt8 d0;
26   CmiUInt8 d1;
27 } CkCacheUserData;
28
29
30 class CkCacheEntryType;
31 class CkCacheRequestorData;
32 class CkCacheEntry;
33
34 #include "CkCache.decl.h"
35
36 class CkCacheStatistics {
37   CmiUInt8 dataArrived;
38   CmiUInt8 dataTotalArrived;
39   CmiUInt8 dataMisses;
40   CmiUInt8 dataLocal;
41   CmiUInt8 dataError;
42   CmiUInt8 totalDataRequested;
43   CmiUInt8 maxData;
44   int index;
45
46   CkCacheStatistics() : dataArrived(0), dataTotalArrived(0),
47     dataMisses(0), dataLocal(0), dataError(0),
48     totalDataRequested(0), maxData(0), index(-1) { }
49
50  public:
51   CkCacheStatistics(CmiUInt8 pa, CmiUInt8 pta, CmiUInt8 pm,
52           CmiUInt8 pl, CmiUInt8 pe, CmiUInt8 tpr,
53           CmiUInt8 mp, int i) :
54     dataArrived(pa), dataTotalArrived(pta), dataMisses(pm),
55     dataLocal(pl), dataError(pe), totalDataRequested(tpr),
56     maxData(mp), index(i) { }
57
58   void printTo(CkOStream &os) {
59     os << "  Cache: " << dataTotalArrived << " data arrived (corresponding to ";
60     os << dataArrived << " messages), " << dataLocal << " from local Chares" << endl;
61     if (dataError > 0) {
62       os << "Cache: ======>>>> ERROR: " << dataError << " data messages arrived without being requested!! <<<<======" << endl;
63     }
64     os << "  Cache: " << dataMisses << " misses during computation" << endl;
65     os << "  Cache: Maximum of " << maxData << " data stored at a time in processor " << index << endl;
66     os << "  Cache: local Chares made " << totalDataRequested << " requests" << endl;
67   }
68
69   static CkReduction::reducerType sum;
70
71   static CkReductionMsg *sumFn(int nMsg, CkReductionMsg **msgs) {
72     CkCacheStatistics ret;
73     ret.maxData = 0;
74     for (int i=0; i<nMsg; ++i) {
75       CkAssert(msgs[i]->getSize() == sizeof(CkCacheStatistics));
76       CkCacheStatistics *data = (CkCacheStatistics *)msgs[i]->getData();
77       ret.dataArrived += data->dataArrived;
78       ret.dataTotalArrived += data->dataTotalArrived;
79       ret.dataMisses += data->dataMisses;
80       ret.dataLocal += data->dataLocal;
81       ret.totalDataRequested += data->totalDataRequested;
82       if (data->maxData > ret.maxData) {
83         ret.maxData = data->maxData;
84         ret.index = data->index;
85       }
86     }
87     return CkReductionMsg::buildNew(sizeof(CkCacheStatistics), &ret);
88   }
89 };
90
91 class CkCacheRequestMsg : public CMessage_CkCacheRequestMsg {
92  public:
93   CkCacheKey key;
94   int replyTo;
95   CkCacheRequestMsg(CkCacheKey k, int reply) : key(k), replyTo(reply) { }
96 };
97
98 class CkCacheFillMsg : public CMessage_CkCacheFillMsg {
99 public:
100   CkCacheKey key;
101   char *data;
102   CkCacheFillMsg (CkCacheKey k) : key(k) {}
103 };
104
105 typedef void (*CkCacheCallback)(CkArrayID, CkArrayIndex&, CkCacheKey, CkCacheUserData &, void*, int);
106
107 class CkCacheRequestorData {
108 public:
109   CkCacheUserData userData;
110   CkCacheCallback fn;
111   CkArrayID requestorID;
112   CkArrayIndex requestorIdx;
113
114   CkCacheRequestorData(CProxyElement_ArrayElement &el, CkCacheCallback f, CkCacheUserData &data) {
115     userData = data;
116     requestorID = el.ckGetArrayID();
117     requestorIdx = el.ckGetIndex();
118     fn = f;
119   }
120   
121   void deliver(CkCacheKey key, void *data, int chunk) {
122     fn(requestorID, requestorIdx, key, userData, data, chunk);
123   }
124 };
125
126 class CkCacheEntryType {
127 public:
128   virtual void * request(CkArrayIndex&, CkCacheKey) = 0;
129   virtual void * unpack(CkCacheFillMsg *, int, CkArrayIndex &) = 0;
130   virtual void writeback(CkArrayIndex&, CkCacheKey, void *) = 0;
131   virtual void free(void *) = 0;
132   virtual int size(void *) = 0;
133 };
134
135 class CkCacheEntry {
136 public:
137   CkCacheKey key;
138   CkArrayIndex home;
139   CkCacheEntryType *type;
140   std::vector<CkCacheRequestorData> requestorVec;
141
142   void *data;
143   
144   bool requestSent;
145   bool replyRecvd;
146   bool writtenBack;
147 #if COSMO_STATS > 1
148   /// total number of requests to this cache entry
149   int totalRequests;
150   /// total number of requests that missed this entry, if the request is
151   /// to another TreePiece in the local processor we never miss
152   int misses;
153 #endif
154   CkCacheEntry(CkCacheKey key, CkArrayIndex &home, CkCacheEntryType *type) {
155     replyRecvd = false;
156     requestSent = false;
157     writtenBack = false;
158     data = NULL;
159     this->key = key;
160     this->home = home;
161     this->type = type;
162     #if COSMO_STATS > 1
163     totalRequests=0;
164     misses=0;
165 #endif
166   }
167
168   ~CkCacheEntry() {
169     CkAssert(requestorVec.empty());
170     if (!writtenBack) writeback();
171     type->free(data);
172   }
173
174   inline void writeback() {
175     type->writeback(home, key, data);
176     writtenBack = true;
177   }
178 };
179
180 class CkCacheArrayCounter : public CkLocIterator {
181 public:
182   int count;
183   CkHashtableT<CkArrayIndex, int> registered;
184   CkCacheArrayCounter() : count(0) { }
185   void addLocation(CkLocation &loc) {
186     registered.put(loc.getIndex()) = ++count;
187   }
188   void reset() {
189     count = 0;
190     registered.empty();
191   }
192 };
193
194 class CkCacheManager : public CBase_CkCacheManager {
195
196   /***********************************************************************
197    * Variables definitions
198    ***********************************************************************/
199   
200   /// Number of chunks in which the cache is splitted
201   int numChunks;
202   /// Number of chunks that have already been completely acknowledged
203   int finishedChunks;
204   
205   /// A list of all the elements that are present in the local processor
206   /// for the current iteration
207   CkCacheArrayCounter localChares;
208   /// A list of all the elements that are present in the local processor
209   /// for the current iteration with respect to writeback
210   CkCacheArrayCounter localCharesWB;
211   /// number of chares that have checked in for the next iteration
212   int syncdChares;
213
214   /// The number of arrays this Manager serves without support for writeback
215   int numLocMgr;
216   /// The group ids of the location managers of the arrays this Manager serves
217   /// with support for writeback
218   CkGroupID *locMgr;
219   /// The number of arrays this Manager serves with support for writeback
220   int numLocMgrWB;
221   /// The group ids of the location managers of the arrays this Manager serves
222   /// with support for writeback
223   CkGroupID *locMgrWB;
224
225 #if COSMO_STATS > 0
226   /// particles arrived from remote processors, this counts only the entries in the cache
227   CmiUInt8 dataArrived;
228   /// particles arrived from remote processors, this counts the real
229   /// number of particles arrived
230   CmiUInt8 dataTotalArrived;
231   /// particles missed while walking the tree for computation
232   CmiUInt8 dataMisses;
233   /// particles that have been imported from local TreePieces
234   CmiUInt8 dataLocal;
235   /// particles arrived which were never requested, basically errors
236   CmiUInt8 dataError;
237   /** counts the total number of particles requested by all
238     the chares on the processor***/
239   CmiUInt8 totalDataRequested;
240   /// maximum number of nodes stored at some point in the cache
241   CmiUInt8 maxData;
242 #endif
243
244   /// weights of the chunks in which the tree is divided, the cache will
245   /// update the chunk division based on these values
246   CmiUInt8 *chunkWeight;
247
248   /// Maximum number of allowed data stored
249   CmiUInt8 maxSize;
250   
251   /// number of acknowledgements awaited before deleting the chunk
252   int *chunkAck;
253   /// number of acknowledgements awaited before writing back the chunk
254   int *chunkAckWB;
255
256   /// hash table containing all the entries currently in the cache
257   std::map<CkCacheKey,CkCacheEntry*> *cacheTable;
258   int storedData;
259
260   /// list of all the outstanding requests. The second field is the chunk for
261   /// which this request is outstanding
262   std::map<CkCacheKey,int> outStandingRequests;
263     
264   /***********************************************************************
265    * Methods definitions
266    ***********************************************************************/
267
268  public:
269   
270   CkCacheManager(int size, CkGroupID gid);
271   CkCacheManager(int size, int n, CkGroupID *gid);
272   CkCacheManager(int size, int n, CkGroupID *gid, int nWB, CkGroupID *gidWB);
273   CkCacheManager(CkMigrateMessage *m);
274   ~CkCacheManager() {}
275   void pup(PUP::er &p);
276  private:
277   void init();
278  public:
279
280   void * requestData(CkCacheKey what, CkArrayIndex &toWhom, int chunk, CkCacheEntryType *type, CkCacheRequestorData &req);
281   void * requestDataNoFetch(CkCacheKey key, int chunk);
282   CkCacheEntry * requestCacheEntryNoFetch(CkCacheKey key, int chunk);
283   void recvData(CkCacheFillMsg *msg);
284   void recvData(CkCacheKey key, CkArrayIndex &from, CkCacheEntryType *type, int chunk, void *data);
285
286   void cacheSync(int &numChunks, CkArrayIndex &chareIdx, int &localIdx);
287
288   /** Called from the TreePieces to acknowledge that a particular chunk
289       can be written back to the original senders */
290   void writebackChunk(int num);
291   /** Called from the TreePieces to acknowledge that a particular chunk
292       has been completely used, and can be deleted */
293   void finishedChunk(int num, CmiUInt8 weight);
294   /** Called from the TreePieces to acknowledge that they have completely
295       finished their computation */
296
297   /** Collect the statistics for the latest iteration */
298   void collectStatistics(CkCallback& cb);
299   std::map<CkCacheKey,CkCacheEntry*> *getCache();
300
301 };
302
303 #endif