Galois
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Chunk.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_CHUNK_H
21 #define GALOIS_WORKLIST_CHUNK_H
22 
23 #include "galois/config.h"
24 #include "galois/FixedSizeRing.h"
25 #include "galois/runtime/Mem.h"
29 
30 namespace galois {
31 namespace runtime {
32 extern unsigned activeThreads;
33 }
34 namespace worklists {
35 
36 namespace internal {
37 // This overly complex specialization avoids a pointer indirection for
38 // non-distributed WL when accessing PerLevel
39 template <bool, template <typename> class PS, typename TQ>
40 struct squeue {
41  PS<TQ> queues;
42  TQ& get(int i) { return *queues.getRemote(i); }
43  TQ& get() { return *queues.getLocal(); }
44  int myEffectiveID() { return substrate::ThreadPool::getTID(); }
45  int size() { return runtime::activeThreads; }
46 };
47 
48 template <template <typename> class PS, typename TQ>
49 struct squeue<false, PS, TQ> {
50  TQ queue;
51  TQ& get(int) { return queue; }
52  TQ& get() { return queue; }
53  int myEffectiveID() { return 0; }
54  int size() { return 0; }
55 };
56 
58 template <typename T, template <typename, bool> class QT, bool Distributed,
59  bool IsStack, int ChunkSize, bool Concurrent>
60 struct ChunkMaster {
61  template <typename _T>
62  using retype =
63  ChunkMaster<_T, QT, Distributed, IsStack, ChunkSize, Concurrent>;
64 
65  template <int _chunk_size>
66  using with_chunk_size =
67  ChunkMaster<T, QT, Distributed, IsStack, _chunk_size, Concurrent>;
68 
69  template <bool _Concurrent>
70  using rethread =
71  ChunkMaster<T, QT, Distributed, IsStack, ChunkSize, _Concurrent>;
72 
73 private:
74  class Chunk : public FixedSizeRing<T, ChunkSize>,
75  public QT<Chunk, Concurrent>::ListNode {};
76 
77  runtime::FixedSizeAllocator<Chunk> alloc;
78 
79  struct p {
80  Chunk* cur;
81  Chunk* next;
82  p() : cur(0), next(0) {}
83  };
84 
85  typedef QT<Chunk, Concurrent> LevelItem;
86 
87  squeue<Concurrent, substrate::PerThreadStorage, p> data;
88  squeue<Distributed, substrate::PerSocketStorage, LevelItem> Q;
89 
90  Chunk* mkChunk() {
91  Chunk* ptr = alloc.allocate(1);
92  alloc.construct(ptr);
93  return ptr;
94  }
95 
96  void delChunk(Chunk* ptr) {
97  alloc.destroy(ptr);
98  alloc.deallocate(ptr, 1);
99  }
100 
101  void pushChunk(Chunk* C) {
102  LevelItem& I = Q.get();
103  I.push(C);
104  }
105 
106  Chunk* popChunkByID(unsigned int i) {
107  LevelItem& I = Q.get(i);
108  return I.pop();
109  }
110 
111  Chunk* popChunk() {
112  int id = Q.myEffectiveID();
113  Chunk* r = popChunkByID(id);
114  if (r)
115  return r;
116 
117  for (int i = id + 1; i < (int)Q.size(); ++i) {
118  r = popChunkByID(i);
119  if (r)
120  return r;
121  }
122 
123  for (int i = 0; i < id; ++i) {
124  r = popChunkByID(i);
125  if (r)
126  return r;
127  }
128 
129  return 0;
130  }
131 
132  template <typename... Args>
133  T* emplacei(p& n, Args&&... args) {
134  T* retval = 0;
135  if (n.next && (retval = n.next->emplace_back(std::forward<Args>(args)...)))
136  return retval;
137  if (n.next)
138  pushChunk(n.next);
139  n.next = mkChunk();
140  retval = n.next->emplace_back(std::forward<Args>(args)...);
141  assert(retval);
142  return retval;
143  }
144 
145 public:
146  typedef T value_type;
147 
148  ChunkMaster() = default;
149  ChunkMaster(const ChunkMaster&) = delete;
150  ChunkMaster& operator=(const ChunkMaster&) = delete;
151 
152  void flush() {
153  p& n = data.get();
154  if (n.next)
155  pushChunk(n.next);
156  n.next = 0;
157  }
158 
166  template <typename... Args>
167  value_type* emplace(Args&&... args) {
168  p& n = data.get();
169  return emplacei(n, std::forward<Args>(args)...);
170  }
171 
177  value_type* peek() {
178  p& n = data.get();
179  if (IsStack) {
180  if (n.next && !n.next->empty())
181  return &n.next->back();
182  if (n.next)
183  delChunk(n.next);
184  n.next = popChunk();
185  if (n.next && !n.next->empty())
186  return &n.next->back();
187  return NULL;
188  } else {
189  if (n.cur && !n.cur->empty())
190  return &n.cur->front();
191  if (n.cur)
192  delChunk(n.cur);
193  n.cur = popChunk();
194  if (!n.cur) {
195  n.cur = n.next;
196  n.next = 0;
197  }
198  if (n.cur && !n.cur->empty())
199  return &n.cur->front();
200  return NULL;
201  }
202  }
203 
209  void pop_peeked() {
210  p& n = data.get();
211  if (IsStack) {
212  n.next->pop_back();
213  return;
214  } else {
215  n.cur->pop_front();
216  return;
217  }
218  }
219 
220  void push(const value_type& val) {
221  p& n = data.get();
222  emplacei(n, val);
223  }
224 
225  template <typename Iter>
226  void push(Iter b, Iter e) {
227  p& n = data.get();
228  while (b != e)
229  emplacei(n, *b++);
230  }
231 
232  template <typename RangeTy>
233  void push_initial(const RangeTy& range) {
234  auto rp = range.local_pair();
235  push(rp.first, rp.second);
236  }
237 
239  p& n = data.get();
241  if (IsStack) {
242  if (n.next && (retval = n.next->extract_back()))
243  return retval;
244  if (n.next)
245  delChunk(n.next);
246  n.next = popChunk();
247  if (n.next)
248  return n.next->extract_back();
250  } else {
251  if (n.cur && (retval = n.cur->extract_front()))
252  return retval;
253  if (n.cur)
254  delChunk(n.cur);
255  n.cur = popChunk();
256  if (!n.cur) {
257  n.cur = n.next;
258  n.next = 0;
259  }
260  if (n.cur)
261  return n.cur->extract_front();
263  }
264  }
265 };
266 
267 } // namespace internal
268 
274 template <int ChunkSize = 64, typename T = int, bool Concurrent = true>
275 using ChunkFIFO = internal::ChunkMaster<T, ConExtLinkedQueue, false, false,
276  ChunkSize, Concurrent>;
278 
279 
284 template <int ChunkSize = 64, typename T = int, bool Concurrent = true>
285 using ChunkLIFO = internal::ChunkMaster<T, ConExtLinkedStack, false, true,
286  ChunkSize, Concurrent>;
288 
294 template <int ChunkSize = 64, typename T = int, bool Concurrent = true>
295 using PerSocketChunkFIFO = internal::ChunkMaster<T, ConExtLinkedQueue, true,
296  false, ChunkSize, Concurrent>;
298 
304 template <int ChunkSize = 64, typename T = int, bool Concurrent = true>
305 using PerSocketChunkLIFO = internal::ChunkMaster<T, ConExtLinkedStack, true,
306  true, ChunkSize, Concurrent>;
308 
315 template <int ChunkSize = 64, typename T = int, bool Concurrent = true>
316 using PerSocketChunkBag = internal::ChunkMaster<T, ConExtLinkedQueue, true,
317  true, ChunkSize, Concurrent>;
319 
320 } // end namespace worklists
321 } // end namespace galois
322 
323 #endif
Definition: WorkListHelpers.h:67
Definition: WorkListHelpers.h:115
internal::ChunkMaster< T, ConExtLinkedQueue, false, false, ChunkSize, Concurrent > ChunkFIFO
Chunk FIFO.
Definition: Chunk.h:276
internal::ChunkMaster< T, ConExtLinkedQueue, true, true, ChunkSize, Concurrent > PerSocketChunkBag
Distributed chunked bag.
Definition: Chunk.h:317
Galois version of boost::optional.
Definition: optional.h:34
internal::ChunkMaster< T, ConExtLinkedStack, true, true, ChunkSize, Concurrent > PerSocketChunkLIFO
Distributed chunked LIFO.
Definition: Chunk.h:306
static unsigned getTID()
Definition: ThreadPool.h:204
unsigned int activeThreads
Definition: Threads.cpp:26
#define GALOIS_WLCOMPILECHECK(name)
Definition: WLCompileCheck.h:26
internal::ChunkMaster< T, ConExtLinkedStack, false, true, ChunkSize, Concurrent > ChunkLIFO
Chunk LIFO.
Definition: Chunk.h:286
void * alloc()
Definition: PerThreadStorage.cpp:42
T value_type
Definition: Executor_ParaMeter.h:111
internal::ChunkMaster< T, ConExtLinkedQueue, true, false, ChunkSize, Concurrent > PerSocketChunkFIFO
Distributed chunked FIFO.
Definition: Chunk.h:296