Itoyori  v0.0.1
coll_mem.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include "ityr/common/util.hpp"
6 #include "ityr/common/numa.hpp"
7 #include "ityr/common/rma.hpp"
10 #include "ityr/ori/mem_mapper.hpp"
11 
12 namespace ityr::ori {
13 
14 using coll_mem_id_t = uint64_t;
15 
16 class coll_mem {
17 public:
18  coll_mem(std::size_t size,
19  coll_mem_id_t id,
20  std::unique_ptr<mem_mapper::base> mmapper)
21  : size_(size),
22  id_(id),
23  mmapper_(std::move(mmapper)),
24  vm_(common::reserve_same_vm_coll(mmapper_->effective_size(), mmapper_->block_size())),
25  home_pm_(init_intra_home_pm()),
26  home_vm_(init_intra_home_vm()),
27  win_(common::rma::create_win(reinterpret_cast<std::byte*>(home_vm().addr()), home_vm().size())),
28  home_all_mapped_(map_ahead_of_time()) {}
29 
30  coll_mem(coll_mem&&) = default;
31  coll_mem& operator=(coll_mem&&) = default;
32 
33  coll_mem_id_t id() const { return id_; }
34  std::size_t size() const { return size_; }
35  std::size_t local_size() const { return home_vm().size(); }
36  std::size_t effective_size() const { return vm_.size(); }
37  bool home_all_mapped() const { return home_all_mapped_; }
38 
39  const mem_mapper::base& mem_mapper() const { return *mmapper_; }
40 
41  const common::virtual_mem& vm() const { return vm_; }
42 
43  const common::physical_mem& home_pm() const {
44  return home_pm_;
45  }
46 
47  const common::virtual_mem& home_vm() const {
48  return home_vm_;
49  }
50 
51  const common::rma::win& win() const { return *win_; }
52 
53 private:
54  static std::string home_shmem_name(coll_mem_id_t id, int inter_rank) {
55  std::stringstream ss;
56  ss << "/ityr_ori_coll_mem_" << id << "_" << inter_rank;
57  return ss.str();
58  }
59 
60  common::physical_mem init_intra_home_pm() const {
62  common::physical_mem pm(home_shmem_name(id_, common::topology::inter_my_rank()),
63  mmapper_->local_size(common::topology::inter_my_rank()),
64  true);
66  return pm;
67 
68  } else {
70  common::physical_mem pm(home_shmem_name(id_, common::topology::inter_my_rank()),
71  mmapper_->local_size(common::topology::inter_my_rank()),
72  false);
73  return pm;
74  }
75  }
76 
77  common::virtual_mem init_intra_home_vm() const {
78  common::virtual_mem vm(home_pm_.size(), mmapper_->block_size());
79  home_pm_.map_to_vm(vm.addr(), vm.size(), 0);
80 
82 
84  std::size_t pm_offset = 0;
85  while (pm_offset < vm.size()) {
86  auto numa_seg = mmapper_->get_numa_segment(common::topology::inter_my_rank(), pm_offset);
87  if (numa_seg.owner == -1 && common::topology::intra_my_rank() == 0) {
88  // interleave all
89  std::byte* numa_seg_addr = reinterpret_cast<std::byte*>(vm.addr()) + numa_seg.pm_offset_b;
90  std::size_t numa_seg_size = numa_seg.pm_offset_e - numa_seg.pm_offset_b;
91  common::numa::interleave(numa_seg_addr, numa_seg_size, common::topology::numa_nodemask_all());
92  }
93  if (numa_seg.owner == common::topology::intra_my_rank()) {
94  std::byte* numa_seg_addr = reinterpret_cast<std::byte*>(vm.addr()) + numa_seg.pm_offset_b;
95  std::size_t numa_seg_size = numa_seg.pm_offset_e - numa_seg.pm_offset_b;
96  common::numa::bind_to(numa_seg_addr, numa_seg_size, common::topology::numa_node(numa_seg.owner));
97  }
98  pm_offset = numa_seg.pm_offset_e;
99  }
101  }
102 
103  return vm;
104  }
105 
106  bool map_ahead_of_time() const {
107  if (common::topology::inter_n_ranks() == 1) {
108  home_pm_.map_to_vm(vm_.addr(), vm_.size(), 0);
109  return true;
110 
111  } else if (mmapper_->should_map_all_home()) {
112  // mmap all home blocks ahead of time if the mem mapper does not consume
113  // too many mmap entries (e.g., for block distribution)
114  std::size_t offset = 0;
115  while (offset < size_) {
116  auto seg = mmapper_->get_segment(offset);
117  if (seg.owner == common::topology::inter_my_rank()) {
118  std::byte* seg_addr = reinterpret_cast<std::byte*>(vm_.addr()) + seg.offset_b;
119  std::size_t seg_size = seg.offset_e - seg.offset_b;
120  home_pm_.map_to_vm(seg_addr, seg_size, seg.pm_offset);
121  }
122  offset = seg.offset_e;
123  }
124  return true;
125  }
126 
127  return false;
128  }
129 
130  std::size_t size_;
131  coll_mem_id_t id_;
132  std::unique_ptr<mem_mapper::base> mmapper_;
133  common::virtual_mem vm_;
134  common::physical_mem home_pm_;
135  common::virtual_mem home_vm_;
136  std::unique_ptr<common::rma::win> win_;
137  bool home_all_mapped_;
138 };
139 
140 template <typename Fn>
141 inline void for_each_mem_segment(const coll_mem& cm, const void* addr, std::size_t size, Fn fn) {
142  ITYR_CHECK(addr >= cm.vm().addr());
143 
144  std::size_t offset_b = reinterpret_cast<uintptr_t>(addr) -
145  reinterpret_cast<uintptr_t>(cm.vm().addr());
146  std::size_t offset_e = offset_b + size;
147 
148  ITYR_CHECK(offset_e <= cm.size());
149 
150  std::size_t offset = offset_b;
151  while (offset < offset_e) {
152  auto seg = cm.mem_mapper().get_segment(offset);
153  fn(seg);
154  offset = seg.offset_e;
155  }
156 }
157 
158 }
Definition: physical_mem.hpp:18
std::size_t size() const
Definition: physical_mem.hpp:41
void map_to_vm(void *addr, std::size_t size, std::size_t offset) const
Definition: physical_mem.hpp:43
Definition: virtual_mem.hpp:24
void * addr() const
Definition: virtual_mem.hpp:46
std::size_t size() const
Definition: virtual_mem.hpp:47
Definition: coll_mem.hpp:16
coll_mem(coll_mem &&)=default
coll_mem & operator=(coll_mem &&)=default
coll_mem_id_t id() const
Definition: coll_mem.hpp:33
std::size_t effective_size() const
Definition: coll_mem.hpp:36
const common::rma::win & win() const
Definition: coll_mem.hpp:51
bool home_all_mapped() const
Definition: coll_mem.hpp:37
const common::virtual_mem & home_vm() const
Definition: coll_mem.hpp:47
std::size_t local_size() const
Definition: coll_mem.hpp:35
std::size_t size() const
Definition: coll_mem.hpp:34
const common::virtual_mem & vm() const
Definition: coll_mem.hpp:41
const mem_mapper::base & mem_mapper() const
Definition: coll_mem.hpp:39
const common::physical_mem & home_pm() const
Definition: coll_mem.hpp:43
coll_mem(std::size_t size, coll_mem_id_t id, std::unique_ptr< mem_mapper::base > mmapper)
Definition: coll_mem.hpp:18
Definition: mem_mapper.hpp:35
virtual segment get_segment(std::size_t offset) const =0
#define ITYR_CHECK(cond)
Definition: util.hpp:48
void bind_to(void *, std::size_t, node_t)
Definition: numa.hpp:88
void interleave(void *, std::size_t, const node_bitmask &)
Definition: numa.hpp:89
std::unique_ptr< win > create_win(T *baseptr, std::size_t count)
Definition: rma.hpp:16
ITYR_RMA_IMPL::win win
Definition: rma.hpp:13
numa::node_t numa_node(rank_t intra_rank)
Definition: topology.hpp:229
rank_t inter_my_rank()
Definition: topology.hpp:215
bool numa_enabled()
Definition: topology.hpp:226
rank_t inter_rank(rank_t global_rank)
Definition: topology.hpp:219
rank_t inter_n_ranks()
Definition: topology.hpp:216
rank_t intra_my_rank()
Definition: topology.hpp:211
const numa::node_bitmask & numa_nodemask_all()
Definition: topology.hpp:230
MPI_Comm intra_mpicomm()
Definition: topology.hpp:210
virtual_mem reserve_same_vm_coll(std::size_t size, std::size_t alignment=alignof(max_align_t))
Definition: virtual_mem.hpp:170
void mpi_barrier(MPI_Comm comm)
Definition: mpi_util.hpp:42
Definition: block_region_set.hpp:9
void for_each_mem_segment(const coll_mem &cm, const void *addr, std::size_t size, Fn fn)
Definition: coll_mem.hpp:141
uint64_t coll_mem_id_t
Definition: coll_mem.hpp:14
constexpr block_size_t block_size
Definition: ori.hpp:19
constexpr auto size(const checkout_span< T, Mode > &cs) noexcept
Definition: checkout_span.hpp:178
ForwardIteratorD move(const ExecutionPolicy &policy, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIteratorD first_d)
Move a range to another.
Definition: parallel_loop.hpp:934