DASH  0.3.0
Halo.h
1 #ifndef DASH__HALO__HALO_H__
2 #define DASH__HALO__HALO_H__
3 
4 #include <dash/internal/Logging.h>
5 
6 
7 #include <dash/halo/Types.h>
8 #include <dash/halo/Region.h>
9 #include <dash/halo/Stencil.h>
10 
11 #include <functional>
12 
13 namespace dash {
14 
15 namespace halo {
16 
17 using namespace internal;
18 
22 template <dim_t NumDimensions>
23 class GlobalBoundarySpec : public Dimensional<BoundaryProp, NumDimensions> {
24 private:
26 
27 public:
28  // TODO constexpr
35  for(dim_t i = 0; i < NumDimensions; ++i) {
36  this->_values[i] = BoundaryProp::NONE;
37  }
38  }
42  template <typename... Values>
43  constexpr GlobalBoundarySpec(BoundaryProp value, Values... values)
44  : Base_t::Dimensional(value, values...) {}
45 }; // GlobalBoundarySpec
46 
47 template <dim_t NumDimensions>
48 std::ostream& operator<<(std::ostream& os,
50  os << "dash::halo::GlobalBoundarySpec<" << NumDimensions << ">"
51  << "(";
52  for(auto d = 0; d < NumDimensions; ++d) {
53  if(d > 0) {
54  os << ",";
55  }
56  os << spec[d];
57  }
58  os << ")";
59 
60  return os;
61 }
62 
63 
64 
69 template <dim_t NumDimensions>
70 class HaloSpec {
71 private:
74  static constexpr auto RegionsMax = NumRegionsMax<NumDimensions>;
75 
76 public:
78  using Specs_t = std::array<RegionSpec_t, RegionsMax>;
79  using region_extent_t = typename RegionSpec_t::region_extent_t;
80  using HaloExtsMaxPair_t = std::pair<region_extent_t, region_extent_t>;
81  using HaloExtsMax_t = std::array<HaloExtsMaxPair_t, NumDimensions>;
82 
83 public:
84  constexpr HaloSpec(const Specs_t& specs) : _specs(specs) {}
85 
86  template <typename StencilSpecT>
87  HaloSpec(const StencilSpecT& stencil_spec) {
88  init_region_specs();
89  read_stencil_points(stencil_spec);
90  }
91 
92  template <typename StencilSpecT, typename... Args>
93  HaloSpec(const StencilSpecT& stencil_spec, const Args&... stencil_specs)
94  : HaloSpec(stencil_specs...) {
95  read_stencil_points(stencil_spec);
96  }
97 
98  template <typename... ARGS>
99  HaloSpec(const RegionSpec_t& region_spec, const ARGS&... args) {
100  init_region_specs();
101  std::array<RegionSpec_t, sizeof...(ARGS) + 1> tmp{ region_spec, args... };
102  for(auto& spec : tmp) {
103  auto& current_spec = _specs[spec.index()];
104  if(current_spec.extent() == 0 && spec.extent() > 0) {
105  ++_num_regions;
106  }
107 
108  if(current_spec.extent() < spec.extent()) {
109  current_spec = spec;
110  set_max_halo_dist(current_spec.coords(), current_spec.extent());
111  }
112  }
113  }
114 
115  HaloSpec(const Self_t& other) { _specs = other._specs; }
116 
117  static constexpr dim_t ndim() { return NumDimensions; }
118 
122  constexpr RegionSpec_t spec(const region_index_t index) const {
123  return _specs[index];
124  }
125 
129  constexpr region_extent_t extent(const region_index_t index) const {
130  return _specs[index].extent();
131  }
132 
136  constexpr region_size_t num_regions() const { return _num_regions; }
137 
141  const Specs_t& specs() const { return _specs; }
142 
146  const HaloExtsMaxPair_t& halo_extension_max(dim_t dim) const {
147  return _halo_extents_max[dim];
148  }
149 
153  const HaloExtsMax_t& halo_extension_max() const { return _halo_extents_max; }
154 
155 private:
156  void init_region_specs() {
157  for(region_index_t r = 0; r < RegionsMax; ++r) {
158  _specs[r] = RegionSpec_t(r, 0);
159  }
160  }
161 
162  /*
163  * Reads all stencil points of the given stencil spec and sets the region
164  * specification.
165  */
166  template <typename StencilSpecT>
167  void read_stencil_points(const StencilSpecT& stencil_spec) {
168  for(const auto& stencil : stencil_spec.specs()) {
169  auto stencil_combination = stencil;
170 
171  set_region_spec(stencil_combination);
172  while(next_region(stencil, stencil_combination)) {
173  set_region_spec(stencil_combination);
174  }
175  }
176  }
177 
178  /*
179  * Sets the region extent dependent on the given stencil point
180  */
181  template <typename StencilPointT>
182  void set_region_spec(const StencilPointT& stencil) {
183  auto index = RegionSpec_t::index(stencil);
184 
185  auto max = stencil.max();
186  auto reg_extent = _specs[index].extent();
187  if(reg_extent == 0 && max > 0) {
188  ++_num_regions;
189  }
190 
191  if(max > reg_extent) {
192  _specs[index] = RegionSpec_t(index, max);
193  set_max_halo_dist(_specs[index].coords(), max);
194  }
195  }
196 
197  /*
198  * Makes sure, that all necessary regions are covered for a stencil point.
199  * E.g. 2-D stencil point (-1,-1) needs not only region 0, it needs also
200  * region 1 when the stencil is shifted to the right.
201  */
202  template <typename StencilPointT>
203  bool next_region(const StencilPointT& stencil,
204  StencilPointT& stencil_combination) {
205  for(dim_t d = 0; d < NumDimensions; ++d) {
206  if(stencil[d] == 0)
207  continue;
208  stencil_combination[d] = (stencil_combination[d] == 0) ? stencil[d] : 0;
209  if(stencil_combination[d] == 0) {
210  return true;
211  }
212  }
213 
214  return false;
215  }
216 
217  void set_max_halo_dist(RegionCoords_t reg_coords, region_extent_t extent) {
218  for(dim_t d = 0; d < NumDimensions; ++d) {
219  if(reg_coords[d] == 1) {
220  continue;
221  }
222 
223  if(reg_coords[d] < 1) {
224  _halo_extents_max[d].first = std::max(_halo_extents_max[d].first, extent);
225  continue;
226  }
227  _halo_extents_max[d].second = std::max(_halo_extents_max[d].second, extent);
228  }
229  }
230 
231 private:
232  Specs_t _specs{};
233  HaloExtsMax_t _halo_extents_max{};
234  region_size_t _num_regions{ 0 };
235 }; // HaloSpec
236 
237 
238 template <dim_t NumDimensions>
239 std::ostream& operator<<(std::ostream& os, const HaloSpec<NumDimensions>& hs) {
240  os << "dash::halo::HaloSpec<" << NumDimensions << ">(";
241  bool begin = true;
242  for(const auto& region_spec : hs.specs()) {
243  if(region_spec.extent() > 0) {
244  if(begin) {
245  os << region_spec;
246  begin = false;
247  } else {
248  os << "," << region_spec;
249  }
250  }
251  }
252  os << "; number region: " << hs.num_regions();
253  os << ")";
254 
255  return os;
256 }
257 
258 template<typename ViewSpecT>
260  static constexpr auto NumDimensions = ViewSpecT::ndim();
261  static constexpr auto CenterIndex = RegionCoords<NumDimensions>::center_index();
262 public:
264  using EnvRegInfo_t = EnvironmentRegionInfo<ViewSpecT>;
265  using RegionBorders_t = typename EnvRegInfo_t::RegionBorders_t;
266  using RegionData_t = typename EnvRegInfo_t::RegionData_t;
268  using MaxDistPair_t = std::pair<region_extent_t, region_extent_t>;
269  using MaxDist_t = std::array<MaxDistPair_t, NumDimensions>;
270  using BlockViewSpec_t = BlockViewSpec<ViewSpecT>;
271 
272 
273 public:
274  BoundaryRegionCheck(const ViewSpecT& view, const MaxDist_t& max_dist, const GlobalBndSpec_t& glob_bnd_spec, const RegionBorders_t& borders)
275  : _view(&view), _max_dist(max_dist) {
276  std::array<BS, NumDimensions> to_small;
277 
278  const auto& view_extents = _view->extents();
279 
280  for(dim_t d = 0; d < NumDimensions; ++d) {
281  auto minmax_dim = max_dist[d];
282  auto dist = minmax_dim.first + minmax_dim.second;
283 
284  to_small[d] = BS::BIGGER;
285  if(view_extents[d] <= dist) {
286  to_small[d] = (view_extents[d] > minmax_dim.first) ? BS::EQUALS_LESS : BS::PRE_ONLY;
287  }
288  }
289 
290  for(int d = 0; d < NumDimensions; ++d) {
291  bool test_small = false;
292  for(int d_tmp = 0; d_tmp < d; ++d_tmp) {
293  if(to_small[d_tmp] != BS::BIGGER) {
294  test_small = true;
295  break;
296  }
297  }
298 
299  if(test_small) {
300  if(borders[d].first && glob_bnd_spec[d] == BoundaryProp::NONE) {
301  _valid_main[d].first = {false, REASON::BORDER};
302  } else {
303  _valid_main[d].first = {false, REASON::TO_SMALL};
304  }
305 
306  if(borders[d].second && glob_bnd_spec[d] == BoundaryProp::NONE) {
307  _valid_main[d].second = {false, REASON::BORDER};
308  } else {
309  _valid_main[d].second = {false, REASON::TO_SMALL};
310  }
311  continue;
312  }
313  if(borders[d].first && glob_bnd_spec[d] == BoundaryProp::NONE) {
314  _valid_main[d].first = {false, REASON::BORDER};
315  } else {
316  _valid_main[d].first = {true, REASON::NONE};
317  }
318 
319  if(borders[d].second && glob_bnd_spec[d] == BoundaryProp::NONE) {
320  _valid_main[d].second = {false, REASON::BORDER};
321  } else {
322  if(_valid_main[d].first.valid && to_small[d] == BS::PRE_ONLY) {
323  _valid_main[d].second = {false, REASON::TO_SMALL};
324  } else {
325  _valid_main[d].second = {true, REASON::NONE};
326  }
327  }
328  }
329  }
330 
331  BlockViewSpec_t block_views() {
332  // TODO PRE and POST Region true but not full POST region possible
333  auto offsets_inner = _view->offsets();
334  auto extents_inner = _view->extents();
335  auto offsets_inner_bnd = _view->offsets();
336  auto extents_inner_bnd = _view->extents();
337 
338  for(int d = 0; d < NumDimensions; ++d) {
339 
340  offsets_inner[d] = _max_dist[d].first;
341  DASH_ASSERT_MSG(extents_inner[d] >= _max_dist[d].first,
342  "Inner view to small for the given Stencil.");
343  auto sum_dist = _max_dist[d].first + _max_dist[d].second;
344  extents_inner[d] -= (extents_inner[d] < sum_dist) ? _max_dist[d].first : sum_dist;
345 
346  offsets_inner_bnd[d] = 0;
347 
348  if(!_valid_main[d].first.valid) {
349  offsets_inner_bnd[d] = _max_dist[d].first;
350  extents_inner_bnd[d] -= _max_dist[d].first;
351  }
352 
353  if(!_valid_main[d].second.valid) {
354  if(extents_inner_bnd[d] >= _max_dist[d].second) {
355  extents_inner_bnd[d] -= _max_dist[d].second;
356  }
357  }
358  }
359 
360  return {ViewSpecT(offsets_inner, extents_inner), ViewSpecT(offsets_inner_bnd, extents_inner_bnd)};
361  }
362 
363  bool is_bnd_region_valid(const RegionSpec_t& region) {
364 
365  auto& coords = region.coords();
366  for(int d = 0; d < NumDimensions; ++d) {
367  if(coords[d] == 0 && !_valid_main[d].first.valid) {
368  return false;
369  }
370 
371  if(coords[d] > 1 && !_valid_main[d].second.valid) {
372  return false;
373  }
374  }
375 
376  return true;
377  }
378 
379  RegionData_t region_data(const RegionSpec_t& region, bool local_offsets = true) {
380 
381  if(region.index() == CenterIndex) {
382  return {ViewSpecT(), false};
383  }
384 
385  RegionData_t region_data;
386  auto& coords = region.coords();
387  for(dim_t d = 0; d < NumDimensions; ++d) {
388  if(coords[d] == 0 && !_valid_main[d].first.valid) {
389  return {ViewSpecT(), false};
390  }
391 
392  if(coords[d] > 1 && !_valid_main[d].second.valid) {
393  return {ViewSpecT(), false};
394  }
395  }
396 
397  auto offsets = _view->offsets();
398  auto extents = _view->extents();
399 
400  if(local_offsets) {
401  std::fill(offsets.begin(), offsets.end(), 0);
402  }
403 
404  for(dim_t d = 0; d < NumDimensions; ++d) {
405 
406  if(coords[d] < 1) {
407  extents[d] = (region.extent() == 0) ? _max_dist[d].first : region.extent();
408  continue;
409  }
410 
411  if(coords[d] == 1) {
412  if(_valid_main[d].first.valid ||
413  (!_valid_main[d].first.valid && _valid_main[d].first.reason == REASON::BORDER)) {
414  extents[d] -= _max_dist[d].first;
415  offsets[d] += _max_dist[d].first;
416  }
417 
418  if(_valid_main[d].second.valid ||
419  (!_valid_main[d].second.valid && _valid_main[d].second.reason == REASON::BORDER)) {
420  extents[d] -= _max_dist[d].second;
421  }
422  continue;
423  }
424 
425  offsets[d] = extents[d] - _max_dist[d].second;
426  extents[d] = (region.extent() == 0) ? _max_dist[d].second : region.extent();
427  }
428 
429  region_data.valid = true;
430  region_data.view = ViewSpecT(offsets, extents);
431  return region_data;
432  }
433 
434  RegionData_t region_data_duplicate(const RegionSpec_t& region, bool local_offsets = true) {
435  if(region.extent() == 0) {
436  return {ViewSpecT(), false};
437  }
438 
439  RegionData_t region_data;
440  auto& coords = region.coords();
441  for(dim_t d = 0; d < NumDimensions; ++d) {
442  if(coords[d] == 0 && !_valid_main[d].first.valid) {
443  return {ViewSpecT(), false};
444  }
445 
446  if(coords[d] > 1 && !_valid_main[d].second.valid) {
447  return {ViewSpecT(), false};
448  }
449  }
450 
451  auto offsets = _view->offsets();
452  auto extents = _view->extents();
453 
454  if(local_offsets) {
455  std::fill(offsets.begin(), offsets.end(), 0);
456  }
457 
458  // TODO PRE and POST Region true but not full POST region possible
459  for(dim_t d = 0; d < NumDimensions; ++d) {
460 
461  if(coords[d] < 1) {
462  extents[d] = region.extent();
463  continue;
464  }
465 
466  if(coords[d] == 1) {
467  continue;
468  }
469 
470  offsets[d] = extents[d] - _max_dist[d].second;
471  extents[d] = region.extent();
472  }
473 
474  region_data.valid = true;
475  region_data.view = ViewSpecT(offsets, extents);
476  return region_data;
477  }
478 
479 private:
480  /*
481  * Defines the relation between block extent and stencil distance
482  * PRE_ONLY -> only the boundary on the pre center side is valid
483  * EQUALS_LESS -> both bboundaries (pre and post center) are valid, but are equal or less than matrix extent
484  * BIGGER -> matrix extent is bigger than stencil distance
485  */
486  enum class BS{
487  PRE_ONLY,
488  EQUALS_LESS,
489  BIGGER
490  };
491 
492  enum class REASON {
493  NONE,
494  TO_SMALL,
495  BORDER
496  };
497 
498  struct valid_region {
499  bool valid{};
500  REASON reason{};
501 
502  };
503 
504 
505 private:
506  const ViewSpecT* _view;
507  const MaxDist_t _max_dist;
508  std::array<std::pair<valid_region, valid_region>,NumDimensions> _valid_main;
509 };
510 
511 
512 template<typename PatternT>
514  static constexpr auto NumDimensions = PatternT::ndim();
515  static constexpr auto RegionsMax = NumRegionsMax<NumDimensions>;
516 
517 public:
518  using ViewSpec_t = typename PatternT::viewspec_type;
519 
520 private:
521  using RegionData_t = RegionData<ViewSpec_t>;
522  using BndInfos_t = std::array<RegionData_t, RegionsMax>;
523  using EnvRegInfo_t = EnvironmentRegionInfo<ViewSpec_t>;
524  using BlockEnv_t = std::array<EnvRegInfo_t, RegionsMax>;
526  using HaloExtsMaxPair_t = typename HaloSpec_t::HaloExtsMaxPair_t;
527  using HaloExtsMax_t = typename HaloSpec_t::HaloExtsMax_t;
529 
530 public:
532 
533  using RegionBorders_t = typename EnvRegInfo_t::RegionBorders_t;
535  using RegIdxMain_t = std::array<typename RegionCoords_t::RegIndexDim_t, NumDimensions>;
536  using BlockViewSpec_t = BlockViewSpec<ViewSpec_t>;
537 
538 
539  BlockEnvironment(const PatternT& pattern, const HaloSpec_t& halo_spec,
540  const ViewSpec_t& view_glob, const GlobalBndSpec_t& glob_bound_spec)
541  : _view(&view_glob), _glob_bnd_spec(&glob_bound_spec) {
542  set_environment(pattern, halo_spec);
543  }
544 
545  BndRegCheck_t boundary_region_check(const HaloSpec_t& halo_spec) const {
546  return BndRegCheck_t(*_view, halo_spec.halo_extension_max(), *_glob_bnd_spec, _borders);
547  }
548 
549  template <typename StencilPointT, std::size_t NumStencilPoints>
550  BndRegCheck_t boundary_region_check(const StencilSpec<StencilPointT, NumStencilPoints>& stencil_spec) const {
551  auto minmax = stencil_spec.minmax_distances();
552  HaloExtsMax_t max_dist{};
553  for(dim_t d = 0; d < NumDimensions; ++d) {
554  max_dist[d] = {std::abs(minmax[d].first), minmax[d].second};
555  }
556 
557  return BndRegCheck_t(*_view, max_dist, *_glob_bnd_spec, _borders);
558  }
559 
560  auto info_dim(dim_t dim) const {
561  return std::make_pair(std::ref(_block_env[_reg_idx_main[dim].first]), std::ref(_block_env[_reg_idx_main[dim].second]));
562  }
563 
564  const EnvRegInfo_t& info(region_index_t region_index) const {
565  return _block_env[region_index];
566  }
567 
568  const BlockEnv_t& info() const {
569  return _block_env;
570  }
571 
572  const auto& view_inner() const {
573  return _block_views.inner;
574  }
575 
576  const auto& view_inner_boundary() const {
577  return _block_views.inner_bound;
578  }
579 
580  const auto& views() const {
581  return _block_views;
582  }
583 
584 private:
585 
586  void set_environment(const PatternT& pattern, const HaloSpec_t& halo_spec) {
587  const auto& view_offsets = _view->offsets();
588  const auto& view_extents = _view->extents();
589 
590  const auto& glob_extent = pattern.extents();
591  for(dim_t d = 0; d < NumDimensions; ++d) {
592  _reg_idx_main[d] = RegionCoords_t::index(d);
593  if(view_offsets[d] == 0) {
594  _borders[d].first = true;
595  }
596  if(view_offsets[d] + view_extents[d] == glob_extent[d]) {
597  _borders[d].second = true;
598  }
599  }
600 
601  BndRegCheck_t bnd_check(*_view, halo_spec.halo_extension_max(), *_glob_bnd_spec, _borders);
602  _block_views = bnd_check.block_views();
603 
604  const auto& team_spec = pattern.teamspec();
605  for(const auto& spec : halo_spec.specs()) {
606  auto halo_extent = spec.extent();
607  if(!halo_extent) {
608  continue;
609  }
610 
611  auto& env_md = _block_env[spec.index()];
612 
613  env_md.bnd_reg_data = bnd_check.region_data(spec);
614 
615  std::array<int, NumDimensions> neighbor_coords_rem;
616  std::array<int, NumDimensions> neighbor_coords;
617  auto reg_coords = spec.coords();
618  auto reg_coords_rem = RegionCoords_t::coords(RegionsMax - 1 - spec.index());
619 
620  env_md.boundary_prop = BoundaryProp::CYCLIC;
621  BoundaryProp bnd_prop_to = BoundaryProp::CYCLIC;
622 
623  const auto& halo_ext_max = halo_spec.halo_extension_max();
624 
625  auto halo_region_offsets = _view->offsets();
626  auto halo_region_extents = _view->extents();
627  for(dim_t d = 0; d < NumDimensions; ++d) {
628 
629  // region coords uses 1 for the center position, while \ref TeamSpec use 0
630  neighbor_coords[d] = static_cast<int>(reg_coords[d]) - 1;
631  neighbor_coords_rem[d] = static_cast<int>(reg_coords_rem[d]) - 1;
632 
633 
634  if(spec[d] == 1) {
635  continue;
636  }
637 
638  halo_region_extents[d] = halo_extent;
639 
640  if(spec[d] < 1) {
641  if(_borders[d].first) {
642  halo_region_offsets[d] = pattern.extent(d) - halo_extent;
643  env_md.boundary_prop = test_bound_prop(env_md.boundary_prop, (*_glob_bnd_spec)[d]);
644  env_md.border_region = true;
645  env_md.region_borders[d].first = true;
646  }else {
647  halo_region_offsets[d] -= halo_extent;
648  }
649 
650  if(_borders[d].second) {
651  bnd_prop_to = test_bound_prop(bnd_prop_to, (*_glob_bnd_spec)[d]);
652  }
653  continue;
654  }
655 
656  // spec[d] > 1
657  if(_borders[d].second) {
658  halo_region_offsets[d] = 0;
659  env_md.boundary_prop = test_bound_prop(env_md.boundary_prop, (*_glob_bnd_spec)[d]);
660  env_md.border_region = true;
661  env_md.region_borders[d].second = true;
662  } else {
663  halo_region_offsets[d] += _view->extent(d);
664  }
665 
666  if(_borders[d].first) {
667  bnd_prop_to = test_bound_prop(bnd_prop_to, (*_glob_bnd_spec)[d]);
668  }
669  }
670 
671  env_md.halo_reg_data = {ViewSpec_t(halo_region_offsets, halo_region_extents), true};
672  if(env_md.boundary_prop != BoundaryProp::NONE) {
673  if(env_md.boundary_prop == BoundaryProp::CYCLIC) {
674  env_md.neighbor_id_from = static_cast<dart_unit_t>(team_spec.periodic_neighbor(neighbor_coords));
675  } else {
676  env_md.neighbor_id_from = static_cast<dart_unit_t>(team_spec.neighbor(neighbor_coords));
677  }
678  } else {
679  env_md.neighbor_id_from = static_cast<dart_unit_t>(team_spec.neighbor(neighbor_coords));
680  env_md.halo_reg_data.valid = false;
681  }
682 
683  if(bnd_prop_to == BoundaryProp::CYCLIC) {
684  env_md.neighbor_id_to = static_cast<dart_unit_t>(team_spec.periodic_neighbor(neighbor_coords_rem));
685  } else {
686  env_md.neighbor_id_to = static_cast<dart_unit_t>(team_spec.neighbor(neighbor_coords_rem));
687  }
688  }
689  }
690 
691  BoundaryProp test_bound_prop(const BoundaryProp& current_prop, const BoundaryProp& new_prop) {
692  if(current_prop == BoundaryProp::NONE || new_prop == BoundaryProp::NONE) {
693  return BoundaryProp::NONE;
694  }
695 
696  if(current_prop == BoundaryProp::CUSTOM || new_prop == BoundaryProp::CUSTOM) {
697  return BoundaryProp::CUSTOM;
698  }
699 
700  return BoundaryProp::CYCLIC;
701  }
702 
703 private:
704  const ViewSpec_t* _view;
705  const GlobalBndSpec_t* _glob_bnd_spec;
706  BlockEnv_t _block_env;
707  RegionBorders_t _borders{};
708  RegIdxMain_t _reg_idx_main;
709  BlockViewSpec_t _block_views;
710 };
711 
712 template<typename PatternT>
713 std::ostream& operator<<(std::ostream& os, const BlockEnvironment<PatternT>& env_info) {
714  static constexpr auto NumDimensions = PatternT::ndim();
715  static constexpr auto RegionsMax = NumRegionsMax<NumDimensions>;
716 
717  const auto& env_mds = env_info.info();
718 
719  os << "dash::halo::BlockEnvironment { ";
720  for(region_index_t r = 0; r < RegionsMax; ++r) {
721  const auto& env_md = env_mds[r];
722  os << dash::myid() << " -> ";
723  os << "region_index: " << r << ";"
724  << env_md << ")\n";
725  }
726  os << "}";
727 
728  return os;
729 }
730 
734 template <typename HaloBlockT, typename StencilSpecT>
736 private:
737  static constexpr auto NumDimensions = HaloBlockT::ndim();
738 
739  using Pattern_t = typename HaloBlockT::Pattern_t;
740  using HaloSpec_t = typename HaloBlockT::HaloSpec_t;
741 
742 public:
743  using HaloBlock_t = HaloBlockT;
744  using ViewSpec_t = typename HaloBlockT::ViewSpec_t;
745  using BoundaryViews_t = typename HaloBlockT::BoundaryViews_t;
746  using pattern_size_t = typename Pattern_t::size_type;
747  using StencilSpec_t = StencilSpecT;
748 
749 public:
750  StencilSpecificViews(const HaloBlockT& halo_block,
751  const StencilSpec_t& stencil_spec,
752  const ViewSpec_t* view_local)
753  : _stencil_spec(&stencil_spec), _view_local(view_local) {
754  HaloSpec_t halo_spec(stencil_spec);
755  auto bnd_region_check = halo_block.block_env().boundary_region_check(halo_spec);
756 
757  auto block_views = bnd_region_check.block_views();
758  _view_inner = block_views.inner;
759  _view_inner_with_boundaries = block_views.inner_bound;
760  for(const auto& region : halo_spec.specs()) {
761  auto bnd_region_data = bnd_region_check.region_data(region);
762  _size_bnd_elems += bnd_region_data.view.size();
763  _boundary_views.push_back(std::move(bnd_region_data.view));
764  }
765  }
766 
770  const StencilSpec_t& stencil_spec() const { return *_stencil_spec; }
771 
775  const ViewSpec_t& view() const { return *_view_local; }
776 
780  const ViewSpec_t& inner() const { return _view_inner; }
781 
785  const ViewSpec_t& inner_with_boundaries() const {
786  return _view_inner_with_boundaries;
787  }
788 
792  const BoundaryViews_t& boundary_views() const { return _boundary_views; }
793 
797  pattern_size_t boundary_size() const { return _size_bnd_elems; }
798 
799 private:
800  const StencilSpec_t* _stencil_spec;
801  const ViewSpec_t* _view_local;
802  ViewSpec_t _view_inner;
803  ViewSpec_t _view_inner_with_boundaries;
804  BoundaryViews_t _boundary_views;
805  pattern_size_t _size_bnd_elems = 0;
806 };
807 
808 template <typename HaloBlockT, typename StencilSpecT>
809 std::ostream& operator<<(
810  std::ostream& os,
811  const StencilSpecificViews<HaloBlockT, StencilSpecT>& stencil_views) {
812  os << "dash::halo::StencilSpecificViews"
813  << "(local: " << stencil_views.view()
814  << "; inner: " << stencil_views.inner()
815  << "; inner_bound: " << stencil_views.inner_with_boundaries()
816  << "; boundary_views: " << stencil_views.boundary_views()
817  << "; boundary elems: " << stencil_views.boundary_size() << ")";
818 
819  return os;
820 }
821 
826 template <typename ElementT, typename PatternT, typename GlobMemT>
827 class HaloBlock {
828 private:
829  static constexpr auto NumDimensions = PatternT::ndim();
830  static constexpr auto RegionsMax = NumRegionsMax<NumDimensions>;
831 
833  using pattern_index_t = typename PatternT::index_type;
837  using Coords_t = typename RegionCoords_t::Coords_t;
838  using region_extent_t = typename RegionSpec_t::region_extent_t;
839 
840 public:
841  using Element_t = ElementT;
842  using Pattern_t = PatternT;
843  using GlobMem_t = GlobMemT;
845  using pattern_size_t = typename PatternT::size_type;
846  using ViewSpec_t = typename PatternT::viewspec_type;
847  using BoundaryViews_t = std::vector<ViewSpec_t>;
849  using RegionVector_t = std::vector<Region_t>;
850  using ElementCoords_t = std::array<pattern_index_t, NumDimensions>;
851  using HaloExtsMax_t = typename HaloSpec_t::HaloExtsMax_t;
852  using RegIndDepVec_t = typename RegionCoords_t::RegIndDepVec_t;
854 
855 public:
859  HaloBlock(GlobMem_t& globmem, const PatternT& pattern, const ViewSpec_t& view,
860  const HaloSpec_t& halo_reg_spec,
861  const GlobBoundSpec_t& bound_spec)
862  : _globmem(globmem), _pattern(pattern), _view(view),
863  _halo_reg_spec(halo_reg_spec), _view_local(_view.extents()),
864  _glob_bound_spec(bound_spec),
865  _block_env(pattern, _halo_reg_spec, _view, _glob_bound_spec) {
866 
867  // TODO put functionallity to HaloSpec
868  _halo_regions.reserve(_halo_reg_spec.num_regions());
869  _boundary_regions.reserve(_halo_reg_spec.num_regions());
870 
871  _view_inner = _block_env.view_inner();
872  _view_inner_with_boundaries = _block_env.view_inner_boundary();
873 
874  /*
875  * Setup for all halo and boundary regions and properties like:
876  * is the region a global boundary region and is the region custom or not
877  */
878 
879  auto bnd_check = _block_env.boundary_region_check(halo_reg_spec);
880  for(region_index_t r = 0; r < RegionsMax; ++r) {
881  const auto& env_reg_info = _block_env.info(r);
882  const auto& spec = _halo_reg_spec.specs()[r];
883 
884  _boundary_views.push_back(env_reg_info.bnd_reg_data.view);
885  _size_bnd_elems += env_reg_info.bnd_reg_data.view.size();
886 
887  auto halo_extent = spec.extent();
888  if(!halo_extent) {
889  continue;
890  }
891 
892  if(env_reg_info.halo_reg_data.valid) {
893  _halo_regions.push_back(
894  Region_t(spec, env_reg_info.halo_reg_data.view,
895  _globmem, _pattern, env_reg_info));
896  _halo_reg_mapping[r] = &_halo_regions.back();
897  _size_halo_elems += env_reg_info.halo_reg_data.view.size();
898  } else {
899  _halo_regions.push_back(
900  Region_t(spec, ViewSpec_t(),
901  _globmem, _pattern, env_reg_info));
902  _halo_reg_mapping[r] = &_halo_regions.back();
903  }
904  auto bnd_reg_data = bnd_check.region_data_duplicate(spec, false);
905  _boundary_regions.push_back(
906  Region_t(spec, bnd_reg_data.view,
907  _globmem, _pattern, env_reg_info));
908  _boundary_reg_mapping[r] = &_boundary_regions.back();
909  }
910  }
911 
912  HaloBlock() = delete;
913 
917  HaloBlock(const Self_t& other) = default;
918 
922  Self_t& operator=(const Self_t& other) = default;
923 
924  static constexpr dim_t ndim() { return NumDimensions; }
925 
929  const Pattern_t& pattern() const { return _pattern; }
930 
934  const GlobMem_t& globmem() const { return _globmem; }
935 
940  return _glob_bound_spec;
941  }
942 
946  const HaloSpec_t& halo_spec() const { return _halo_reg_spec; }
947 
951  BlockEnv_t block_env() { return _block_env; }
952 
956  const BlockEnv_t& block_env() const { return _block_env; }
957 
958 
962  const Region_t* halo_region(const region_index_t index) const {
963  return _halo_reg_mapping[index];
964  }
965 
969  const RegionVector_t& halo_regions() const { return _halo_regions; }
970 
974  const Region_t* boundary_region(const region_index_t index) const {
975  return _boundary_reg_mapping[index];
976  }
977 
982  const RegionVector_t& boundary_regions() const { return _boundary_regions; }
983 
984  RegIndDepVec_t boundary_dependencies(region_index_t index) const {
985  RegIndDepVec_t index_dep{};
986  for(auto reg_index : RegionCoords_t::boundary_dependencies(index)) {
987  auto region = halo_region(reg_index);
988  if(region != nullptr) {
989  index_dep.push_back(reg_index);
990  }
991  }
992 
993  return index_dep;
994  }
995 
999  const ViewSpec_t& view() const { return _view; }
1000 
1004  const ViewSpec_t& view_local() const { return _view_local; }
1005 
1009  const ViewSpec_t& view_inner_with_boundaries() const {
1010  return _view_inner_with_boundaries;
1011  }
1012 
1017  const ViewSpec_t& view_inner() const { return _view_inner; }
1018 
1023  const BoundaryViews_t& boundary_views() const { return _boundary_views; }
1024 
1028  pattern_size_t halo_size() const { return _size_halo_elems; }
1029 
1033  pattern_size_t boundary_size() const { return _size_bnd_elems; }
1034 
1038  region_index_t index_at(const ViewSpec_t& view,
1039  const ElementCoords_t& coords) const {
1040  using signed_extent_t = typename std::make_signed<pattern_size_t>::type;
1041  const auto& extents = view.extents();
1042  const auto& offsets = view.offsets();
1043 
1044  region_index_t index = 0;
1045  if(coords[0] >= offsets[0]
1046  && coords[0] < static_cast<signed_extent_t>(extents[0]))
1047  index = 1;
1048  else if(coords[0] >= static_cast<signed_extent_t>(extents[0]))
1049  index = 2;
1050  for(auto d = 1; d < NumDimensions; ++d) {
1051  if(coords[d] < offsets[d])
1052  index *= REGION_INDEX_BASE;
1053  else if(coords[d] < static_cast<signed_extent_t>(extents[d]))
1054  index = 1 + index * REGION_INDEX_BASE;
1055  else
1056  index = 2 + index * REGION_INDEX_BASE;
1057  }
1058 
1059  return index;
1060  }
1061 
1062 private:
1063  GlobMem_t& _globmem;
1064 
1065  const PatternT& _pattern;
1066 
1067  const ViewSpec_t& _view;
1068 
1069  const HaloSpec_t& _halo_reg_spec;
1070 
1071  const ViewSpec_t _view_local;
1072 
1073  const GlobBoundSpec_t _glob_bound_spec;
1074 
1075  BlockEnv_t _block_env;
1076 
1077  ViewSpec_t _view_inner_with_boundaries;
1078 
1079  ViewSpec_t _view_inner;
1080 
1081  RegionVector_t _halo_regions;
1082 
1083  std::array<Region_t*, RegionsMax> _halo_reg_mapping{};
1084 
1085  RegionVector_t _boundary_regions;
1086 
1087  std::array<Region_t*, RegionsMax> _boundary_reg_mapping{};
1088 
1089  BoundaryViews_t _boundary_views;
1090 
1091  pattern_size_t _size_bnd_elems = 0;
1092 
1093  pattern_size_t _size_halo_elems = 0;
1094 }; // class HaloBlock
1095 
1096 template <typename ElementT, typename PatternT, typename GlobMemT>
1097 std::ostream& operator<<(std::ostream& os,
1098  const HaloBlock<ElementT, PatternT, GlobMemT>& haloblock) {
1099  bool begin = true;
1100  os << "dash::halo::HaloBlock<" << typeid(ElementT).name() << ">("
1101  << "view global: " << haloblock.view()
1102  << "; halo spec: " << haloblock.halo_spec()
1103  << "; view local: " << haloblock.view_local()
1104  << "; view inner: " << haloblock.view_inner()
1105  << "; view inner_bnd: " << haloblock.view_inner_with_boundaries()
1106  << "; halo regions { ";
1107  for(const auto& region : haloblock.halo_regions()) {
1108  if(begin) {
1109  os << region;
1110  begin = false;
1111  } else {
1112  os << "," << region;
1113  }
1114  }
1115  os << " } "
1116  << "; halo elems: " << haloblock.halo_size() << "; boundary regions: { ";
1117  for(const auto& region : haloblock.boundary_regions()) {
1118  if(begin) {
1119  os << region;
1120  begin = false;
1121  } else {
1122  os << "," << region;
1123  }
1124  }
1125  os << " } "
1126  << "; boundary views: " << haloblock.boundary_views()
1127  << "; boundary elems: " << haloblock.boundary_size() << ")";
1128 
1129  return os;
1130 }
1131 
1132 
1133 
1134 } // namespace halo
1135 
1136 } // namespace dash
1137 
1138 #endif // DASH__HALO_HALO_H__
GlobalBoundarySpec()
Default constructor.
Definition: Halo.h:34
constexpr region_extent_t extent() const
Returns the extent.
Definition: Region.h:359
Returns second operand.
Definition: Operation.h:218
constexpr region_extent_t extent(const region_index_t index) const
Extent for a given region index.
Definition: Halo.h:129
global_unit_t myid()
Shortcut to query the global unit ID of the calling unit.
constexpr std::enable_if< std::is_integral< IndexType >::value, IndexType >::type index(IndexType idx)
Definition: Iterator.h:60
This class is a simple memory pool which holds allocates elements of size ValueType.
Definition: AllOf.h:8
const ViewSpec_t & view_inner_with_boundaries() const
Returns a local ViewSpec that combines the boundary and inner view.
Definition: Halo.h:1009
const ViewSpec_t & inner() const
Returns ViewSpec including all inner elements.
Definition: Halo.h:780
const HaloSpec_t & halo_spec() const
Returns used HaloSpec.
Definition: Halo.h:946
const Region_t * halo_region(const region_index_t index) const
Returns a specific halo region and nullptr if no region exists.
Definition: Halo.h:962
const BoundaryViews_t & boundary_views() const
Returns a set of local views that contains all boundary elements.
Definition: Halo.h:1023
pattern_size_t halo_size() const
Number of halo elements.
Definition: Halo.h:1028
const ViewSpec_t & view() const
Returns ViewSpec including all elements (locally)
Definition: Halo.h:775
Takes the local part of the NArray and builds halo and boundary regions.
Definition: Halo.h:827
constexpr auto begin(RangeType &&range) -> decltype(std::forward< RangeType >(range).begin())
Definition: Range.h:89
No global boundary Halos.
const Pattern_t & pattern() const
The pattern instance that created the encapsulated block.
Definition: Halo.h:929
int32_t dart_unit_t
Data type for storing a unit ID.
Definition: dart_types.h:154
int dim_t
Scalar type for a dimension value, with 0 indicating the first dimension.
Definition: Types.h:39
const GlobBoundSpec_t & global_boundary_spec() const
Returns the GlobalBoundarySpec used by the HaloBlock instance.
Definition: Halo.h:939
const StencilSpec_t & stencil_spec() const
Returns StencilSpec.
Definition: Halo.h:770
constexpr const StencilArray_t & specs() const
Definition: Stencil.h:211
Returns second operand.
Definition: Operation.h:201
const ViewSpec_t & view() const
Returns the initial global ViewSpec.
Definition: Halo.h:999
Reduce operands to their maximum value.
Definition: Operation.h:144
pattern_size_t boundary_size() const
Number of boundary elements (no duplicates)
Definition: Halo.h:1033
const RegionVector_t & halo_regions() const
Returns all halo regions.
Definition: Halo.h:969
const ViewSpec_t & inner_with_boundaries() const
Returns ViewSpec including all inner and boundary elements.
Definition: Halo.h:785
void fill(GlobIterType first, GlobIterType last, const typename GlobIterType::value_type &value)
Assigns the given value to the elements in the range [first, last)
Definition: Fill.h:35
pattern_size_t boundary_size() const
Returns the number of all boundary elements (no dublicates)
Definition: Halo.h:797
const ViewSpec_t & view_inner() const
Returns the inner ViewSpec with local offsets depending on the used HaloSpec.
Definition: Halo.h:1017
N-Dimensional region coordinates and associated indices for all possible Halo/Boundary regions of a H...
Definition: Region.h:40
constexpr region_size_t num_regions() const
Number of specified regions.
Definition: Halo.h:136
Adapts all views HaloBlock provides to the given StencilSpec.
Definition: Halo.h:735
const Specs_t & specs() const
Used RegionSpec instance.
Definition: Halo.h:141
const BoundaryViews_t & boundary_views() const
Returns all boundary views including all boundary elements (no dublicates)
Definition: Halo.h:792
region_index_t index_at(const ViewSpec_t &view, const ElementCoords_t &coords) const
Returns the region index belonging to the given coordinates and ViewSpec.
Definition: Halo.h:1038
Base class for dimensional attributes, stores an n-dimensional value with identical type all dimensio...
Definition: Dimensional.h:101
HaloBlock(GlobMem_t &globmem, const PatternT &pattern, const ViewSpec_t &view, const HaloSpec_t &halo_reg_spec, const GlobBoundSpec_t &bound_spec)
Constructor.
Definition: Halo.h:859
Contains all specified Halo regions.
Definition: Halo.h:70
constexpr dim_t ndim(const DimensionalType &d)
Definition: Dimensional.h:56
DistanceAll_t minmax_distances() const
Returns the minimal and maximal distances of all stencil points for all dimensions.
Definition: Stencil.h:267
const BlockEnv_t & block_env() const
Returns the environment information object BlockEnvironment.
Definition: Halo.h:956
const HaloExtsMaxPair_t & halo_extension_max(dim_t dim) const
Returns the maximal extension for a specific dimension.
Definition: Halo.h:146
const RegionVector_t & boundary_regions() const
Returns all boundary regions.
Definition: Halo.h:982
constexpr GlobalBoundarySpec(BoundaryProp value, Values... values)
Constructor to define custom BoundaryProp values.
Definition: Halo.h:43
static region_index_t index(const StencilT &stencil)
Returns the region index for a given StencilPoint.
Definition: Region.h:328
Provides RegionIter and some region metadata like RegionSpec, size etc.
Definition: Region.h:411
BlockEnv_t block_env()
Returns the environment information object BlockEnvironment.
Definition: Halo.h:951
const GlobMem_t & globmem() const
The global memory instance that created the encapsulated block.
Definition: Halo.h:934
constexpr RegionSpec_t spec(const region_index_t index) const
Matching RegionSpec for a given region index.
Definition: Halo.h:122
const HaloExtsMax_t & halo_extension_max() const
Returns the maximal halo extension for every dimension.
Definition: Halo.h:153
constexpr const RegionCoords_t & coords() const
Returns the RegionCoords.
Definition: Region.h:354
constexpr DimensionalType::extent_type extent(const DimensionalType &d)
Definition: Dimensional.h:73
A collection of stencil points (Stencil) e.g.
Definition: Stencil.h:167
Global boundary property specification for every dimension.
Definition: Halo.h:23
Definition: main.cpp:123
Region specification connecting RegionCoords with an extent.
Definition: Region.h:294
const ViewSpec_t & view_local() const
Returns the initial local ViewSpec.
Definition: Halo.h:1004
const Region_t * boundary_region(const region_index_t index) const
Returns a specific region and nullptr if no region exists.
Definition: Halo.h:974