00001
00027 #ifndef GALOIS_RUNTIME_PERTHREADWORKLIST_H
00028 #define GALOIS_RUNTIME_PERTHREADWORKLIST_H
00029
00030 #include <vector>
00031 #include <deque>
00032 #include <list>
00033 #include <set>
00034 #include <limits>
00035 #include <iterator>
00036
00037 #include <cstdio>
00038
00039 #include <boost/iterator/counting_iterator.hpp>
00040 #include <boost/iterator/transform_iterator.hpp>
00041
00042 #include "Galois/Threads.h"
00043 #include "Galois/PriorityQueue.h"
00044 #include "Galois/TwoLevelIterator.h"
00045 #include "Galois/Runtime/PerThreadStorage.h"
00046 #include "Galois/Runtime/ThreadPool.h"
00047 #include "Galois/Runtime/mm/Mem.h"
00048 #include "Galois/Runtime/ll/gio.h"
00049
00050 namespace Galois {
00051 namespace Runtime {
00052
00053 namespace {
00054
00055 enum GlobalPos {
00056 GLOBAL_BEGIN, GLOBAL_END
00057 };
00058
00059
00060
00061
00062
00063 #ifdef ADAPTOR_BASED_OUTER_ITER
00064
00065 template<typename PerThrdWL>
00066 struct WLindexer:
00067 public std::unary_function<unsigned, typename PerThrdWL::Cont_ty&>
00068 {
00069 typedef typename PerThrdWL::Cont_ty Ret_ty;
00070
00071 PerThrdWL* wl;
00072
00073 WLindexer(): wl(NULL) {}
00074
00075 WLindexer(PerThrdWL& _wl): wl(&_wl) {}
00076
00077 Ret_ty& operator()(unsigned i) const {
00078 assert(wl != NULL);
00079 assert(i < wl->numRows());
00080 return const_cast<Ret_ty&>(wl->get(i));
00081 }
00082 };
00083
00084 template<typename PerThrdWL>
00085 struct TypeFactory {
00086 typedef typename boost::transform_iterator<WLindexer<PerThrdWL>, boost::counting_iterator<unsigned> > OuterIter;
00087 typedef typename std::reverse_iterator<OuterIter> RvrsOuterIter;
00088 };
00089
00090
00091 template<typename PerThrdWL>
00092 typename TypeFactory<PerThrdWL>::OuterIter make_outer_begin(PerThrdWL& wl) {
00093 return boost::make_transform_iterator(
00094 boost::counting_iterator<unsigned>(0), WLindexer<PerThrdWL>(wl));
00095 }
00096
00097 template<typename PerThrdWL>
00098 typename TypeFactory<PerThrdWL>::OuterIter make_outer_end(PerThrdWL& wl) {
00099 return boost::make_transform_iterator(
00100 boost::counting_iterator<unsigned>(wl.numRows()), WLindexer<PerThrdWL>(wl));
00101 }
00102
00103 template<typename PerThrdWL>
00104 typename TypeFactory<PerThrdWL>::RvrsOuterIter make_outer_rbegin(PerThrdWL& wl) {
00105 return typename TypeFactory<PerThrdWL>::RvrsOuterIter(make_outer_end(wl));
00106 }
00107
00108 template<typename PerThrdWL>
00109 typename TypeFactory<PerThrdWL>::RvrsOuterIter make_outer_rend(PerThrdWL& wl) {
00110 return typename TypeFactory<PerThrdWL>::RvrsOuterIter(make_outer_begin(wl));
00111 }
00112
00113 #else
00114
00115 template<typename PerThrdWL>
00116 class OuterPerThreadWLIter: public std::iterator<std::random_access_iterator_tag, typename PerThrdWL::Cont_ty> {
00117 typedef typename PerThrdWL::Cont_ty Cont_ty;
00118 typedef std::iterator<std::random_access_iterator_tag, Cont_ty> Super_ty;
00119 typedef typename Super_ty::difference_type Diff_ty;
00120
00121 PerThrdWL* workList;
00122
00123
00124 Diff_ty row;
00125
00126 void assertInRange() const {
00127 assert((row >= 0) && (row < workList->numRows()));
00128 }
00129
00130 Cont_ty& getWL() {
00131 assertInRange();
00132 return (*workList)[row];
00133 }
00134
00135 const Cont_ty& getWL() const {
00136 assertInRange();
00137 return (*workList)[row];
00138 }
00139
00140
00141 public:
00142 OuterPerThreadWLIter(): Super_ty(), workList(NULL), row(0) {}
00143
00144 OuterPerThreadWLIter(PerThrdWL& wl, const GlobalPos& pos)
00145 : Super_ty(), workList(&wl), row(0) {
00146
00147 switch (pos) {
00148 case GLOBAL_BEGIN:
00149 row = 0;
00150 break;
00151 case GLOBAL_END:
00152 row = wl.numRows();
00153 break;
00154 default:
00155 std::abort();
00156 }
00157 }
00158
00159 typename Super_ty::reference operator*() { return getWL(); }
00160
00161 typename Super_ty::reference operator*() const { return getWL(); }
00162
00163 typename Super_ty::pointer operator->() { return &(getWL()); }
00164
00165 typename Super_ty::value_type* operator->() const { return &(getWL()); }
00166
00167 OuterPerThreadWLIter& operator++() {
00168 ++row;
00169 return *this;
00170 }
00171
00172 OuterPerThreadWLIter operator++(int) {
00173 OuterPerThreadWLIter tmp(*this);
00174 operator++();
00175 return tmp;
00176 }
00177
00178 OuterPerThreadWLIter& operator--() {
00179 --row;
00180 return *this;
00181 }
00182
00183 OuterPerThreadWLIter operator--(int) {
00184 OuterPerThreadWLIter tmp(*this);
00185 operator--();
00186 return tmp;
00187 }
00188
00189 OuterPerThreadWLIter& operator+=(Diff_ty d) {
00190 row = unsigned(Diff_ty(row) + d);
00191 return *this;
00192 }
00193
00194 OuterPerThreadWLIter& operator-=(Diff_ty d) {
00195 row = unsigned (Diff_ty(row) - d);
00196 return *this;
00197 }
00198
00199 friend OuterPerThreadWLIter operator+(const OuterPerThreadWLIter& it, Diff_ty d) {
00200 OuterPerThreadWLIter tmp(it);
00201 tmp += d;
00202 return tmp;
00203 }
00204
00205 friend OuterPerThreadWLIter operator+(Diff_ty d, const OuterPerThreadWLIter& it) {
00206 return it + d;
00207 }
00208
00209 friend OuterPerThreadWLIter operator-(const OuterPerThreadWLIter& it, Diff_ty d) {
00210 OuterPerThreadWLIter tmp(it);
00211 tmp -= d;
00212 return tmp;
00213 }
00214
00215 friend Diff_ty operator-(const OuterPerThreadWLIter& left, const OuterPerThreadWLIter& right) {
00216 return Diff_ty(left.row) - Diff_ty(right.row);
00217 }
00218
00219 typename Super_ty::reference operator[](Diff_ty d) {
00220 return *((*this) + d);
00221 }
00222
00223 friend bool operator==(const OuterPerThreadWLIter& left, const OuterPerThreadWLIter& right) {
00224 assert(left.workList == right.workList);
00225 return(left.row == right.row);
00226 }
00227
00228 friend bool operator!=(const OuterPerThreadWLIter& left, const OuterPerThreadWLIter& right) {
00229 return !(left == right);
00230 }
00231
00232 friend bool operator<(const OuterPerThreadWLIter& left, const OuterPerThreadWLIter& right) {
00233 assert(left.workList == right.workList);
00234
00235 return (left.row < right.row);
00236 }
00237
00238 friend bool operator<=(const OuterPerThreadWLIter& left, const OuterPerThreadWLIter& right) {
00239 return (left == right) || (left < right);
00240 }
00241
00242 friend bool operator>(const OuterPerThreadWLIter& left, const OuterPerThreadWLIter& right) {
00243 return !(left <= right);
00244 }
00245
00246 friend bool operator>=(const OuterPerThreadWLIter& left, const OuterPerThreadWLIter& right) {
00247 return !(left < right);
00248 }
00249 };
00250
00251
00252 template<typename PerThrdWL>
00253 OuterPerThreadWLIter<PerThrdWL> make_outer_begin(PerThrdWL& wl) {
00254 return OuterPerThreadWLIter<PerThrdWL>(wl, GLOBAL_BEGIN);
00255 }
00256
00257 template<typename PerThrdWL>
00258 OuterPerThreadWLIter<PerThrdWL> make_outer_end(PerThrdWL& wl) {
00259 return OuterPerThreadWLIter<PerThrdWL>(wl, GLOBAL_END);
00260 }
00261
00262 template<typename PerThrdWL>
00263 std::reverse_iterator<OuterPerThreadWLIter<PerThrdWL> >
00264 make_outer_rbegin(PerThrdWL& wl) {
00265 typedef typename std::reverse_iterator<OuterPerThreadWLIter<PerThrdWL> > Ret_ty;
00266 return Ret_ty(make_outer_end(wl));
00267 }
00268
00269 template<typename PerThrdWL>
00270 std::reverse_iterator<OuterPerThreadWLIter<PerThrdWL> >
00271 make_outer_rend(PerThrdWL& wl) {
00272 typedef typename std::reverse_iterator<OuterPerThreadWLIter<PerThrdWL> > Ret_ty;
00273 return Ret_ty(make_outer_begin(wl));
00274 }
00275
00276 #endif
00277
00278 }
00279
00280
00281 template<typename Cont_tp>
00282 class PerThreadWorkList {
00283 public:
00284 typedef Cont_tp Cont_ty;
00285 typedef typename Cont_ty::value_type value_type;
00286 typedef typename Cont_ty::reference reference;
00287 typedef typename Cont_ty::pointer pointer;
00288 typedef typename Cont_ty::size_type size_type;
00289
00290 typedef typename Cont_ty::iterator local_iterator;
00291 typedef typename Cont_ty::const_iterator local_const_iterator;
00292 typedef typename Cont_ty::reverse_iterator local_reverse_iterator;
00293 typedef typename Cont_ty::const_reverse_iterator local_const_reverse_iterator;
00294
00295 typedef PerThreadWorkList This_ty;
00296
00297 #ifdef ADAPTOR_BASED_OUTER_ITER
00298 typedef typename TypeFactory<This_ty>::OuterIter OuterIter;
00299 typedef typename TypeFactory<This_ty>::RvrsOuterIter RvrsOuterIter;
00300 #else
00301 typedef OuterPerThreadWLIter<This_ty> OuterIter;
00302 typedef typename std::reverse_iterator<OuterIter> RvrsOuterIter;
00303 #endif
00304 typedef typename Galois::ChooseStlTwoLevelIterator<OuterIter, typename Cont_ty::iterator>::type global_iterator;
00305 typedef typename Galois::ChooseStlTwoLevelIterator<OuterIter, typename Cont_ty::const_iterator>::type global_const_iterator;
00306 typedef typename Galois::ChooseStlTwoLevelIterator<RvrsOuterIter, typename Cont_ty::reverse_iterator>::type global_reverse_iterator;
00307 typedef typename Galois::ChooseStlTwoLevelIterator<RvrsOuterIter, typename Cont_ty::const_reverse_iterator>::type global_const_reverse_iterator;
00308
00309 private:
00310
00311
00312
00313 #if 0
00314 struct FakePTS {
00315 std::vector<Cont_ty*> v;
00316
00317 FakePTS () {
00318 v.resize (size ());
00319 }
00320
00321 Cont_ty** getLocal () const {
00322 return getRemote (Galois::Runtime::LL::getTID ());
00323 }
00324
00325 Cont_ty** getRemote (size_t i) const {
00326 assert (i < v.size ());
00327 return const_cast<Cont_ty**> (&v[i]);
00328 }
00329
00330 size_t size () const { return Galois::Runtime::LL::getMaxThreads(); }
00331
00332 };
00333 #endif
00334
00335 typedef Galois::Runtime::PerThreadStorage<Cont_ty*> PerThrdCont_ty;
00336 PerThrdCont_ty perThrdCont;
00337
00338 void destroy() {
00339 for (unsigned i = 0; i < perThrdCont.size(); ++i) {
00340 delete *perThrdCont.getRemote(i);
00341 *perThrdCont.getRemote(i) = NULL;
00342 }
00343 }
00344
00345 protected:
00346 PerThreadWorkList(): perThrdCont() {
00347 for (unsigned i = 0; i < perThrdCont.size(); ++i) {
00348 *perThrdCont.getRemote(i) = NULL;
00349 }
00350 }
00351
00352 void init(const Cont_ty& cont) {
00353 for (unsigned i = 0; i < perThrdCont.size(); ++i) {
00354 *perThrdCont.getRemote(i) = new Cont_ty(cont);
00355 }
00356 }
00357
00358 ~PerThreadWorkList() {
00359 destroy();
00360 }
00361
00362 public:
00363 unsigned numRows() const { return perThrdCont.size(); }
00364
00365 Cont_ty& get() { return **(perThrdCont.getLocal()); }
00366
00367 const Cont_ty& get() const { return **(perThrdCont.getLocal()); }
00368
00369 Cont_ty& get(unsigned i) { return **(perThrdCont.getRemote(i)); }
00370
00371 const Cont_ty& get(unsigned i) const { return **(perThrdCont.getRemote(i)); }
00372
00373 Cont_ty& operator [](unsigned i) { return get(i); }
00374
00375 const Cont_ty& operator [](unsigned i) const { return get(i); }
00376
00377
00378 global_iterator begin_all() {
00379 return Galois::stl_two_level_begin(
00380 make_outer_begin(*this), make_outer_end(*this));
00381 }
00382
00383 global_iterator end_all() {
00384 return Galois::stl_two_level_end(
00385 make_outer_begin(*this), make_outer_end(*this));
00386 }
00387
00388 global_const_iterator begin_all() const {
00389 return Galois::stl_two_level_cbegin(
00390 make_outer_begin(*this), make_outer_end(*this));
00391 }
00392
00393 global_const_iterator end_all() const {
00394 return Galois::stl_two_level_cend(
00395 make_outer_begin(*this), make_outer_end(*this));
00396 }
00397
00398 global_const_iterator cbegin_all() const {
00399 return Galois::stl_two_level_cbegin(
00400 make_outer_begin(*this), make_outer_end(*this));
00401 }
00402
00403 global_const_iterator cend_all() const {
00404 return Galois::stl_two_level_cend(
00405 make_outer_begin(*this), make_outer_end(*this));
00406 }
00407
00408 global_reverse_iterator rbegin_all() {
00409 return Galois::stl_two_level_rbegin(
00410 make_outer_rbegin(*this), make_outer_rend(*this));
00411 }
00412
00413 global_reverse_iterator rend_all() {
00414 return Galois::stl_two_level_rend(
00415 make_outer_rbegin(*this), make_outer_rend(*this));
00416 }
00417
00418 global_const_reverse_iterator rbegin_all() const {
00419 return Galois::stl_two_level_crbegin(
00420 make_outer_rbegin(*this), make_outer_rend(*this));
00421 }
00422
00423 global_const_reverse_iterator rend_all() const {
00424 return Galois::stl_two_level_crend(
00425 make_outer_rbegin(*this), make_outer_rend(*this));
00426 }
00427
00428 global_const_reverse_iterator crbegin_all() const {
00429 return Galois::stl_two_level_crbegin(
00430 make_outer_rbegin(*this), make_outer_rend(*this));
00431 }
00432
00433 global_const_reverse_iterator crend_all() const {
00434 return Galois::stl_two_level_crend(
00435 make_outer_rbegin(*this), make_outer_rend(*this));
00436 }
00437
00438 size_type size_all() const {
00439 size_type sz = 0;
00440
00441 for (unsigned i = 0; i < perThrdCont.size(); ++i) {
00442 sz += get(i).size();
00443 }
00444
00445 return sz;
00446 }
00447
00448 void clear_all() {
00449 for (unsigned i = 0; i < perThrdCont.size(); ++i) {
00450 get(i).clear();
00451 }
00452 }
00453
00454 bool empty_all() const {
00455 bool res = true;
00456 for (unsigned i = 0; i < perThrdCont.size(); ++i) {
00457 res = res && get(i).empty();
00458 }
00459
00460 return res;
00461 }
00462
00463
00464 template<typename Iter, typename R>
00465 void fill_serial(Iter begin, Iter end,
00466 R(Cont_ty::*pushFn)(const value_type&) = &Cont_ty::push_back) {
00467
00468 const unsigned P = Galois::getActiveThreads();
00469
00470 typedef typename std::iterator_traits<Iter>::difference_type Diff_ty;
00471
00472
00473 Diff_ty block_size = (std::distance(begin, end) + (P-1) ) / P;
00474
00475 assert(block_size >= 1);
00476
00477 Iter block_begin = begin;
00478
00479 for (unsigned i = 0; i < P; ++i) {
00480
00481 Iter block_end = block_begin;
00482
00483 if (std::distance(block_end, end) < block_size) {
00484 block_end = end;
00485
00486 } else {
00487 std::advance(block_end, block_size);
00488 }
00489
00490 for (; block_begin != block_end; ++block_begin) {
00491
00492 ((*this)[i].*pushFn)(value_type(*block_begin));
00493 }
00494
00495 if (block_end == end) {
00496 break;
00497 }
00498 }
00499 }
00500 };
00501
00502
00503 namespace PerThreadFactory {
00504 typedef MM::SimpleBumpPtrWithMallocFallback<MM::FreeListHeap<MM::SystemBaseAlloc> > BasicHeap;
00505 typedef MM::ThreadAwarePrivateHeap<BasicHeap> Heap;
00506
00507 template<typename T>
00508 struct Alloc { typedef typename MM::ExternRefGaloisAllocator<T, Heap> type; };
00509
00510 template<typename T>
00511 struct FSBAlloc { typedef typename MM::FSBGaloisAllocator<T> type; };
00512
00513 template<typename T>
00514 struct Vector { typedef typename std::vector<T, typename Alloc<T>::type > type; };
00515
00516 template<typename T>
00517 struct Deque { typedef typename std::deque<T, typename Alloc<T>::type > type; };
00518
00519 template<typename T>
00520 struct List { typedef typename std::list<T, typename FSBAlloc<T>::type > type; };
00521
00522 template<typename T, typename C>
00523 struct Set { typedef typename std::set<T, C, typename FSBAlloc<T>::type > type; };
00524
00525 template<typename T, typename C>
00526 struct PQ { typedef MinHeap<T, C, typename Vector<T>::type > type; };
00527 };
00528
00529
00530 template<typename T>
00531 class PerThreadVector: public PerThreadWorkList<typename PerThreadFactory::template Vector<T>::type> {
00532 public:
00533 typedef typename PerThreadFactory::Heap Heap_ty;
00534 typedef typename PerThreadFactory::template Alloc<T>::type Alloc_ty;
00535 typedef typename PerThreadFactory::template Vector<T>::type Cont_ty;
00536
00537 protected:
00538 typedef PerThreadWorkList<Cont_ty> Super_ty;
00539
00540 Heap_ty heap;
00541 Alloc_ty alloc;
00542
00543 public:
00544 PerThreadVector(): Super_ty(), heap(), alloc(&heap) {
00545 Super_ty::init(Cont_ty(alloc));
00546 }
00547
00548 void reserve_all(size_t sz) {
00549 size_t numT = Galois::getActiveThreads();
00550 size_t perT = (sz + numT - 1) / numT;
00551
00552 for (unsigned i = 0; i < numT; ++i) {
00553 Super_ty::get(i).reserve(perT);
00554 }
00555 }
00556 };
00557
00558
00559 template<typename T>
00560 class PerThreadDeque:
00561 public PerThreadWorkList<typename PerThreadFactory::template Deque<T>::type> {
00562
00563 public:
00564 typedef typename PerThreadFactory::Heap Heap_ty;
00565 typedef typename PerThreadFactory::template Alloc<T>::type Alloc_ty;
00566
00567 protected:
00568 typedef typename PerThreadFactory::template Deque<T>::type Cont_ty;
00569 typedef PerThreadWorkList<Cont_ty> Super_ty;
00570
00571 Heap_ty heap;
00572 Alloc_ty alloc;
00573
00574 public:
00575 PerThreadDeque(): Super_ty(), heap(), alloc(&heap) {
00576 Super_ty::init(Cont_ty(alloc));
00577 }
00578 };
00579
00580 template<typename T>
00581 class PerThreadList:
00582 public PerThreadWorkList<typename PerThreadFactory::template List<T>::type> {
00583
00584 public:
00585 typedef typename PerThreadFactory::Heap Heap_ty;
00586 typedef typename PerThreadFactory::template Alloc<T>::type Alloc_ty;
00587
00588 protected:
00589 typedef typename PerThreadFactory::template List<T>::type Cont_ty;
00590 typedef PerThreadWorkList<Cont_ty> Super_ty;
00591
00592 Heap_ty heap;
00593 Alloc_ty alloc;
00594
00595 public:
00596 PerThreadList(): Super_ty(), heap(), alloc(&heap) {
00597 Super_ty::init(Cont_ty(alloc));
00598 }
00599 };
00600
00601 template<typename T, typename C=std::less<T> >
00602 class PerThreadSet:
00603 public PerThreadWorkList<typename PerThreadFactory::template Set<T, C>::type> {
00604
00605 public:
00606 typedef typename PerThreadFactory::template FSBAlloc<T>::type Alloc_ty;
00607
00608 protected:
00609 typedef typename PerThreadFactory::template Set<T, C>::type Cont_ty;
00610 typedef PerThreadWorkList<Cont_ty> Super_ty;
00611
00612 Alloc_ty alloc;
00613
00614 public:
00615 explicit PerThreadSet(const C& cmp = C()): Super_ty(), alloc() {
00616 Super_ty::init(Cont_ty(cmp, alloc));
00617 }
00618
00619 typedef typename Super_ty::global_const_iterator global_const_iterator;
00620 typedef typename Super_ty::global_const_reverse_iterator global_const_reverse_iterator;
00621
00622
00623 global_const_iterator begin_all() const { return Super_ty::cbegin_all(); }
00624 global_const_iterator end_all() const { return Super_ty::cend_all(); }
00625
00626
00627 global_const_reverse_iterator rbegin_all() const { return Super_ty::crbegin_all(); }
00628 global_const_reverse_iterator rend_all() const { return Super_ty::crend_all(); }
00629 };
00630
00631
00632 template<typename T, typename C=std::less<T> >
00633 class PerThreadMinHeap:
00634 public PerThreadWorkList<typename PerThreadFactory::template PQ<T, C>::type> {
00635
00636 public:
00637 typedef typename PerThreadFactory::Heap Heap_ty;
00638 typedef typename PerThreadFactory::template Alloc<T>::type Alloc_ty;
00639
00640 protected:
00641 typedef typename PerThreadFactory::template Vector<T>::type Vec_ty;
00642 typedef typename PerThreadFactory::template PQ<T, C>::type Cont_ty;
00643 typedef PerThreadWorkList<Cont_ty> Super_ty;
00644
00645 Heap_ty heap;
00646 Alloc_ty alloc;
00647
00648 public:
00649 explicit PerThreadMinHeap(const C& cmp = C()): Super_ty(), heap(), alloc(&heap) {
00650 Super_ty::init(Cont_ty(cmp, Vec_ty(alloc)));
00651 }
00652
00653 typedef typename Super_ty::global_const_iterator global_const_iterator;
00654 typedef typename Super_ty::global_const_reverse_iterator global_const_reverse_iterator;
00655
00656
00657 global_const_iterator begin_all() const { return Super_ty::cbegin_all(); }
00658 global_const_iterator end_all() const { return Super_ty::cend_all(); }
00659
00660
00661 global_const_reverse_iterator rbegin_all() const { return Super_ty::crbegin_all(); }
00662 global_const_reverse_iterator rend_all() const { return Super_ty::crend_all(); }
00663 };
00664
00665
00666 }
00667 }
00668 #endif