Distributed Ranges
Loading...
Searching...
No Matches
global.hpp
1// SPDX-FileCopyrightText: Intel Corporation
2//
3// SPDX-License-Identifier: BSD-3-Clause
4
5#pragma once
6
7// File with initialization/cleanup functions, global objects created during
8// initialization and helper functions using these objects. For general helper
9// functions see sycl_support.hpp and common_support.hpp
10
11#include <unistd.h>
12
13#include <dr/detail/sycl_utils.hpp>
14#include <dr/mp/sycl_support.hpp>
15
16namespace dr::mp {
17
18namespace __detail {
19
21 void init() {
22 void *data = nullptr;
23 std::size_t size = 0;
24 if (comm_.rank() == 0) {
25 root_scratchpad_.resize(scratchpad_size_);
26 data = root_scratchpad_.data();
27 size = rng::size(root_scratchpad_) * sizeof(root_scratchpad_[0]);
28 }
29 root_win_.create(comm_, data, size);
30 root_win_.fence();
31 }
32
34 root_win_.fence();
35 root_win_.free();
36 }
37
38 global_context() { init(); }
39#ifdef SYCL_LANGUAGE_VERSION
40 global_context(sycl::queue q, sycl::usm::alloc kind)
41 : sycl_queue_(q), sycl_mem_kind_(kind), dpl_policy_(q), use_sycl_(true) {
42 init();
43 }
44
45 sycl::queue sycl_queue_;
46 sycl::usm::alloc sycl_mem_kind_;
47 decltype(oneapi::dpl::execution::make_device_policy(
48 std::declval<sycl::queue>())) dpl_policy_;
49#endif
50
51 static constexpr std::size_t scratchpad_size_ = 1000000;
52 bool use_sycl_ = false;
53 dr::communicator comm_;
54 // container owns the window, we just track MPI handle
55 std::set<MPI_Win> wins_;
56 dr::rma_window root_win_;
57 std::vector<char> root_scratchpad_;
58};
59
60inline global_context *global_context_ = nullptr;
61
62inline bool finalized_ = false;
63inline bool we_initialized_mpi_ = false;
64
65inline auto gcontext() {
66 assert(global_context_ && "Call mp::init() after MPI_Init()");
67 return global_context_;
68}
69
70// Initialize MPI if not already initialized.
71inline void initialize_mpi() {
72 int initialized;
73 MPI_Initialized(&initialized);
74 if (!initialized) {
75 DRLOG("initializing MPI");
76 MPI_Init(nullptr, nullptr);
77 we_initialized_mpi_ = true;
78 } else {
79 DRLOG("initializing MPI skipped - already initialized");
80 }
81
82#ifdef DRISHMEM
83 DRLOG("calling ishmem_init()");
84 ishmem_init();
85#endif
86}
87
88// Finalize MPI *if* we initialized it and it has not been finalized.
89inline void finalize_mpi() {
90 int finalized;
91 MPI_Finalized(&finalized);
92
93 if (we_initialized_mpi_ && !finalized) {
94 MPI_Finalize();
95 }
96
97#ifdef DRISHMEM
98 DRLOG("calling ishmem_finalize()");
99 ishmem_finalize();
100#endif
101}
102
103} // namespace __detail
104
105inline auto root_win() { return __detail::gcontext()->root_win_; }
106inline dr::communicator &default_comm() { return __detail::gcontext()->comm_; }
107
108inline bool finalized() { return __detail::finalized_; }
109inline std::size_t rank() { return default_comm().rank(); }
110inline std::size_t nprocs() { return default_comm().size(); } // dr-style ignore
111
112inline std::set<MPI_Win> &active_wins() { return __detail::gcontext()->wins_; }
113
114inline void barrier() { __detail::gcontext()->comm_.barrier(); }
115inline auto use_sycl() { return __detail::gcontext()->use_sycl_; }
116
117inline void fence() {
118#ifdef DRISHMEM
119 DRLOG("global fence in ISHMEM");
120 ishmem_fence();
121 DRLOG("global fence in ISHMEM finished");
122#endif
123 for (auto win : __detail::gcontext()->wins_) {
124 DRLOG("global fence, for window:{}", win);
125 MPI_Win_fence(0, win);
126 }
127 DRLOG("global fence finished");
128}
129
130inline void init() {
131 __detail::initialize_mpi();
132 assert(__detail::global_context_ == nullptr &&
133 "Do not call mp::init() more than once");
134 __detail::global_context_ = new __detail::global_context;
135}
136
137inline void finalize() {
138 assert(__detail::global_context_ != nullptr);
139 delete __detail::global_context_;
140 __detail::global_context_ = nullptr;
141 __detail::finalize_mpi();
142 __detail::finalized_ = true;
143}
144
145inline std::string hostname() {
146 constexpr std::size_t MH = 2048;
147 char buf[MH + 1];
148 gethostname(buf, MH);
149 return std::string(buf);
150}
151
152#ifdef SYCL_LANGUAGE_VERSION
153inline sycl::queue &sycl_queue() { return __detail::gcontext()->sycl_queue_; }
154inline auto sycl_mem_kind() { return __detail::gcontext()->sycl_mem_kind_; }
155inline auto dpl_policy() { return __detail::gcontext()->dpl_policy_; }
156
157inline sycl::queue select_queue(bool check_different_devices = false) {
158 std::vector<sycl::device> devices;
159
160 auto root_devices = sycl::platform().get_devices();
161
162 for (auto &&root_device : root_devices) {
163 dr::drlog.debug("Root device: {}\n",
164 root_device.get_info<sycl::info::device::name>());
165 if (dr::__detail::partitionable(root_device)) {
166 auto subdevices = root_device.create_sub_devices<
167 sycl::info::partition_property::partition_by_affinity_domain>(
168 sycl::info::partition_affinity_domain::numa);
169 assert(rng::size(subdevices) > 0);
170
171 for (auto &&subdevice : subdevices) {
172 dr::drlog.debug(" add subdevice: {}\n",
173 subdevice.get_info<sycl::info::device::name>());
174 devices.push_back(subdevice);
175 }
176 } else {
177 dr::drlog.debug(" add root device: {}\n",
178 root_device.get_info<sycl::info::device::name>());
179 devices.push_back(root_device);
180 }
181 }
182
183 assert(rng::size(devices) > 0);
184 const auto my_rank = dr::communicator(MPI_COMM_WORLD).rank();
185 assert(!check_different_devices || my_rank < rng::size(devices));
186
187 // Round robin assignment of devices to ranks
188 return sycl::queue(devices[my_rank % rng::size(devices)]);
189}
190
191inline void init(sycl::queue q,
192 sycl::usm::alloc kind = sycl::usm::alloc::shared) {
193 __detail::initialize_mpi();
194 assert(__detail::global_context_ == nullptr &&
195 "Do not call mp::init() more than once");
196 __detail::global_context_ = new __detail::global_context(q, kind);
197}
198
199template <typename Selector = decltype(sycl::default_selector_v)>
200inline void init(Selector &&selector = sycl::default_selector_v) {
201 __detail::initialize_mpi();
202 sycl::queue q = mp::select_queue();
203 init(q);
204}
205
206#else // SYCL_LANGUAGE_VERSION
207inline auto sycl_queue() {
208 assert(false);
209 return 0;
210}
211inline const auto &dpl_policy() {
212 assert(false);
213 return std::execution::seq;
214}
215
216#endif // SYCL_LANGUAGE_VERSION
217
218} // namespace dr::mp
Definition: communicator.hpp:13
Definition: communicator.hpp:242
Definition: global.hpp:20