Galois
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Range.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_RUNTIME_RANGE_H
21 #define GALOIS_RUNTIME_RANGE_H
22 
23 #include <iterator>
24 
25 #include <boost/iterator/counting_iterator.hpp>
26 
27 #include "galois/config.h"
28 #include "galois/gstl.h"
30 
31 namespace galois {
32 namespace runtime {
33 
34 extern unsigned int activeThreads;
35 
36 // TODO(ddn): update to have better forward iterator behavor for blocked/local
37 // iteration
38 
39 template <typename T>
40 class LocalRange {
41  T* container;
42 
43 public:
44  typedef T container_type;
45  typedef typename T::iterator iterator;
46  typedef typename T::local_iterator local_iterator;
49 
50  LocalRange(T& c) : container(&c) {}
51 
52  iterator begin() const { return container->begin(); }
53  iterator end() const { return container->end(); }
54 
55  // TODO fix constness of local containers
56  /* const */ T& get_container() const { return *container; }
57 
58  std::pair<block_iterator, block_iterator> block_pair() const {
61  }
62 
63  std::pair<local_iterator, local_iterator> local_pair() const {
64  return std::make_pair(container->local_begin(), container->local_end());
65  }
66 
67  local_iterator local_begin() const { return container->local_begin(); }
68  local_iterator local_end() const { return container->local_end(); }
69 
70  block_iterator block_begin() const { return block_pair().first; }
71  block_iterator block_end() const { return block_pair().second; }
72 };
73 
74 template <typename T>
75 inline LocalRange<T> makeLocalRange(T& obj) {
76  return LocalRange<T>(obj);
77 }
78 
79 template <typename IterTy>
81  IterTy ii, ei;
82 
83 public:
84  typedef IterTy iterator;
87 
89 
90  StandardRange(IterTy b, IterTy e) : ii(b), ei(e) {}
91 
92  iterator begin() const { return ii; }
93  iterator end() const { return ei; }
94 
95  std::pair<block_iterator, block_iterator> block_pair() const {
98  }
99 
100  std::pair<local_iterator, local_iterator> local_pair() const {
101  return block_pair();
102  }
103 
104  local_iterator local_begin() const { return block_begin(); }
105  local_iterator local_end() const { return block_end(); }
106 
107  block_iterator block_begin() const { return block_pair().first; }
108  block_iterator block_end() const { return block_pair().second; }
109 };
110 
111 template <typename IterTy>
112 inline StandardRange<IterTy> makeStandardRange(IterTy begin, IterTy end) {
113  return StandardRange<IterTy>(begin, end);
114 }
115 
121 template <typename IterTy>
123  IterTy global_begin, global_end;
124  const uint32_t* thread_beginnings;
125 
126 public:
127  typedef IterTy iterator;
130 
132 
133  SpecificRange(IterTy b, IterTy e, const uint32_t* thread_ranges)
134  : global_begin(b), global_end(e), thread_beginnings(thread_ranges) {}
135 
136  iterator begin() const { return global_begin; }
137  iterator end() const { return global_end; }
138 
139  /* Using the thread_beginnings array which tells you which node each thread
140  * should begin at, we can get the local block range for a particular
141  * thread. If the local range falls outside of global range, do nothing.
142  *
143  * @returns A pair of iterators that specifies the beginning and end
144  * of the range for this particular thread.
145  */
146  std::pair<block_iterator, block_iterator> block_pair() const {
147  uint32_t my_thread_id = substrate::ThreadPool::getTID();
148  uint32_t total_threads = runtime::activeThreads;
149 
150  iterator local_begin = thread_beginnings[my_thread_id];
151  iterator local_end = thread_beginnings[my_thread_id + 1];
152 
153  assert(local_begin <= local_end);
154 
155  if (thread_beginnings[total_threads] == *global_end && *global_begin == 0) {
156  return std::make_pair(local_begin, local_end);
157  } else {
158  // This path assumes that we were passed in thread_beginnings for the
159  // range 0 to last node, but the passed in range to execute is NOT the
160  // entire 0 to thread end range; therefore, work under the assumption that
161  // only some threads will execute things only if they "own" nodes in the
162  // range
163  iterator left = local_begin;
164  iterator right = local_end;
165 
166  // local = what this thread CAN do
167  // global = what this thread NEEDS to do
168 
169  // cutoff left and right if global begin/end require less than what we
170  // need
171  if (local_begin < global_begin) {
172  left = global_begin;
173  }
174  if (local_end > global_end) {
175  right = global_end;
176  }
177  // make sure range is sensible after changing left and right
178  if (left >= right || right <= left) {
179  left = right = global_end;
180  }
181 
182  // Explanations/reasoning of possible cases
183  // [ ] = local ranges
184  // o = need to be included; global ranges = leftmost and rightmost circle
185  // x = not included
186  // ooooo[ooooooooxxxx]xxxxxx handled (left the same, right moved)
187  // xxxxx[xxxxxooooooo]oooooo handled (left moved, right the same)
188  // xxxxx[xxoooooooxxx]xxxxxx handled (both left/right moved)
189  // xxxxx[xxxxxxxxxxxx]oooooo handled (left will be >= right, set l = r)
190  // oooox[xxxxxxxxxxxx]xxxxxx handled (right will be <= left, set l = r)
191  // xxxxx[oooooooooooo]xxxxxx handled (left, right the same = local range)
192 
193  return std::make_pair(left, right);
194  }
195  }
196 
197  std::pair<local_iterator, local_iterator> local_pair() const {
198  return block_pair();
199  }
200 
201  local_iterator local_begin() const { return block_begin(); }
202  local_iterator local_end() const { return block_end(); }
203 
204  block_iterator block_begin() const { return block_pair().first; }
205  block_iterator block_end() const { return block_pair().second; }
206 };
207 
218 template <typename IterTy>
219 inline SpecificRange<IterTy> makeSpecificRange(IterTy begin, IterTy end,
220  const uint32_t* thread_ranges) {
221  return SpecificRange<IterTy>(begin, end, thread_ranges);
222 }
223 
224 } // end namespace runtime
225 
226 namespace internal {
227 
228 // supported variants
229 // range(beg, end)
230 // range(C& cont)
231 // range(const T& x); // single item or drop this in favor of initializer list
232 // range(std::initializer_list<T>)
233 template <typename I, bool IS_INTEGER = false>
234 class IteratorRangeMaker {
235  I m_beg;
236  I m_end;
237 
238 public:
239  IteratorRangeMaker(const I& beg, const I& end) : m_beg(beg), m_end(end) {}
240 
241  template <typename Arg>
242  auto operator()(const Arg&) const {
243  return runtime::makeStandardRange(m_beg, m_end);
244  }
245 };
246 
247 template <typename I>
248 class IteratorRangeMaker<I, true> {
249  I m_beg;
250  I m_end;
251 
252 public:
253  IteratorRangeMaker(const I& beg, const I& end) : m_beg(beg), m_end(end) {}
254 
255  template <typename Arg>
256  auto operator()(const Arg&) const {
257  return runtime::makeStandardRange(boost::counting_iterator<I>(m_beg),
258  boost::counting_iterator<I>(m_end));
259  }
260 };
261 
262 template <typename T>
263 class InitListRangeMaker {
264  std::initializer_list<T> m_list;
265 
266 public:
267  explicit InitListRangeMaker(const std::initializer_list<T>& l) : m_list(l) {}
268 
269  template <typename Arg>
270  auto operator()(const Arg&) const {
271  return runtime::makeStandardRange(m_list.begin(), m_list.end());
272  }
273 };
274 
275 template <typename C, bool HAS_LOCAL_RANGE = true>
276 class ContainerRangeMaker {
277  C& m_cont;
278 
279 public:
280  explicit ContainerRangeMaker(C& cont) : m_cont(cont) {}
281 
282  template <typename Arg>
283  auto operator()(const Arg&) const {
284  return runtime::makeLocalRange(m_cont);
285  }
286 };
287 
288 template <typename C>
289 class ContainerRangeMaker<C, false> {
290 
291  C& m_cont;
292 
293 public:
294  explicit ContainerRangeMaker(C& cont) : m_cont(cont) {}
295 
296  template <typename Arg>
297  auto operator()(const Arg&) const {
298  return runtime::makeStandardRange(m_cont.begin(), m_cont.end());
299  }
300 };
301 
302 template <typename C>
303 class HasLocalIter {
304 
305  template <typename T>
306  using CallExprType = typename std::remove_reference<decltype(
307  std::declval<T>().local_begin())>::type;
308 
309  template <typename T>
310  static std::true_type go(typename std::add_pointer<CallExprType<T>>::type);
311 
312  template <typename T>
313  static std::false_type go(...);
314 
315 public:
316  constexpr static const bool value =
317  std::is_same<decltype(go<C>(nullptr)), std::true_type>::value;
318 };
319 
320 } // end namespace internal
321 
322 template <typename C>
323 auto iterate(C& cont) {
324  return internal::ContainerRangeMaker<C, internal::HasLocalIter<C>::value>(
325  cont);
326 }
327 
328 template <typename T>
329 auto iterate(std::initializer_list<T> initList) {
330  return internal::InitListRangeMaker<T>(initList);
331 }
332 
333 template <typename I>
334 auto iterate(const I& beg, const I& end) {
335  return internal::IteratorRangeMaker<I, std::is_integral<I>::value>(beg, end);
336 }
337 
338 } // end namespace galois
339 #endif
StandardRange(IterTy b, IterTy e)
Definition: Range.h:90
iterator local_iterator
Definition: Range.h:128
SpecificRange(IterTy b, IterTy e, const uint32_t *thread_ranges)
Definition: Range.h:133
std::pair< IterTy, IterTy > block_range(IterTy b, IterTy e, unsigned id, unsigned num)
Returns a continuous block from the range based on the number of divisions and the id of the block re...
Definition: gstl.h:244
local_iterator local_begin() const
Definition: Range.h:104
iterator local_iterator
Definition: Range.h:85
LocalRange(T &c)
Definition: Range.h:50
local_iterator local_begin() const
Definition: Range.h:201
Definition: Range.h:40
iterator end() const
Definition: Range.h:93
LocalRange< T > makeLocalRange(T &obj)
Definition: Range.h:75
block_iterator block_end() const
Definition: Range.h:205
iterator end() const
Definition: Range.h:53
T::iterator iterator
Definition: Range.h:45
SpecificRange< IterTy > makeSpecificRange(IterTy begin, IterTy end, const uint32_t *thread_ranges)
Creates a SpecificRange object.
Definition: Range.h:219
local_iterator local_end() const
Definition: Range.h:68
std::iterator_traits< iterator >::value_type value_type
Definition: Range.h:48
iterator block_iterator
Definition: Range.h:129
local_iterator local_begin() const
Definition: Range.h:67
block_iterator block_begin() const
Definition: Range.h:204
iterator end() const
Definition: Range.h:137
iterator begin() const
Definition: Range.h:92
std::pair< block_iterator, block_iterator > block_pair() const
Definition: Range.h:146
static unsigned getTID()
Definition: ThreadPool.h:204
IterTy iterator
Definition: Range.h:127
unsigned int activeThreads
Definition: Threads.cpp:26
block_iterator block_end() const
Definition: Range.h:108
iterator block_iterator
Definition: Range.h:47
block_iterator block_end() const
Definition: Range.h:71
local_iterator local_end() const
Definition: Range.h:105
void operator()(void)
Definition: Executor_ParaMeter.h:417
SpecificRange is a range type where a threads range is specified by an an int array that tells you wh...
Definition: Range.h:122
T & get_container() const
Definition: Range.h:56
std::pair< local_iterator, local_iterator > local_pair() const
Definition: Range.h:197
StandardRange< IterTy > makeStandardRange(IterTy begin, IterTy end)
Definition: Range.h:112
iterator begin() const
Definition: Range.h:52
local_iterator local_end() const
Definition: Range.h:202
T container_type
Definition: Range.h:44
IterTy iterator
Definition: Range.h:84
block_iterator block_begin() const
Definition: Range.h:107
Definition: Range.h:80
std::iterator_traits< IterTy >::value_type value_type
Definition: Range.h:131
T::local_iterator local_iterator
Definition: Range.h:46
auto iterate(C &cont)
Definition: Range.h:323
std::pair< local_iterator, local_iterator > local_pair() const
Definition: Range.h:63
block_iterator block_begin() const
Definition: Range.h:70
T value_type
Definition: Executor_ParaMeter.h:111
std::pair< block_iterator, block_iterator > block_pair() const
Definition: Range.h:95
std::pair< local_iterator, local_iterator > local_pair() const
Definition: Range.h:100
std::iterator_traits< IterTy >::value_type value_type
Definition: Range.h:88
iterator block_iterator
Definition: Range.h:86
iterator begin() const
Definition: Range.h:136
std::pair< block_iterator, block_iterator > block_pair() const
Definition: Range.h:58