00001 #include "CkCache.h"
00002
00003 CkCacheManager::CkCacheManager(int size, CkGroupID gid) {
00004 init();
00005 numLocMgr = 1;
00006 numLocMgrWB = 0;
00007 locMgr = new CkGroupID[1];
00008 locMgr[0] = gid;
00009 maxSize = (CmiUInt8)size * 1024 * 1024;
00010 }
00011
00012 CkCacheManager::CkCacheManager(int size, int n, CkGroupID *gid) {
00013 init();
00014 numLocMgr = n;
00015 numLocMgrWB = 0;
00016 locMgr = new CkGroupID[n];
00017 for (int i=0; i<n; ++i) locMgr[i] = gid[i];
00018 maxSize = (CmiUInt8)size * 1024 * 1024;
00019 }
00020
00021 CkCacheManager::CkCacheManager(int size, int n, CkGroupID *gid, int nWB, CkGroupID *gidWB) {
00022 init();
00023 numLocMgr = n;
00024 locMgr = new CkGroupID[n];
00025 for (int i=0; i<n; ++i) locMgr[i] = gid[i];
00026 numLocMgrWB = nWB;
00027 locMgrWB = new CkGroupID[nWB];
00028 for (int i=0; i<n; ++i) locMgrWB[i] = gidWB[i];
00029 maxSize = (CmiUInt8)size * 1024 * 1024;
00030 }
00031
00032 CkCacheManager::CkCacheManager(CkMigrateMessage* m) : CBase_CkCacheManager(m) {
00033 init();
00034 }
00035
00036 void CkCacheManager::init() {
00037 numChunks = 0;
00038 numLocMgr = 0;
00039 locMgr = NULL;
00040 maxSize = 0;
00041 syncdChares = 0;
00042 cacheTable = NULL;
00043 chunkAck = NULL;
00044 chunkWeight = NULL;
00045 storedData = 0;
00046 #if COSMO_STATS > 0
00047 dataArrived = 0;
00048 dataTotalArrived = 0;
00049 dataMisses = 0;
00050 dataLocal = 0;
00051 totalDataRequested = 0;
00052 #endif
00053 }
00054
00055 void CkCacheManager::pup(PUP::er &p) {
00056 CBase_CkCacheManager::pup(p);
00057 p | numLocMgr;
00058 if (p.isUnpacking()) locMgr = new CkGroupID[numLocMgr];
00059 PUParray(p,locMgr,numLocMgr);
00060 p | numLocMgrWB;
00061 if (p.isUnpacking()) locMgrWB = new CkGroupID[numLocMgrWB];
00062 PUParray(p,locMgrWB,numLocMgrWB);
00063 p | maxSize;
00064 }
00065
00066 void * CkCacheManager::requestData(CkCacheKey what, CkArrayIndex &_toWhom, int chunk, CkCacheEntryType *type, CkCacheRequestorData &req){
00067
00068 std::map<CkCacheKey,CkCacheEntry *>::iterator p;
00069 CkArrayIndex toWhom(_toWhom);
00070 CkAssert(chunkAck[chunk] > 0);
00071 p = cacheTable[chunk].find(what);
00072 CkCacheEntry *e;
00073 #if COSMO_STATS > 0
00074 totalDataRequested++;
00075 #endif
00076 if (p != cacheTable[chunk].end()) {
00077 e = p->second;
00078 CkAssert(e->home == toWhom);
00079
00080
00081 #if COSMO_STATS > 1
00082 e->totalRequests++;
00083 #endif
00084 if (e->data != NULL) {
00085 return e->data;
00086 }
00087 if (!e->requestSent) {
00088 e->requestSent = true;
00089 if ((e->data = type->request(toWhom, what)) != NULL) {
00090 e->replyRecvd = true;
00091 return e->data;
00092 }
00093 }
00094 } else {
00095 e = new CkCacheEntry(what, toWhom, type);
00096 #if COSMO_STATS > 1
00097 e->totalRequests++;
00098 #endif
00099 cacheTable[chunk][what] = e;
00100 e->requestSent = true;
00101 if ((e->data = type->request(toWhom, what)) != NULL) {
00102 e->replyRecvd = true;
00103 return e->data;
00104 }
00105 }
00106
00107 e->requestorVec.push_back(req);
00108 outStandingRequests[what] = chunk;
00109 #if COSMO_STATS > 1
00110 e->misses++;
00111 #endif
00112 return NULL;
00113 }
00114
00115 void * CkCacheManager::requestDataNoFetch(CkCacheKey key, int chunk) {
00116 std::map<CkCacheKey,CkCacheEntry *>::iterator p = cacheTable[chunk].find(key);
00117 if (p != cacheTable[chunk].end()) {
00118 return p->second->data;
00119 }
00120 return NULL;
00121 }
00122
00123 CkCacheEntry * CkCacheManager::requestCacheEntryNoFetch(CkCacheKey key, int chunk) {
00124 std::map<CkCacheKey,CkCacheEntry *>::iterator p = cacheTable[chunk].find(key);
00125 if (p != cacheTable[chunk].end()) {
00126 return p->second;
00127 }
00128 return NULL;
00129 }
00130
00131 std::map<CkCacheKey,CkCacheEntry*> *CkCacheManager::getCache(){
00132 return cacheTable;
00133 }
00134
00135 void CkCacheManager::recvData(CkCacheFillMsg *msg) {
00136 CkCacheKey key = msg->key;
00137 std::map<CkCacheKey,int>::iterator pchunk = outStandingRequests.find(key);
00138 CkAssert(pchunk != outStandingRequests.end());
00139 int chunk = pchunk->second;
00140 CkAssert(chunk >= 0 && chunk < numChunks);
00141 CkAssert(chunkAck[chunk] > 0);
00142 outStandingRequests.erase(pchunk);
00143
00144 std::map<CkCacheKey,CkCacheEntry*>::iterator p;
00145 p = cacheTable[chunk].find(key);
00146 CkAssert(p != cacheTable[chunk].end());
00147 CkCacheEntry *e = p->second;
00148 e->data = e->type->unpack(msg, chunk, e->home);
00149 storedData += e->type->size(e->data);
00150
00151 std::vector<CkCacheRequestorData>::iterator caller;
00152 for (caller = e->requestorVec.begin(); caller != e->requestorVec.end(); caller++) {
00153 caller->deliver(key, e->data, chunk);
00154 }
00155 e->requestorVec.clear();
00156 }
00157
00158 void CkCacheManager::recvData(CkCacheKey key, CkArrayIndex &from, CkCacheEntryType *type, int chunk, void *data) {
00159 std::map<CkCacheKey,CkCacheEntry*>::iterator p = cacheTable[chunk].find(key);
00160 CkCacheEntry *e;
00161 if (p == cacheTable[chunk].end()) {
00162 e = new CkCacheEntry(key, from, type);
00163 cacheTable[chunk][key] = e;
00164 } else {
00165 e = p->second;
00166 storedData -= e->type->size(e->data);
00167 e->type->writeback(e->home, e->key, e->data);
00168 }
00169 e->replyRecvd = true;
00170 e->data = data;
00171 storedData += e->type->size(data);
00172
00173 std::vector<CkCacheRequestorData>::iterator caller;
00174 for (caller = e->requestorVec.begin(); caller != e->requestorVec.end(); caller++) {
00175 caller->deliver(key, e->data, chunk);
00176 }
00177 e->requestorVec.clear();
00178 }
00179
00180 void CkCacheManager::cacheSync(int &_numChunks, CkArrayIndex &chareIdx, int &localIdx) {
00181 finishedChunks = 0;
00182 if (syncdChares > 0) {
00183 _numChunks = numChunks;
00184
00185 } else {
00186 syncdChares = 1;
00187
00188
00189 localChares.reset();
00190 localCharesWB.reset();
00191 for (int i=0; i<numLocMgr; ++i) {
00192 CkLocMgr *mgr = (CkLocMgr *)CkLocalBranch(locMgr[i]);
00193 mgr->iterate(localChares);
00194 }
00195 for (int i=0; i<numLocMgrWB; ++i) {
00196 CkLocMgr *mgr = (CkLocMgr *)CkLocalBranch(locMgrWB[i]);
00197 mgr->iterate(localChares);
00198 mgr->iterate(localCharesWB);
00199 }
00200
00201 #if COSMO_STATS > 0
00202 dataArrived = 0;
00203 dataTotalArrived = 0;
00204 dataMisses = 0;
00205 dataLocal = 0;
00206 totalDataRequested = 0;
00207 maxData = 0;
00208 #endif
00209
00210 for (int chunk=0; chunk<numChunks; ++chunk) {
00211 CkAssert(cacheTable[chunk].empty());
00212 CkAssert(chunkAck[chunk]==0);
00213 CkAssert(chunkAckWB[chunk]==0);
00214 }
00215 CkAssert(outStandingRequests.empty());
00216 storedData = 0;
00217
00218 if (numChunks != _numChunks) {
00219 if(numChunks != 0) {
00220 delete []cacheTable;
00221 delete []chunkAck;
00222 delete []chunkAckWB;
00223 delete []chunkWeight;
00224 }
00225
00226 numChunks = _numChunks;
00227 cacheTable = new std::map<CkCacheKey,CkCacheEntry*>[numChunks];
00228 chunkAck = new int[numChunks];
00229 chunkAckWB = new int[numChunks];
00230 chunkWeight = new CmiUInt8[numChunks];
00231 }
00232 for (int i=0; i<numChunks; ++i) {
00233 chunkAck[i] = localChares.count;
00234 chunkAckWB[i] = localCharesWB.count;
00235 chunkWeight[i] = 0;
00236 }
00237
00238 #if COSMO_STATS > 0
00239 CmiResetMaxMemory();
00240 #endif
00241 }
00242
00243 localIdx = localChares.registered.get(chareIdx);
00244 CkAssert(localIdx != 0);
00245 }
00246
00247 void CkCacheManager::writebackChunk(int chunk) {
00248 CkAssert(chunkAckWB[chunk] > 0);
00249 if (--chunkAckWB[chunk] == 0) {
00250
00251
00252
00253 std::map<CkCacheKey,CkCacheEntry*>::iterator iter;
00254 for (iter = cacheTable[chunk].begin(); iter != cacheTable[chunk].end(); iter++) {
00255 CkCacheEntry *e = iter->second;
00256 e->writeback();
00257 }
00258
00259 }
00260 }
00261
00262 void CkCacheManager::finishedChunk(int chunk, CmiUInt8 weight) {
00263 CkAssert(chunkAck[chunk] > 0);
00264 chunkWeight[chunk] += weight;
00265
00266 if (--chunkAck[chunk] == 0) {
00267
00268
00269
00270
00271
00272 #if COSMO_STATS > 0
00273 if (maxData < storedData) maxData = storedData;
00274 #endif
00275
00276 std::map<CkCacheKey,CkCacheEntry*>::iterator iter;
00277 for (iter = cacheTable[chunk].begin(); iter != cacheTable[chunk].end(); iter++) {
00278 CkCacheEntry *e = iter->second;
00279 storedData -= e->type->size(e->data);
00280
00281
00282
00283 delete e;
00284 }
00285 cacheTable[chunk].clear();
00286 if (++finishedChunks == numChunks) {
00287 finishedChunks = 0;
00288 syncdChares = 0;
00289 }
00290 }
00291 }
00292
00293 CkReduction::reducerType CkCacheStatistics::sum;
00294
00295 void CkCacheManager::collectStatistics(CkCallback &cb) {
00296 #if COSMO_STATS > 0
00297 CkCacheStatistics cs(dataArrived, dataTotalArrived,
00298 dataMisses, dataLocal, dataError, totalDataRequested,
00299 maxData, CkMyPe());
00300 contribute(sizeof(CkCacheStatistics), &cs, CkCacheStatistics::sum, cb);
00301 #else
00302 CkAbort("Invalid call, only valid if COSMO_STATS is defined");
00303 #endif
00304 }
00305
00306 #include "CkCache.def.h"