use super::{AdaptiveMemory, ExclusivePools};
use crate::memory_management::Cleanup;
use crate::memory_management::relocation::{CopyQueue, RelocationNeed, RelocationReason};
use crate::{
config::memory::MemoryLogLevel,
logging::ServerLogger,
memory_management::{
ErrorGraph, ManagedMemoryBinding, ManagedMemoryHandle, MemoryConfiguration,
MemoryPoolReport,
memory_pool::{MemoryPool, PageMapping},
},
server::IoError,
storage::ComputeStorage,
};
use alloc::{boxed::Box, format, string::String, vec::Vec};
use cubecl_environment::sync::Arc;
use cubecl_ir::MemoryDeviceProperties;
pub enum DynamicMemory {
Exclusive(ExclusivePools),
Adaptive(Box<AdaptiveMemory>),
}
impl DynamicMemory {
pub fn new(
properties: &MemoryDeviceProperties,
config: MemoryConfiguration,
logger: Arc<ServerLogger>,
name: String,
) -> Self {
match config {
MemoryConfiguration::ExclusivePages => {
let pools = ExclusivePools::new(properties);
logger.log_memory(
|level| !matches!(level, MemoryLogLevel::Disabled),
|| format!("[{name}] Using memory pools:\n{pools}"),
);
DynamicMemory::Exclusive(pools)
}
#[allow(unreachable_patterns)]
_ => DynamicMemory::Adaptive(Box::new(AdaptiveMemory::new(properties, logger, name))),
}
}
pub fn pool(&self, index: u8) -> Option<&dyn MemoryPool> {
match self {
DynamicMemory::Exclusive(pools) => Some(pools.pool(index)?),
DynamicMemory::Adaptive(memory) => memory.pool(index),
}
}
pub fn pool_mut(&mut self, index: u8) -> Option<&mut dyn MemoryPool> {
match self {
DynamicMemory::Exclusive(pools) => Some(pools.pool_mut(index)?),
DynamicMemory::Adaptive(memory) => memory.pool_mut(index),
}
}
pub fn materialize<Storage: ComputeStorage>(
&mut self,
storage: &mut Storage,
binding: &ManagedMemoryBinding,
) -> Result<(), IoError> {
match self {
DynamicMemory::Exclusive(_) => Ok(()),
DynamicMemory::Adaptive(memory) => memory.materialize(storage, binding),
}
}
pub fn reserve<Storage: ComputeStorage>(
&mut self,
storage: &mut Storage,
size: u64,
mapping: PageMapping,
failures: &mut ErrorGraph,
) -> Result<ManagedMemoryHandle, IoError> {
match self {
DynamicMemory::Exclusive(pools) => pools.reserve(storage, size, mapping, failures),
DynamicMemory::Adaptive(memory) => memory.reserve(storage, size, mapping, failures),
}
}
pub fn try_reserve(
&mut self,
size: u64,
failures: &mut ErrorGraph,
) -> Option<ManagedMemoryHandle> {
match self {
DynamicMemory::Exclusive(pools) => pools.try_reserve(size, failures),
DynamicMemory::Adaptive(memory) => memory.try_reserve(size, failures),
}
}
pub fn has_outdated(&self) -> bool {
match self {
DynamicMemory::Exclusive(_) => false,
DynamicMemory::Adaptive(memory) => memory.has_outdated(),
}
}
pub fn relocation_need(&self) -> RelocationNeed {
match self {
DynamicMemory::Exclusive(_) => RelocationNeed::Nothing,
DynamicMemory::Adaptive(memory) => memory.relocation_need(),
}
}
pub fn relocate<Storage: ComputeStorage>(
&mut self,
storage: &mut Storage,
copier: &mut dyn CopyQueue<Storage>,
reason: RelocationReason,
failures: &mut ErrorGraph,
) {
match self {
DynamicMemory::Exclusive(_) => {}
DynamicMemory::Adaptive(memory) => memory.relocate(storage, copier, reason, failures),
}
}
pub fn cleanup<Storage: ComputeStorage>(
&mut self,
storage: &mut Storage,
alloc_nr: u64,
cleanup: Cleanup,
failures: &mut ErrorGraph,
) {
match self {
DynamicMemory::Exclusive(pools) => pools.cleanup(storage, alloc_nr, cleanup, failures),
DynamicMemory::Adaptive(memory) => memory.cleanup(storage, alloc_nr, cleanup, failures),
}
}
pub fn report(&self) -> Vec<MemoryPoolReport> {
match self {
DynamicMemory::Exclusive(pools) => pools.report(),
DynamicMemory::Adaptive(memory) => memory.report(),
}
}
}
impl core::fmt::Display for DynamicMemory {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
DynamicMemory::Exclusive(pools) => write!(f, "{pools}"),
DynamicMemory::Adaptive(memory) => write!(f, "{memory}"),
}
}
}