DASH  0.3.0
DynamicPattern.h
1 #ifndef DASH__DYNAMIC_PATTERN_H__INCLUDED
2 #define DASH__DYNAMIC_PATTERN_H__INCLUDED
3 
4 #include <functional>
5 #include <array>
6 #include <type_traits>
7 
8 #include <dash/Types.h>
9 #include <dash/Distribution.h>
10 #include <dash/Exception.h>
11 #include <dash/Dimensional.h>
12 #include <dash/Cartesian.h>
13 #include <dash/Team.h>
14 #include <dash/PatternProperties.h>
15 
16 #include <dash/internal/Math.h>
17 #include <dash/internal/Logging.h>
18 #include <dash/internal/PatternArguments.h>
19 
20 namespace dash {
21 
22 #ifndef DOXYGEN
23 
29 template<
30  dim_t NumDimensions,
31  MemArrange Arrangement = dash::ROW_MAJOR,
32  typename IndexType = dash::default_index_t >
33 class DynamicPattern;
34 
35 #endif // DOXYGEN
36 
43 template<
44  MemArrange Arrangement,
45  typename IndexType >
46 class DynamicPattern<1, Arrangement, IndexType>
47 {
48 private:
49  static const dim_t NumDimensions = 1;
50 
51 public:
52  static constexpr char const * PatternName = "DynamicPattern1D";
53 
54 public:
57  // Minimal number of blocks in every dimension, i.e. one block
58  // per unit.
60  // Block extents are constant for every dimension.
62  // Identical number of elements in every block.
64  // Size of blocks may differ.
66  // Partitioning is dynamic.
71  // Number of blocks assigned to a unit may differ.
76  // Elements are contiguous in local memory within single block.
78  // Local element order corresponds to a logical linearization
79  // within single blocks.
82 
83 private:
85  typedef DynamicPattern<NumDimensions, Arrangement, IndexType>
86  self_t;
88  typedef typename std::make_unsigned<IndexType>::type
89  SizeType;
99  TeamSpec_t;
101  SizeSpec_t;
103  ViewSpec_t;
104  typedef internal::PatternArguments<NumDimensions, IndexType>
105  PatternArguments_t;
106 
107 public:
108  typedef IndexType index_type;
109  typedef SizeType size_type;
110  typedef ViewSpec_t viewspec_type;
111  typedef struct {
112  team_unit_t unit;
113  IndexType index;
114  } local_index_t;
115  typedef struct {
116  team_unit_t unit;
117  std::array<index_type, NumDimensions> coords;
118  } local_coords_t;
119 
120 public:
127  template<typename ... Args>
132  SizeType arg,
136  Args && ... args)
137  : DynamicPattern(PatternArguments_t(arg, args...))
138 
139  {
140  DASH_LOG_TRACE("DynamicPattern()", "Constructor with argument list");
141  DASH_ASSERT_EQ(
142  _local_sizes.size(), _nunits,
143  "Number of given local sizes " << _local_sizes.size() << " " <<
144  "does not match number of units" << _nunits);
145  initialize_local_range();
146  DASH_LOG_TRACE("DynamicPattern()", "DynamicPattern initialized");
147  }
148 
156  const SizeSpec_t & sizespec,
158  const DistributionSpec_t & distspec,
160  const TeamSpec_t & teamspec,
162  Team & team = dash::Team::All())
163  : _size(sizespec.size()),
164  _local_sizes(initialize_local_sizes(
165  _size,
166  distspec,
167  team)),
168  _block_offsets(initialize_block_offsets(
169  _local_sizes)),
170  _memory_layout(std::array<SizeType, 1> { _size }),
171  _blockspec(initialize_blockspec(
172  _size,
173  _local_sizes)),
174  _distspec(DistributionSpec_t()),
175  _team(&team),
176  _myid(_team->myid()),
177  _teamspec(
178  teamspec,
179  _distspec,
180  *_team),
181  _nunits(_team->size()),
182  _blocksize(initialize_blocksize(
183  _size,
184  _distspec,
185  _nunits)),
186  _nblocks(_nunits),
187  _local_size(
188  initialize_local_extent(_team->myid())),
189  _local_memory_layout(std::array<SizeType, 1> { _local_size }),
190  _local_capacity(initialize_local_capacity())
191  {
192  DASH_LOG_TRACE("DynamicPattern()", "(sizespec, dist, team)");
193  DASH_ASSERT_EQ(
194  _local_sizes.size(), _nunits,
195  "Number of given local sizes " << _local_sizes.size() << " " <<
196  "does not match number of units" << _nunits);
197  initialize_local_range();
198  DASH_LOG_TRACE("DynamicPattern()", "DynamicPattern initialized");
199  }
200 
208  const SizeSpec_t & sizespec,
210  const DistributionSpec_t & distspec,
212  Team & team = dash::Team::All())
213  : _size(sizespec.size()),
214  _local_sizes(initialize_local_sizes(
215  _size,
216  distspec,
217  team)),
218  _block_offsets(initialize_block_offsets(
219  _local_sizes)),
220  _memory_layout(std::array<SizeType, 1> { _size }),
221  _blockspec(initialize_blockspec(
222  _size,
223  _local_sizes)),
224  _distspec(DistributionSpec_t()),
225  _team(&team),
226  _myid(_team->myid()),
227  _teamspec(_distspec, *_team),
228  _nunits(_team->size()),
229  _blocksize(initialize_blocksize(
230  _size,
231  _distspec,
232  _nunits)),
233  _nblocks(_nunits),
234  _local_size(
235  initialize_local_extent(_team->myid())),
236  _local_memory_layout(std::array<SizeType, 1> { _local_size }),
237  _local_capacity(initialize_local_capacity())
238  {
239  DASH_LOG_TRACE("DynamicPattern()", "(sizespec, dist, team)");
240  DASH_ASSERT_EQ(
241  _local_sizes.size(), _nunits,
242  "Number of given local sizes " << _local_sizes.size() << " " <<
243  "does not match number of units" << _nunits);
244  initialize_local_range();
245  DASH_LOG_TRACE("DynamicPattern()", "DynamicPattern initialized");
246  }
247 
254  template<typename ... Args>
257  const std::vector<size_type> & local_sizes,
261  SizeType arg,
265  Args && ... args)
266  : DynamicPattern(local_sizes, PatternArguments_t(arg, args...))
267  {
268  DASH_LOG_TRACE("DynamicPattern()", "Constructor with argument list");
269  DASH_ASSERT_EQ(
270  _local_sizes.size(), _nunits,
271  "Number of given local sizes " << _local_sizes.size() << " " <<
272  "does not match number of units" << _nunits);
273  initialize_local_range();
274  DASH_LOG_TRACE("DynamicPattern()", "DynamicPattern initialized");
275  }
276 
284  const std::vector<size_type> & local_sizes,
286  const TeamSpec_t & teamspec,
288  dash::Team & team = dash::Team::All())
289  : _size(initialize_size(
290  local_sizes)),
291  _local_sizes(local_sizes),
292  _block_offsets(initialize_block_offsets(
293  _local_sizes)),
294  _memory_layout(std::array<SizeType, 1> { _size }),
295  _blockspec(initialize_blockspec(
296  _size,
297  _local_sizes)),
298  _distspec(DistributionSpec_t()),
299  _team(&team),
300  _myid(_team->myid()),
301  _teamspec(
302  teamspec,
303  _distspec,
304  *_team),
305  _nunits(_team->size()),
306  _blocksize(initialize_blocksize(
307  _size,
308  _distspec,
309  _nunits)),
310  _nblocks(_nunits),
311  _local_size(
312  initialize_local_extent(_team->myid())),
313  _local_memory_layout(std::array<SizeType, 1> { _local_size }),
314  _local_capacity(initialize_local_capacity())
315  {
316  DASH_LOG_TRACE("DynamicPattern()", "(sizespec, dist, teamspec, team)");
317  DASH_ASSERT_EQ(
318  _local_sizes.size(), _nunits,
319  "Number of given local sizes " << _local_sizes.size() << " " <<
320  "does not match number of units" << _nunits);
321  initialize_local_range();
322  DASH_LOG_TRACE("DynamicPattern()", "DynamicPattern initialized");
323  }
324 
332  const std::vector<size_type> & local_sizes,
334  Team & team = dash::Team::All())
335  : _size(initialize_size(
336  local_sizes)),
337  _local_sizes(local_sizes),
338  _block_offsets(initialize_block_offsets(
339  _local_sizes)),
340  _memory_layout(std::array<SizeType, 1> { _size }),
341  _blockspec(initialize_blockspec(
342  _size,
343  _local_sizes)),
344  _distspec(DistributionSpec_t()),
345  _team(&team),
346  _myid(_team->myid()),
347  _teamspec(_distspec, *_team),
348  _nunits(_team->size()),
349  _blocksize(initialize_blocksize(
350  _size,
351  _distspec,
352  _nunits)),
353  _nblocks(_nunits),
354  _local_size(
355  initialize_local_extent(_team->myid())),
356  _local_memory_layout(std::array<SizeType, 1> { _local_size }),
357  _local_capacity(initialize_local_capacity())
358  {
359  DASH_LOG_TRACE("DynamicPattern()", "(sizespec, dist, team)");
360  DASH_ASSERT_EQ(
361  _local_sizes.size(), _nunits,
362  "Number of given local sizes " << _local_sizes.size() << " " <<
363  "does not match number of units" << _nunits);
364  initialize_local_range();
365  DASH_LOG_TRACE("DynamicPattern()", "DynamicPattern initialized");
366  }
367 
371  DynamicPattern(const self_t & other)
372  : _size(other._size),
373  _local_sizes(other._local_sizes),
374  _block_offsets(other._block_offsets),
375  _memory_layout(other._memory_layout),
376  _blockspec(other._blockspec),
377  _distspec(other._distspec),
378  _team(other._team),
379  _myid(other._myid),
380  _teamspec(other._teamspec),
381  _nunits(other._nunits),
382  _blocksize(other._blocksize),
383  _nblocks(other._nblocks),
384  _local_size(other._local_size),
385  _local_memory_layout(other._local_memory_layout),
386  _local_capacity(other._local_capacity),
387  _lbegin(other._lbegin),
388  _lend(other._lend)
389  {
390  // No need to copy _arguments as it is just used to
391  // initialize other members.
392  DASH_LOG_TRACE("DynamicPattern(other)", "DynamicPattern copied");
393  }
394 
401  DynamicPattern(self_t & other)
402  : DynamicPattern(static_cast<const self_t &>(other))
403  { }
404 
410  const self_t & other) const
411  {
412  if (this == &other) {
413  return true;
414  }
415  // no need to compare all members as most are derived from
416  // constructor arguments.
417  return(
418  _size == other._size &&
419  _local_sizes == other._local_sizes &&
420  _distspec == other._distspec &&
421  _teamspec == other._teamspec &&
422  _nblocks == other._nblocks &&
423  _blocksize == other._blocksize &&
424  _nunits == other._nunits
425  );
426  }
427 
433  const self_t & other) const
434  {
435  return !(*this == other);
436  }
437 
441  self_t & operator=(const self_t & other) = default;
442 
448  IndexType lbegin() const
449  {
450  return _lbegin;
451  }
452 
458  IndexType lend() const
459  {
460  return _lend;
461  }
462 
466 
470  inline void local_resize(team_unit_t unit, size_type local_size)
471  {
472  _local_sizes[unit] = local_size;
473  }
474 
478  inline void local_resize(size_type local_size)
479  {
480  _local_sizes[_myid] = local_size;
481  }
482 
487  inline void balance()
488  {
489  }
490 
494 
502  const std::array<IndexType, NumDimensions> & coords,
504  const ViewSpec_t & viewspec) const
505  {
506  DASH_LOG_TRACE_VAR("DynamicPattern.unit_at()", coords);
507  // Apply viewspec offsets to coordinates:
508  team_unit_t unit_id(((coords[0] + viewspec.offset(0)) / _blocksize)
509  % _nunits);
510  DASH_LOG_TRACE_VAR("DynamicPattern.unit_at >", unit_id);
511  return unit_id;
512  }
513 
520  const std::array<IndexType, NumDimensions> & g_coords) const
521  {
522  DASH_LOG_TRACE_VAR("DynamicPattern.unit_at()", g_coords);
523  auto g_coord = g_coords[0];
524  for (team_unit_t unit_idx{0}; unit_idx < _nunits - 1; ++unit_idx) {
525  if (_block_offsets[unit_idx+1] >= g_coord) {
526  DASH_LOG_TRACE_VAR("DynamicPattern.unit_at >", unit_idx);
527  return unit_idx;
528  }
529  }
530  DASH_LOG_TRACE_VAR("DynamicPattern.unit_at >", _nunits-1);
531  return _nunits-1;
532  }
533 
541  IndexType global_pos,
543  const ViewSpec_t & viewspec) const
544  {
545  DASH_LOG_TRACE_VAR("DynamicPattern.unit_at()", global_pos);
546  DASH_LOG_TRACE_VAR("DynamicPattern.unit_at()", viewspec);
547  // Apply viewspec offsets to coordinates:
548  auto g_coord = global_pos + viewspec.offset(0);
549  for (team_unit_t unit_idx{0}; unit_idx < _nunits - 1; ++unit_idx) {
550  if (_block_offsets[unit_idx+1] >= static_cast<size_type>(g_coord)) {
551  DASH_LOG_TRACE_VAR("DynamicPattern.unit_at >", unit_idx);
552  return unit_idx;
553  }
554  }
555  DASH_LOG_TRACE_VAR("DynamicPattern.unit_at >", _nunits-1);
556  return _nunits-1;
557  }
558 
566  IndexType g_index) const
567  {
568  DASH_LOG_TRACE_VAR("DynamicPattern.unit_at()", g_index);
569  for (team_unit_t unit_idx{0}; unit_idx < _nunits - 1; ++unit_idx) {
570  if (_block_offsets[unit_idx+1] > static_cast<size_type>(g_index)) {
571  DASH_LOG_TRACE_VAR("DynamicPattern.unit_at >", unit_idx);
572  return unit_idx;
573  }
574  }
575  DASH_LOG_TRACE_VAR("DynamicPattern.unit_at >", _nunits-1);
576  return team_unit_t(_nunits-1);
577  }
578 
582 
592  IndexType extent(dim_t dim) const
593  {
594  DASH_ASSERT_EQ(
595  0, dim,
596  "Wrong dimension for Pattern::local_extent. " <<
597  "Expected dimension = 0, got " << dim);
598  return _size;
599  }
600 
612  IndexType local_extent(dim_t dim) const
613  {
614  DASH_ASSERT_EQ(
615  0, dim,
616  "Wrong dimension for Pattern::local_extent. " <<
617  "Expected dimension = 0, got " << dim);
618  return _local_size;
619  }
620 
632  std::array<SizeType, NumDimensions> local_extents(
633  team_unit_t unit) const
634  {
635  DASH_LOG_DEBUG_VAR("DynamicPattern.local_extents()", unit);
636  DASH_LOG_DEBUG_VAR("DynamicPattern.local_extents >", _local_size);
637  return std::array<SizeType, 1> { _local_size };
638  }
639 
643 
650  IndexType local_at(
652  const std::array<IndexType, NumDimensions> & local_coords,
654  const ViewSpec_t & viewspec) const
655  {
656  return local_coords[0] + viewspec.offset(0);
657  }
658 
664  IndexType local_at(
666  const std::array<IndexType, NumDimensions> & local_coords) const
667  {
668  return local_coords[0];
669  }
670 
679  local_coords_t local(
680  const std::array<IndexType, NumDimensions> & g_coords) const
681  {
682  DASH_LOG_TRACE_VAR("DynamicPattern.local()", g_coords);
683  IndexType g_index = g_coords[0];
684  local_index_t l_index;
685  for (auto unit_idx = _nunits-1; unit_idx >= 0; --unit_idx) {
686  index_type block_offset = _block_offsets[unit_idx];
687  if (block_offset <= g_index) {
688  l_index.unit = unit_idx;
689  l_index.index = g_index - block_offset;
690  DASH_LOG_TRACE_VAR("DynamicPattern.local >", l_index.unit);
691  DASH_LOG_TRACE_VAR("DynamicPattern.local >", l_index.index);
692  return l_index;
693  }
694  }
695  DASH_THROW(
697  "DynamicPattern.local: global coord " << g_index << " is out of bounds");
698  }
699 
707  local_index_t local(
708  IndexType g_index) const
709  {
710  DASH_LOG_TRACE_VAR("DynamicPattern.local()", g_index);
711  DASH_LOG_TRACE_VAR("DynamicPattern.local", _block_offsets.size());
712  DASH_ASSERT_GT(_nunits, 0,
713  "team size is 0");
714  DASH_ASSERT_GE(_block_offsets.size(), _nunits,
715  "missing block offsets");
716  local_index_t l_index;
717  index_type unit_idx = static_cast<index_type>(_nunits-1);
718  for (; unit_idx >= 0; --unit_idx) {
719  DASH_LOG_TRACE_VAR("DynamicPattern.local", unit_idx);
720  index_type block_offset = _block_offsets[unit_idx];
721  DASH_LOG_TRACE_VAR("DynamicPattern.local", block_offset);
722  if (block_offset <= g_index) {
723  l_index.unit = unit_idx;
724  l_index.index = g_index - block_offset;
725  DASH_LOG_TRACE_VAR("DynamicPattern.local >", l_index.unit);
726  DASH_LOG_TRACE_VAR("DynamicPattern.local >", l_index.index);
727  return l_index;
728  }
729  }
730  DASH_THROW(
732  "DynamicPattern.local: global index " << g_index << " is out of bounds");
733  }
734 
741  std::array<IndexType, NumDimensions> local_coords(
742  const std::array<IndexType, NumDimensions> & g_coords) const
743  {
744  DASH_LOG_TRACE_VAR("DynamicPattern.local_coords()", g_coords);
745  IndexType g_index = g_coords[0];
746  index_type unit_idx = static_cast<index_type>(_nunits-1);
747  for (; unit_idx >= 0; --unit_idx) {
748  index_type block_offset = _block_offsets[unit_idx];
749  if (block_offset <= g_index) {
750  auto l_coord = g_index - block_offset;
751  DASH_LOG_TRACE_VAR("DynamicPattern.local_coords >", l_coord);
752  return std::array<IndexType, 1> { l_coord };
753  }
754  }
755  DASH_THROW(
757  "DynamicPattern.local_coords: global index " << g_index <<
758  " is out of bounds");
759  }
760 
767  local_index_t local_index(
768  const std::array<IndexType, NumDimensions> & g_coords) const
769  {
770  IndexType g_index = g_coords[0];
771  DASH_LOG_TRACE_VAR("DynamicPattern.local_index()", g_coords);
772  local_index_t l_index;
773  index_type unit_idx = static_cast<index_type>(_nunits-1);
774  for (; unit_idx >= 0; --unit_idx) {
775  index_type block_offset = _block_offsets[unit_idx];
776  if (block_offset <= g_index) {
777  l_index.unit = unit_idx;
778  l_index.index = g_index - block_offset;
779  DASH_LOG_TRACE_VAR("DynamicPattern.local >", l_index.unit);
780  DASH_LOG_TRACE_VAR("DynamicPattern.local >", l_index.index);
781  return l_index;
782  }
783  }
784  DASH_THROW(
786  "DynamicPattern.local: global index " << g_index << " is out of bounds");
787  }
788 
792 
798  std::array<IndexType, NumDimensions> global(
799  team_unit_t unit,
800  const std::array<IndexType, NumDimensions> & local_coords) const
801  {
802  DASH_LOG_DEBUG_VAR("DynamicPattern.global()", unit);
803  DASH_LOG_DEBUG_VAR("DynamicPattern.global()", local_coords);
804  DASH_LOG_TRACE_VAR("DynamicPattern.global", _nunits);
805  if (_nunits < 2) {
806  return local_coords;
807  }
808  // Initialize global index with element phase (= local coords):
809  index_type glob_index = _block_offsets[unit] + local_coords[0];
810  DASH_LOG_TRACE_VAR("DynamicPattern.global >", glob_index);
811  return std::array<IndexType, 1> { glob_index };
812  }
813 
819  std::array<IndexType, NumDimensions> global(
820  const std::array<IndexType, NumDimensions> & l_coords) const
821  {
822  return global(_team->myid(), l_coords);
823  }
824 
833  IndexType global(
834  team_unit_t unit,
835  IndexType l_index) const
836  {
837  return global(unit, std::array<IndexType, 1> { l_index })[0];
838  }
839 
848  IndexType global(
849  IndexType l_index) const
850  {
851  return global(_team->myid(), std::array<IndexType, 1> { l_index })[0];
852  }
853 
862  IndexType global_index(
863  team_unit_t unit,
864  const std::array<IndexType, NumDimensions> & l_coords) const
865  {
866  auto g_index = global(unit, l_coords[0]);
867  return g_index;
868  }
869 
873 
882  IndexType at(
883  const std::array<IndexType, NumDimensions> & g_coords) const
884  {
885  return local_coords(g_coords)[0];
886  }
887 
895  IndexType at(
896  const std::array<IndexType, NumDimensions> & g_coords,
897  const ViewSpec_t & viewspec) const
898  {
899  auto vs_coords = g_coords;
900  vs_coords[0] += viewspec.offset(0);
901  return local_coords(vs_coords)[0];
902  }
903 
911  template<typename ... Values>
912  IndexType at(IndexType value, Values ... values) const
913  {
914  static_assert(
915  sizeof...(values) == NumDimensions-1,
916  "Wrong parameter number");
917  std::array<IndexType, NumDimensions> inputindex = {
918  value, (IndexType)values...
919  };
920  return at(inputindex);
921  }
922 
926 
935  dim_t dim,
937  IndexType dim_offset,
939  team_unit_t unit,
941  const ViewSpec_t & viewspec) const
942  {
943  DASH_ASSERT_EQ(
944  0, dim,
945  "Wrong dimension for Pattern::has_local_elements. " <<
946  "Expected dimension = 0, got " << dim);
947  DASH_LOG_TRACE_VAR("DynamicPattern.has_local_elements()", dim_offset);
948  DASH_LOG_TRACE_VAR("DynamicPattern.has_local_elements()", unit);
949  DASH_LOG_TRACE_VAR("DynamicPattern.has_local_elements()", viewspec);
950  DASH_THROW(
952  "DynamicPattern.has_local_elements is not implemented");
953  }
954 
960  inline bool is_local(
961  IndexType index,
962  team_unit_t unit) const
963  {
964  DASH_LOG_TRACE_VAR("DynamicPattern.is_local()", index);
965  DASH_LOG_TRACE_VAR("DynamicPattern.is_local()", unit);
966  bool is_loc = index >= _block_offsets[unit] &&
967  (unit == _nunits-1 ||
968  index < _block_offsets[unit+1]);
969  DASH_LOG_TRACE_VAR("DynamicPattern.is_local >", is_loc);
970  return is_loc;
971  }
972 
979  inline bool is_local(
980  IndexType index) const
981  {
982  auto unit = team().myid();
983  DASH_LOG_TRACE_VAR("DynamicPattern.is_local()", index);
984  DASH_LOG_TRACE_VAR("DynamicPattern.is_local", unit);
985  bool is_loc = index >= _block_offsets[unit] &&
986  (unit == _nunits-1 ||
987  index < _block_offsets[unit+1]);
988  DASH_LOG_TRACE_VAR("DynamicPattern.is_local >", is_loc);
989  return is_loc;
990  }
991 
995 
999  const BlockSpec_t & blockspec() const
1000  {
1001  return _blockspec;
1002  }
1003 
1009  index_type block_at(
1011  const std::array<index_type, NumDimensions> & g_coords) const
1012  {
1013  DASH_LOG_TRACE_VAR("DynamicPattern.block_at()", g_coords);
1014  auto g_coord = g_coords[0];
1015  for (index_type block_idx = 0; block_idx < _nunits - 1; ++block_idx) {
1016  if (_block_offsets[block_idx+1] >= g_coord) {
1017  DASH_LOG_TRACE_VAR("DynamicPattern.block_at >", block_idx);
1018  return block_idx;
1019  }
1020  }
1021  DASH_LOG_TRACE_VAR("DynamicPattern.block_at >", _nunits-1);
1022  return _nunits-1;
1023  }
1024 
1029  ViewSpec_t block(
1030  index_type g_block_index) const
1031  {
1032  DASH_LOG_DEBUG_VAR("DynamicPattern<1>.block >", g_block_index);
1033  index_type offset = _block_offsets[g_block_index];
1034  auto block_size = _local_sizes[g_block_index];
1035  std::array<index_type, NumDimensions> offsets = { offset };
1036  std::array<size_type, NumDimensions> extents = { block_size };
1037  ViewSpec_t block_vs(offsets, extents);
1038  DASH_LOG_DEBUG_VAR("DynamicPattern<1>.block >", block_vs);
1039  return block_vs;
1040  }
1041 
1046  ViewSpec_t local_block(
1047  index_type l_block_index) const
1048  {
1049  DASH_LOG_DEBUG_VAR("DynamicPattern<1>.local_block()", l_block_index);
1050  DASH_ASSERT_EQ(
1051  0, l_block_index,
1052  "DynamicPattern always assigns exactly 1 block to a single unit");
1053  index_type block_offset = _block_offsets[_team->myid()];
1054  size_type block_size = _local_sizes[_team->myid()];
1055  std::array<index_type, NumDimensions> offsets = { block_offset };
1056  std::array<size_type, NumDimensions> extents = { block_size };
1057  ViewSpec_t block_vs(offsets, extents);
1058  DASH_LOG_DEBUG_VAR("DynamicPattern<1>.local_block >", block_vs);
1059  return block_vs;
1060  }
1061 
1066  ViewSpec_t local_block_local(
1067  index_type l_block_index) const
1068  {
1069  DASH_LOG_DEBUG_VAR("DynamicPattern<1>.local_block_local >", l_block_index);
1070  size_type block_size = _local_sizes[_team->myid()];
1071  std::array<index_type, NumDimensions> offsets = { 0 };
1072  std::array<size_type, NumDimensions> extents = { block_size };
1073  ViewSpec_t block_vs(offsets, extents);
1074  DASH_LOG_DEBUG_VAR("DynamicPattern<1>.local_block_local >", block_vs);
1075  return block_vs;
1076  }
1077 
1085  SizeType blocksize(
1087  dim_t dimension) const
1088  {
1089  return _blocksize;
1090  }
1091 
1100  SizeType max_blocksize() const
1101  {
1102  return _blocksize;
1103  }
1104 
1111  inline SizeType local_capacity(
1112  team_unit_t unit = UNDEFINED_TEAM_UNIT_ID) const
1113  {
1114  return _local_capacity;
1115  }
1116 
1127  inline SizeType local_size(
1128  team_unit_t unit = UNDEFINED_TEAM_UNIT_ID) const
1129  {
1130  return _local_size;
1131  }
1132 
1138  inline IndexType num_units() const
1139  {
1140  return _nunits;
1141  }
1142 
1148  inline IndexType capacity() const
1149  {
1150  return _size;
1151  }
1152 
1158  inline IndexType size() const
1159  {
1160  return _size;
1161  }
1162 
1167  inline dash::Team & team() const
1168  {
1169  return *_team;
1170  }
1171 
1175  const DistributionSpec_t & distspec() const
1176  {
1177  return _distspec;
1178  }
1179 
1185  SizeSpec_t sizespec() const
1186  {
1187  return SizeSpec_t(std::array<SizeType, 1> { _size });
1188  }
1189 
1195  const std::array<SizeType, NumDimensions> & extents() const
1196  {
1197  return std::array<SizeType, 1> { _size };
1198  }
1199 
1206  const TeamSpec_t & teamspec() const
1207  {
1208  return _teamspec;
1209  }
1210 
1217  std::array<IndexType, NumDimensions> coords(
1218  IndexType index) const
1219  {
1220  return std::array<IndexType, 1> { index };
1221  }
1222 
1229  std::array<IndexType, NumDimensions> coords(
1230  IndexType index,
1231  const ViewSpec_t & viewspec) const
1232  {
1233  return std::array<IndexType, 1> { index + viewspec.offset(0) };
1234  }
1235 
1236 
1240  constexpr static MemArrange memory_order()
1241  {
1242  return Arrangement;
1243  }
1244 
1248  constexpr static dim_t ndim()
1249  {
1250  return 1;
1251  }
1252 
1253 private:
1254 
1255 
1256  DynamicPattern(const PatternArguments_t & arguments)
1257  : DynamicPattern(
1258  initialize_local_sizes(
1259  arguments.sizespec().size(),
1260  arguments.distspec(),
1261  arguments.team()),
1262  arguments)
1263  {}
1264 
1265  DynamicPattern(
1266  const std::vector<size_type> & local_sizes,
1267  const PatternArguments_t & arguments)
1268  : _size(arguments.sizespec().size()),
1269  _local_sizes(local_sizes),
1270  _block_offsets(initialize_block_offsets(
1271  _local_sizes)),
1272  _memory_layout(std::array<SizeType, 1> { _size }),
1273  _blockspec(initialize_blockspec(
1274  _size,
1275  _local_sizes)),
1276  _distspec(arguments.distspec()),
1277  _team(&arguments.team()),
1278  _myid(_team->myid()),
1279  _teamspec(arguments.teamspec()),
1280  _nunits(_team->size()),
1281  _blocksize(initialize_blocksize(
1282  _size,
1283  _distspec,
1284  _nunits)),
1285  _nblocks(_nunits),
1286  _local_size(
1287  initialize_local_extent(_team->myid())),
1288  _local_memory_layout(std::array<SizeType, 1> { _local_size }),
1289  _local_capacity(initialize_local_capacity())
1290  {}
1291 
1295  SizeType initialize_size(
1296  const std::vector<size_type> & local_sizes) const
1297  {
1298  DASH_LOG_TRACE_VAR("DynamicPattern.init_size()", local_sizes);
1299  size_type size = 0;
1300  for (size_type unit_idx = 0; unit_idx < local_sizes.size(); ++unit_idx) {
1301  size += local_sizes[unit_idx];
1302  }
1303  DASH_LOG_TRACE_VAR("DynamicPattern.init_size >", size);
1304  return size;
1305  }
1306 
1311  std::vector<size_type> initialize_local_sizes(
1312  size_type total_size,
1313  const DistributionSpec_t & distspec,
1314  const dash::Team & team) const
1315  {
1316  DASH_LOG_TRACE_VAR("DynamicPattern.init_local_sizes()", total_size);
1317  std::vector<size_type> l_sizes;
1318  auto nunits = team.size();
1319  DASH_LOG_TRACE_VAR("DynamicPattern.init_local_sizes()", nunits);
1320  if (nunits < 1) {
1321  return l_sizes;
1322  }
1323  auto dist_type = distspec[0].type;
1324  DASH_LOG_TRACE_VAR("DynamicPattern.init_local_sizes()", dist_type);
1325  // Tiled and blocked distribution:
1326  if (dist_type == dash::internal::DIST_BLOCKED ||
1327  dist_type == dash::internal::DIST_TILE) {
1328  auto blocksize = dash::math::div_ceil(total_size, nunits);
1329  for (size_type u = 0; u < nunits; ++u) {
1330  l_sizes.push_back(blocksize);
1331  }
1332  // Unspecified distribution (default-constructed pattern instance),
1333  // set all local sizes to 0:
1334  } else if (dist_type == dash::internal::DIST_UNDEFINED) {
1335  for (size_type u = 0; u < nunits; ++u) {
1336  l_sizes.push_back(0);
1337  }
1338  // No distribution, assign all indices to unit 0:
1339  } else if (dist_type == dash::internal::DIST_NONE) {
1340  l_sizes.push_back(total_size);
1341  for (size_type u = 0; u < nunits-1; ++u) {
1342  l_sizes.push_back(0);
1343  }
1344  // Incompatible distribution type:
1345  } else {
1346  DASH_THROW(
1348  "DynamicPattern expects TILE (" << dash::internal::DIST_TILE << ") " <<
1349  "or BLOCKED (" << dash::internal::DIST_BLOCKED << ") " <<
1350  "distribution, got " << dist_type);
1351  }
1352  DASH_LOG_TRACE_VAR("DynamicPattern.init_local_sizes >", l_sizes);
1353  return l_sizes;
1354  }
1355 
1356  BlockSpec_t initialize_blockspec(
1357  size_type size,
1358  const std::vector<size_type> & local_sizes) const
1359  {
1360  DASH_LOG_TRACE_VAR("DynamicPattern.init_blockspec", local_sizes);
1361  BlockSpec_t blockspec({
1362  static_cast<size_type>(local_sizes.size())
1363  });
1364  DASH_LOG_TRACE_VAR("DynamicPattern.init_blockspec >", blockspec);
1365  return blockspec;
1366  }
1367 
1372  std::vector<size_type> initialize_block_offsets(
1373  const std::vector<size_type> & local_sizes) const
1374  {
1375  DASH_LOG_TRACE_VAR("DynamicPattern.init_block_offsets", local_sizes);
1376  std::vector<size_type> block_offsets;
1377  if (local_sizes.size() > 0) {
1378  // NOTE: Assuming 1 block for every unit.
1379  block_offsets.push_back(0);
1380  for (size_type unit_idx = 0;
1381  unit_idx < local_sizes.size()-1;
1382  ++unit_idx)
1383  {
1384  auto block_offset = block_offsets[unit_idx] +
1385  local_sizes[unit_idx];
1386  block_offsets.push_back(block_offset);
1387  }
1388  }
1389  DASH_LOG_TRACE_VAR("DynamicPattern.init_block_offsets >", block_offsets);
1390  return block_offsets;
1391  }
1392 
1397  SizeType initialize_blocksize(
1398  SizeType size,
1399  const DistributionSpec_t & distspec,
1400  SizeType nunits) const
1401  {
1402  DASH_LOG_TRACE_VAR("DynamicPattern.init_blocksize", nunits);
1403  if (nunits == 0) {
1404  return 0;
1405  }
1406  // NOTE: Assuming 1 block for every unit.
1407  return 1;
1408  }
1409 
1413  SizeType initialize_num_local_blocks(
1414  SizeType num_blocks,
1415  SizeType blocksize,
1416  const DistributionSpec_t & distspec,
1417  SizeType nunits,
1418  SizeType local_size) const
1419  {
1420  auto num_l_blocks = local_size;
1421  if (blocksize > 0) {
1422  num_l_blocks = dash::math::div_ceil(
1423  num_l_blocks,
1424  blocksize);
1425  } else {
1426  num_l_blocks = 0;
1427  }
1428  DASH_LOG_TRACE_VAR("DynamicPattern.init_num_local_blocks", num_l_blocks);
1429  return num_l_blocks;
1430  }
1431 
1435  SizeType initialize_local_capacity() const
1436  {
1437  SizeType l_capacity = 0;
1438  if (_nunits == 0) {
1439  return 0;
1440  }
1441  DASH_LOG_TRACE_VAR("DynamicPattern.init_lcapacity", _nunits);
1442  // Local capacity is maximum number of elements assigned to a single unit,
1443  // i.e. the maximum local size:
1444  l_capacity = *(std::max_element(_local_sizes.begin(),
1445  _local_sizes.end()));
1446  DASH_LOG_DEBUG_VAR("DynamicPattern.init_lcapacity >", l_capacity);
1447  return l_capacity;
1448  }
1449 
1454  void initialize_local_range()
1455  {
1456  auto l_size = _local_size;
1457  DASH_LOG_DEBUG_VAR("DynamicPattern.init_local_range()", l_size);
1458  if (l_size == 0) {
1459  _lbegin = 0;
1460  _lend = 0;
1461  } else {
1462  // First local index transformed to global index
1463  _lbegin = global(0);
1464  // Index past last local index transformed to global index.
1465  // global(l_size) would be out of range, so we use the global index
1466  // to the last element and increment by 1:
1467  _lend = global(l_size - 1) + 1;
1468  }
1469  DASH_LOG_DEBUG_VAR("DynamicPattern.init_local_range >", _lbegin);
1470  DASH_LOG_DEBUG_VAR("DynamicPattern.init_local_range >", _lend);
1471  }
1472 
1476  SizeType initialize_local_extent(
1477  team_unit_t unit) const
1478  {
1479  DASH_LOG_DEBUG_VAR("DynamicPattern.init_local_extent()", unit);
1480  DASH_LOG_DEBUG_VAR("DynamicPattern.init_local_extent()", _nunits);
1481  if (_nunits == 0) {
1482  return 0;
1483  }
1484  // Local size of given unit:
1485  SizeType l_extent = _local_sizes[static_cast<int>(unit)];
1486  DASH_LOG_DEBUG_VAR("DynamicPattern.init_local_extent >", l_extent);
1487  return l_extent;
1488  }
1489 
1490 private:
1492  SizeType _size;
1494  std::vector<size_type> _local_sizes;
1496  std::vector<size_type> _block_offsets;
1498  MemoryLayout_t _memory_layout;
1500  BlockSpec_t _blockspec;
1503  DistributionSpec_t _distspec;
1505  dash::Team * _team = nullptr;
1507  team_unit_t _myid;
1509  TeamSpec_t _teamspec;
1511  SizeType _nunits = 0;
1513  SizeType _blocksize = 0;
1515  SizeType _nblocks = 0;
1517  SizeType _local_size;
1519  LocalMemoryLayout_t _local_memory_layout;
1521  SizeType _local_capacity;
1523  IndexType _lbegin;
1525  IndexType _lend;
1526 
1527 }; // class DynamicPattern<1>
1528 
1529 } // namespace dash
1530 
1531 #endif // DASH__DYNAMIC_PATTERN_H__INCLUDED
constexpr team_unit_t UNDEFINED_TEAM_UNIT_ID
Invalid local unit ID.
Definition: Types.h:341
const BlockSpec_t & blockspec() const
block
All blocks have identical size.
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.
IndexType global_index(team_unit_t unit, const std::array< IndexType, NumDimensions > &l_coords) const
Resolve an element&#39;s linear global index from a given unit&#39;s local coordinates of that element...
DynamicPattern(const SizeSpec_t &sizespec, const DistributionSpec_t &distspec, Team &team=dash::Team::All())
Constructor, initializes a pattern from explicit instances of SizeSpec, DistributionSpec and Team...
This class is a simple memory pool which holds allocates elements of size ValueType.
Definition: AllOf.h:8
Local element order corresponds to a logical linearization within single blocks (if blocked) or withi...
std::array< IndexType, NumDimensions > global(const std::array< IndexType, NumDimensions > &l_coords) const
Converts local coordinates of active unit to global coordinates.
Specifies cartesian extents in a specific number of dimensions.
Definition: Cartesian.h:197
IndexType at(const std::array< IndexType, NumDimensions > &g_coords, const ViewSpec_t &viewspec) const
Global coordinates and viewspec to local index.
const std::array< SizeType, NumDimensions > & extents() const
Size specification of the index space mapped by this pattern.
Specifies view parameters for implementing submat, rows and cols.
Definition: Dimensional.h:430
SizeType local_size(team_unit_t unit=UNDEFINED_TEAM_UNIT_ID) const
The actual number of elements in this pattern that are local to the calling unit in total...
DynamicPattern(const std::vector< size_type > &local_sizes, const TeamSpec_t &teamspec, dash::Team &team=dash::Team::All())
Constructor, initializes a pattern from explicit instances of SizeSpec, DistributionSpec, TeamSpec and a Team.
int dim_t
Scalar type for a dimension value, with 0 indicating the first dimension.
Definition: Types.h:39
IndexType local_extent(dim_t dim) const
The actual number of elements in this pattern that are local to the calling unit in the given dimensi...
SizeSpec_t sizespec() const
Size specification of the index space mapped by this pattern.
pattern_partitioning_properties< pattern_partitioning_tag::minimal, pattern_partitioning_tag::rectangular, pattern_partitioning_tag::balanced, pattern_partitioning_tag::unbalanced, pattern_partitioning_tag::dynamic > partitioning_properties
Satisfiable properties in pattern property category Partitioning:
team_unit_t unit_at(const std::array< IndexType, NumDimensions > &coords, const ViewSpec_t &viewspec) const
unit_at
IndexType extent(dim_t dim) const
extent
const DistributionSpec_t & distspec() const
Distribution specification of this pattern.
IndexType lbegin() const
Resolves the global index of the first local element in the pattern.
pattern_mapping_properties< pattern_mapping_tag::unbalanced > mapping_properties
Satisfiable properties in pattern property category Mapping:
ViewSpec_t block(index_type g_block_index) const
View spec (offset and extents) of block at global linear block index in cartesian element space...
The number of blocks assigned to units may differ.
local_index_t local(IndexType g_index) const
Converts global index to its associated unit and respective local index.
void balance()
Balance the number of local elements across all units in the pattern&#39;s associated team...
static constexpr dim_t ndim()
Number of dimensions of the cartesian space partitioned by the pattern.
SizeType local_capacity(team_unit_t unit=UNDEFINED_TEAM_UNIT_ID) const
Maximum number of elements assigned to a single unit in total, equivalent to the local capacity of ev...
bool operator==(const self_t &other) const
Equality comparison operator.
Minimal number of blocks in every dimension, typically at most one block per unit.
Block extents are constant for every dimension.
constexpr std::enable_if< dash::view_traits< ViewType >::is_view::value &&dash::view_traits< ViewType >::is_local::value, const typename ViewType::global_type & >::type global(const ViewType &v)
Definition: Global.h:19
size_t size() const
The number of units in this team.
Definition: Team.h:498
index_type block_at(const std::array< index_type, NumDimensions > &g_coords) const
Index of block at given global coordinates.
Cartesian space defined by extents in n dimensions.
Definition: Cartesian.h:26
IndexType at(const std::array< IndexType, NumDimensions > &g_coords) const
at
internal::default_signed_index default_index_t
Signed integer type used as default for index values.
Definition: Types.h:59
dash::Team & team() const
The Team containing the units to which this pattern&#39;s elements are mapped.
std::array< IndexType, NumDimensions > global(team_unit_t unit, const std::array< IndexType, NumDimensions > &local_coords) const
global
A Team instance specifies a subset of all available units.
Definition: Team.h:41
std::array< IndexType, NumDimensions > coords(IndexType index, const ViewSpec_t &viewspec) const
Convert given global linear offset (index) to global cartesian coordinates using viewspec.
Elements are contiguous in local memory within a single block and thus indexed blockwise.
DynamicPattern(const self_t &other)
Copy constructor.
DynamicPattern(const SizeSpec_t &sizespec, const DistributionSpec_t &distspec, const TeamSpec_t &teamspec, Team &team=dash::Team::All())
Constructor, initializes a pattern from explicit instances of SizeSpec, DistributionSpec, TeamSpec and Team.
Defines a cartesian, totally-ordered index space by mapping linear indices to cartesian coordinates d...
Definition: Cartesian.h:239
Data range is partitioned dynamically.
IndexType global(team_unit_t unit, IndexType l_index) const
Resolve an element&#39;s linear global index from the given unit&#39;s local index of that element...
bool operator!=(const self_t &other) const
Inquality comparison operator.
SizeType blocksize(dim_t dimension) const
Maximum number of elements in a single block in the given dimension.
DynamicPattern(const std::vector< size_type > &local_sizes, Team &team=dash::Team::All())
Constructor, initializes a pattern from explicit instances of SizeSpec, DistributionSpec, TeamSpec and a Team.
IndexType local_at(const std::array< IndexType, NumDimensions > &local_coords, const ViewSpec_t &viewspec) const
local
IndexType at(IndexType value, Values ... values) const
Global coordinates to local index.
DynamicPattern(SizeType arg, Args &&... args)
Constructor, initializes a pattern from an argument list consisting of the pattern size (extent...
pattern_layout_properties< pattern_layout_tag::blocked, pattern_layout_tag::linear > layout_properties
Satisfiable properties in pattern property category Layout:
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
local_coords_t local(const std::array< IndexType, NumDimensions > &g_coords) const
Converts global coordinates to their associated unit and its respective local coordinates.
std::array< SizeType, NumDimensions > local_extents(team_unit_t unit) const
The actual number of elements in this pattern that are local to the given unit, by dimension...
ViewSpec_t local_block(index_type l_block_index) const
View spec (offset and extents) of block at local linear block index in global cartesian element space...
IndexType local_at(const std::array< IndexType, NumDimensions > &local_coords) const
Convert given local coordinates to linear local offset (index).
bool has_local_elements(dim_t dim, IndexType dim_offset, team_unit_t unit, const ViewSpec_t &viewspec) const
is_local
bool is_local(IndexType index, team_unit_t unit) const
Whether the given global index is local to the specified unit.
GlobIter max_element(const GlobIter &first, const GlobIter &last, Compare compare=Compare())
Finds an iterator pointing to the element with the greatest value in the range [first,last).
Definition: MinMax.h:332
void local_resize(team_unit_t unit, size_type local_size)
resize / balance
static constexpr MemArrange memory_order()
Memory order followed by the pattern.
SizeType max_blocksize() const
Maximum number of elements in a single block in all dimensions.
std::array< IndexType, NumDimensions > local_coords(const std::array< IndexType, NumDimensions > &g_coords) const
Converts global coordinates to their associated unit&#39;s respective local coordinates.
DynamicPattern(const std::vector< size_type > &local_sizes, SizeType arg, Args &&... args)
Constructor, initializes a pattern from an argument list consisting of the pattern size (extent...
std::array< IndexType, NumDimensions > coords(IndexType index) const
Convert given global linear offset (index) to global cartesian coordinates.
ViewSpec_t local_block_local(index_type l_block_index) const
View spec (offset and extents) of block at local linear block index in local cartesian element space...
team_unit_t unit_at(const std::array< IndexType, NumDimensions > &g_coords) const
Convert given coordinate in pattern to its assigned unit id.
team_unit_t unit_at(IndexType global_pos, const ViewSpec_t &viewspec) const
Convert given global linear index to its assigned unit id.
IndexType global(IndexType l_index) const
Resolve an element&#39;s linear global index from the calling unit&#39;s local index of that element...
team_unit_t unit_at(IndexType g_index) const
Convert given global linear index to its assigned unit id.
static Team & All()
The invariant Team instance containing all available units.
Definition: Team.h:213
see https://en.cppreference.com/w/cpp/feature_test for recommended feature tests
Definition: cstddef.h:8
IndexType lend() const
Resolves the global index past the last local element in the pattern.
IndexType capacity() const
The maximum number of elements arranged in this pattern.
DynamicPattern(self_t &other)
Copy constructor using non-const lvalue reference parameter.
IndexType size() const
The number of elements arranged in this pattern.
local_index_t local_index(const std::array< IndexType, NumDimensions > &g_coords) const
Converts global coordinates to their associated unit and their respective local index.
IndexType num_units() const
The number of units to which this pattern&#39;s elements are mapped.
const TeamSpec_t & teamspec() const
Cartesian arrangement of the Team containing the units to which this pattern&#39;s elements are mapped...
DistributionSpec describes distribution patterns of all dimensions,.
Definition: Dimensional.h:222
void local_resize(size_type local_size)
Update the number of local elements of the active unit.
Generic type of mapping properties of a model satisfying the Pattern concept.
bool is_local(IndexType index) const
Whether the given global index is local to the unit that created this pattern instance.