use crate::{
memory_management::{
memory_pool::{SliceBinding, SliceHandle},
MemoryHandle, MemoryUsage,
},
storage::{BindingResource, ComputeStorage},
ExecutionMode,
};
use alloc::vec::Vec;
use core::{fmt::Debug, future::Future};
use cubecl_common::benchmark::TimestampsResult;
pub trait ComputeServer: Send + core::fmt::Debug
where
Self: Sized,
{
type Kernel: Send;
type Storage: ComputeStorage;
type Feature: Ord + Copy + Debug + Send + Sync;
fn read(
&mut self,
bindings: Vec<Binding>,
) -> impl Future<Output = Vec<Vec<u8>>> + Send + 'static;
fn get_resource(&mut self, binding: Binding) -> BindingResource<Self>;
fn create(&mut self, data: &[u8]) -> Handle;
fn empty(&mut self, size: usize) -> Handle;
unsafe fn execute(
&mut self,
kernel: Self::Kernel,
count: CubeCount,
bindings: Vec<Binding>,
kind: ExecutionMode,
);
fn flush(&mut self);
fn sync(&mut self) -> impl Future<Output = ()> + Send + 'static;
fn sync_elapsed(&mut self) -> impl Future<Output = TimestampsResult> + Send + 'static;
fn memory_usage(&self) -> MemoryUsage;
fn enable_timestamps(&mut self);
fn disable_timestamps(&mut self);
}
#[derive(new, Debug)]
pub struct Handle {
pub memory: SliceHandle,
pub offset_start: Option<u64>,
pub offset_end: Option<u64>,
size: u64,
}
impl Handle {
pub fn offset_start(mut self, offset: u64) -> Self {
if let Some(val) = &mut self.offset_start {
*val += offset;
} else {
self.offset_start = Some(offset);
}
self
}
pub fn offset_end(mut self, offset: u64) -> Self {
if let Some(val) = &mut self.offset_end {
*val += offset;
} else {
self.offset_end = Some(offset);
}
self
}
pub fn size(&self) -> u64 {
self.size - self.offset_start.unwrap_or(0) - self.offset_end.unwrap_or(0)
}
}
#[derive(new, Debug)]
pub struct Binding {
pub memory: SliceBinding,
pub offset_start: Option<u64>,
pub offset_end: Option<u64>,
}
impl Handle {
pub fn can_mut(&self) -> bool {
self.memory.can_mut()
}
}
impl Handle {
pub fn binding(self) -> Binding {
Binding {
memory: MemoryHandle::binding(self.memory),
offset_start: self.offset_start,
offset_end: self.offset_end,
}
}
}
impl Clone for Handle {
fn clone(&self) -> Self {
Self {
memory: self.memory.clone(),
offset_start: self.offset_start,
offset_end: self.offset_end,
size: self.size,
}
}
}
impl Clone for Binding {
fn clone(&self) -> Self {
Self {
memory: self.memory.clone(),
offset_start: self.offset_start,
offset_end: self.offset_end,
}
}
}
pub enum CubeCount {
Static(u32, u32, u32),
Dynamic(Binding),
}
impl CubeCount {
pub fn new_single() -> Self {
CubeCount::Static(1, 1, 1)
}
pub fn new_1d(x: u32) -> Self {
CubeCount::Static(x, 1, 1)
}
pub fn new_2d(x: u32, y: u32) -> Self {
CubeCount::Static(x, y, 1)
}
pub fn new_3d(x: u32, y: u32) -> Self {
CubeCount::Static(x, y, 1)
}
}
impl Debug for CubeCount {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
CubeCount::Static(x, y, z) => f.write_fmt(format_args!("({x}, {y}, {z})")),
CubeCount::Dynamic(_) => f.write_str("binding"),
}
}
}
impl Clone for CubeCount {
fn clone(&self) -> Self {
match self {
Self::Static(x, y, z) => Self::Static(*x, *y, *z),
Self::Dynamic(handle) => Self::Dynamic(handle.clone()),
}
}
}