use std::collections::HashMap;
use std::time::{Duration, Instant};
use super::super::{GeneratedCode, TPUConfig, TPUVersion};
use crate::error::{OptimError, Result};
use crate::main_types::PodTopology;
pub struct RuntimeIntegration {
target_config: TPUConfig,
runtime_config: RuntimeConfig,
device_manager: DeviceManager,
executable_manager: ExecutableManager,
memory_manager: RuntimeMemoryManager,
integration_stats: RuntimeIntegrationStats,
}
#[derive(Debug, Clone)]
pub struct RuntimeConfig {
pub async_execution: bool,
pub enable_profiling: bool,
pub max_concurrent_executions: usize,
pub memory_pool_size: usize,
pub operation_timeout_ms: u64,
pub enable_error_checking: bool,
pub optimization_level: RuntimeOptimizationLevel,
}
#[derive(Debug, Clone)]
pub enum RuntimeOptimizationLevel {
None,
Basic,
Aggressive,
Maximum,
}
#[derive(Debug, Default)]
pub struct RuntimeIntegrationStats {
pub executables_created: usize,
pub total_executions: usize,
pub avg_execution_time_us: u64,
pub peak_memory_usage: usize,
pub device_utilization: f64,
pub runtime_overhead_us: u64,
pub error_count: usize,
}
pub struct DeviceManager {
available_devices: Vec<TPUDevice>,
device_assignments: HashMap<String, usize>,
device_status: HashMap<usize, DeviceStatus>,
capabilities_cache: HashMap<usize, DeviceCapabilities>,
}
#[derive(Debug, Clone)]
pub struct TPUDevice {
pub id: usize,
pub device_type: TPUDeviceType,
pub version: TPUVersion,
pub memory_capacity: usize,
pub compute_throughput: f64,
pub state: DeviceState,
pub last_health_check: Instant,
}
#[derive(Debug, Clone)]
pub enum TPUDeviceType {
SingleChip,
Pod,
Slice,
Virtual,
}
#[derive(Debug, Clone)]
pub enum DeviceState {
Available,
InUse,
Initializing,
Error(String),
Maintenance,
}
#[derive(Debug, Default)]
pub struct DeviceStatus {
pub utilization: f64,
pub memory_usage: usize,
pub temperature: f32,
pub power_consumption: f32,
pub error_flags: Vec<String>,
pub performance_counters: HashMap<String, u64>,
}
#[derive(Debug, Clone)]
pub struct DeviceCapabilities {
pub supported_dtypes: Vec<String>,
pub max_matrix_dims: (usize, usize),
pub vector_width: usize,
pub memory_bandwidth: f64,
pub special_instructions: Vec<String>,
pub interconnect_capabilities: InterconnectCapabilities,
}
#[derive(Debug, Clone)]
pub struct InterconnectCapabilities {
pub inter_chip_bandwidth: f64,
pub inter_pod_bandwidth: f64,
pub collective_ops: Vec<String>,
pub topology_type: TopologyType,
}
#[derive(Debug, Clone)]
pub enum TopologyType {
Mesh,
Torus,
Tree,
Custom(String),
}
pub struct ExecutableManager {
executable_cache: ExecutableCache,
}
#[derive(Debug)]
pub struct TPUExecutable {
pub id: String,
pub binary: Vec<u8>,
pub metadata: ExecutableMetadata,
pub input_specs: Vec<BufferSpec>,
pub output_specs: Vec<BufferSpec>,
pub resource_requirements: ExecutableResourceRequirements,
pub performance_profile: ExecutionProfile,
}
#[derive(Debug, Clone)]
pub struct ExecutableMetadata {
pub compilation_time: Instant,
pub compiler_version: String,
pub target_requirements: TargetRequirements,
pub optimization_level: String,
pub debug_info: Option<DebugInfo>,
}
#[derive(Debug, Clone)]
pub struct BufferSpec {
pub name: String,
pub size: usize,
pub dtype: String,
pub shape: Vec<usize>,
pub alignment: usize,
pub access_pattern: BufferAccessPattern,
}
#[derive(Debug, Clone)]
pub enum BufferAccessPattern {
Sequential,
Random,
Strided(usize),
ReadOnly,
WriteOnly,
}
#[derive(Debug, Default)]
pub struct ExecutableResourceRequirements {
pub memory_bytes: usize,
pub compute_flops: u64,
pub communication_bytes: usize,
pub execution_time_estimate_us: u64,
pub device_count: usize,
}
#[derive(Debug, Default)]
pub struct ExecutionProfile {
pub avg_execution_time_us: u64,
pub peak_memory_usage: usize,
pub throughput: f64,
pub resource_utilization: f64,
pub execution_history: Vec<ExecutionRecord>,
}
#[derive(Debug)]
pub struct ExecutionRecord {
pub timestamp: Instant,
pub duration: Duration,
pub input_sizes: Vec<usize>,
pub output_sizes: Vec<usize>,
pub device_utilization: f64,
pub memory_usage: usize,
}
#[derive(Debug, Clone)]
pub struct TargetRequirements {
pub min_tpu_version: TPUVersion,
pub required_memory: usize,
pub required_features: Vec<String>,
pub optional_features: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct DebugInfo {
pub source_mapping: HashMap<usize, String>,
pub symbol_table: HashMap<String, usize>,
pub line_info: Vec<LineInfo>,
}
#[derive(Debug, Clone)]
pub struct LineInfo {
pub address: usize,
pub file: String,
pub line: u32,
pub function: String,
}
pub struct ExecutableCache {
cache: HashMap<String, CachedExecutable>,
config: CacheConfig,
stats: CacheStats,
}
#[derive(Debug)]
pub struct CachedExecutable {
pub executable: TPUExecutable,
pub last_access: Instant,
pub access_count: u64,
pub score: f64,
}
#[derive(Debug)]
pub struct CacheConfig {
pub max_size: usize,
pub max_entries: usize,
pub eviction_policy: EvictionPolicy,
}
#[derive(Debug)]
pub enum EvictionPolicy {
LRU,
LFU,
Optimal,
}
#[derive(Debug, Default)]
pub struct CacheStats {
pub hits: u64,
pub misses: u64,
pub evictions: u64,
pub utilization: f64,
}
#[derive(Debug)]
pub struct LoadingRequest {
pub id: String,
pub code: GeneratedCode,
pub target_device: usize,
pub priority: u32,
pub timestamp: Instant,
}
#[derive(Debug)]
pub struct ExecutionContext {
pub id: String,
pub device_id: usize,
pub input_buffers: HashMap<String, Buffer>,
pub output_buffers: HashMap<String, Buffer>,
pub temp_buffers: HashMap<String, Buffer>,
pub state: ContextState,
pub performance_counters: HashMap<String, u64>,
}
#[derive(Debug)]
pub struct Buffer {
pub id: String,
pub size: usize,
pub memory_location: MemoryLocation,
pub status: BufferStatus,
pub access_tracking: AccessTracking,
}
#[derive(Debug)]
pub enum MemoryLocation {
Device(usize),
Host,
Shared,
External(String),
}
#[derive(Debug)]
pub enum BufferStatus {
Allocated,
Ready,
InUse,
Transferring,
Error(String),
}
#[derive(Debug, Default)]
pub struct AccessTracking {
pub read_count: u64,
pub write_count: u64,
pub last_access: Option<Instant>,
pub pattern: Option<BufferAccessPattern>,
}
#[derive(Debug)]
pub enum ContextState {
Ready,
Executing,
Waiting,
Error(String),
}
const RUNTIME_DEVICE_POOL: &str = "device";
pub struct RuntimeMemoryManager {
memory_pools: HashMap<String, MemoryPool>,
buffer_allocations: HashMap<String, BufferAllocation>,
usage_stats: MemoryUsageStats,
}
#[derive(Debug)]
pub struct MemoryPool {
pub name: String,
pub size: usize,
pub available: usize,
pub location: MemoryLocation,
pub fragmentation: f64,
}
#[derive(Debug)]
pub struct BufferAllocation {
pub buffer_id: String,
pub size: usize,
pub pool: String,
pub timestamp: Instant,
pub ref_count: usize,
}
#[derive(Debug, Default)]
pub struct MemoryUsageStats {
pub total_allocated: usize,
pub peak_usage: usize,
pub fragmentation_ratio: f64,
pub allocation_count: usize,
pub deallocation_count: usize,
}
impl RuntimeIntegration {
pub fn new(target_config: TPUConfig) -> Self {
let runtime_config = RuntimeConfig {
async_execution: true,
enable_profiling: false,
max_concurrent_executions: 4,
memory_pool_size: 1024 * 1024 * 1024, operation_timeout_ms: 30000, enable_error_checking: true,
optimization_level: RuntimeOptimizationLevel::Basic,
};
Self {
device_manager: DeviceManager::new(&target_config),
executable_manager: ExecutableManager::new(),
memory_manager: RuntimeMemoryManager::new(&runtime_config),
target_config,
runtime_config,
integration_stats: RuntimeIntegrationStats::default(),
}
}
pub fn integrate(&mut self, code: GeneratedCode, target_tpu: &TPUConfig) -> Result<Vec<u8>> {
let start_time = Instant::now();
if self.runtime_config.enable_error_checking && code.kernel_code.trim().is_empty() {
self.integration_stats.error_count += 1;
return Err(OptimError::from(
"runtime integration received an empty computation kernel".to_string(),
));
}
let executable = self.create_executable(code)?;
let device_id = match self
.device_manager
.select_device(&executable.metadata.target_requirements, target_tpu)
{
Ok(device_id) => device_id,
Err(error) => {
self.integration_stats.error_count += 1;
return Err(error);
}
};
let footprint = executable
.binary
.len()
.saturating_add(executable.metadata.target_requirements.required_memory);
let executable_id = executable.id.clone();
if let Err(error) = self.memory_manager.reserve(&executable_id, footprint) {
self.integration_stats.error_count += 1;
return Err(error);
}
let evicted = self.executable_manager.load_executable(executable)?;
for evicted_id in &evicted {
self.memory_manager.release(evicted_id);
self.device_manager.unassign(evicted_id);
}
self.device_manager.assign(&executable_id, device_id);
let binary = self.create_binary(&executable_id)?;
self.integration_stats.runtime_overhead_us = start_time.elapsed().as_micros() as u64;
self.integration_stats.executables_created += 1;
self.integration_stats.peak_memory_usage = self
.integration_stats
.peak_memory_usage
.max(self.memory_manager.total_allocated());
self.integration_stats.device_utilization = self.device_manager.utilization();
Ok(binary)
}
pub fn unload_executable(&mut self, executable_id: &str) -> bool {
let removed = self.executable_manager.remove_executable(executable_id);
if removed {
self.memory_manager.release(executable_id);
self.device_manager.unassign(executable_id);
}
removed
}
pub fn cache_statistics(&self) -> &CacheStats {
self.executable_manager.cache_statistics()
}
pub fn memory_statistics(&self) -> &MemoryUsageStats {
self.memory_manager.usage_stats()
}
pub fn integration_statistics(&self) -> &RuntimeIntegrationStats {
&self.integration_stats
}
fn create_executable(&self, code: GeneratedCode) -> Result<TPUExecutable> {
let executable = TPUExecutable {
id: format!("exec_{}", self.integration_stats.executables_created),
binary: code.kernel_code.as_bytes().to_vec(),
metadata: ExecutableMetadata {
compilation_time: Instant::now(),
compiler_version: "1.0.0".to_string(),
target_requirements: TargetRequirements {
min_tpu_version: self.target_config.tpu_version,
required_memory: 1024 * 1024, required_features: vec!["matmul".to_string()],
optional_features: vec![],
},
optimization_level: "O2".to_string(),
debug_info: None,
},
input_specs: vec![],
output_specs: vec![],
resource_requirements: ExecutableResourceRequirements::default(),
performance_profile: ExecutionProfile::default(),
};
Ok(executable)
}
fn create_binary(&mut self, executable_id: &str) -> Result<Vec<u8>> {
let executable = self
.executable_manager
.get_executable(executable_id)
.ok_or_else(|| {
OptimError::from(format!(
"cannot create binary: executable {executable_id} is not loaded"
))
})?;
let id_bytes = executable_id.as_bytes();
let code = &executable.binary;
let mut binary = Vec::with_capacity(16 + id_bytes.len() + code.len());
binary.extend_from_slice(b"TPUX");
binary.extend_from_slice(&1u32.to_le_bytes());
binary.extend_from_slice(&(id_bytes.len() as u32).to_le_bytes());
binary.extend_from_slice(id_bytes);
binary.extend_from_slice(&(code.len() as u64).to_le_bytes());
binary.extend_from_slice(code);
Ok(binary)
}
}
impl DeviceManager {
pub fn new(target_config: &TPUConfig) -> Self {
let mut devices = Vec::new();
let num_chips = match target_config.pod_topology {
PodTopology::Single => 1,
PodTopology::Pod2x2 => 4,
PodTopology::Pod4x4 => 16,
PodTopology::Pod8x8 => 64,
PodTopology::Pod16x16 => 256,
PodTopology::Pod32x32 => 1024,
};
let mut device_status = HashMap::with_capacity(num_chips);
let mut capabilities_cache = HashMap::with_capacity(num_chips);
for i in 0..num_chips {
let memory_capacity = 16 * 1024 * 1024 * 1024 / num_chips;
devices.push(TPUDevice {
id: i,
device_type: TPUDeviceType::SingleChip,
version: target_config.tpu_version,
memory_capacity,
compute_throughput: 420.0 / num_chips as f64,
state: DeviceState::Available,
last_health_check: Instant::now(),
});
device_status.insert(i, DeviceStatus::default());
capabilities_cache.insert(i, device_capabilities(target_config.tpu_version));
}
Self {
available_devices: devices,
device_assignments: HashMap::new(),
device_status,
capabilities_cache,
}
}
pub fn select_device(
&self,
requirements: &TargetRequirements,
target_tpu: &TPUConfig,
) -> Result<usize> {
if tpu_version_rank(target_tpu.tpu_version) < tpu_version_rank(requirements.min_tpu_version)
{
return Err(OptimError::from(format!(
"target {:?} is older than the executable's minimum {:?}",
target_tpu.tpu_version, requirements.min_tpu_version
)));
}
let mut best: Option<(usize, f64)> = None;
for device in &self.available_devices {
if !matches!(device.state, DeviceState::Available | DeviceState::InUse) {
continue;
}
if device.memory_capacity < requirements.required_memory {
continue;
}
if tpu_version_rank(device.version) < tpu_version_rank(requirements.min_tpu_version) {
continue;
}
if let Some(capabilities) = self.capabilities_cache.get(&device.id) {
let supports_all = requirements.required_features.iter().all(|feature| {
capabilities
.special_instructions
.iter()
.any(|available| available == feature)
});
if !supports_all {
continue;
}
}
let utilization = self
.device_status
.get(&device.id)
.map(|status| status.utilization)
.unwrap_or(0.0);
match best {
Some((_, best_utilization)) if best_utilization <= utilization => {}
_ => best = Some((device.id, utilization)),
}
}
best.map(|(id, _)| id).ok_or_else(|| {
OptimError::from(format!(
"no TPU device among {} available satisfies the executable's requirements \
({} bytes, features {:?})",
self.available_devices.len(),
requirements.required_memory,
requirements.required_features
))
})
}
pub fn assign(&mut self, executable_id: &str, device_id: usize) {
self.device_assignments
.insert(executable_id.to_string(), device_id);
if let Some(device) = self
.available_devices
.iter_mut()
.find(|device| device.id == device_id)
{
device.state = DeviceState::InUse;
}
}
pub fn unassign(&mut self, executable_id: &str) {
if let Some(device_id) = self.device_assignments.remove(executable_id) {
let still_used = self
.device_assignments
.values()
.any(|assigned| *assigned == device_id);
if !still_used {
if let Some(device) = self
.available_devices
.iter_mut()
.find(|device| device.id == device_id)
{
device.state = DeviceState::Available;
}
}
}
}
pub fn utilization(&self) -> f64 {
if self.available_devices.is_empty() {
return 0.0;
}
let busy: std::collections::HashSet<usize> =
self.device_assignments.values().copied().collect();
busy.len() as f64 / self.available_devices.len() as f64
}
pub fn devices(&self) -> &[TPUDevice] {
&self.available_devices
}
pub fn capabilities(&self, device_id: usize) -> Option<&DeviceCapabilities> {
self.capabilities_cache.get(&device_id)
}
pub fn status(&self, device_id: usize) -> Option<&DeviceStatus> {
self.device_status.get(&device_id)
}
}
fn tpu_version_rank(version: TPUVersion) -> u8 {
match version {
TPUVersion::V2 => 2,
TPUVersion::V3 => 3,
TPUVersion::V4 => 4,
TPUVersion::V5e => 5,
TPUVersion::V5p => 6,
}
}
fn device_capabilities(version: TPUVersion) -> DeviceCapabilities {
let (matrix_dims, vector_width, memory_bandwidth, inter_chip, inter_pod) = match version {
TPUVersion::V2 => ((128, 128), 8, 600.0, 500.0, 100.0),
TPUVersion::V3 => ((128, 128), 8, 900.0, 900.0, 200.0),
TPUVersion::V4 => ((128, 128), 8, 1200.0, 1200.0, 300.0),
TPUVersion::V5e => ((128, 128), 8, 819.0, 1600.0, 400.0),
TPUVersion::V5p => ((128, 128), 8, 2765.0, 4800.0, 800.0),
};
DeviceCapabilities {
supported_dtypes: vec![
"f32".to_string(),
"bf16".to_string(),
"f16".to_string(),
"s32".to_string(),
"s8".to_string(),
],
max_matrix_dims: matrix_dims,
vector_width,
memory_bandwidth,
special_instructions: vec![
"matmul".to_string(),
"conv".to_string(),
"reduce".to_string(),
"transpose".to_string(),
],
interconnect_capabilities: InterconnectCapabilities {
inter_chip_bandwidth: inter_chip,
inter_pod_bandwidth: inter_pod,
collective_ops: vec![
"all-reduce".to_string(),
"all-gather".to_string(),
"reduce-scatter".to_string(),
],
topology_type: TopologyType::Mesh,
},
}
}
impl Default for ExecutableManager {
fn default() -> Self {
Self::new()
}
}
impl ExecutableManager {
pub fn new() -> Self {
Self {
executable_cache: ExecutableCache::new(),
}
}
pub fn load_executable(&mut self, executable: TPUExecutable) -> Result<Vec<String>> {
Ok(self.executable_cache.insert(executable))
}
pub fn get_executable(&mut self, id: &str) -> Option<&TPUExecutable> {
self.executable_cache.lookup(id)
}
pub fn remove_executable(&mut self, id: &str) -> bool {
self.executable_cache.remove(id)
}
pub fn cache_statistics(&self) -> &CacheStats {
self.executable_cache.statistics()
}
}
impl Default for ExecutableCache {
fn default() -> Self {
Self::new()
}
}
impl ExecutableCache {
pub fn new() -> Self {
Self {
cache: HashMap::new(),
config: CacheConfig {
max_size: 100 * 1024 * 1024, max_entries: 100,
eviction_policy: EvictionPolicy::LRU,
},
stats: CacheStats::default(),
}
}
pub fn insert(&mut self, executable: TPUExecutable) -> Vec<String> {
let id = executable.id.clone();
let size = executable.binary.len();
self.cache.insert(
id,
CachedExecutable {
executable,
last_access: Instant::now(),
access_count: 1,
score: size as f64,
},
);
let evicted = self.enforce_budget();
self.refresh_utilization();
evicted
}
pub fn peek(&self, id: &str) -> Option<&TPUExecutable> {
self.cache.get(id).map(|entry| &entry.executable)
}
pub fn lookup(&mut self, id: &str) -> Option<&TPUExecutable> {
match self.cache.get_mut(id) {
Some(entry) => {
entry.last_access = Instant::now();
entry.access_count += 1;
entry.score = entry.executable.binary.len() as f64 * entry.access_count as f64;
self.stats.hits += 1;
Some(&entry.executable)
}
None => {
self.stats.misses += 1;
None
}
}
}
pub fn remove(&mut self, id: &str) -> bool {
let removed = self.cache.remove(id).is_some();
if removed {
self.refresh_utilization();
}
removed
}
pub fn statistics(&self) -> &CacheStats {
&self.stats
}
fn occupied_bytes(&self) -> usize {
self.cache
.values()
.map(|entry| entry.executable.binary.len())
.sum()
}
fn enforce_budget(&mut self) -> Vec<String> {
let mut evicted = Vec::new();
while self.cache.len() > self.config.max_entries.max(1)
|| (self.occupied_bytes() > self.config.max_size && self.cache.len() > 1)
{
let victim = match self.config.eviction_policy {
EvictionPolicy::LRU => self
.cache
.iter()
.min_by_key(|(_, entry)| entry.last_access)
.map(|(id, _)| id.clone()),
EvictionPolicy::LFU => self
.cache
.iter()
.min_by_key(|(_, entry)| entry.access_count)
.map(|(id, _)| id.clone()),
EvictionPolicy::Optimal => self
.cache
.iter()
.min_by(|a, b| a.1.score.total_cmp(&b.1.score))
.map(|(id, _)| id.clone()),
};
match victim {
Some(id) => {
self.cache.remove(&id);
self.stats.evictions += 1;
evicted.push(id);
}
None => break,
}
}
evicted
}
fn refresh_utilization(&mut self) {
self.stats.utilization = if self.config.max_size == 0 {
0.0
} else {
self.occupied_bytes() as f64 / self.config.max_size as f64
};
}
}
impl RuntimeMemoryManager {
pub fn reserve(&mut self, buffer_id: &str, size: usize) -> Result<()> {
let pool = self
.memory_pools
.get_mut(RUNTIME_DEVICE_POOL)
.ok_or_else(|| {
OptimError::from(format!(
"runtime memory pool {RUNTIME_DEVICE_POOL} is missing"
))
})?;
if size > pool.available {
return Err(OptimError::from(format!(
"executable needs {size} bytes but only {} of {} bytes are free in the runtime pool",
pool.available, pool.size
)));
}
pool.available -= size;
pool.fragmentation = if pool.size == 0 {
0.0
} else {
1.0 - (pool.available as f64 / pool.size as f64)
};
self.buffer_allocations.insert(
buffer_id.to_string(),
BufferAllocation {
buffer_id: buffer_id.to_string(),
size,
pool: RUNTIME_DEVICE_POOL.to_string(),
timestamp: Instant::now(),
ref_count: 1,
},
);
self.usage_stats.total_allocated += size;
self.usage_stats.allocation_count += 1;
self.usage_stats.peak_usage = self
.usage_stats
.peak_usage
.max(self.usage_stats.total_allocated);
self.usage_stats.fragmentation_ratio = self
.memory_pools
.get(RUNTIME_DEVICE_POOL)
.map(|pool| pool.fragmentation)
.unwrap_or(0.0);
Ok(())
}
pub fn release(&mut self, buffer_id: &str) -> usize {
let Some(allocation) = self.buffer_allocations.remove(buffer_id) else {
return 0;
};
if let Some(pool) = self.memory_pools.get_mut(&allocation.pool) {
pool.available = pool
.available
.saturating_add(allocation.size)
.min(pool.size);
pool.fragmentation = if pool.size == 0 {
0.0
} else {
1.0 - (pool.available as f64 / pool.size as f64)
};
}
self.usage_stats.total_allocated = self
.usage_stats
.total_allocated
.saturating_sub(allocation.size);
self.usage_stats.deallocation_count += 1;
self.usage_stats.fragmentation_ratio = self
.memory_pools
.get(&allocation.pool)
.map(|pool| pool.fragmentation)
.unwrap_or(0.0);
allocation.size
}
pub fn total_allocated(&self) -> usize {
self.usage_stats.total_allocated
}
pub fn usage_stats(&self) -> &MemoryUsageStats {
&self.usage_stats
}
pub fn new(runtime_config: &RuntimeConfig) -> Self {
let mut memory_pools = HashMap::new();
memory_pools.insert(
"device".to_string(),
MemoryPool {
name: "device".to_string(),
size: runtime_config.memory_pool_size,
available: runtime_config.memory_pool_size,
location: MemoryLocation::Device(0),
fragmentation: 0.0,
},
);
Self {
memory_pools,
buffer_allocations: HashMap::new(),
usage_stats: MemoryUsageStats::default(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::main_types::TPUConfig;
#[test]
fn test_runtime_integration_creation() {
use crate::main_types::{PodTopology, TPUConfig, TPUVersion};
let tpu_config = TPUConfig {
tpu_version: TPUVersion::V4,
num_cores: 8,
enable_xla: true,
xla_optimization_level: crate::main_types::XLAOptimizationLevel::Standard,
mixed_precision: true,
batch_size_per_core: 32,
enable_pod_coordination: false,
pod_topology: PodTopology::Pod2x2,
memory_optimization: crate::main_types::TPUMemoryOptimization::Balanced,
gradient_compression: true,
prefetch_depth: 2,
experimental_features: false,
};
let runtime = RuntimeIntegration::new(tpu_config);
assert_eq!(runtime.integration_stats.executables_created, 0);
assert_eq!(runtime.integration_stats.total_executions, 0);
assert!(runtime.runtime_config.async_execution);
}
#[test]
fn test_device_manager_creation() {
use crate::main_types::{PodTopology, TPUConfig, TPUVersion};
let tpu_config = TPUConfig {
tpu_version: TPUVersion::V4,
num_cores: 8,
enable_xla: true,
xla_optimization_level: crate::main_types::XLAOptimizationLevel::Standard,
mixed_precision: true,
batch_size_per_core: 32,
enable_pod_coordination: false,
pod_topology: PodTopology::Pod2x2,
memory_optimization: crate::main_types::TPUMemoryOptimization::Balanced,
gradient_compression: true,
prefetch_depth: 2,
experimental_features: false,
};
let device_manager = DeviceManager::new(&tpu_config);
assert_eq!(device_manager.available_devices.len(), 4);
for device in &device_manager.available_devices {
assert!(matches!(device.state, DeviceState::Available));
assert_eq!(device.version, TPUVersion::V4);
}
}
#[test]
fn test_create_binary_serializes_real_code_not_placeholder() {
use crate::main_types::{PodTopology, TPUConfig, TPUVersion};
let tpu_config = TPUConfig {
tpu_version: TPUVersion::V4,
num_cores: 8,
enable_xla: true,
xla_optimization_level: crate::main_types::XLAOptimizationLevel::Standard,
mixed_precision: true,
batch_size_per_core: 32,
enable_pod_coordination: false,
pod_topology: PodTopology::Single,
memory_optimization: crate::main_types::TPUMemoryOptimization::Balanced,
gradient_compression: true,
prefetch_depth: 2,
experimental_features: false,
};
let kernel = "tpu.matmul %a, %b -> %c";
let code = GeneratedCode {
kernel_code: kernel.to_string(),
init_code: String::new(),
cleanup_code: String::new(),
memory_code: String::new(),
};
let mut runtime = RuntimeIntegration::new(tpu_config.clone());
let binary = runtime
.integrate(code, &tpu_config)
.expect("integration should produce a binary");
assert_ne!(binary, vec![0xDE, 0xAD, 0xBE, 0xEF]);
assert!(
binary.starts_with(b"TPUX"),
"binary must carry container magic"
);
assert!(
binary.windows(kernel.len()).any(|w| w == kernel.as_bytes()),
"binary must embed the real compiled kernel code"
);
}
#[test]
fn test_create_binary_missing_executable_errors() {
use crate::main_types::{PodTopology, TPUConfig, TPUVersion};
let tpu_config = TPUConfig {
tpu_version: TPUVersion::V4,
num_cores: 8,
enable_xla: true,
xla_optimization_level: crate::main_types::XLAOptimizationLevel::Standard,
mixed_precision: true,
batch_size_per_core: 32,
enable_pod_coordination: false,
pod_topology: PodTopology::Single,
memory_optimization: crate::main_types::TPUMemoryOptimization::Balanced,
gradient_compression: true,
prefetch_depth: 2,
experimental_features: false,
};
let mut runtime = RuntimeIntegration::new(tpu_config);
assert!(
runtime.create_binary("never_loaded").is_err(),
"create_binary must fail for an unloaded executable id"
);
assert_eq!(runtime.cache_statistics().misses, 1);
assert_eq!(runtime.cache_statistics().hits, 0);
}
#[test]
fn integrate_reserves_and_unload_releases() {
let tpu_config = test_config(PodTopology::Pod2x2);
let mut runtime = RuntimeIntegration::new(tpu_config.clone());
let code = GeneratedCode {
kernel_code: "tpu.add %a, %b -> %c".to_string(),
init_code: String::new(),
cleanup_code: String::new(),
memory_code: String::new(),
};
runtime
.integrate(code, &tpu_config)
.expect("integration should succeed");
assert!(
runtime.memory_statistics().total_allocated > 0,
"the executable's footprint must actually be reserved"
);
assert_eq!(runtime.cache_statistics().hits, 1);
assert_eq!(runtime.integration_statistics().executables_created, 1);
assert!(runtime.integration_statistics().device_utilization > 0.0);
assert!(runtime.unload_executable("exec_0"));
assert_eq!(runtime.memory_statistics().total_allocated, 0);
assert!(!runtime.unload_executable("exec_0"));
}
#[test]
fn integrate_rejects_an_empty_kernel() {
let tpu_config = test_config(PodTopology::Single);
let mut runtime = RuntimeIntegration::new(tpu_config.clone());
let code = GeneratedCode {
kernel_code: " \n".to_string(),
init_code: String::new(),
cleanup_code: String::new(),
memory_code: String::new(),
};
assert!(runtime.integrate(code, &tpu_config).is_err());
assert_eq!(runtime.integration_statistics().error_count, 1);
}
#[test]
fn integrate_rejects_a_target_older_than_the_executable_needs() {
let build_config = test_config(PodTopology::Single);
let mut runtime = RuntimeIntegration::new(build_config.clone());
let mut older = build_config.clone();
older.tpu_version = TPUVersion::V2;
let code = GeneratedCode {
kernel_code: "tpu.matmul %a, %b -> %c".to_string(),
init_code: String::new(),
cleanup_code: String::new(),
memory_code: String::new(),
};
assert!(runtime.integrate(code, &older).is_err());
}
fn test_config(pod_topology: PodTopology) -> TPUConfig {
TPUConfig {
tpu_version: TPUVersion::V4,
num_cores: 8,
enable_xla: true,
xla_optimization_level: crate::main_types::XLAOptimizationLevel::Standard,
mixed_precision: true,
batch_size_per_core: 32,
enable_pod_coordination: false,
pod_topology,
memory_optimization: crate::main_types::TPUMemoryOptimization::Balanced,
gradient_compression: true,
prefetch_depth: 2,
experimental_features: false,
}
}
}