Add a flag to provide timer for the case of no objs in Meta-Balancer
[charm.git] / src / libs / ck-libs / cache / CkCache.C
1 #include "CkCache.h"
2
3   CkCacheManager::CkCacheManager(int size, CkGroupID gid) {
4     init();
5     numLocMgr = 1;
6     numLocMgrWB = 0;
7     locMgr = new CkGroupID[1];
8     locMgr[0] = gid;
9     maxSize = (CmiUInt8)size * 1024 * 1024;
10   }
11
12   CkCacheManager::CkCacheManager(int size, int n, CkGroupID *gid) {
13     init();
14     numLocMgr = n;
15     numLocMgrWB = 0;
16     locMgr = new CkGroupID[n];
17     for (int i=0; i<n; ++i) locMgr[i] = gid[i];
18     maxSize = (CmiUInt8)size * 1024 * 1024;
19   }
20
21   CkCacheManager::CkCacheManager(int size, int n, CkGroupID *gid, int nWB, CkGroupID *gidWB) {
22     init();
23     numLocMgr = n;
24     locMgr = new CkGroupID[n];
25     for (int i=0; i<n; ++i) locMgr[i] = gid[i];
26     numLocMgrWB = nWB;
27     locMgrWB = new CkGroupID[nWB];
28     for (int i=0; i<n; ++i) locMgrWB[i] = gidWB[i];
29     maxSize = (CmiUInt8)size * 1024 * 1024;
30   }
31
32   CkCacheManager::CkCacheManager(CkMigrateMessage* m) : CBase_CkCacheManager(m) {
33     init();
34   }
35
36   void CkCacheManager::init() {
37     numChunks = 0;
38     numLocMgr = 0;
39     locMgr = NULL;
40     maxSize = 0;
41     syncdChares = 0;
42     cacheTable = NULL;
43     chunkAck = NULL;
44     chunkWeight = NULL;
45     storedData = 0;
46 #if COSMO_STATS > 0
47     dataArrived = 0;
48     dataTotalArrived = 0;
49     dataMisses = 0;
50     dataLocal = 0;
51     totalDataRequested = 0;
52 #endif
53   }
54
55   void CkCacheManager::pup(PUP::er &p) {
56     CBase_CkCacheManager::pup(p);
57     p | numLocMgr;
58     if (p.isUnpacking()) locMgr = new CkGroupID[numLocMgr];
59     PUParray(p,locMgr,numLocMgr);
60     p | numLocMgrWB;
61     if (p.isUnpacking()) locMgrWB = new CkGroupID[numLocMgrWB];
62     PUParray(p,locMgrWB,numLocMgrWB);
63     p | maxSize;
64   }
65
66   void * CkCacheManager::requestData(CkCacheKey what, CkArrayIndex &_toWhom, int chunk, CkCacheEntryType *type, CkCacheRequestorData &req){
67
68     std::map<CkCacheKey,CkCacheEntry *>::iterator p;
69     CkArrayIndex toWhom(_toWhom);
70     CkAssert(chunkAck[chunk] > 0);
71     p = cacheTable[chunk].find(what);
72     CkCacheEntry *e;
73 #if COSMO_STATS > 0
74     totalDataRequested++;
75 #endif
76     if (p != cacheTable[chunk].end()) {
77       e = p->second;
78       CkAssert(e->home == toWhom);
79       //CkAssert(e->begin == begin);
80       //CkAssert(e->end == end);
81 #if COSMO_STATS > 1
82       e->totalRequests++;
83 #endif
84       if (e->data != NULL) {
85         return e->data;
86       }
87       if (!e->requestSent) {// || _nocache) {
88         e->requestSent = true;
89         if ((e->data = type->request(toWhom, what)) != NULL) {
90           e->replyRecvd = true;
91           return e->data;
92         }
93       }
94     } else {
95       e = new CkCacheEntry(what, toWhom, type);
96 #if COSMO_STATS > 1
97       e->totalRequests++;
98 #endif
99       cacheTable[chunk][what] = e;
100       e->requestSent = true;
101       if ((e->data = type->request(toWhom, what)) != NULL) {
102         e->replyRecvd = true;
103         return e->data;
104       }
105     }
106
107     e->requestorVec.push_back(req);
108     outStandingRequests[what] = chunk;
109 #if COSMO_STATS > 1
110     e->misses++;
111 #endif
112     return NULL;
113   }
114
115   void * CkCacheManager::requestDataNoFetch(CkCacheKey key, int chunk) {
116     std::map<CkCacheKey,CkCacheEntry *>::iterator p = cacheTable[chunk].find(key);
117     if (p != cacheTable[chunk].end()) {
118       return p->second->data;
119     }
120     return NULL;
121   }
122   
123   CkCacheEntry * CkCacheManager::requestCacheEntryNoFetch(CkCacheKey key, int chunk) {
124     std::map<CkCacheKey,CkCacheEntry *>::iterator p = cacheTable[chunk].find(key);
125     if (p != cacheTable[chunk].end()) {
126       return p->second;
127     }
128     return NULL;
129   }
130   
131   std::map<CkCacheKey,CkCacheEntry*> *CkCacheManager::getCache(){
132     return cacheTable;
133   }
134
135   void CkCacheManager::recvData(CkCacheFillMsg *msg) {
136     CkCacheKey key = msg->key;
137     std::map<CkCacheKey,int>::iterator pchunk = outStandingRequests.find(key);
138     CkAssert(pchunk != outStandingRequests.end());
139     int chunk = pchunk->second;
140     CkAssert(chunk >= 0 && chunk < numChunks);
141     CkAssert(chunkAck[chunk] > 0);
142     outStandingRequests.erase(pchunk);
143     
144     std::map<CkCacheKey,CkCacheEntry*>::iterator p;
145     p = cacheTable[chunk].find(key);
146     CkAssert(p != cacheTable[chunk].end());
147     CkCacheEntry *e = p->second;
148     e->data = e->type->unpack(msg, chunk, e->home);
149     storedData += e->type->size(e->data);
150     
151     std::vector<CkCacheRequestorData>::iterator caller;
152     for (caller = e->requestorVec.begin(); caller != e->requestorVec.end(); caller++) {
153       caller->deliver(key, e->data, chunk);
154     }
155     e->requestorVec.clear();
156   }
157   
158   void CkCacheManager::recvData(CkCacheKey key, CkArrayIndex &from, CkCacheEntryType *type, int chunk, void *data) {
159     std::map<CkCacheKey,CkCacheEntry*>::iterator p = cacheTable[chunk].find(key);
160     CkCacheEntry *e;
161     if (p == cacheTable[chunk].end()) {
162       e = new CkCacheEntry(key, from, type);
163       cacheTable[chunk][key] = e;
164     } else {
165       e = p->second;
166       storedData -= e->type->size(e->data);
167       e->type->writeback(e->home, e->key, e->data);
168     }
169     e->replyRecvd = true;
170     e->data = data;
171     storedData += e->type->size(data);
172     
173     std::vector<CkCacheRequestorData>::iterator caller;
174     for (caller = e->requestorVec.begin(); caller != e->requestorVec.end(); caller++) {
175       caller->deliver(key, e->data, chunk);
176     }
177     e->requestorVec.clear();
178   }
179
180   void CkCacheManager::cacheSync(int &_numChunks, CkArrayIndex &chareIdx, int &localIdx) {
181     finishedChunks = 0;
182     if (syncdChares > 0) {
183       _numChunks = numChunks;
184       //CkPrintf("Cache %d: sync following\n",thisgroup.idx);
185     } else {
186       syncdChares = 1;
187       //CkPrintf("Cache %d: sync\n",thisgroup.idx);
188
189       localChares.reset();
190       localCharesWB.reset();
191       for (int i=0; i<numLocMgr; ++i) {
192         CkLocMgr *mgr = (CkLocMgr *)CkLocalBranch(locMgr[i]);
193         mgr->iterate(localChares);
194       }
195       for (int i=0; i<numLocMgrWB; ++i) {
196         CkLocMgr *mgr = (CkLocMgr *)CkLocalBranch(locMgrWB[i]);
197         mgr->iterate(localChares);
198         mgr->iterate(localCharesWB);
199       }
200
201 #if COSMO_STATS > 0
202       dataArrived = 0;
203       dataTotalArrived = 0;
204       dataMisses = 0;
205       dataLocal = 0;
206       totalDataRequested = 0;
207       maxData = 0;
208 #endif
209
210       for (int chunk=0; chunk<numChunks; ++chunk) {
211         CkAssert(cacheTable[chunk].empty());
212         CkAssert(chunkAck[chunk]==0);
213         CkAssert(chunkAckWB[chunk]==0);
214       }
215       CkAssert(outStandingRequests.empty());
216       storedData = 0;
217
218       if (numChunks != _numChunks) {
219         if(numChunks != 0) {
220           delete []cacheTable;
221           delete []chunkAck;
222           delete []chunkAckWB;
223           delete []chunkWeight;
224         }
225           
226         numChunks = _numChunks;
227         cacheTable = new std::map<CkCacheKey,CkCacheEntry*>[numChunks];
228         chunkAck = new int[numChunks];
229         chunkAckWB = new int[numChunks];
230         chunkWeight = new CmiUInt8[numChunks];
231       }
232       for (int i=0; i<numChunks; ++i) {
233         chunkAck[i] = localChares.count;
234         chunkAckWB[i] = localCharesWB.count;
235         chunkWeight[i] = 0;
236       }
237       
238 #if COSMO_STATS > 0
239       CmiResetMaxMemory();
240 #endif
241     }
242
243     localIdx = localChares.registered.get(chareIdx);
244     CkAssert(localIdx != 0);
245   }
246
247   void CkCacheManager::writebackChunk(int chunk) {
248     CkAssert(chunkAckWB[chunk] > 0);
249     if (--chunkAckWB[chunk] == 0) {
250       // we can safely write back the chunk to the senders
251       // at this point no more changes to the data can be made until next fetch
252
253       std::map<CkCacheKey,CkCacheEntry*>::iterator iter;
254       for (iter = cacheTable[chunk].begin(); iter != cacheTable[chunk].end(); iter++) {
255         CkCacheEntry *e = iter->second;
256         e->writeback();
257       }
258
259     }
260   }
261
262   void CkCacheManager::finishedChunk(int chunk, CmiUInt8 weight) {
263     CkAssert(chunkAck[chunk] > 0);
264     chunkWeight[chunk] += weight;
265     //CkPrintf("Cache %d: finishedChunk %d\n",thisgroup.idx,chunkAck[chunk]);
266     if (--chunkAck[chunk] == 0) {
267       // we can safely delete the chunk from the cache
268       
269       // TODO: if chunks are held back due to restrictions, here is a
270       // good position to release them
271
272 #if COSMO_STATS > 0
273       if (maxData < storedData) maxData = storedData;
274 #endif
275
276       std::map<CkCacheKey,CkCacheEntry*>::iterator iter;
277       for (iter = cacheTable[chunk].begin(); iter != cacheTable[chunk].end(); iter++) {
278         CkCacheEntry *e = iter->second;
279         storedData -= e->type->size(e->data);
280         
281         // TODO: Store communication pattern here
282
283         delete e;
284       }
285       cacheTable[chunk].clear();
286       if (++finishedChunks == numChunks) {
287         finishedChunks = 0;
288         syncdChares = 0;
289       }
290     }
291   }
292   
293   CkReduction::reducerType CkCacheStatistics::sum;
294
295   void CkCacheManager::collectStatistics(CkCallback &cb) {
296 #if COSMO_STATS > 0
297     CkCacheStatistics cs(dataArrived, dataTotalArrived,
298         dataMisses, dataLocal, dataError, totalDataRequested,
299         maxData, CkMyPe());
300     contribute(sizeof(CkCacheStatistics), &cs, CkCacheStatistics::sum, cb);
301 #else
302     CkAbort("Invalid call, only valid if COSMO_STATS is defined");
303 #endif
304   }
305
306 #include "CkCache.def.h"