00001
00002 #ifndef MSA_DISTARRAY_H
00003 #define MSA_DISTARRAY_H
00004
00005 #include <utility>
00006 #include <algorithm>
00007 #include "msa-DistPageMgr.h"
00008
00009 namespace MSA {
00010
00011 static const int DEFAULT_SYNC_SINGLE = 0;
00012 static const bool MSA_CLEAR_ALL = true;
00013
00014 struct MSA_InvalidHandle { };
00015
00016 template <typename ENTRY>
00017 class Writable
00018 {
00019 ENTRY &e;
00020
00021 public:
00022 Writable(ENTRY &e_) : e(e_) {}
00023 inline const ENTRY& operator= (const ENTRY& rhs) { e = rhs; return rhs; }
00024 };
00025
00026 template <class MSA>
00027 class Accumulable
00028 {
00029 typedef typename MSA::T ENTRY;
00030 ENTRY &e;
00031
00032 public:
00033 Accumulable(ENTRY &e_) : e(e_) {}
00034 template<typename T>
00035 inline void operator+=(const T &rhs)
00036 { MSA::OPS::accumulate(e, rhs); }
00037 template<typename T>
00038 inline void accumulate(const T& rhs)
00039 { MSA::OPS::accumulate(e, rhs); }
00040 };
00041
00042 template<class MSA> class MSARead;
00043 template<class MSA> class MSAWrite;
00044 template<class MSA> class MSAAccum;
00045
00046 template<class MSA>
00047 class MSAHandle
00048 {
00049 protected:
00050 MSA *msa;
00051 bool valid;
00052
00053 inline void checkInvalidate()
00054 {
00055 #if CMK_ERROR_CHECKING
00056 checkValid();
00057 valid = false;
00058 #endif
00059 }
00060
00061 MSAHandle(MSA *msa_)
00062 : msa(msa_), valid(true)
00063 { }
00064 inline void checkValid()
00065 {
00066 #if CMK_ERROR_CHECKING
00067 if (!valid)
00068 throw MSA_InvalidHandle();
00069 #endif
00070 }
00071
00072 public:
00073 void syncRelease()
00074 {
00075 checkInvalidate();
00076 if (msa->active)
00077 msa->cache->SyncRelease();
00078 else
00079 CmiAbort("sync from an inactive thread!\n");
00080 msa->active = false;
00081 }
00082
00083 void syncDone()
00084 {
00085 checkInvalidate();
00086 msa->sync();
00087 }
00088
00089 MSARead<MSA> syncToRead()
00090 {
00091 checkInvalidate();
00092 msa->sync();
00093 return MSARead<MSA>(msa);
00094 }
00095
00096 MSAWrite<MSA> syncToWrite()
00097 {
00098 checkInvalidate();
00099 msa->sync();
00100 return MSAWrite<MSA>(msa);
00101 }
00102
00103 MSAWrite<MSA> syncToReWrite()
00104 {
00105 checkInvalidate();
00106 msa->sync(DEFAULT_SYNC_SINGLE, MSA_CLEAR_ALL);
00107 return MSAWrite<MSA>(msa);
00108 }
00109
00110 MSAAccum<MSA> syncToAccum()
00111 {
00112 checkInvalidate();
00113 msa->sync();
00114 return MSAAccum<MSA>(msa);
00115 }
00116
00117 MSAAccum<MSA> syncToEAccum()
00118 {
00119 checkInvalidate();
00120 msa->sync(DEFAULT_SYNC_SINGLE, MSA_CLEAR_ALL);
00121 return MSAAccum<MSA>(msa);
00122 }
00123
00124 void pup(PUP::er &p)
00125 {
00126 p|valid;
00127 if (valid) {
00128 if (p.isUnpacking())
00129 msa = new MSA;
00130 p|(*msa);
00131 }
00132 else if (p.isUnpacking())
00133 msa = NULL;
00134 }
00135
00136 inline int length() { return msa->length(); }
00137
00138 MSAHandle() : msa(NULL), valid(false) {}
00139 };
00140
00141 template <class MSA>
00142 class MSARead : public MSAHandle<MSA>
00143 {
00144 protected:
00145 using MSAHandle<MSA>::checkValid;
00146 using MSAHandle<MSA>::checkInvalidate;
00147 using MSAHandle<MSA>::msa;
00148
00149 typedef typename MSA::T ENTRY;
00150
00151 public:
00152 MSARead(MSA *msa_)
00153 : MSAHandle<MSA>(msa_) { }
00154 MSARead() {}
00155
00156
00157 inline const ENTRY& get(int x)
00158 {
00159 checkValid();
00160 return msa->get(x);
00161 }
00162 inline const ENTRY& operator()(int x) { return get(x); }
00163 inline const ENTRY& get2(int x)
00164 {
00165 checkValid();
00166 return msa->get2(x);
00167 }
00168
00169 #ifndef FOR_SUN_CC_ONLY
00170
00171 inline const ENTRY& get(int x, int y)
00172 {
00173 checkValid();
00174 return msa->get(x, y);
00175 }
00176 #endif
00177 inline const ENTRY& operator()(int x, int y) { return get(x, y); }
00178 inline const ENTRY& get2(int x, int y)
00179 {
00180 checkValid();
00181 return msa->get2(x, y);
00182 }
00183
00184 #ifndef FOR_SUN_CC_ONLY
00185
00186 inline const ENTRY& get(int x, int y, int z)
00187 {
00188 checkValid();
00189 return msa->get(x, y, z);
00190 }
00191 #endif
00192 inline const ENTRY& operator()(int x, int y, int z) { return get(x, y, z); }
00193 inline const ENTRY& get2(int x, int y, int z)
00194 {
00195 checkValid();
00196 return msa->get2(x, y, z);
00197 }
00198
00199
00200 void read(ENTRY *buf, int x1, int y1, int z1, int x2, int y2, int z2)
00201 {
00202 checkValid();
00203
00204 CkAssert(x1 <= x2);
00205 CkAssert(y1 <= y2);
00206 CkAssert(z1 <= z2);
00207
00208 CkAssert(x1 >= msa->xa);
00209 CkAssert(y1 >= msa->ya);
00210 CkAssert(z1 >= msa->za);
00211
00212 CkAssert(x2 <= msa->xb);
00213 CkAssert(y2 <= msa->yb);
00214 CkAssert(z2 <= msa->zb);
00215
00216 int i = 0;
00217
00218 for (int ix = x1; ix <= x2; ++ix)
00219 for (int iy = y1; iy <= y2; ++iy)
00220 for (int iz = z1; iz <= z2; ++iz)
00221 buf[i++] = msa->get(ix, iy, iz);
00222 }
00223 };
00224
00225 template <class MSA>
00226 class MSAWrite : public MSAHandle<MSA>
00227 {
00228 protected:
00229 using MSAHandle<MSA>::checkValid;
00230 using MSAHandle<MSA>::checkInvalidate;
00231 using MSAHandle<MSA>::msa;
00232
00233 typedef typename MSA::T ENTRY;
00234
00235 public:
00236 MSAWrite(MSA *msa_)
00237 : MSAHandle<MSA>(msa_) { }
00238 MSAWrite() {}
00239
00240
00241 inline Writable<ENTRY> set(int x)
00242 {
00243 checkValid();
00244 return Writable<ENTRY>(msa->set(x));
00245 }
00246 inline Writable<ENTRY> operator()(int x)
00247 {
00248 return set(x);
00249 }
00250
00251
00252 inline Writable<ENTRY> set(int x, int y)
00253 {
00254 checkValid();
00255 return Writable<ENTRY>(msa->set(x,y));
00256 }
00257 inline Writable<ENTRY> operator()(int x, int y)
00258 {
00259 return set(x,y);
00260 }
00261
00262
00263 inline Writable<ENTRY> set(int x, int y, int z)
00264 {
00265 checkValid();
00266 return Writable<ENTRY>(msa->set(x,y,z));
00267 }
00268 inline Writable<ENTRY> operator()(int x, int y, int z)
00269 {
00270 return set(x,y,z);
00271 }
00272
00273 void write(int x1, int y1, int z1, int x2, int y2, int z2, const ENTRY *buf)
00274 {
00275 checkValid();
00276
00277 CkAssert(x1 <= x2);
00278 CkAssert(y1 <= y2);
00279 CkAssert(z1 <= z2);
00280
00281 CkAssert(x1 >= msa->xa);
00282 CkAssert(y1 >= msa->ya);
00283 CkAssert(z1 >= msa->za);
00284
00285 CkAssert(x2 <= msa->xb);
00286 CkAssert(y2 <= msa->yb);
00287 CkAssert(z2 <= msa->zb);
00288
00289 int i = 0;
00290
00291 for (int ix = x1; ix <= x2; ++ix)
00292 for (int iy = y1; iy <= y2; ++iy)
00293 for (int iz = z1; iz <= z2; ++iz)
00294 {
00295 msa->set(ix, iy, iz) = buf[i++];
00296 }
00297 }
00298 };
00299
00300 template<class MSA>
00301 class MSAAccum : public MSAHandle<MSA>
00302 {
00303 protected:
00304 using MSAHandle<MSA>::checkValid;
00305 using MSAHandle<MSA>::checkInvalidate;
00306 using MSAHandle<MSA>::msa;
00307
00308 typedef typename MSA::T ENTRY;
00309
00310 public:
00311 MSAAccum(MSA *msa_)
00312 : MSAHandle<MSA>(msa_) { }
00313 MSAAccum() {}
00314
00315
00316 inline Accumulable<MSA> accumulate(int x)
00317 {
00318 checkValid();
00319 return Accumulable<MSA>(msa->accumulate(x));
00320 }
00321 inline Accumulable<MSA> operator() (int x)
00322 { return accumulate(x); }
00323
00324 #ifndef FOR_SUN_CC_ONLY
00325
00326 inline Accumulable<MSA> accumulate(int x, int y)
00327 {
00328 checkValid();
00329 return Accumulable<MSA>(msa->accumulate(x,y));
00330 }
00331 #endif
00332 inline Accumulable<MSA> operator() (int x, int y)
00333 { return accumulate(x,y); }
00334
00335 #ifndef FOR_SUN_CC_ONLY
00336
00337 inline Accumulable<MSA> accumulate(int x, int y, int z)
00338 {
00339 checkValid();
00340 return Accumulable<MSA>(msa->accumulate(x,y,z));
00341 }
00342 #endif
00343 inline Accumulable<MSA> operator() (int x, int y, int z)
00344 { return accumulate(x,y,z); }
00345
00346 #ifndef FOR_SUN_CC_ONLY
00347 void accumulate(int x1, int y1, int z1, int x2, int y2, int z2, const ENTRY *buf)
00348 {
00349 checkValid();
00350 CkAssert(x1 <= x2);
00351 CkAssert(y1 <= y2);
00352 CkAssert(z1 <= z2);
00353
00354 CkAssert(x1 >= msa->xa);
00355 CkAssert(y1 >= msa->ya);
00356 CkAssert(z1 >= msa->za);
00357
00358 CkAssert(x2 <= msa->xb);
00359 CkAssert(y2 <= msa->yb);
00360 CkAssert(z2 <= msa->zb);
00361
00362 int i = 0;
00363
00364 for (int ix = x1; ix <= x2; ++ix)
00365 for (int iy = y1; iy <= y2; ++iy)
00366 for (int iz = z1; iz <= z2; ++iz)
00367 msa->accumulate(ix, iy, iz, buf[i++]);
00368 }
00369 #endif
00370 };
00371
00372
00393 template<class ENTRY, class ENTRY_OPS_CLASS, unsigned int ENTRIES_PER_PAGE=MSA_DEFAULT_ENTRIES_PER_PAGE>
00394 class MSA1D
00395 {
00396 public:
00397 typedef MSA_CacheGroup<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> CacheGroup_t;
00398 typedef CProxy_MSA_CacheGroup<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> CProxy_CacheGroup_t;
00399 typedef CProxy_MSA_PageArray<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> CProxy_PageArray_t;
00400
00401 typedef ENTRY T;
00402 typedef ENTRY_OPS_CLASS OPS;
00403 typedef MSA1D<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> thisMSA;
00404 typedef MSAHandle<thisMSA> Handle;
00405 typedef MSARead<thisMSA> Read;
00406 typedef MSAAccum<thisMSA> Accum;
00407 typedef MSAWrite<thisMSA> Write;
00408 friend class MSAHandle<thisMSA>;
00409 friend class MSARead<thisMSA>;
00410 friend class MSAWrite<thisMSA>;
00411 friend class MSAAccum<thisMSA>;
00412
00413 protected:
00415 unsigned int nEntries;
00416 bool initHandleGiven;
00417
00419 CacheGroup_t* cache;
00420 CProxy_CacheGroup_t cg;
00421
00422 inline const ENTRY* readablePage(unsigned int page)
00423 {
00424 return (const ENTRY*)(cache->readablePage(page));
00425 }
00426
00427
00428 inline const ENTRY* readablePage2(unsigned int page)
00429 {
00430 return (const ENTRY*)(cache->readablePage2(page));
00431 }
00432
00433
00434
00435 inline ENTRY* writeablePage(unsigned int page, unsigned int offset)
00436 {
00437 return (ENTRY*)(cache->writeablePage(page, offset));
00438 }
00439
00440 public:
00441
00442 inline MSA1D()
00443 :initHandleGiven(false)
00444 {}
00445
00446 virtual void pup(PUP::er &p){
00447 p|nEntries;
00448 p|cg;
00449 if (p.isUnpacking()) cache=cg.ckLocalBranch();
00450 }
00451
00456 inline MSA1D(unsigned int nEntries_, unsigned int num_wrkrs,
00457 unsigned int maxBytes=MSA_DEFAULT_MAX_BYTES)
00458 : nEntries(nEntries_), initHandleGiven(false)
00459 {
00460
00461 unsigned int nPages = (nEntries + ENTRIES_PER_PAGE - 1)/ENTRIES_PER_PAGE;
00462 CProxy_PageArray_t pageArray = CProxy_PageArray_t::ckNew(nPages);
00463 cg = CProxy_CacheGroup_t::ckNew(nPages, pageArray, maxBytes, nEntries, num_wrkrs);
00464 pageArray.setCacheProxy(cg);
00465 pageArray.ckSetReductionClient(new CkCallback(CkIndex_MSA_CacheGroup<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE>::SyncDone(NULL), cg));
00466 cache = cg.ckLocalBranch();
00467 }
00468
00469
00470 inline MSA1D(CProxy_CacheGroup_t cg_) : cg(cg_), initHandleGiven(false)
00471 {
00472 cache = cg.ckLocalBranch();
00473 nEntries = cache->getNumEntries();
00474 }
00475
00476 inline ~MSA1D()
00477 {
00478
00479
00480
00481
00482 cache->unroll();
00483
00484 }
00485
00490 inline void changePE()
00491 {
00492 cache = cg.ckLocalBranch();
00493
00494
00495 }
00496
00497
00499 inline unsigned int length() const { return nEntries; }
00500
00501 inline const CProxy_CacheGroup_t &getCacheGroup() const { return cg; }
00502
00503
00504
00505 inline unsigned int getNumEntriesPerPage() const { return ENTRIES_PER_PAGE; }
00506
00508 inline unsigned int getPageIndex(unsigned int idx)
00509 {
00510 return idx / ENTRIES_PER_PAGE;
00511 }
00512
00514 inline unsigned int getOffsetWithinPage(unsigned int idx)
00515 {
00516 return idx % ENTRIES_PER_PAGE;
00517 }
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527 inline void enroll(int num_workers)
00528 {
00529
00530
00531
00532
00533 cache->enroll(num_workers);
00534 }
00535
00536
00537
00538
00539
00540 inline ENTRY& getPageBottom(unsigned int idx, MSA_Page_Fault_t accessMode)
00541 {
00542 if (accessMode==Read_Fault) {
00543 unsigned int page = idx / ENTRIES_PER_PAGE;
00544 return const_cast<ENTRY&>(readablePage(page)[0]);
00545 } else {
00546 CkAssert(accessMode==Write_Fault || accessMode==Accumulate_Fault);
00547 unsigned int page = idx / ENTRIES_PER_PAGE;
00548 unsigned int offset = idx % ENTRIES_PER_PAGE;
00549 ENTRY* e=writeablePage(page, offset);
00550 return e[0];
00551 }
00552 }
00553
00554 inline void FreeMem()
00555 {
00556 cache->FreeMem();
00557 }
00558
00562 inline void Prefetch(unsigned int start, unsigned int end)
00563 {
00564 unsigned int page1 = start / ENTRIES_PER_PAGE;
00565 unsigned int page2 = end / ENTRIES_PER_PAGE;
00566 cache->Prefetch(page1, page2);
00567 }
00568
00570 inline int WaitAll() { return cache->WaitAll(); }
00571
00573 inline void Unlock() { return cache->UnlockPages(); }
00574
00581 inline void Unlock(unsigned int start, unsigned int end)
00582 {
00583 unsigned int page1 = start / ENTRIES_PER_PAGE;
00584 unsigned int page2 = end / ENTRIES_PER_PAGE;
00585 cache->UnlockPages(page1, page2);
00586 }
00587
00588 inline Write getInitialWrite()
00589 {
00590 if (initHandleGiven)
00591 throw MSA_InvalidHandle();
00592
00593 initHandleGiven = true;
00594 return Write(this);
00595 }
00596
00597 inline Accum getInitialAccum()
00598 {
00599 if (initHandleGiven)
00600 throw MSA_InvalidHandle();
00601
00602 initHandleGiven = true;
00603 return Accum(this);
00604 }
00605
00606
00607
00608 protected:
00611 inline const ENTRY& get(unsigned int idx)
00612 {
00613 unsigned int page = idx / ENTRIES_PER_PAGE;
00614 unsigned int offset = idx % ENTRIES_PER_PAGE;
00615 return readablePage(page)[offset];
00616 }
00617
00618 inline const ENTRY& operator[](unsigned int idx)
00619 {
00620 return get(idx);
00621 }
00622
00627 inline const ENTRY& get2(unsigned int idx)
00628 {
00629 unsigned int page = idx / ENTRIES_PER_PAGE;
00630 unsigned int offset = idx % ENTRIES_PER_PAGE;
00631 return readablePage2(page)[offset];
00632 }
00633
00637 inline ENTRY& set(unsigned int idx)
00638 {
00639 unsigned int page = idx / ENTRIES_PER_PAGE;
00640 unsigned int offset = idx % ENTRIES_PER_PAGE;
00641 ENTRY* e=writeablePage(page, offset);
00642 return e[offset];
00643 }
00644
00649 inline ENTRY& accumulate(unsigned int idx)
00650 {
00651 unsigned int page = idx / ENTRIES_PER_PAGE;
00652 unsigned int offset = idx % ENTRIES_PER_PAGE;
00653 return cache->accumulate(page, offset);
00654 }
00655
00659 inline void accumulate(unsigned int idx, const ENTRY& ent)
00660 {
00661 ENTRY_OPS_CLASS::accumulate(accumulate(idx),ent);
00662 }
00663
00665 inline void sync(int single=0, bool clear = false)
00666 {
00667 cache->SyncReq(single, clear);
00668 }
00669 };
00670
00671
00672
00673
00674 template<class ENTRY, class ENTRY_OPS_CLASS, unsigned int ENTRIES_PER_PAGE=MSA_DEFAULT_ENTRIES_PER_PAGE, MSA_Array_Layout_t ARRAY_LAYOUT=MSA_ROW_MAJOR>
00675 class MSA2D : public MSA1D<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE>
00676 {
00677 public:
00678 typedef CProxy_MSA_CacheGroup<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> CProxy_CacheGroup_t;
00679 typedef MSA1D<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> super;
00680
00681 typedef ENTRY T;
00682 typedef ENTRY_OPS_CLASS OPS;
00683 typedef MSA2D<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> thisMSA;
00684 typedef MSAHandle<thisMSA> Handle;
00685 typedef MSARead<thisMSA> Read;
00686 typedef MSAAccum<thisMSA> Accum;
00687 typedef MSAWrite<thisMSA> Write;
00688 friend class MSAHandle<thisMSA>;
00689 friend class MSARead<thisMSA>;
00690 friend class MSAWrite<thisMSA>;
00691 friend class MSAAccum<thisMSA>;
00692
00693 protected:
00694 unsigned int rows, cols;
00695
00696 public:
00697
00698 inline MSA2D() : super() {}
00699 virtual void pup(PUP::er &p) {
00700 super::pup(p);
00701 p|rows; p|cols;
00702 };
00703
00704 inline MSA2D(unsigned int rows_, unsigned int cols_, unsigned int numwrkrs,
00705 unsigned int maxBytes=MSA_DEFAULT_MAX_BYTES)
00706 :super(rows_*cols_, numwrkrs, maxBytes)
00707 {
00708 rows = rows_; cols = cols_;
00709 }
00710
00711 inline MSA2D(unsigned int rows_, unsigned int cols_, CProxy_CacheGroup_t cg_)
00712 : rows(rows_), cols(cols_), super(cg_)
00713 {}
00714
00715
00716 inline unsigned int getIndex(unsigned int row, unsigned int col)
00717 {
00718 unsigned int index;
00719
00720 if(ARRAY_LAYOUT==MSA_ROW_MAJOR)
00721 index = row*cols + col;
00722 else
00723 index = col*rows + row;
00724
00725 return index;
00726 }
00727
00728
00729 inline unsigned int getPageIndex(unsigned int row, unsigned int col)
00730 {
00731 return getIndex(row, col)/ENTRIES_PER_PAGE;
00732 }
00733
00734 inline unsigned int getOffsetWithinPage(unsigned int row, unsigned int col)
00735 {
00736 return getIndex(row, col)%ENTRIES_PER_PAGE;
00737 }
00738
00739 inline unsigned int getRows(void) const {return rows;}
00740 inline unsigned int getCols(void) const {return cols;}
00741 inline unsigned int getColumns(void) const {return cols;}
00742 inline MSA_Array_Layout_t getArrayLayout() const {return ARRAY_LAYOUT;}
00743
00744 inline void Prefetch(unsigned int start, unsigned int end)
00745 {
00746
00747 if(start > end)
00748 {
00749 unsigned int temp = start;
00750 start = end;
00751 end = temp;
00752 }
00753
00754 unsigned int index1 = (ARRAY_LAYOUT==MSA_ROW_MAJOR) ? getIndex(start, 0) : getIndex(0, start);
00755 unsigned int index2 = (ARRAY_LAYOUT==MSA_ROW_MAJOR) ? getIndex(end, cols-1) : getIndex(rows-1, end);
00756
00757 MSA1D<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE>::Prefetch(index1, index2);
00758 }
00759
00760
00761 inline void UnlockPages(unsigned int start, unsigned int end)
00762 {
00763 if(start > end)
00764 {
00765 unsigned int temp = start;
00766 start = end;
00767 end = temp;
00768 }
00769
00770 unsigned int index1 = (ARRAY_LAYOUT==MSA_ROW_MAJOR) ? getIndex(start, 0) : getIndex(0, start);
00771 unsigned int index2 = (ARRAY_LAYOUT==MSA_ROW_MAJOR) ? getIndex(end, cols-1) : getIndex(rows-1, end);
00772
00773 MSA1D<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE>::Unlock(index1, index2);
00774 }
00775
00776 inline Write getInitialWrite()
00777 {
00778 if (super::initHandleGiven)
00779 throw MSA_InvalidHandle();
00780
00781 super::initHandleGiven = true;
00782 return Write(this);
00783 }
00784
00785 inline Accum getInitialAccum()
00786 {
00787 if (super::initHandleGiven)
00788 throw MSA_InvalidHandle();
00789
00790 super::initHandleGiven = true;
00791 return Accum(this);
00792 }
00793
00794 protected:
00795 inline const ENTRY& get(unsigned int row, unsigned int col)
00796 {
00797 return super::get(getIndex(row, col));
00798 }
00799
00800
00801 inline const ENTRY& get2(unsigned int row, unsigned int col)
00802 {
00803 return super::get2(getIndex(row, col));
00804 }
00805
00806
00807 inline ENTRY& set(unsigned int row, unsigned int col)
00808 {
00809 return super::set(getIndex(row, col));
00810 }
00811 };
00812
00833 template<class ENTRY, class ENTRY_OPS_CLASS, unsigned int ENTRIES_PER_PAGE>
00834 class MSA3D
00835 {
00837 int xa, xb, ya, yb, za, zb;
00839 unsigned dim_x, dim_y, dim_z;
00840
00841 public:
00842 typedef MSA_CacheGroup<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> CacheGroup_t;
00843 typedef CProxy_MSA_CacheGroup<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> CProxy_CacheGroup_t;
00844 typedef CProxy_MSA_PageArray<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> CProxy_PageArray_t;
00845
00846 typedef ENTRY T;
00847 typedef ENTRY_OPS_CLASS OPS;
00848 typedef MSA3D<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> thisMSA;
00849 typedef MSAHandle<thisMSA> Handle;
00850 typedef MSARead<thisMSA> Read;
00851 typedef MSAAccum<thisMSA> Accum;
00852 typedef MSAWrite<thisMSA> Write;
00853 friend class MSAHandle<thisMSA>;
00854 friend class MSARead<thisMSA>;
00855 friend class MSAWrite<thisMSA>;
00856 friend class MSAAccum<thisMSA>;
00857
00858 protected:
00860 unsigned int nEntries;
00861 bool initHandleGiven;
00862
00864 CacheGroup_t* cache;
00865 CProxy_CacheGroup_t cg;
00866
00867 inline const ENTRY* readablePage(unsigned int page)
00868 {
00869 return (const ENTRY*)(cache->readablePage(page));
00870 }
00871
00872
00873 inline const ENTRY* readablePage2(unsigned int page)
00874 {
00875 return (const ENTRY*)(cache->readablePage2(page));
00876 }
00877
00878
00879
00880 inline ENTRY* writeablePage(unsigned int page, unsigned int offset)
00881 {
00882 return (ENTRY*)(cache->writeablePage(page, offset));
00883 }
00884
00885 public:
00886
00887 inline MSA3D()
00888 :initHandleGiven(false)
00889 {}
00890
00891 virtual void pup(PUP::er &p){
00892 p|xa; p|xb;
00893 p|ya; p|yb;
00894 p|za; p|zb;
00895 p|dim_x;
00896 p|dim_y;
00897 p|dim_z;
00898 p|nEntries;
00899 p|cg;
00900 if (p.isUnpacking()) cache=cg.ckLocalBranch();
00901 }
00902
00909 inline MSA3D(unsigned x, unsigned y, unsigned z, unsigned int num_wrkrs,
00910 unsigned int maxBytes=MSA_DEFAULT_MAX_BYTES)
00911 : xa(0), ya(0), za(0), xb(x-1), yb(y-1), zb(z-1), dim_x(x), dim_y(y), dim_z(z),
00912 initHandleGiven(false)
00913 {
00914 unsigned nEntries = x*y*z;
00915 unsigned int nPages = (nEntries + ENTRIES_PER_PAGE - 1)/ENTRIES_PER_PAGE;
00916 CProxy_PageArray_t pageArray = CProxy_PageArray_t::ckNew(nPages);
00917 cg = CProxy_CacheGroup_t::ckNew(nPages, pageArray, maxBytes, nEntries, num_wrkrs);
00918 pageArray.setCacheProxy(cg);
00919
00920 cache = cg.ckLocalBranch();
00921 }
00922
00929 inline MSA3D(int xa_, int xb_, int ya_, int yb_, int za_, int zb_,
00930 unsigned int num_wrkrs, unsigned int maxBytes=MSA_DEFAULT_MAX_BYTES)
00931 : xa(xa_), xb(xb_), ya(ya_), yb(yb_), za(za_), zb(zb_),
00932 dim_x(xb-xa+1), dim_y(yb-ya+1), dim_z(zb-za+1),
00933 initHandleGiven(false)
00934 {
00935 unsigned nEntries = dim_x*dim_y*dim_z;
00936 unsigned int nPages = (nEntries + ENTRIES_PER_PAGE - 1)/ENTRIES_PER_PAGE;
00937 CProxy_PageArray_t pageArray = CProxy_PageArray_t::ckNew(nPages);
00938 cg = CProxy_CacheGroup_t::ckNew(nPages, pageArray, maxBytes, nEntries, num_wrkrs);
00939 pageArray.setCacheProxy(cg);
00940
00941 cache = cg.ckLocalBranch();
00942 }
00943
00944 inline ~MSA3D()
00945 {
00946
00947
00948
00949
00950
00951
00952 }
00953
00958 inline void changePE()
00959 {
00960 cache = cg.ckLocalBranch();
00961
00962
00963 }
00964
00965
00966
00967 inline const CProxy_CacheGroup_t &getCacheGroup() const { return cg; }
00968
00969
00970
00971 inline unsigned int getNumEntriesPerPage() const { return ENTRIES_PER_PAGE; }
00972
00973 inline unsigned int index(unsigned x, unsigned y, unsigned z)
00974 {
00975 x -= xa;
00976 y -= ya;
00977 z -= za;
00978 CkAssert(x < dim_x);
00979 CkAssert(y < dim_y);
00980 CkAssert(z < dim_z);
00981 return ((x*dim_y) + y) * dim_z + z;
00982 }
00983
00985 inline unsigned int getPageIndex(unsigned int idx)
00986 {
00987 return idx / ENTRIES_PER_PAGE;
00988 }
00989
00991 inline unsigned int getOffsetWithinPage(unsigned int idx)
00992 {
00993 return idx % ENTRIES_PER_PAGE;
00994 }
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004 inline void enroll(int num_workers)
01005 {
01006
01007
01008
01009
01010 cache->enroll(num_workers);
01011 }
01012
01013 void enroll()
01014 {
01015 cache->enroll();
01016 }
01017
01018
01019
01020
01021
01022 inline ENTRY& getPageBottom(unsigned int idx, MSA_Page_Fault_t accessMode)
01023 {
01024 if (accessMode==Read_Fault) {
01025 unsigned int page = idx / ENTRIES_PER_PAGE;
01026 return const_cast<ENTRY&>(readablePage(page)[0]);
01027 } else {
01028 CkAssert(accessMode==Write_Fault || accessMode==Accumulate_Fault);
01029 unsigned int page = idx / ENTRIES_PER_PAGE;
01030 unsigned int offset = idx % ENTRIES_PER_PAGE;
01031 ENTRY* e=writeablePage(page, offset);
01032 return e[0];
01033 }
01034 }
01035
01036 inline void FreeMem()
01037 {
01038 cache->FreeMem();
01039 }
01040
01044 inline void Prefetch(unsigned int start, unsigned int end)
01045 {
01046 unsigned int page1 = start / ENTRIES_PER_PAGE;
01047 unsigned int page2 = end / ENTRIES_PER_PAGE;
01048 cache->Prefetch(page1, page2);
01049 }
01050
01052 inline int WaitAll() { return cache->WaitAll(); }
01053
01055 inline void Unlock() { return cache->UnlockPages(); }
01056
01063 inline void Unlock(unsigned int start, unsigned int end)
01064 {
01065 unsigned int page1 = start / ENTRIES_PER_PAGE;
01066 unsigned int page2 = end / ENTRIES_PER_PAGE;
01067 cache->UnlockPages(page1, page2);
01068 }
01069
01070 inline Write getInitialWrite()
01071 {
01072 if (initHandleGiven)
01073 CmiAbort("Trying to get an MSA's initial handle a second time");
01074
01075 initHandleGiven = true;
01076 return Write(this);
01077 }
01078
01079 inline Accum getInitialAccum()
01080 {
01081 if (initHandleGiven)
01082 CmiAbort("Trying to get an MSA's initial handle a second time");
01083
01084 initHandleGiven = true;
01085 return Accum(this);
01086 }
01087
01088
01089
01090 protected:
01093 inline const ENTRY& get(unsigned x, unsigned y, unsigned z)
01094 {
01095 unsigned int idx = index(x,y,z);
01096 unsigned int page = idx / ENTRIES_PER_PAGE;
01097 unsigned int offset = idx % ENTRIES_PER_PAGE;
01098 return readablePage(page)[offset];
01099 }
01100
01105 inline const ENTRY& get2(unsigned x, unsigned y, unsigned z)
01106 {
01107 unsigned int idx = index(x,y,z);
01108 unsigned int page = idx / ENTRIES_PER_PAGE;
01109 unsigned int offset = idx % ENTRIES_PER_PAGE;
01110 return readablePage2(page)[offset];
01111 }
01112
01116 inline ENTRY& set(unsigned x, unsigned y, unsigned z)
01117 {
01118 unsigned int idx = index(x,y,z);
01119 unsigned int page = idx / ENTRIES_PER_PAGE;
01120 unsigned int offset = idx % ENTRIES_PER_PAGE;
01121 ENTRY* e=writeablePage(page, offset);
01122 return e[offset];
01123 }
01124
01129 inline ENTRY& accumulate(unsigned x, unsigned y, unsigned z)
01130 {
01131 unsigned int idx = index(x,y,z);
01132 unsigned int page = idx / ENTRIES_PER_PAGE;
01133 unsigned int offset = idx % ENTRIES_PER_PAGE;
01134 return cache->accumulate(page, offset);
01135 }
01136
01140 inline void accumulate(unsigned x, unsigned y, unsigned z, const ENTRY& ent)
01141 {
01142 ENTRY_OPS_CLASS::accumulate(accumulate(x,y,z),ent);
01143 }
01144
01146 inline void sync(int single=0, bool clear = false)
01147 {
01148 cache->SyncReq(single, clear);
01149 }
01150 };
01151
01152 }
01153 #endif