Galois
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Details.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_GRAPHS_DETAILS_H
21 #define GALOIS_GRAPHS_DETAILS_H
22 
23 #include <algorithm>
24 #include <boost/mpl/if.hpp>
25 
26 #include "galois/config.h"
27 #include "galois/LargeArray.h"
28 #include "galois/LazyObject.h"
29 #include "galois/NoDerefIterator.h"
30 #include "galois/Threads.h"
32 #include "galois/runtime/Context.h"
34 
35 // Forward declarations
36 
37 namespace galois::graphs {
38 
43 
44 } // namespace galois::graphs
45 
46 namespace galois::graphs::internal {
47 
48 template <typename, typename, typename, typename, typename>
49 struct EdgeSortReference;
50 } // namespace galois::graphs::internal
51 
52 namespace galois::graphs {
53 
55 template <typename GraphNode, typename EdgeTy>
56 class EdgeSortValue : public StrictObject<EdgeTy> {
57  template <typename, typename, typename, typename, typename>
59 
60  GraphNode rawDst;
61 
62 public:
63  GraphNode dst;
65  typedef typename Super::value_type value_type;
66 
67  EdgeSortValue(GraphNode d, GraphNode rd, const value_type& v)
68  : Super(v), rawDst(rd), dst(d) {}
69 
70  template <typename ER>
71  EdgeSortValue(const ER& ref) {
72  ref.initialize(*this);
73  }
74 };
75 
76 } // namespace galois::graphs
77 
78 namespace galois::graphs::internal {
79 
80 template <bool Enable>
81 class LocalIteratorFeature {
82  typedef std::pair<uint64_t, uint64_t> Range;
83  substrate::PerThreadStorage<Range> localIterators;
84 
85 public:
86  uint64_t localBegin(uint64_t numNodes) const {
87  return std::min(localIterators.getLocal()->first, numNodes);
88  }
89 
90  uint64_t localEnd(uint64_t numNodes) const {
91  return std::min(localIterators.getLocal()->second, numNodes);
92  }
93 
94  void setLocalRange(uint64_t begin, uint64_t end) {
95  Range& r = *localIterators.getLocal();
96  r.first = begin;
97  r.second = end;
98  }
99 };
100 
101 template <>
102 struct LocalIteratorFeature<false> {
103  uint64_t localBegin(uint64_t numNodes) const {
104  unsigned int id = substrate::ThreadPool::getTID();
105  unsigned int num = galois::getActiveThreads();
106  uint64_t begin = (numNodes + num - 1) / num * id;
107  return std::min(begin, numNodes);
108  }
109 
110  uint64_t localEnd(uint64_t numNodes) const {
111  unsigned int id = substrate::ThreadPool::getTID();
112  unsigned int num = galois::getActiveThreads();
113  uint64_t end = (numNodes + num - 1) / num * (id + 1);
114  return std::min(end, numNodes);
115  }
116 
117  void setLocalRange(uint64_t, uint64_t) {}
118 };
119 
121 template <typename GraphNode, typename EdgeIndex, typename EdgeDst,
122  typename EdgeData, typename GraphNodeConverter>
123 struct EdgeSortReference {
124  typedef typename EdgeData::raw_value_type EdgeTy;
125  EdgeIndex at;
126  EdgeDst* edgeDst;
127  EdgeData* edgeData;
128 
129  EdgeSortReference(EdgeIndex x, EdgeDst* dsts, EdgeData* data)
130  : at(x), edgeDst(dsts), edgeData(data) {}
131 
132  // Explicitly declare what the implicit copy constructor
133  // would do since using the implicit copy constructor
134  // from a class with a non-defaulted copy assignment
135  // operator is deprecated.
136  EdgeSortReference(EdgeSortReference const& x) {
137  at = x.at;
138  edgeDst = x.edgeDst;
139  edgeData = x.edgeData;
140  }
141 
142  EdgeSortReference operator=(const EdgeSortValue<GraphNode, EdgeTy>& x) {
143  edgeDst->set(at, x.rawDst);
144  edgeData->set(at, x.get());
145  return *this;
146  }
147 
148  EdgeSortReference operator=(const EdgeSortReference& x) {
149  edgeDst->set(at, edgeDst->at(x.at));
150  edgeData->set(at, edgeData->at(x.at));
151  return *this;
152  }
153 
154  EdgeSortValue<GraphNode, EdgeTy> operator*() const {
155  return EdgeSortValue<GraphNode, EdgeTy>(
156  GraphNodeConverter()(edgeDst->at(at)), edgeDst->at(at),
157  edgeData->at(at));
158  }
159 
160  void initialize(EdgeSortValue<GraphNode, EdgeTy>& value) const {
161  value = *(*this);
162  }
163 };
164 
168 template <typename EdgeSortValueTy, typename CompTy>
169 struct EdgeSortCompWrapper {
170  const CompTy& comp;
171 
172  EdgeSortCompWrapper(const CompTy& c) : comp(c) {}
173  bool operator()(const EdgeSortValueTy& a, const EdgeSortValueTy& b) const {
174  return comp(a.get(), b.get());
175  }
176 };
177 
178 struct Identity {
179  template <typename T>
180  T operator()(const T& x) const {
181  return x;
182  }
183 };
184 
198 template <typename GraphNode, typename EdgeIndex, typename EdgeDst,
199  typename EdgeData, typename GraphNodeConverter = Identity>
200 class EdgeSortIterator
201  : public boost::iterator_facade<
202  EdgeSortIterator<GraphNode, EdgeIndex, EdgeDst, EdgeData,
203  GraphNodeConverter>,
204  EdgeSortValue<GraphNode, typename EdgeData::raw_value_type>,
205  boost::random_access_traversal_tag,
206  EdgeSortReference<GraphNode, EdgeIndex, EdgeDst, EdgeData,
207  GraphNodeConverter>> {
208  typedef EdgeSortIterator<GraphNode, EdgeIndex, EdgeDst, EdgeData,
209  GraphNodeConverter>
210  Self;
211  typedef EdgeSortReference<GraphNode, EdgeIndex, EdgeDst, EdgeData,
212  GraphNodeConverter>
213  Reference;
214 
215  EdgeIndex at;
216  EdgeDst* edgeDst;
217  EdgeData* edgeData;
218 
219 public:
220  EdgeSortIterator() : at(0) {}
221  EdgeSortIterator(EdgeIndex x, EdgeDst* dsts, EdgeData* data)
222  : at(x), edgeDst(dsts), edgeData(data) {}
223 
224 private:
225  friend class boost::iterator_core_access;
226 
227  bool equal(const Self& other) const { return at == other.at; }
228  Reference dereference() const { return Reference(at, edgeDst, edgeData); }
229  ptrdiff_t distance_to(const Self& other) const {
230  return other.at - (ptrdiff_t)at;
231  }
232  void increment() { ++at; }
233  void decrement() { --at; }
234  void advance(ptrdiff_t n) { at += n; }
235 };
236 
237 template <typename IdTy>
238 class IntrusiveId {
239  IdTy id;
240 
241 public:
242  IdTy& getId() { return id; }
243  void setId(size_t n) { id = n; }
244 };
245 
246 template <>
247 class IntrusiveId<void> {
248 public:
249  char getId() { return 0; }
250  void setId(size_t) {}
251 };
252 
254 class NoLockable {};
255 
257 template <typename NodeTy, bool HasLockable>
258 struct NodeInfoBaseTypes {
259  typedef NodeTy& reference;
260 };
261 
262 template <bool HasLockable>
263 struct NodeInfoBaseTypes<void, HasLockable> {
264  typedef void* reference;
265 };
266 
268 template <typename NodeTy, bool HasLockable>
269 class NodeInfoBase
270  : public boost::mpl::if_c<HasLockable, galois::runtime::Lockable,
271  NoLockable>::type,
272  public NodeInfoBaseTypes<NodeTy, HasLockable> {
273  NodeTy data;
274 
275 public:
276  template <typename... Args>
277  NodeInfoBase(Args&&... args) : data(std::forward<Args>(args)...) {}
278 
279  typename NodeInfoBase::reference getData() { return data; }
280 };
281 
282 template <bool HasLockable>
283 struct NodeInfoBase<void, HasLockable>
284  : public boost::mpl::if_c<HasLockable, galois::runtime::Lockable,
285  NoLockable>::type,
286  public NodeInfoBaseTypes<void, HasLockable> {
287  typename NodeInfoBase::reference getData() { return 0; }
288 };
289 
290 template <bool Enable>
291 class OutOfLineLockableFeature {
292  typedef NodeInfoBase<void, true> OutOfLineLock;
293  LargeArray<OutOfLineLock> outOfLineLocks;
294 
295 public:
296  struct size_of_out_of_line {
297  static const size_t value = sizeof(OutOfLineLock);
298  };
299 
300  void outOfLineAcquire(size_t n, MethodFlag mflag) {
301  galois::runtime::acquire(&outOfLineLocks[n], mflag);
302  }
303  void outOfLineAllocateLocal(size_t numNodes) {
304  outOfLineLocks.allocateLocal(numNodes);
305  }
306  void outOfLineAllocateInterleaved(size_t numNodes) {
307  outOfLineLocks.allocateInterleaved(numNodes);
308  }
309  void outOfLineAllocateBlocked(size_t numNodes) {
310  outOfLineLocks.allocateBlocked(numNodes);
311  }
312  void outOfLineAllocateFloating(size_t numNodes) {
313  outOfLineLocks.allocateFloating(numNodes);
314  }
315 
316  template <typename RangeArrayType>
317  void outOfLineAllocateSpecified(size_t n, RangeArrayType threadRanges) {
318  outOfLineLocks.allocateSpecified(n, threadRanges);
319  }
320 
321  void outOfLineConstructAt(size_t n) { outOfLineLocks.constructAt(n); }
322 };
323 
324 template <>
325 class OutOfLineLockableFeature<false> {
326 public:
327  struct size_of_out_of_line {
328  static const size_t value = 0;
329  };
330  void outOfLineAcquire(size_t, MethodFlag) {}
331  void outOfLineAllocateLocal(size_t) {}
332  void outOfLineAllocateInterleaved(size_t) {}
333  void outOfLineAllocateBlocked(size_t) {}
334  void outOfLineAllocateFloating(size_t) {}
335  void outOfLineConstructAt(size_t) {}
336  template <typename RangeArrayType>
337  void outOfLineAllocateSpecified(size_t, RangeArrayType) {}
338 };
339 
341 template <typename NodeInfoPtrTy, typename EdgeTy>
342 struct EdgeInfoBase : public LazyObject<EdgeTy> {
343  NodeInfoPtrTy dst;
344 };
345 
350 template <typename GraphTy>
351 class EdgesIterator {
352  typename GraphTy::edge_iterator ii, ee;
353 
354 public:
355  typedef NoDerefIterator<typename GraphTy::edge_iterator> iterator;
356 
357  EdgesIterator(GraphTy& g, typename GraphTy::GraphNode n, MethodFlag f)
358  : ii(g.edge_begin(n, f)), ee(g.edge_end(n, f)) {}
359  EdgesIterator(typename GraphTy::edge_iterator _ii,
360  typename GraphTy::edge_iterator _ee)
361  : ii(_ii), ee(_ee) {}
362 
363  iterator begin() { return make_no_deref_iterator(ii); }
364  iterator end() { return make_no_deref_iterator(ee); }
365 };
366 
367 template <typename ItTy>
368 runtime::iterable<NoDerefIterator<ItTy>> make_no_deref_range(ItTy ii, ItTy ee) {
369  return runtime::make_iterable(make_no_deref_iterator(ii),
371 }
372 
377 template <typename GraphTy>
378 class InEdgesIterator {
379  GraphTy& g;
380  typename GraphTy::GraphNode n;
381  MethodFlag flag;
382 
383 public:
384  typedef NoDerefIterator<typename GraphTy::in_edge_iterator> iterator;
385 
386  InEdgesIterator(GraphTy& g, typename GraphTy::GraphNode n, MethodFlag f)
387  : g(g), n(n), flag(f) {}
388 
389  iterator begin() { return make_no_deref_iterator(g.in_edge_begin(n, flag)); }
390  iterator end() { return make_no_deref_iterator(g.in_edge_end(n, flag)); }
391 };
392 
393 template <typename GraphTy>
394 class EdgesWithNoFlagIterator {
395  GraphTy& g;
396  typename GraphTy::GraphNode n;
397 
398 public:
399  typedef NoDerefIterator<typename GraphTy::edge_iterator> iterator;
400 
401  EdgesWithNoFlagIterator(GraphTy& g, typename GraphTy::GraphNode n)
402  : g(g), n(n) {}
403 
404  iterator begin() { return make_no_deref_iterator(g.edge_begin(n)); }
405  iterator end() { return make_no_deref_iterator(g.edge_end(n)); }
406 };
407 
408 template <typename A, typename B, typename C, typename D, typename E>
409 void swap(EdgeSortReference<A, B, C, D, E> a,
410  EdgeSortReference<A, B, C, D, E> b) {
411  auto aa = *a;
412  auto bb = *b;
413  a = bb;
414  b = aa;
415 }
416 
417 } // namespace galois::graphs::internal
418 
419 #endif
unsigned int getActiveThreads() noexcept
Returns the number of threads in use.
Definition: Threads.cpp:37
StrictObject< EdgeTy > Super
Definition: Details.h:64
Single object with specialization for void type.
Definition: LazyObject.h:37
friend struct internal::EdgeSortReference
Definition: Details.h:58
EdgeTy value_type
Definition: LazyObject.h:41
static unsigned getTID()
Definition: ThreadPool.h:204
Proxy object for internal EdgeSortReference.
Definition: Details.h:56
void acquire(Lockable *lockable, galois::MethodFlag m)
Master function which handles conflict detection used to acquire a lockable thing.
Definition: libgalois/include/galois/runtime/Context.h:218
MethodFlag
What should the runtime do when executing a method.
Definition: MethodFlags.h:34
GraphNode dst
Definition: Details.h:63
void operator()(void)
Definition: Executor_ParaMeter.h:417
const Ty min(std::atomic< Ty > &a, const Ty &b)
Definition: AtomicHelpers.h:70
NoDerefIterator< Iterator > make_no_deref_iterator(Iterator it)
Convenience function to create NoDerefIterator.
Definition: NoDerefIterator.h:48
EdgeSortValue(const ER &ref)
Definition: Details.h:71
EdgeSortValue(GraphNode d, GraphNode rd, const value_type &v)
Definition: Details.h:67
Super::value_type value_type
Definition: Details.h:65