use std::sync::Arc;
use burn_remote::Endpoint;
use burn_remote::server::{CustomOpRegistry, IrohRemoteProtocol, PeerAuthorizer, RemoteProtocol};
use burn_remote::telemetry::TelemetryProbe;
use crate::backends::*;
use crate::{Dispatch, DispatchDevice, DispatchDeviceId};
pub use burn_remote::server::Channel;
macro_rules! host_devices {
($id:expr, $variant:ident) => {{
let devices = Dispatch::enumerate($id)
.into_iter()
.filter_map(|device| match device {
DispatchDevice::$variant(device) => Some(device),
_ => 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(feature = "cpu")]
DispatchDevice::Cpu(_) => {
type $b = Cpu;
let $devices = host_devices!(DispatchDeviceId::Cpu, Cpu);
$body
}
#[cfg(feature = "cuda")]
DispatchDevice::Cuda(_) => {
type $b = Cuda;
let $devices = host_devices!(DispatchDeviceId::Cuda, Cuda);
$body
}
#[cfg(feature = "metal")]
DispatchDevice::Metal(_) => {
type $b = Metal;
let $devices = host_devices!(DispatchDeviceId::Metal, Metal);
$body
}
#[cfg(feature = "rocm")]
DispatchDevice::Rocm(_) => {
type $b = Rocm;
let $devices = host_devices!(DispatchDeviceId::Rocm, Rocm);
$body
}
#[cfg(feature = "vulkan")]
DispatchDevice::Vulkan(_) => {
type $b = Vulkan;
let $devices = host_devices!(DispatchDeviceId::Vulkan, Vulkan);
$body
}
#[cfg(feature = "wgpu")]
DispatchDevice::Wgpu(_) => {
type $b = Wgpu;
let $devices = host_devices!(DispatchDeviceId::Wgpu, Wgpu);
$body
}
#[cfg(feature = "webgpu")]
DispatchDevice::WebGpu(_) => {
type $b = WebGpu;
let $devices = host_devices!(DispatchDeviceId::WebGpu, WebGpu);
$body
}
#[cfg(any(feature = "flex", default_backend))]
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 = "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(),
))
})
}