Realm
A distributed, event-based tasking library
Loading...
Searching...
No Matches
ucp_internal.h
Go to the documentation of this file.
1/*
2 * Copyright 2025 NVIDIA Corporation
3 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18// UCP network module internals
19
20#ifndef UCP_INTERNAL_H
21#define UCP_INTERNAL_H
22
23#include "realm/mem_impl.h"
24#include "realm/activemsg.h"
25#include "realm/atomics.h"
26#include "realm/mutex.h"
28
29#ifdef REALM_USE_CUDA
32#endif
33
36#include "realm/ucx/spinlock.h"
38#include "realm/ucx/ucc_comm.h"
39#include <ucp/api/ucp.h>
40
41#include <memory>
42#include <vector>
43#include <unordered_map>
44#include <unordered_set>
45
46namespace Realm {
47 namespace UCP {
48
55
63
64 struct CompList;
65 struct RemoteComp;
66 struct UCPRDMAInfo;
67 struct Request;
68
69 struct UCPMsgHdr {
70 uint32_t crc;
72 unsigned short msgid;
73 RemoteComp *remote_comp;
76#ifdef REALM_USE_CUDA
77 int src_dev_index;
78#endif
79 char realm_hdr[0];
80 } __attribute__((packed)); // gcc-specific
81
83 public:
85 ~UCPPoller() = default;
89 bool do_work(TimeLimit work_until);
90 void add_worker(UCPWorker *worker);
91
92 private:
93 std::vector<UCPWorker *> workers;
94 Mutex shutdown_mutex;
95 // set and cleared inside mutex, but tested outside
96 atomic<bool> shutdown_flag;
97 Mutex::CondVar shutdown_cond;
98 // set and cleared inside mutex, but tested outside
99 Mutex poll_notify_mutex;
100 atomic<bool> poll_notify_flag;
101 Mutex::CondVar poll_notify_cond;
102 };
103
105 public:
106 friend class UCPMessageImpl;
107 friend class ::Realm::UCPModule;
108 struct Config {
110 bool bind_hostmem{true};
113 int prog_boff_max{4}; // progress thread maximum backoff
116 bool mpool_leakcheck{false};
117 bool crc_check{true};
118 bool hbuf_malloc{false};
119 bool pbuf_malloc{false};
120 bool use_wakeup{false};
122 size_t fp_max{2 << 10 /* 2K */}; // fast path max message size
123 size_t pbuf_mp_max_size{8 << 10 /* 8K */};
124 size_t pbuf_mp_max_chunk_size{4 << 20 /* 4M */};
125 size_t pbuf_mp_max_count{SIZE_MAX};
126 size_t pbuf_mp_init_count{1024};
127 size_t pbuf_mp_thresh{2 << 10 /* 2K */};
128 size_t mmp_max_obj_size{2 << 10 /* 2K */}; // malloc mpool max object size
129 size_t outstanding_reqs_limit{1 << 17 /* 128K (count) */};
130 std::string ib_seg_size;
131 std::string host_nics;
132 std::string zcopy_thresh_host;
133 std::string tls_host;
134#ifdef REALM_USE_CUDA
135 bool bind_cudamem{true};
136 std::string gpu_nics;
137 std::string zcopy_thresh_dev;
138 std::string tls_dev;
139#endif
140 };
141
144 bool bootstrap();
145 bool init(const Config &config);
146 void finalize();
147 void attach(std::vector<NetworkSegment *> &segments);
148 void detach(std::vector<NetworkSegment *> &segments);
149 void get_shared_peers(Realm::NodeSet &shared_peers);
150 void barrier();
151 void broadcast(NodeID root, const void *val_in, void *val_out, size_t bytes);
152 void gather(NodeID root, const void *val_in, void *vals_out, size_t bytes);
153 void allgather(const char *val_in, size_t bytes, std::vector<char> &vals_out,
154 size_t *lengths);
155 void allgatherv(const char *val_in, size_t bytes, std::vector<char> &vals_out,
156 std::vector<size_t> &lengths);
158 void quiescence_allreduce_sum(const uint64_t *local_counts, uint64_t *total_counts,
159 size_t count);
160 size_t recommended_max_payload(const void *data, const NetworkSegment *src_segment,
161 const RemoteAddress *dest_payload_addr,
162 bool with_congestion, size_t header_size);
163
164 bool get_ucp_ep(const UCPWorker *worker, NodeID target,
165 const UCPRDMAInfo *rdma_info, ucp_ep_h *ep) const;
166
169
170 void *hbuf_get(UCPWorker *worker, size_t size);
171 void hbuf_release(UCPWorker *worker, void *buf);
172
173 void *pbuf_get(UCPWorker *worker, size_t size);
174 void pbuf_release(UCPWorker *worker, void *buf);
175
176 void notify_msg_sent(uint64_t count);
177
178 const UCPContext *get_context(const NetworkSegment *segment) const;
179 // the public interface exposes the tx worker only
180 UCPWorker *get_tx_worker(const UCPContext *context, uint8_t priority) const;
181
182 size_t num_eps(const UCPContext &context) const;
183
184 protected:
185 UCPModule *module;
187
188 private:
189 struct AmHandlersArgs {
190 UCPInternal *internal;
191 UCPWorker *worker;
192 };
193
194 struct Workers {
195 std::vector<UCPWorker *> tx_workers;
196 std::vector<UCPWorker *> rx_workers;
197 };
198
199#ifdef REALM_UCX_DYNAMIC_LOAD
200 bool resolve_ucp_api_fnptrs();
201#endif
202
203#ifdef REALM_USE_CUDA
204 bool init_ucp_contexts(const std::unordered_set<Realm::Cuda::GPU *> &gpus);
205#else
206 bool init_ucp_contexts();
207#endif
208
209 bool create_workers();
210 void destroy_workers();
211 size_t get_num_workers();
212 bool set_am_handlers();
213 bool create_eps(uint8_t priority);
214 bool create_eps();
215 bool create_pollers();
216 const UCPContext *get_context_host() const;
217#if defined(REALM_USE_CUDA)
218 const UCPContext *get_context_device(int dev_index) const;
219#endif
220 const std::vector<UCPWorker *> &get_tx_workers(const UCPContext *context) const;
221 const std::vector<UCPWorker *> &get_rx_workers(const UCPContext *context) const;
222 UCPWorker *get_rx_worker(const UCPContext *context, uint8_t priority) const;
223 bool is_congested();
224 bool add_rdma_info(NetworkSegment *segment, const UCPContext *context,
225 ucp_mem_h mem_h);
226 void add_rdma_info_odr(NetworkSegment *segment, const UCPContext *context);
227 bool am_msg_recv_data_ready(UCPInternal *internal, UCPWorker *worker,
228 const UCPMsgHdr *ucp_msg_hdr, size_t header_size,
229 void *payload, size_t payload_size, int payload_mode);
230 static ucs_status_t am_remote_comp_handler(void *arg, const void *header,
231 size_t header_size, void *data,
232 size_t data_size,
233 const ucp_am_recv_param_t *param);
234 static void am_send_reply_comp_handler(void *request, ucs_status_t status,
235 void *user_data);
236 static void am_realm_comp_handler(NodeID sender,
239 static void am_rndv_recv_data_handler(void *request, ucs_status_t status,
240 size_t length, void *user_data);
241 static ucs_status_t am_msg_recv_handler(void *arg, const void *header,
242 size_t header_size, void *payload,
243 size_t payload_size,
244 const ucp_am_recv_param_t *param);
245 static ucs_status_t am_rdma_msg_recv_handler(void *arg, const void *header,
246 size_t header_size, void *payload,
247 size_t payload_size,
248 const ucp_am_recv_param_t *param);
249
250 bool compute_shared_ranks();
251 using WorkersMap = std::unordered_map<const UCPContext *, Workers>;
252 using AttachMap = std::unordered_map<const UCPContext *, std::vector<ucp_mem_h>>;
253
254#ifdef REALM_UCX_DYNAMIC_LOAD
255 void *libucp{nullptr};
256#endif
257 bool initialized_boot{false};
258 bool initialized_ucp{false};
259 Config config;
260 bootstrap_handle_t boot_handle;
261 std::unique_ptr<ucc::UCCComm> ucc_comm{nullptr};
262 int num_shared_ranks{0};
263 std::vector<NodeID> shared_ranks;
264 std::list<UCPContext> ucp_contexts;
265#ifdef REALM_USE_CUDA
266 std::unordered_map<int, UCPContext *> dev_ctx_map;
267#endif
268 WorkersMap workers;
269 std::list<UCPPoller> pollers;
270 std::list<AmHandlersArgs> am_handlers_args;
271 AttachMap attach_mem_hs;
272 atomic<uint64_t> total_msg_sent;
273 atomic<uint64_t> total_msg_received;
274 atomic<uint64_t> total_rcomp_sent;
275 atomic<uint64_t> total_rcomp_received;
276 atomic<uint64_t> outstanding_reqs;
277 // Monotonic count of requests ever acquired (mirrors
278 // outstanding_reqs.fetch_add(1) in request_get but never decrements).
279 // Sampled as QuiescenceState::events_added so the Mattern's stability
280 // check can detect activity even when outstanding_reqs is the same
281 // value across rounds while individual requests come and go.
282 atomic<uint64_t> total_reqs_acquired;
283 MPool *rcba_mp;
284 SpinLock rcba_mp_spinlock;
285 size_t ib_seg_size;
286 size_t zcopy_thresh_host;
287 };
288
290 public:
291 UCPMessageImpl(UCPInternal *internal, NodeID target, unsigned short msgid,
292 size_t header_size, size_t max_payload_size,
293 const void *src_payload_addr, size_t src_payload_lines,
294 size_t src_payload_line_stride, const NetworkSegment *_src_segment,
295 const RemoteAddress *_dest_payload_addr, size_t storage_size);
296
297 UCPMessageImpl(UCPInternal *internal, const NodeSet &targets, unsigned short msgid,
298 size_t header_size, size_t max_payload_size,
299 const void *src_payload_addr, size_t src_payload_lines,
300 size_t src_payload_line_stride, size_t storage_size);
301
303
304 virtual void *add_local_completion(size_t size);
305 virtual void *add_remote_completion(size_t size);
306
307 virtual void commit(size_t act_payload_size);
308 virtual void cancel();
309
310 private:
311 bool set_inline_payload_base();
312 bool commit_with_rma(ucp_ep_h ep);
313 bool commit_unicast(size_t act_payload_size);
314 bool commit_multicast(size_t act_payload_size);
315 bool send_fast_path(ucp_ep_h ep, size_t act_payload_size);
316 bool send_slow_path(ucp_ep_h ep, size_t act_payload_size, uint32_t flags);
317 Request *make_request(size_t act_payload_size);
318 static void cleanup_request(Request *req, UCPInternal *internal);
319 static bool send_request(Request *req, unsigned am_id);
320 static void am_local_failure_handler(Request *req, UCPInternal *internal);
321 static void am_local_comp_handler(void *request, ucs_status_t status,
322 void *user_data);
323 static void am_put_comp_handler(void *request, ucs_status_t status,
324 void *user_data);
325 static void am_put_flush_comp_handler(void *request, ucs_status_t status,
326 void *user_data);
327
328 UCPInternal *internal;
329 UCPWorker *worker;
330 NodeID target;
331 NodeSet targets;
332 const void *src_payload_addr;
333 size_t src_payload_lines;
334 size_t src_payload_line_stride;
335 size_t header_size;
336 PayloadBaseType payload_base_type;
337 UCPRDMAInfo *dest_payload_rdma_info{nullptr};
338 CompList *local_comp{nullptr};
339 RemoteComp *remote_comp{nullptr};
340 bool is_multicast{false};
341 ucs_memory_type_t memtype;
342
343 UCPMsgHdr ucp_msg_hdr;
344 // nothing should be added after 'ucp_msg_hdr'
345 };
346
348 public:
349 UCPRemoteMemoryCommon(const ByteArray &rdma_info_ba);
350
352
353 virtual bool get_remote_addr(off_t offset, RemoteAddress &remote_addr);
354
355 private:
356 UCPRDMAInfo *rdma_info;
357 size_t rdma_info_size;
358 };
359
360 /* A block of memory on a remote process
361 * Parent class RemoteMemory has node id in me.memory_owner_node()
362 */
364 public:
365 UCPRemoteMemory(RuntimeImpl *_runtime_impl, Memory me, size_t size,
366 Memory::Kind kind, const ByteArray &rdma_info_ba,
367 UCPInternal *internal);
368
369 virtual void get_bytes(off_t offset, void *dst, size_t size);
370 virtual void put_bytes(off_t offset, const void *src, size_t size);
371 virtual bool get_remote_addr(off_t offset, RemoteAddress &remote_addr);
372 };
373
374 // Intermediate buffer memory
376 public:
378 const ByteArray &rdma_info_ba, UCPInternal *internal);
379
380 virtual bool get_remote_addr(off_t offset, RemoteAddress &remote_addr);
381 };
382
383 }; // namespace UCP
384
385}; // namespace Realm
386
387#endif
Definition activemsg.h:221
Definition bgwork.h:129
Definition bytearray.h:53
Definition ib_memory.h:30
uintptr_t CallbackData
Definition activemsg.h:367
Memory me
Definition mem_impl.h:194
size_t size
Definition mem_impl.h:195
MemoryKind kind
Definition mem_impl.h:196
Definition memory.h:33
Kind
Definition memory.h:59
Definition network.h:409
Definition nodeset.h:117
Definition mem_impl.h:549
Definition channel.h:102
Definition runtime_impl.h:267
Definition timers.h:129
Definition ucp_module.h:31
Definition ucp_context.h:152
Definition ucp_internal.h:375
UCPIBMemory(RuntimeImpl *_runtime_impl, Memory me, size_t size, Memory::Kind kind, const ByteArray &rdma_info_ba, UCPInternal *internal)
virtual bool get_remote_addr(off_t offset, RemoteAddress &remote_addr)
Definition ucp_internal.h:104
void allgather(const char *val_in, size_t bytes, std::vector< char > &vals_out, size_t *lengths)
void allgatherv(const char *val_in, size_t bytes, std::vector< char > &vals_out, std::vector< size_t > &lengths)
void detach(std::vector< NetworkSegment * > &segments)
UCPInternal(Realm::UCPModule *_module, Realm::RuntimeImpl *_runtime)
void notify_msg_sent(uint64_t count)
Request * request_get(UCPWorker *worker)
UCPModule *RuntimeImpl * runtime
Definition ucp_internal.h:186
void broadcast(NodeID root, const void *val_in, void *val_out, size_t bytes)
UCPWorker * get_tx_worker(const UCPContext *context, uint8_t priority) const
void get_shared_peers(Realm::NodeSet &shared_peers)
size_t num_eps(const UCPContext &context) const
void * hbuf_get(UCPWorker *worker, size_t size)
void * pbuf_get(UCPWorker *worker, size_t size)
void quiescence_allreduce_sum(const uint64_t *local_counts, uint64_t *total_counts, size_t count)
void hbuf_release(UCPWorker *worker, void *buf)
const UCPContext * get_context(const NetworkSegment *segment) const
void pbuf_release(UCPWorker *worker, void *buf)
size_t recommended_max_payload(const void *data, const NetworkSegment *src_segment, const RemoteAddress *dest_payload_addr, bool with_congestion, size_t header_size)
void request_release(Request *req)
bool init(const Config &config)
void sample_quiescence_state(NetworkModule::QuiescenceState &state)
void attach(std::vector< NetworkSegment * > &segments)
bool get_ucp_ep(const UCPWorker *worker, NodeID target, const UCPRDMAInfo *rdma_info, ucp_ep_h *ep) const
void gather(NodeID root, const void *val_in, void *vals_out, size_t bytes)
Definition ucp_internal.h:289
virtual void commit(size_t act_payload_size)
UCPMessageImpl(UCPInternal *internal, NodeID target, unsigned short msgid, size_t header_size, size_t max_payload_size, const void *src_payload_addr, size_t src_payload_lines, size_t src_payload_line_stride, const NetworkSegment *_src_segment, const RemoteAddress *_dest_payload_addr, size_t storage_size)
virtual void * add_local_completion(size_t size)
UCPMessageImpl(UCPInternal *internal, const NodeSet &targets, unsigned short msgid, size_t header_size, size_t max_payload_size, const void *src_payload_addr, size_t src_payload_lines, size_t src_payload_line_stride, size_t storage_size)
virtual void * add_remote_completion(size_t size)
Definition ucp_internal.h:82
bool do_work(TimeLimit work_until)
void add_worker(UCPWorker *worker)
Definition ucp_internal.h:347
virtual bool get_remote_addr(off_t offset, RemoteAddress &remote_addr)
UCPRemoteMemoryCommon(const ByteArray &rdma_info_ba)
Definition ucp_internal.h:363
virtual bool get_remote_addr(off_t offset, RemoteAddress &remote_addr)
UCPRemoteMemory(RuntimeImpl *_runtime_impl, Memory me, size_t size, Memory::Kind kind, const ByteArray &rdma_info_ba, UCPInternal *internal)
virtual void get_bytes(off_t offset, void *dst, size_t size)
virtual void put_bytes(off_t offset, const void *src, size_t size)
Definition ucp_context.h:40
Definition mutex.h:325
Definition mutex.h:223
Definition atomics.h:31
PayloadBaseType
Definition ucp_internal.h:57
@ PAYLOAD_BASE_EXTERNAL
Definition ucp_internal.h:60
@ PAYLOAD_BASE_LAST
Definition ucp_internal.h:61
@ PAYLOAD_BASE_INTERNAL
Definition ucp_internal.h:59
@ PAYLOAD_BASE_INLINE
Definition ucp_internal.h:58
Realm::UCP::UCPPoller __attribute__
AmWithRemoteAddrMode
Definition ucp_internal.h:50
@ AM_WITH_REMOTE_ADDR_MODE_PUT
Definition ucp_internal.h:52
@ AM_WITH_REMOTE_ADDR_MODE_AUTO
Definition ucp_internal.h:51
@ AM_WITH_REMOTE_ADDR_MODE_AM
Definition ucp_internal.h:53
Definition activemsg.h:42
int NodeID
Definition nodeset.h:40
Definition network.h:46
Definition ucp_internal.h:108
int rdesc_rel_max
Definition ucp_internal.h:115
bool use_wakeup
Definition ucp_internal.h:120
std::string zcopy_thresh_host
Definition ucp_internal.h:132
size_t outstanding_reqs_limit
Definition ucp_internal.h:129
std::string host_nics
Definition ucp_internal.h:131
std::string ib_seg_size
Definition ucp_internal.h:130
int num_priorities
Definition ucp_internal.h:112
int prog_itr_max
Definition ucp_internal.h:114
size_t pbuf_mp_max_count
Definition ucp_internal.h:125
size_t pbuf_mp_thresh
Definition ucp_internal.h:127
size_t pbuf_mp_max_size
Definition ucp_internal.h:123
bool pbuf_malloc
Definition ucp_internal.h:119
size_t pbuf_mp_max_chunk_size
Definition ucp_internal.h:124
size_t fp_max
Definition ucp_internal.h:122
size_t priority_size_max
Definition ucp_internal.h:121
size_t pbuf_mp_init_count
Definition ucp_internal.h:126
std::string tls_host
Definition ucp_internal.h:133
int prog_boff_max
Definition ucp_internal.h:113
bool bind_hostmem
Definition ucp_internal.h:110
size_t mmp_max_obj_size
Definition ucp_internal.h:128
bool hbuf_malloc
Definition ucp_internal.h:118
bool mpool_leakcheck
Definition ucp_internal.h:116
AmWithRemoteAddrMode am_wra_mode
Definition ucp_internal.h:109
int pollers_max
Definition ucp_internal.h:111
bool crc_check
Definition ucp_internal.h:117
Definition ucp_internal.h:69
char realm_hdr[0]
Definition ucp_internal.h:79
uint32_t crc
Definition ucp_internal.h:70
size_t rdma_payload_size
Definition ucp_internal.h:75
unsigned short msgid
Definition ucp_internal.h:72
RemoteComp * remote_comp
Definition ucp_internal.h:73
NodeID src
Definition ucp_internal.h:71
void * rdma_payload_addr
Definition ucp_internal.h:74
Definition bootstrap.h:32
NodeID src
Definition ucp_internal.h:1
unsigned short msgid
Definition ucp_internal.h:2