use std::sync::Arc;
use burn_remote::Endpoint;
use burn_remote::server::{CustomOpRegistry, IrohRemoteProtocol, PeerAuthorizer, RemoteProtocol};
use burn_remote::telemetry::TelemetryProbe;
use crate::DispatchDevice;
use crate::backends::*;
#[cfg(any(feature = "flex", feature = "ndarray"))]
use crate::{Dispatch, DispatchDeviceId};
pub use burn_remote::server::Channel;
macro_rules! host_devices {
(cube: $device:expr) => {{
let devices = $crate::backend::cube_devices($device.runtime());
if devices.len() > 1 {
devices
} else {
vec![$device.clone()]
}
}};
($id:expr, $variant:ident) => {{
let devices = Dispatch::enumerate($id)
.into_iter()
.filter_map(|device| match device {
DispatchDevice::$variant(device) => Some(device),
#[allow(unreachable_patterns)]
_ => None,
})
.collect::<Vec<_>>();
if devices.len() > 1 {
devices
} else {
vec![Default::default()]
}
}};
}
macro_rules! with_backend {
($device:expr, |$b:ident, $devices:ident| $body:expr) => {
match $device.inner() {
#[cfg(cube_backend)]
DispatchDevice::Cube(device) => {
type $b = Cube;
let $devices = host_devices!(cube: device);
$body
}
#[cfg(feature = "flex")]
DispatchDevice::Flex(_) => {
type $b = Flex;
let $devices = host_devices!(DispatchDeviceId::Flex, Flex);
$body
}
#[cfg(feature = "ndarray")]
DispatchDevice::NdArray(_) => {
type $b = NdArray;
let $devices = host_devices!(DispatchDeviceId::NdArray, NdArray);
$body
}
#[cfg(feature = "tch")]
DispatchDevice::LibTorch(_) => {
panic!("LibTorch is not supported as a remote-server backend (no BackendIr impl)")
}
#[cfg(feature = "remote")]
DispatchDevice::Remote(_) => {
panic!("Cannot host a remote server on a remote device")
}
#[cfg(feature = "capture")]
DispatchDevice::Capture(_) => {
panic!("Cannot host a remote server on a capture device")
}
#[cfg(feature = "autodiff")]
DispatchDevice::Autodiff(_) => {
unreachable!("Autodiff stripped by .inner() above")
}
}
};
}
#[cfg(not(target_family = "wasm"))]
pub fn start(device: DispatchDevice, channel: Channel) {
with_backend!(device, |B, devices| {
burn_remote::server::RemoteServerBuilder::<B>::new(devices)
.channel(channel)
.start()
})
}
#[cfg(not(target_family = "wasm"))]
pub async fn start_async(device: DispatchDevice, channel: Channel) {
with_backend!(device, |B, devices| {
burn_remote::server::RemoteServerBuilder::<B>::new(devices)
.channel(channel)
.start_async()
.await
})
}
pub fn remote_protocol(
device: DispatchDevice,
endpoint: &Endpoint,
probe: TelemetryProbe,
authorizer: Arc<dyn PeerAuthorizer>,
) -> RemoteProtocol {
with_backend!(device, |B, devices| {
RemoteProtocol::new(IrohRemoteProtocol::<B>::new(
endpoint.clone(),
devices,
authorizer,
probe,
CustomOpRegistry::default(),
))
})
}