burn_dispatch/ops/
distributed.rs1use alloc::vec::Vec;
2
3use burn_backend::{
4 DeviceId,
5 distributed::{
6 CollectiveTensor, DistributedConfig, DistributedOps, DistributedParams, ReduceOperation,
7 TensorRef,
8 },
9 tensor::FloatTensor,
10};
11
12use crate::{Dispatch, DispatchDevice};
13
14macro_rules! dispatch_distributed_devices_arms {
15 (
16 $device:expr,
17 $devices:expr,
18 |$inner_devices:ident| $body:expr;
19 $([$Backend:ident, $cfg:meta]),*
20 ) => {
21 match $device {
22 #[cfg(feature = "autodiff")]
24 $crate::DispatchDevice::Autodiff(inner) => {
25 let inner_devices = $devices
26 .iter()
27 .map(|d| {
28 match &d {
29 #[cfg(feature = "autodiff")]
30 $crate::DispatchDevice::Autodiff(d_inner) => *d_inner.inner.clone(),
31 _ => unreachable!("All devices are expected to be of the same variant."),
32 }
33 })
34 .collect::<Vec<_>>();
35 let inner_devices = inner_devices.as_slice();
36 dispatch_distributed_devices_arms!(
38 @autodiff
39 &**inner,
40 &*inner_devices,
41 |$inner_devices| $body;
42 $([$Backend, $cfg]),*
43 )
44 },
45 $(
46 #[cfg($cfg)]
47 $crate::DispatchDevice::$Backend(_) => {
48 type B = $crate::backends::$Backend;
49 let $inner_devices = $devices
50 .iter()
51 .map(|d| {
52 #[allow(irrefutable_let_patterns)]
56 let DispatchDevice::$Backend(dev) = d else {
57 unreachable!("All devices are expected to be of the same variant.")
58 };
59 dev.clone()
60 })
61 .collect::<Vec<_>>();
62 $body
63 }
64 )*
65 #[allow(unreachable_patterns)]
66 other => panic!("Distributed operations are not supported for device {other:?}"),
67 }
68 };
69 (
70 @autodiff
71 $device:expr,
72 $devices:expr,
73 |$inner_devices:ident| $body:expr;
74 $([$Backend:ident, $cfg:meta]),*
75 ) => {
76 match $device {
77 $(
78 #[cfg($cfg)]
79 $crate::DispatchDevice::$Backend(_) => {
80 type B = $crate::backends::Autodiff<$crate::backends::$Backend>;
81 let $inner_devices = $devices
82 .iter()
83 .map(|d| {
84 #[allow(irrefutable_let_patterns)]
88 let DispatchDevice::$Backend(dev) = d else {
89 unreachable!("All devices are expected to be of the same variant.")
90 };
91 dev.clone()
92 })
93 .collect::<Vec<_>>();
94 $body
95 }
96 )*
97 $crate::DispatchDevice::Autodiff(_) => panic!("Autodiff should not wrap an autodiff device."),
98 #[allow(unreachable_patterns)]
99 other => panic!("Distributed operations are not supported for device {other:?}"),
100 }
101 };
102}
103
104macro_rules! dispatch_distributed_devices {
106 ($device:expr, $devices:expr, |$inner_devices:ident| $body:expr) => {
107 distributed_backend_list!(
108 dispatch_distributed_devices_arms,
109 $device,
110 $devices,
111 |$inner_devices| $body
112 )
113 };
114}
115
116macro_rules! dispatch_distributed_float_arms {
117 ($tensor:expr, |$inner:ident| $body:expr; $([$Backend:ident, $cfg:meta]),*) => {{
118 let autodiff = $tensor.autodiff;
119 match $tensor.kind {
120 #[cfg(feature = "autodiff")]
121 $crate::DispatchTensorKind::Autodiff(inner) => match *inner {
122 $(
123 #[cfg($cfg)]
124 $crate::DispatchTensorKind::$Backend($inner) => {
125 let $crate::DispatchAutodiffContext::Enabled(checkpointing) = autodiff else {
126 panic!("an autodiff float primitive must have an enabled autodiff context")
127 };
128 with_autodiff_backend!($Backend, checkpointing, |B| {
129 let $inner = $inner.autodiff();
130 $crate::DispatchTensor {
131 kind: $crate::DispatchTensorKind::Autodiff(alloc::boxed::Box::new(
132 $crate::DispatchTensorKind::$Backend(
133 $crate::BackendTensor::Autodiff($body),
134 ),
135 )),
136 autodiff,
137 }
138 })
139 }
140 )*
141 #[allow(unreachable_patterns)]
142 other => panic!("Distributed operations are not supported for tensor kind {other:?}"),
143 },
144 $(
145 #[cfg($cfg)]
146 $crate::DispatchTensorKind::$Backend($inner) => {
147 assert_eq!(
148 autodiff,
149 $crate::DispatchAutodiffContext::Disabled,
150 "an enabled float tensor must use an autodiff primitive",
151 );
152 type B = $crate::backends::$Backend;
153 let $inner = $inner.float();
154 $crate::DispatchTensor {
155 kind: $crate::DispatchTensorKind::$Backend(
156 $crate::BackendTensor::Float($body),
157 ),
158 autodiff,
159 }
160 }
161 )*
162 #[allow(unreachable_patterns)]
163 other => panic!("Distributed operations are not supported for tensor kind {other:?}"),
164 }
165 }};
166}
167
168macro_rules! dispatch_distributed_float {
169 ($tensor:expr, |$inner:ident| $body:expr) => {
170 distributed_backend_list!(dispatch_distributed_float_arms, $tensor, |$inner| $body)
171 };
172}
173
174#[allow(unused_variables, unreachable_code)]
178impl DistributedOps<Self> for Dispatch {
179 fn start_communication_server(devices: &[DispatchDevice], config: DistributedConfig) {
180 if !devices.is_empty() {
181 let first = &devices[0];
182 dispatch_distributed_devices!(first, devices, |inner_devices| {
183 B::start_communication_server(&inner_devices, config)
184 });
185 }
186 }
187
188 fn close_communication_server(device: &DispatchDevice) {
189 dispatch_device!(@distributed device, |device| {
190 B::close_communication_server(device)
191 })
192 }
193
194 fn register_sync_parameters(
195 device: &DispatchDevice,
196 sharded_param_ids: Vec<DistributedParams>,
197 ) {
198 dispatch_device!(@distributed device, |device| B::register_sync_parameters(
199 device,
200 sharded_param_ids,
201 ))
202 }
203
204 fn submit_sync_collective(device: &DispatchDevice) {
205 dispatch_device!(@distributed device, |device| B::submit_sync_collective(device))
206 }
207
208 fn submit_gradient_sync(_tensor: TensorRef<Self>, _distributed_params: DistributedParams) {
209 unimplemented!()
210 }
211
212 fn all_reduce(
213 tensor: FloatTensor<Self>,
214 op: ReduceOperation,
215 device_ids: Vec<DeviceId>,
216 ) -> CollectiveTensor<Self> {
217 let tensor: FloatTensor<Self> = dispatch_distributed_float!(tensor, |tensor| {
222 let collective_tensor = B::all_reduce(tensor, op, device_ids);
223 unsafe { collective_tensor.assume_resolved() }
224 });
225 CollectiveTensor::new(tensor)
226 }
227
228 fn sync_collective(device: &DispatchDevice) {
229 dispatch_device!(@distributed device, |device| B::sync_collective(device))
230 }
231
232 unsafe fn comm_device(_tensor: &TensorRef<Self>) -> DispatchDevice {
233 unimplemented!()
234 }
235
236 unsafe fn float_from_ref(_tensor: &TensorRef<Self>) -> FloatTensor<Self> {
237 unimplemented!()
238 }
239}