metrale_comm/nccl_backend/
recv_buffer.rs1use anyhow::{Context, Result};
13
14pub const ALL_REDUCE_DTYPE_BYTES: usize = 2;
18
19pub fn required_recv_bytes(
24 max_batch_tokens: usize,
25 hidden_size: usize,
26 dtype_bytes: usize,
27) -> Result<usize> {
28 max_batch_tokens
29 .checked_mul(hidden_size)
30 .and_then(|elems| elems.checked_mul(dtype_bytes))
31 .with_context(|| {
32 format!(
33 "receive-buffer size overflows usize: \
34 max_batch_tokens={max_batch_tokens} × hidden_size={hidden_size} \
35 × dtype_bytes={dtype_bytes}"
36 )
37 })
38}
39
40pub fn required_model_recv_bytes(tokens: usize, hidden: usize, vocab: usize) -> Result<usize> {
47 required_recv_bytes(tokens, hidden.max(vocab), ALL_REDUCE_DTYPE_BYTES)
48}
49
50pub(crate) fn ensure_payload_fits(
53 bytes: usize,
54 capacity: usize,
55 rank: usize,
56 world_size: usize,
57) -> Result<()> {
58 if bytes > capacity {
59 anyhow::bail!(
60 "2-rank all-reduce payload exceeds receive-buffer capacity: \
61 requested {bytes} bytes ({} elements × {ALL_REDUCE_DTYPE_BYTES} B/elem), \
62 capacity {capacity} bytes, rank {rank}, world_size {world_size}. \
63 The receive buffer is sized from the configured maximum transfer \
64 (max_batch_tokens × hidden_size × {ALL_REDUCE_DTYPE_BYTES} B); a larger \
65 payload would write past the allocation. Refusing to send.",
66 bytes / ALL_REDUCE_DTYPE_BYTES,
67 );
68 }
69 Ok(())
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75
76 const BF16: usize = 2;
77 const FP32: usize = 4;
78
79 #[test]
80 fn short_prefill_still_covers_vocab_parallel_logits() {
81 let capacity = required_model_recv_bytes(33, 1024, 163840).unwrap();
82 assert!(ensure_payload_fits(163584 * 2, capacity, 0, 2).is_ok());
83 assert!(ensure_payload_fits(33 * 163840 * 2, capacity, 0, 2).is_ok());
84 assert!(required_model_recv_bytes(usize::MAX, 1024, 163840).is_err());
85 assert_eq!(required_model_recv_bytes(2, 4096, 1024).unwrap(), 16384);
86 }
87
88 const OLD_FIXED_BUFFER: usize = 64 * 1024 * 1024;
90
91 #[test]
93 fn all_reduce_dtype_width_is_bf16() {
94 assert_eq!(ALL_REDUCE_DTYPE_BYTES, BF16);
95 }
96
97 #[test]
100 fn exact_boundary_bf16() {
101 let need = required_recv_bytes(8192, 4096, BF16).unwrap();
102 assert_eq!(need, 67_108_864);
103 assert_eq!(
104 need, OLD_FIXED_BUFFER,
105 "DS4F default sat exactly on the cap"
106 );
107 assert!(ensure_payload_fits(need, need, 0, 2).is_ok());
108 }
109
110 #[test]
113 fn over_boundary_bf16() {
114 let need = required_recv_bytes(8193, 4096, BF16).unwrap();
115 assert_eq!(need, 67_117_056);
116 assert!(need > OLD_FIXED_BUFFER);
117 assert!(ensure_payload_fits(need, need, 0, 2).is_ok());
118 assert!(ensure_payload_fits(need, OLD_FIXED_BUFFER, 0, 2).is_err());
119 }
120
121 #[test]
124 fn wide_model_bf16() {
125 let need = required_recv_bytes(8192, 6144, BF16).unwrap();
126 assert_eq!(need, 100_663_296);
127 assert_eq!(
128 need - OLD_FIXED_BUFFER,
129 33_554_432,
130 "the overrun this fixes"
131 );
132 assert!(ensure_payload_fits(need, need, 0, 2).is_ok());
133 assert!(ensure_payload_fits(need, OLD_FIXED_BUFFER, 0, 2).is_err());
134 }
135
136 #[test]
138 fn fp32_is_representable() {
139 let need = required_recv_bytes(8192, 4096, FP32).unwrap();
140 assert_eq!(need, 134_217_728);
141 assert_eq!(need, 2 * required_recv_bytes(8192, 4096, BF16).unwrap());
142 assert_eq!(
143 need,
144 2 * OLD_FIXED_BUFFER,
145 "FP32 would have been a 2× overrun"
146 );
147 assert!(ensure_payload_fits(need, need, 0, 2).is_ok());
148 }
149
150 #[test]
152 fn decode_b1_bf16() {
153 let cap = required_recv_bytes(8192, 4096, BF16).unwrap();
154 let decode = 4096 * BF16;
155 assert_eq!(decode, 8_192);
156 assert!(ensure_payload_fits(decode, cap, 0, 2).is_ok());
157 }
158
159 #[test]
162 fn zero_elements() {
163 let cap = required_recv_bytes(8192, 4096, BF16).unwrap();
164 assert_eq!(required_recv_bytes(0, 4096, BF16).unwrap(), 0);
165 assert!(ensure_payload_fits(0, cap, 0, 2).is_ok());
166 assert!(ensure_payload_fits(0, 0, 0, 2).is_ok());
167 }
168
169 #[test]
171 fn overflow_is_rejected() {
172 assert!(required_recv_bytes(usize::MAX, 4096, BF16).is_err());
173 assert!(required_recv_bytes(usize::MAX, 1, 2).is_err());
174 assert!(required_recv_bytes(usize::MAX / 2 + 1, 2, 1).is_err());
175 assert!(required_recv_bytes(1 << 62, 4, 1).is_err());
177 }
178
179 #[test]
182 fn one_byte_short_is_rejected() {
183 let need = required_recv_bytes(8192, 4096, BF16).unwrap();
184 let err = ensure_payload_fits(need, need - 1, 1, 2)
185 .unwrap_err()
186 .to_string();
187 assert!(
188 err.contains(&need.to_string()),
189 "must report requested bytes: {err}"
190 );
191 assert!(
192 err.contains(&(need - 1).to_string()),
193 "must report capacity: {err}"
194 );
195 assert!(err.contains("world_size 2"), "must report the path: {err}");
196 }
197}