Galois
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
StableIterator.h
Go to the documentation of this file.
1 /*
2  * This file belongs to the Galois project, a C++ library for exploiting
3  * parallelism. The code is being released under the terms of the 3-Clause BSD
4  * License (a copy is located in LICENSE.txt at the top-level directory).
5  *
6  * Copyright (C) 2018, The University of Texas at Austin. All rights reserved.
7  * UNIVERSITY EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES CONCERNING THIS
8  * SOFTWARE AND DOCUMENTATION, INCLUDING ANY WARRANTIES OF MERCHANTABILITY,
9  * FITNESS FOR ANY PARTICULAR PURPOSE, NON-INFRINGEMENT AND WARRANTIES OF
10  * PERFORMANCE, AND ANY WARRANTY THAT MIGHT OTHERWISE ARISE FROM COURSE OF
11  * DEALING OR USAGE OF TRADE. NO WARRANTY IS EITHER EXPRESS OR IMPLIED WITH
12  * RESPECT TO THE USE OF THE SOFTWARE OR DOCUMENTATION. Under no circumstances
13  * shall University be liable for incidental, special, indirect, direct or
14  * consequential damages or loss of profits, interruption of business, or
15  * related expenses which may arise from use of Software or Documentation,
16  * including but not limited to those resulting from defects in Software and/or
17  * Documentation, or loss or inaccuracy of data of any kind.
18  */
19 
20 #ifndef GALOIS_WORKLIST_STABLEITERATOR_H
21 #define GALOIS_WORKLIST_STABLEITERATOR_H
22 
23 #include "galois/config.h"
24 #include "galois/gstl.h"
25 #include "galois/worklists/Chunk.h"
26 
27 namespace galois {
28 namespace worklists {
29 
38 template <bool Steal = false, typename Container = PerSocketChunkFIFO<>,
39  typename Iterator = int*>
42  typedef Iterator iterator;
43 
45  template <typename _T>
46  using retype =
48 
49  template <bool b>
50  using rethread =
52 
53  template <typename _iterator>
54  struct with_iterator {
56  };
57 
58  template <bool _steal>
59  struct with_steal {
61  };
62 
63  template <typename _container>
64  struct with_container {
66  };
67 
68 private:
69  struct shared_state {
70  Iterator stealBegin;
71  Iterator stealEnd;
72  substrate::SimpleLock stealLock;
73  bool stealAvail;
74  };
75 
76  struct state {
78  Iterator localBegin;
79  Iterator localEnd;
80  unsigned int nextVictim;
81  unsigned int numStealFailures;
82 
83  void populateSteal() {
84  if (Steal && localBegin != localEnd) {
85  shared_state& s = stealState.data;
86  s.stealLock.lock();
87  s.stealEnd = localEnd;
88  s.stealBegin = localEnd = galois::split_range(localBegin, localEnd);
89  if (s.stealBegin != s.stealEnd)
90  s.stealAvail = true;
91  s.stealLock.unlock();
92  }
93  }
94  };
95 
96  substrate::PerThreadStorage<state> TLDS;
97  Container inner;
98 
99  bool doSteal(state& dst, state& src, bool wait) {
100  shared_state& s = src.stealState.data;
101  if (s.stealAvail) {
102  if (wait) {
103  s.stealLock.lock();
104  } else if (!s.stealLock.try_lock()) {
105  return false;
106  }
107  if (s.stealBegin != s.stealEnd) {
108  dst.localBegin = s.stealBegin;
109  s.stealBegin = dst.localEnd =
110  galois::split_range(s.stealBegin, s.stealEnd);
111  s.stealAvail = s.stealBegin != s.stealEnd;
112  }
113  s.stealLock.unlock();
114  }
115  return dst.localBegin != dst.localEnd;
116  }
117 
118  // pop already failed, try again with stealing
119  galois::optional<value_type> pop_steal(state& data) {
120  // always try stealing self
121  if (doSteal(data, data, true))
122  return *data.localBegin++;
123  // only try stealing one other
124  if (doSteal(data, *TLDS.getRemote(data.nextVictim), false)) {
125  // share the wealth
126  if (data.nextVictim != substrate::ThreadPool::getTID())
127  data.populateSteal();
128  return *data.localBegin++;
129  }
130  ++data.nextVictim;
131  ++data.numStealFailures;
132  data.nextVictim %= runtime::activeThreads;
134  }
135 
136 public:
139  template <typename RangeTy>
140  void push_initial(const RangeTy& r) {
141  state& data = *TLDS.getLocal();
142  auto lp = r.local_pair();
143  data.localBegin = lp.first;
144  data.localEnd = lp.second;
145  data.nextVictim = substrate::ThreadPool::getTID();
146  data.numStealFailures = 0;
147  data.populateSteal();
148  }
149 
152  state& data = *TLDS.getLocal();
153  if (data.localBegin != data.localEnd)
154  return *data.localBegin++;
155 
157  if (Steal && 2 * data.numStealFailures > runtime::activeThreads)
158  if ((item = pop_steal(data)))
159  return item;
160  if ((item = inner.pop()))
161  return item;
162  if (Steal)
163  return pop_steal(data);
164  return item;
165  }
166 
167  void push(const value_type& val) { inner.push(val); }
168 
169  template <typename Iter>
170  void push(Iter b, Iter e) {
171  while (b != e)
172  push(*b++);
173  }
174 };
175 GALOIS_WLCOMPILECHECK(StableIterator)
176 
177 } // namespace worklists
178 } // namespace galois
179 #endif
Definition: StableIterator.h:59
StableIterator< Steal, _container, Iterator > type
Definition: StableIterator.h:65
T * getLocal()
Definition: PerThreadStorage.h:128
std::iterator_traits< Iterator >::value_type value_type
Definition: StableIterator.h:41
Galois version of boost::optional.
Definition: optional.h:34
StableIterator< _steal, Container, Iterator > type
Definition: StableIterator.h:60
Iterator iterator
Definition: StableIterator.h:42
static unsigned getTID()
Definition: ThreadPool.h:204
void push(Iter b, Iter e)
Definition: StableIterator.h:170
unsigned int activeThreads
Definition: Threads.cpp:26
#define GALOIS_WLCOMPILECHECK(name)
Definition: WLCompileCheck.h:26
Low-overhead worklist when initial range is not invalidated by the operator.
Definition: StableIterator.h:40
StableIterator< Steal, Container, _iterator > type
Definition: StableIterator.h:55
SimpleLock is a spinlock.
Definition: SimpleLock.h:36
void push_initial(const RangeTy &r)
push initial range onto the queue called with the same b and e on each thread
Definition: StableIterator.h:140
T * getRemote(unsigned int thread)
Definition: PerThreadStorage.h:149
void push(const value_type &val)
Definition: StableIterator.h:167
galois::optional< value_type > pop()
pop a value from the queue.
Definition: StableIterator.h:151
T value_type
Definition: Executor_ParaMeter.h:111
T data
Definition: CacheLineStorage.h:33
IterTy split_range(IterTy b, IterTy e)
Finds the midpoint of a range.
Definition: gstl.h:232