DASH  0.3.0
LocalRange.h
1 #ifndef DASH__ALGORITHM__LOCAL_RANGE_H__
2 #define DASH__ALGORITHM__LOCAL_RANGE_H__
3 
4 #include <dash/view/IndexSet.h>
5 #include <dash/view/Sub.h>
6 #include <dash/view/ViewMod.h>
7 
8 #include <dash/Range.h>
9 
10 #include <dash/internal/Logging.h>
11 
12 
13 namespace dash {
14 
15 template <
16  dim_t SubDim,
17  class DomainT,
18  class OffsetT >
19 constexpr auto
20 sub(
21  OffsetT begin,
22  OffsetT end,
23  const DomainT & domain)
24  -> typename std::enable_if<
26  ViewSubMod<DomainT, SubDim>
27  >::type;
28 
29 
30 template<typename ElementType>
31 struct LocalRange {
32  ElementType * begin;
33  ElementType * end;
34 };
35 
36 template<typename IndexType>
38  IndexType begin;
39  IndexType end;
40 };
41 
42 #if 0
43 template<class GlobInputIter>
44 typename std::enable_if<
45  ( !GlobInputIter::has_view::value &&
46  typename GlobInputIter::pattern_type::ndim() == 1 ),
48 >::type
51  const GlobInputIter & first,
53  const GlobInputIter & last)
54 {
55  typedef typename GlobInputIter::pattern_type::index_type idx_t;
56 
57  auto grange = dash::make_range(first, last);
58  auto lrange = dash::index(
60  dash::sub( // < sub needed as temporary
61  first.pos(), // workaround as
62  last.pos(), // index(local(container.local)
63  grange) ) ); // is not defined in some cases
64 
65  idx_t lrange_begin = *dash::begin(lrange);
66  idx_t lrange_end = *dash::end(lrange);
67 
68  return LocalIndexRange<idx_t> { lrange_begin, lrange_end };
69 }
70 #endif
71 
96 template<class GlobInputIter>
97 typename std::enable_if<
98  !GlobInputIter::has_view::value,
100 >::type
103  const GlobInputIter & first,
105  const GlobInputIter & last)
106 {
107  typedef typename GlobInputIter::pattern_type::index_type idx_t;
108 
109  typedef typename GlobInputIter::pattern_type pattern_t;
110  typedef typename pattern_t::index_type idx_t;
111  // Get offsets of iterators within global memory, O(1):
112  auto begin_gindex = static_cast<idx_t>(first.pos());
113  auto end_gindex = static_cast<idx_t>(last.pos());
114  DASH_LOG_TRACE("local_index_range(GlobIt,GlobIt)",
115  begin_gindex, end_gindex);
116  // Get pattern from global iterators, O(1):
117  const auto& pattern = first.pattern();
118  DASH_LOG_TRACE_VAR("local_index_range", pattern.local_size());
119  if (pattern.local_size() == 0) {
120  // Local index range is empty
121  DASH_LOG_TRACE("local_index_range (lsize:0) ->", 0, 0);
122  return LocalIndexRange<idx_t> { 0, 0 };
123  }
124  // Global index of first element in pattern, O(1):
125  idx_t lbegin_gindex = pattern.lbegin();
126  // Global index of last element in pattern, O(1):
127  idx_t lend_gindex = pattern.lend();
128  DASH_LOG_TRACE_VAR("local_index_range", lbegin_gindex);
129  DASH_LOG_TRACE_VAR("local_index_range", lend_gindex);
130  if (lend_gindex <= begin_gindex || // local end before global begin
131  lbegin_gindex >= end_gindex) { // local begin after global end
132  // No overlap, intersection is empty
133  DASH_LOG_TRACE("local_index_range (intersect:0) >", 0, 0);
134  return LocalIndexRange<idx_t> { 0, 0 };
135  }
136  // Intersect local range and global range, in global index domain:
137  auto goffset_lbegin = std::max<idx_t>(lbegin_gindex, begin_gindex);
138  auto goffset_lend = std::min<idx_t>(lend_gindex, end_gindex);
139  // Global positions of local range to global coordinates, O(d):
140  auto lbegin_gcoords = pattern.coords(goffset_lbegin);
141  // Subtract 1 from global end offset as it points one coordinate
142  // past the last index which is out of the valid coordinates range:
143  auto lend_gcoords = pattern.coords(goffset_lend-1);
144  // Global coordinates of local range to local indices, O(d):
145  auto lbegin_index = pattern.at(lbegin_gcoords);
146  // Add 1 to local end index to it points one coordinate past the
147  // last index:
148  auto lend_index = pattern.at(lend_gcoords);
149  if (lend_index
150  == std::numeric_limits<typename pattern_t::index_type>::max()) {
151  DASH_LOG_ERROR("local_index_range !",
152  "index type too small for for local index range");
153  }
154  lend_index += 1;
155  // Return local index range
156  DASH_LOG_TRACE("local_index_range >", lbegin_index, lend_index);
157  return LocalIndexRange<idx_t> { lbegin_index, lend_index };
158 }
159 
183 template<class GlobInputIter>
184 typename std::enable_if<
185  GlobInputIter::has_view::value,
187 >::type
190  const GlobInputIter & first,
192  const GlobInputIter & last)
193 {
194  typedef typename GlobInputIter::pattern_type pattern_t;
195  typedef typename pattern_t::index_type idx_t;
196  // Get offsets of iterators within global memory, O(1):
197  auto begin_gindex = static_cast<idx_t>(first.pos());
198  auto end_gindex = static_cast<idx_t>(last.pos());
199  DASH_LOG_TRACE("local_index_range(ViewIt,ViewIt)",
200  begin_gindex, end_gindex);
201  DASH_ASSERT_GT(begin_gindex+1, 0,
202  "local_index_range: begin.gidx must not be negative");
203  DASH_ASSERT_GT(end_gindex+1, 0,
204  "local_index_range: end.gidx must not be negative");
205  // Check if input range is relative to a view spec (e.g. a block):
206  if (first.is_relative() && last.is_relative()) {
207  DASH_LOG_TRACE("local_index_range", "input iterators are relative");
208  if (first.viewspec() == last.viewspec()) {
209  DASH_LOG_TRACE("local_index_range", "input iterators in same view");
210  auto l_first = first.lpos();
211  bool first_is_local = l_first.unit == first.team().myid();
212  // No need to check if last is local as both are relative to the
213  // same view.
214  if (first_is_local) {
215  auto l_last_idx = last.lpos().index;
216  auto l_first_idx = l_first.index;
217  DASH_LOG_TRACE("local_index_range >", l_first_idx, l_last_idx);
218  return LocalIndexRange<idx_t> { l_first_idx, l_last_idx };
219  }
220  DASH_LOG_TRACE("local_index_range >", "not local -> (0,0)");
221  return LocalIndexRange<idx_t>{0, 0};
222  }
223  DASH_THROW(
225  "dash::local_index_range: views of first and last iterators "
226  "differ");
227  }
228  // Get pattern from global iterators, O(1):
229  const auto& pattern = first.pattern();
230  DASH_LOG_TRACE_VAR("local_index_range", pattern.local_size());
231  if (pattern.local_size() == 0) {
232  // Local index range is empty
233  DASH_LOG_TRACE("local_index_range (lsize:0) ->", 0, 0);
234  return LocalIndexRange<idx_t> { 0, 0 };
235  }
236  // Global index of first element in pattern, O(1):
237  idx_t lbegin_gindex = pattern.lbegin();
238  // Global index of last element in pattern, O(1):
239  idx_t lend_gindex = pattern.lend();
240  DASH_LOG_TRACE_VAR("local_index_range", lbegin_gindex);
241  DASH_LOG_TRACE_VAR("local_index_range", lend_gindex);
242  if (lend_gindex <= begin_gindex || // local end before global begin
243  lbegin_gindex >= end_gindex) { // local begin after global end
244  // No overlap, intersection is empty
245  DASH_LOG_TRACE("local_index_range (intersect:0)->", 0, 0);
246  return LocalIndexRange<idx_t> { 0, 0 };
247  }
248  // Intersect local range and global range, in global index domain:
249  auto goffset_lbegin = std::max<idx_t>(lbegin_gindex, begin_gindex);
250  auto goffset_lend = std::min<idx_t>(lend_gindex, end_gindex);
251  // Global positions of local range to global coordinates, O(d):
252  auto lbegin_gcoords = pattern.coords(goffset_lbegin);
253  // Subtract 1 from global end offset as it points one coordinate
254  // past the last index which is out of the valid coordinates range:
255  auto lend_gcoords = pattern.coords(goffset_lend-1);
256  // Global coordinates of local range to local indices, O(d):
257  auto lbegin_index = pattern.at(lbegin_gcoords);
258  // Add 1 to local end index to it points one coordinate past the
259  // last index:
260  auto lend_index = pattern.at(lend_gcoords);
261  if (lend_index
262  == std::numeric_limits<typename pattern_t::index_type>::max()) {
263  DASH_LOG_ERROR("local_index_range !",
264  "index type too small for for local index range");
265  }
266  lend_index += 1;
267  // Return local index range
268  DASH_LOG_TRACE("local_index_range ->", lbegin_index, lend_index);
269  return LocalIndexRange<idx_t> { lbegin_index, lend_index };
270 }
271 
293 template<class GlobIterType>
297  const GlobIterType & first,
299  const GlobIterType & last)
300 {
301  typedef typename GlobIterType::pattern_type pattern_t;
302  typedef typename GlobIterType::value_type value_t;
303  typedef typename pattern_t::index_type idx_t;
304  DASH_LOG_TRACE("local_range()",
305  "gfirst.pos:", first.pos(),
306  "glast.pos:", last.pos());
307  // Global iterators to local index range, O(d):
308  auto index_range = dash::local_index_range(first, last);
309  idx_t lbegin_index = index_range.begin;
310  idx_t lend_index = index_range.end;
311  if (lbegin_index == lend_index) {
312  // Local range is empty
313  DASH_LOG_TRACE("local_range >", "empty local range",
314  lbegin_index, lend_index);
315  return LocalRange<const value_t> { nullptr, nullptr };
316  }
317  // Local start address from global memory:
318  const auto& pattern = first.pattern();
319 
320  auto* lbegin = dash::local_begin(
321  static_cast<typename GlobIterType::pointer>(first.globmem().begin()),
322  first.team().myid());
323  // Add local offsets to local start address:
324  if (lbegin == nullptr) {
325  DASH_LOG_TRACE("local_range >", "lbegin null");
326  return LocalRange<const value_t> { nullptr, nullptr };
327  }
328  DASH_LOG_TRACE("local_range >",
329  "lbegin:", lbegin,
330  "l_idx_range:", lbegin_index, "-", lend_index);
332  lbegin + lbegin_index,
333  lbegin + lend_index };
334 }
335 
336 template<class GlobIterType>
340  GlobIterType & first,
342  GlobIterType & last)
343 {
344  typedef typename GlobIterType::pattern_type pattern_t;
345  typedef typename GlobIterType::value_type value_t;
346  typedef typename pattern_t::index_type idx_t;
347  DASH_LOG_TRACE("local_range()",
348  "gfirst.pos:", first.pos(),
349  "glast.pos:", last.pos());
351  auto index_range = dash::local_index_range(first, last);
352  idx_t lbegin_index = index_range.begin;
353  idx_t lend_index = index_range.end;
354  if (lbegin_index == lend_index) {
355  // Local range is empty
356  DASH_LOG_TRACE("local_range >", "empty local range",
357  lbegin_index, lend_index);
358  return LocalRange<value_t> { nullptr, nullptr };
359  }
360  // Local start address from global memory:
361 
362  auto* lbegin = dash::local_begin(
363  static_cast<typename GlobIterType::pointer>(first.globmem().begin()),
364  first.team().myid());
365 
366  // Add local offsets to local start address:
367  if (lbegin == nullptr) {
368  DASH_LOG_TRACE("local_range >", "lbegin null");
369  return LocalRange<value_t> { nullptr, nullptr };
370  }
371  DASH_LOG_TRACE("local_range >",
372  "lbegin:", lbegin,
373  "l_idx_range:", lbegin_index, "-", lend_index);
374  return LocalRange<value_t> {
375  lbegin + lbegin_index,
376  lbegin + lend_index };
377 }
378 
379 } // namespace dash
380 
381 #include <dash/algorithm/LocalRanges.h>
382 
383 #endif // DASH__ALGORITHM__LOCAL_RANGE_H__
DASH_CONSTEXPR std::enable_if< std::is_same< typename dash::memory_space_traits< MemSpaceT >::memory_space_layout_tag, memory_space_contiguous >::value, T >::type * local_begin(GlobPtr< T, MemSpaceT > global_begin, dash::team_unit_t unit)
Returns the begin of the local memory portion within a global memory segment.
Definition: GlobPtr.h:593
constexpr std::enable_if< std::is_integral< IndexType >::value, IndexType >::type index(IndexType idx)
Definition: Iterator.h:60
constexpr dash::IteratorRange< const Iterator, const Sentinel > make_range(const Iterator &begin, const Sentinel &end)
Adapter utility function.
Definition: Range.h:433
constexpr auto end(RangeType &&range) -> decltype(std::forward< RangeType >(range).end())
Definition: Range.h:98
constexpr auto local(ViewType &v) -> typename std::enable_if<(std::is_pointer< typename ViewType::iterator >::value||(dash::view_traits< ViewValueT >::is_local::value)), ViewType &>::type
Definition: Local.h:28
This class is a simple memory pool which holds allocates elements of size ValueType.
Definition: AllOf.h:8
constexpr auto begin(RangeType &&range) -> decltype(std::forward< RangeType >(range).begin())
Definition: Range.h:89
LocalRange< const typename GlobIterType::value_type > local_range(const GlobIterType &first, const GlobIterType &last)
Resolves the local address range between global iterators.
Definition: LocalRange.h:295
int dim_t
Scalar type for a dimension value, with 0 indicating the first dimension.
Definition: Types.h:39
Returns second operand.
Definition: Operation.h:201
View type traits.
Definition: ViewTraits.h:31
constexpr dim_t ndim(const DimensionalType &d)
Definition: Dimensional.h:56
std::enable_if< !GlobInputIter::has_view::value, LocalIndexRange< typename GlobInputIter::pattern_type::index_type >>::type local_index_range(const GlobInputIter &first, const GlobInputIter &last)
Resolves the local index range between global iterators.
Definition: LocalRange.h:101
constexpr auto domain(ViewT &&view) -> typename std::enable_if< dash::detail::has_type_domain_type< ViewValueT >::value, decltype(std::forward< ViewT >(view).domain()) >::type
Definition: Domain.h:23