DASH  0.3.0
GlobHeapPtr.h
1 #ifndef DASH__MEMORY__GLOB_HEAP_PTR_H__INCLUDED
2 #define DASH__MEMORY__GLOB_HEAP_PTR_H__INCLUDED
3 
4 #include <dash/dart/if/dart.h>
5 
6 #include <dash/Types.h>
7 #include <dash/Allocator.h>
8 #include <dash/Team.h>
9 #include <dash/GlobSharedRef.h>
10 
11 #include <dash/internal/Logging.h>
12 
13 #include <type_traits>
14 #include <list>
15 #include <vector>
16 #include <sstream>
17 #include <iostream>
18 
19 
20 namespace dash {
21 
25 template <
26  typename ElementType,
27  class MemSpaceT>
28 class GlobHeapPtr {
29 
30  typedef MemSpaceT GlobHeapMemType;
31  typedef GlobHeapPtr<ElementType, GlobHeapMemType> self_t;
32 
33  template <typename ElementType_, class MemSpaceT_>
34  friend std::ostream &operator<<(
35  std::ostream & os,
37 
38 public:
39  typedef typename GlobHeapMemType::index_type index_type;
40  typedef typename std::make_unsigned<index_type>::type size_type;
41 
42  typedef ElementType value_type;
43 
44  typedef GlobSharedRef< value_type, self_t> reference;
45  typedef GlobSharedRef<const value_type, self_t> const_reference;
46 
47  typedef value_type * raw_pointer;
48 
49  typedef GlobHeapMemType globmem_type;
50  typedef typename GlobHeapMemType::local_pointer local_pointer;
51 
52  typedef struct {
53  team_unit_t unit;
54  index_type index;
55  } local_index;
56 
57  template <typename U>
59 
60 private:
61  typedef std::vector<std::vector<size_type> >
62  bucket_cumul_sizes_map;
63 
64 private:
66  const globmem_type * _globmem = nullptr;
68  const bucket_cumul_sizes_map * _bucket_cumul_sizes = nullptr;
70  local_pointer _lbegin;
72  index_type _idx = 0;
74  index_type _max_idx = 0;
76  team_unit_t _myid;
78  team_unit_t _idx_unit_id;
80  index_type _idx_local_idx = -1;
82  index_type _idx_bucket_idx = -1;
84  index_type _idx_bucket_phase = -1;
85 
86 public:
91  : _globmem(nullptr),
92  _bucket_cumul_sizes(nullptr),
93  _idx(0),
94  _max_idx(0),
95  _myid(dash::Team::GlobalUnitID()),
96  _idx_unit_id(DART_UNDEFINED_UNIT_ID),
97  _idx_local_idx(-1),
98  _idx_bucket_idx(-1),
99  _idx_bucket_phase(-1)
100  {
101  DASH_LOG_TRACE_VAR("GlobHeapPtr()", _idx);
102  DASH_LOG_TRACE_VAR("GlobHeapPtr()", _max_idx);
103  }
104 
110  const MemSpaceT * gmem,
111  index_type position = 0)
112  : _globmem(reinterpret_cast<const globmem_type *>(gmem)),
113  _bucket_cumul_sizes(&_globmem->_bucket_cumul_sizes),
114  _lbegin(_globmem->lbegin()),
115  _idx(position),
116  _max_idx(gmem->size() - 1),
117  _myid(gmem->team().myid()),
118  _idx_unit_id(0),
119  _idx_local_idx(0),
120  _idx_bucket_idx(0),
121  _idx_bucket_phase(0)
122  {
123  DASH_LOG_TRACE("GlobHeapPtr(gmem,idx)", "gidx:", position);
124  for (auto unit_bucket_cumul_sizes : *_bucket_cumul_sizes) {
125  DASH_LOG_TRACE_VAR("GlobHeapPtr(gmem,idx)",
126  unit_bucket_cumul_sizes);
127  size_type bucket_cumul_size_prev = 0;
128  for (auto bucket_cumul_size : unit_bucket_cumul_sizes) {
129  DASH_LOG_TRACE_VAR("GlobHeapPtr(gmem,idx)", bucket_cumul_size);
130  if (position < bucket_cumul_size) {
131  DASH_LOG_TRACE_VAR("GlobHeapPtr(gmem,idx)", position);
132  _idx_bucket_phase -= bucket_cumul_size;
133  position = 0;
134  _idx_local_idx = position;
135  _idx_bucket_phase = position - bucket_cumul_size_prev;
136  break;
137  }
138  bucket_cumul_size_prev = bucket_cumul_size;
139  ++_idx_bucket_idx;
140  }
141  if (position == 0) {
142  break;
143  }
144  // Advance to next unit, adjust position relative to next unit's
145  // local index space:
146  position -= unit_bucket_cumul_sizes.back();
147  ++_idx_unit_id;
148  }
149  DASH_LOG_TRACE("GlobHeapPtr(gmem,idx)",
150  "gidx:", _idx,
151  "unit:", _idx_unit_id,
152  "lidx:", _idx_local_idx,
153  "bucket:", _idx_bucket_idx,
154  "phase:", _idx_bucket_phase);
155  }
156 
162  const MemSpaceT * gmem,
163  team_unit_t unit,
164  index_type local_index)
165  : _globmem(reinterpret_cast<const globmem_type *>(gmem)),
166  _bucket_cumul_sizes(&_globmem->_bucket_cumul_sizes),
167  _lbegin(_globmem->lbegin()),
168  _idx(0),
169  _max_idx(gmem->size() - 1),
170  _myid(gmem->team().myid()),
171  _idx_unit_id(unit),
172  _idx_local_idx(0),
173  _idx_bucket_idx(0),
174  _idx_bucket_phase(0)
175  {
176  DASH_LOG_TRACE("GlobHeapPtr(gmem,unit,lidx)",
177  "unit:", unit,
178  "lidx:", local_index);
179  DASH_ASSERT_LT(unit, _bucket_cumul_sizes->size(), "invalid unit id");
180 
181  for (size_type unit = 0; unit < _idx_unit_id; ++unit) {
182  auto prec_unit_local_size = (*_bucket_cumul_sizes)[unit].back();
183  _idx += prec_unit_local_size;
184  }
185  increment(local_index);
186  DASH_LOG_TRACE("GlobHeapPtr(gmem,unit,lidx) >",
187  "gidx:", _idx,
188  "maxidx:", _max_idx,
189  "unit:", _idx_unit_id,
190  "lidx:", _idx_local_idx,
191  "bucket:", _idx_bucket_idx,
192  "phase:", _idx_bucket_phase);
193  }
194 
198  template<typename E_, typename M_>
200  const GlobHeapPtr<E_, M_> & other)
201  : _globmem(other._globmem),
202  _bucket_cumul_sizes(other._bucket_cumul_sizes),
203  _lbegin(other._lbegin),
204  _idx(other._idx),
205  _max_idx(other._max_idx),
206  _idx_unit_id(other._idx_unit_id),
207  _idx_local_idx(other._idx_local_idx),
208  _idx_bucket_idx(other._idx_bucket_idx),
209  _idx_bucket_phase(other._idx_bucket_phase)
210  { }
211 
215  template<typename E_, typename M_>
216  self_t & operator=(
217  const GlobHeapPtr<E_, M_> & other)
218  {
219  _globmem = other._globmem;
220  _bucket_cumul_sizes = other._bucket_cumul_sizes;
221  _lbegin = other._lbegin;
222  _idx = other._idx;
223  _max_idx = other._max_idx;
224  _idx_unit_id = other._idx_unit_id;
225  _idx_local_idx = other._idx_local_idx;
226  _idx_bucket_idx = other._idx_bucket_idx;
227  _idx_bucket_phase = other._idx_bucket_phase;
228  }
229 
237  {
238  DASH_LOG_TRACE_VAR("GlobHeapPtr.dart_gptr()", _idx);
239  // Create global pointer from unit, bucket and phase:
240  dart_gptr_t dart_gptr = _globmem->dart_gptr_at(
241  _idx_unit_id,
242  _idx_bucket_idx,
243  _idx_bucket_phase);
244  DASH_LOG_TRACE_VAR("GlobHeapPtr.dart_gptr >", dart_gptr);
245  return dart_gptr;
246  }
247 
253  reference operator*() const
254  {
255  auto lptr = local();
256  if (lptr != nullptr) {
257  return reference(static_cast<raw_pointer>(lptr));
258  } else {
259  return reference(dart_gptr());
260  }
261  }
262 
267  reference operator[](
269  index_type g_index) const
270  {
271  DASH_LOG_TRACE_VAR("GlobHeapPtr.[]()", g_index);
272  auto git = *this;
273  git += g_index;
274  auto lptr = git.local();
275  if (lptr != nullptr) {
276  return reference(lptr);
277  } else {
278  auto gref = *git;
279  DASH_LOG_TRACE_VAR("GlobHeapPtr.[] >", gref);
280  return gref;
281  }
282  }
283 
288  inline bool is_local() const
289  {
290  return (_myid == _idx_unit_id);
291  }
292 
296  local_pointer local() const
297  {
298  if (_myid != _idx_unit_id) {
299  // Iterator position does not point to local element
300  return nullptr;
301  }
302  return (_lbegin + _idx_local_idx);
303  }
304 
308  inline local_index lpos() const
309  {
310  local_index local_pos;
311  local_pos.unit = _idx_unit_id;
312  local_pos.index = _idx_local_idx;
313  return local_pos;
314  }
315 
319  inline self_t global() const
320  {
321  return *this;
322  }
323 
327  inline index_type pos() const
328  {
329  return _idx;
330  }
331 
335  inline index_type gpos() const
336  {
337  return _idx;
338  }
339 
344  inline const globmem_type & globmem() const
345  {
346  return *_globmem;
347  }
348 
353  inline globmem_type & globmem()
354  {
355  return *_globmem;
356  }
357 
361  inline self_t & operator++()
362  {
363  increment(1);
364  return *this;
365  }
366 
370  inline self_t & operator--()
371  {
372  decrement(1);
373  return *this;
374  }
375 
379  inline self_t operator++(int)
380  {
381  auto result = *this;
382  increment(1);
383  return result;
384  }
385 
389  inline self_t operator--(int)
390  {
391  auto result = *this;
392  decrement(1);
393  return result;
394  }
395 
396  inline self_t & operator+=(index_type offset)
397  {
398  increment(offset);
399  return *this;
400  }
401 
402  inline self_t & operator-=(index_type offset)
403  {
404  increment(offset);
405  return *this;
406  }
407 
408  inline self_t operator+(index_type offset) const
409  {
410  auto res = *this;
411  res.increment(offset);
412  return res;
413  }
414 
415  inline self_t operator-(index_type offset) const
416  {
417  auto res = *this;
418  res.decrement(offset);
419  return res;
420  }
421 
422  inline index_type operator+(
423  const self_t & other) const
424  {
425  return _idx + other._idx;
426  }
427 
428  inline index_type operator-(
429  const self_t & other) const
430  {
431  return _idx - other._idx;
432  }
433 
434  template<typename E_, typename M_>
435  inline bool operator<(const GlobHeapPtr<E_, M_> & other) const
436  {
437  return (_idx < other._idx);
438  }
439 
440  template<typename E_, typename M_>
441  inline bool operator<=(const GlobHeapPtr<E_, M_> & other) const
442  {
443  return (_idx <= other._idx);
444  }
445 
446  template<typename E_, typename M_>
447  inline bool operator>(const GlobHeapPtr<E_, M_> & other) const
448  {
449  return (_idx > other._idx);
450  }
451 
452  template<typename E_, typename M_>
453  inline bool operator>=(const GlobHeapPtr<E_, M_> & other) const
454  {
455  return (_idx >= other._idx);
456  }
457 
458  template<typename E_, typename M_>
459  inline bool operator==(const GlobHeapPtr<E_, M_> & other) const
460  {
461  return _idx == other._idx;
462  }
463 
464  template<typename E_, typename M_>
465  inline bool operator!=(const GlobHeapPtr<E_, M_> & other) const
466  {
467  return _idx != other._idx;
468  }
469 
470 private:
474  void increment(int offset)
475  {
476  DASH_LOG_TRACE("GlobHeapPtr.increment()",
477  "gidx:", _idx,
478  "unit:", _idx_unit_id,
479  "lidx:", _idx_local_idx,
480  "bidx:", _idx_bucket_idx,
481  "bphase:", _idx_bucket_phase,
482  "offset:", offset);
483  _idx += offset;
484  auto current_bucket_size =
485  (*_bucket_cumul_sizes)[_idx_unit_id][_idx_bucket_idx];
486  if (_idx_local_idx + offset < current_bucket_size) {
487  DASH_LOG_TRACE("GlobHeapPtr.increment", "position current bucket");
488  // element is in bucket currently referenced by this pointer:
489  _idx_bucket_phase += offset;
490  _idx_local_idx += offset;
491  } else {
492  DASH_LOG_TRACE("GlobHeapPtr.increment",
493  "position in succeeding bucket");
494  // iterate units:
495  auto unit_id_max = _bucket_cumul_sizes->size() - 1;
496  for (; _idx_unit_id <= unit_id_max; ++_idx_unit_id) {
497  if (offset == 0) {
498  break;
499  }
500  auto unit_bkt_sizes = (*_bucket_cumul_sizes)[_idx_unit_id];
501  auto unit_bkt_sizes_total = unit_bkt_sizes.back();
502  auto unit_num_bkts = unit_bkt_sizes.size();
503  DASH_LOG_TRACE("GlobHeapPtr.increment",
504  "unit:", _idx_unit_id,
505  "remaining offset:", offset,
506  "total local bucket size:", unit_bkt_sizes_total);
507  if (_idx_local_idx + offset >= unit_bkt_sizes_total) {
508  // offset refers to next unit:
509  DASH_LOG_TRACE("GlobHeapPtr.increment",
510  "position in remote range");
511  // subtract remaining own local size from remaining offset:
512  offset -= (unit_bkt_sizes_total - _idx_local_idx);
513  if (_idx_unit_id == unit_id_max) {
514  // end pointer, offset exceeds iteration space:
515  _idx_bucket_idx = unit_num_bkts - 1;
516  auto last_bkt_size = unit_bkt_sizes.back();
517  if (unit_num_bkts > 1) {
518  last_bkt_size -= unit_bkt_sizes[_idx_bucket_idx-1];
519  }
520  _idx_bucket_phase = last_bkt_size + offset;
521  _idx_local_idx += unit_bkt_sizes_total + offset;
522  break;
523  }
524  _idx_local_idx = 0;
525  _idx_bucket_idx = 0;
526  _idx_bucket_phase = 0;
527  } else {
528  // offset refers to current unit:
529  DASH_LOG_TRACE("GlobHeapPtr.increment",
530  "position in local range",
531  "current bucket phase:", _idx_bucket_phase,
532  "cumul. bucket sizes:", unit_bkt_sizes);
533  _idx_local_idx += offset;
534  // iterate the unit's bucket sizes:
535  for (; _idx_bucket_idx < unit_num_bkts; ++_idx_bucket_idx) {
536  auto cumul_bucket_size = unit_bkt_sizes[_idx_bucket_idx];
537  if (_idx_local_idx < cumul_bucket_size) {
538  auto cumul_prev = _idx_bucket_idx > 0
539  ? unit_bkt_sizes[_idx_bucket_idx-1]
540  : 0;
541  // offset refers to current bucket:
542  _idx_bucket_phase = _idx_local_idx - cumul_prev;
543  offset = 0;
544  break;
545  }
546  }
547  if (offset == 0) {
548  break;
549  }
550  }
551  }
552  }
553  DASH_LOG_TRACE("GlobHeapPtr.increment >",
554  "gidx:", _idx,
555  "unit:", _idx_unit_id,
556  "lidx:", _idx_local_idx,
557  "bidx:", _idx_bucket_idx,
558  "bphase:", _idx_bucket_phase);
559  }
560 
564  void decrement(int offset)
565  {
566  DASH_LOG_TRACE("GlobHeapPtr.decrement()",
567  "gidx:", _idx,
568  "unit:", _idx_unit_id,
569  "lidx:", _idx_local_idx,
570  "bidx:", _idx_bucket_idx,
571  "bphase:", _idx_bucket_phase,
572  "offset:", -offset);
573  if (offset > _idx) {
574  DASH_THROW(dash::exception::OutOfRange,
575  "offset " << offset << " is out of range");
576  }
577  _idx -= offset;
578  if (offset <= _idx_bucket_phase) {
579  // element is in bucket currently referenced by this pointer:
580  _idx_bucket_phase -= offset;
581  _idx_local_idx -= offset;
582  } else {
583  // iterate units:
584  auto first_unit = _idx_unit_id;
585  for (; _idx_unit_id >= 0; --_idx_unit_id) {
586  auto unit_bkt_sizes = (*_bucket_cumul_sizes)[_idx_unit_id];
587  auto unit_bkt_sizes_total = unit_bkt_sizes.back();
588  auto unit_num_bkts = unit_bkt_sizes.size();
589  if (_idx_unit_id != first_unit) {
590  --offset;
591  _idx_bucket_idx = unit_num_bkts - 1;
592  _idx_local_idx = unit_bkt_sizes_total - 1;
593  auto last_bkt_size = unit_bkt_sizes.back();
594  if (unit_num_bkts > 1) {
595  last_bkt_size -= unit_bkt_sizes[_idx_bucket_idx-1];
596  }
597  _idx_bucket_phase = last_bkt_size - 1;
598  }
599  if (offset <= _idx_local_idx) {
600  // offset refers to current unit:
601  // iterate the unit's bucket sizes:
602  for (; _idx_bucket_idx >= 0; --_idx_bucket_idx) {
603  auto bucket_size = unit_bkt_sizes[_idx_bucket_idx];
604  if (offset <= _idx_bucket_phase) {
605  // offset refers to current bucket:
606  _idx_local_idx -= offset;
607  _idx_bucket_phase -= offset;
608  offset = 0;
609  break;
610  } else {
611  // offset refers to preceeding bucket:
612  _idx_local_idx -= (_idx_bucket_phase + 1);
613  offset -= (_idx_bucket_phase + 1);
614  _idx_bucket_phase = unit_bkt_sizes[_idx_bucket_idx-1] - 1;
615  }
616  }
617  } else {
618  // offset refers to preceeding unit:
619  offset -= _idx_local_idx;
620  }
621  if (offset == 0) {
622  break;
623  }
624  }
625  }
626  DASH_LOG_TRACE("GlobHeapPtr.decrement >",
627  "gidx:", _idx,
628  "unit:", _idx_unit_id,
629  "lidx:", _idx_local_idx,
630  "bidx:", _idx_bucket_idx,
631  "bphase:", _idx_bucket_phase);
632  }
633 
634 }; // class GlobHeapPtr
635 
643 template <typename ElementType, class MemSpaceT>
644 auto distance(
648  const dash::GlobHeapPtr<ElementType, MemSpaceT> &last) -> typename MemSpaceT::index_type
649 {
650 
651  if (last._globmem == first._globmem) {
652  return last - first;
653  }
654  else {
655  return std::numeric_limits<typename MemSpaceT::index_type>::max();
656  }
657 }
658 
659 template <typename ElementType, class MemSpaceT>
660 std::ostream &operator<<(
661  std::ostream &os, const dash::GlobHeapPtr<ElementType, MemSpaceT> &gptr)
662 {
663  std::ostringstream ss;
664  ss << "dash::GlobHeapPtr<" << typeid(ElementType).name() << ">("
665  << "gidx:" << gptr._idx << ", ("
666  << "unit:" << gptr._idx_unit_id << ", "
667  << "lidx:" << gptr._idx_local_idx << "), ("
668  << "bidx:" << gptr._idx_bucket_idx << ", "
669  << "bphase:" << gptr._idx_bucket_phase << ")"
670  << ")";
671  return operator<<(os, ss.str());
672 }
673 
674 } // namespace dash
675 
676 #endif // DASH__MEMORY__GLOB_HEAP_PTR_H__INCLUDED
reference operator*() const
Dereference operator.
Definition: GlobHeapPtr.h:253
global_unit_t myid()
Shortcut to query the global unit ID of the calling unit.
self_t operator--(int)
Postfix decrement operator.
Definition: GlobHeapPtr.h:389
constexpr std::enable_if< std::is_integral< IndexType >::value, IndexType >::type index(IndexType idx)
Definition: Iterator.h:60
size_t size()
Return the number of units in the global team.
This class is a simple memory pool which holds allocates elements of size ValueType.
Definition: AllOf.h:8
local_index lpos() const
Unit and local offset at the pointer&#39;s position.
Definition: GlobHeapPtr.h:308
index_type pos() const
Position of the pointer in global index space.
Definition: GlobHeapPtr.h:327
GlobHeapPtr(const MemSpaceT *gmem, index_type position=0)
Constructor, creates a global pointer on global memory from global offset in logical storage order...
Definition: GlobHeapPtr.h:109
self_t & operator=(const GlobHeapPtr< E_, M_ > &other)
Assignment operator.
Definition: GlobHeapPtr.h:216
GlobHeapPtr(const MemSpaceT *gmem, team_unit_t unit, index_type local_index)
Constructor, creates a global pointer on global memory from unit and local offset in logical storage ...
Definition: GlobHeapPtr.h:161
Returns second operand.
Definition: Operation.h:201
self_t operator++(int)
Postfix increment operator.
Definition: GlobHeapPtr.h:379
index_type gpos() const
Position of the pointer in global index range.
Definition: GlobHeapPtr.h:335
dart_gptr_t dart_gptr() const
Explicit conversion to dart_gptr_t.
Definition: GlobHeapPtr.h:236
A Team instance specifies a subset of all available units.
Definition: Team.h:41
GlobHeapPtr()
Default constructor.
Definition: GlobHeapPtr.h:90
const globmem_type & globmem() const
The instance of GlobStaticMem used by this pointer to resolve addresses in global memory...
Definition: GlobHeapPtr.h:344
GlobHeapPtr(const GlobHeapPtr< E_, M_ > &other)
Copy constructor.
Definition: GlobHeapPtr.h:199
Iterator on global buckets.
Definition: GlobHeapMem.h:32
self_t & operator--()
Prefix decrement operator.
Definition: GlobHeapPtr.h:370
DART Global pointer type.
Definition: dart_globmem.h:77
self_t global() const
Map pointer to global index domain.
Definition: GlobHeapPtr.h:319
struct dash::unit_id< dash::local_unit, dart_team_unit_t > team_unit_t
Unit ID to use for team-local IDs.
Definition: Types.h:319
bool is_local() const
Checks whether the element referenced by this global pointer is in the calling unit&#39;s local memory...
Definition: GlobHeapPtr.h:288
globmem_type & globmem()
The instance of GlobStaticMem used by this pointer to resolve addresses in global memory...
Definition: GlobHeapPtr.h:353
self_t & operator++()
Prefix increment operator.
Definition: GlobHeapPtr.h:361
#define DART_UNDEFINED_UNIT_ID
Undefined unit ID.
Definition: dart_types.h:160
local_pointer local() const
Conversion to local bucket pointer.
Definition: GlobHeapPtr.h:296
reference operator[](index_type g_index) const
Subscript operator, returns global reference to element at given global index.
Definition: GlobHeapPtr.h:267
dash::gptrdiff_t distance(GlobPtr< T, MemSpaceT > gbegin, GlobPtr< T, MemSpaceT > gend)
Returns the number of hops from gbegin to gend.
Definition: GlobPtr.h:547