use crate::{DType, Device, Result, Tensor, TensorError};
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
use wgpu::util::DeviceExt;
#[derive(Debug, Clone, PartialEq)]
pub enum KernelStrategy {
TensorCore {
precision: TensorCorePrecision,
tile_size: usize,
hopper_optimizations: bool,
fp8_support: bool,
},
SIMDGroup {
group_size: usize,
vectorization_width: usize,
apple_neural_engine: bool,
memory_coalescing: bool,
},
Wavefront {
wavefront_size: usize,
lds_optimization: bool,
rdna3_optimizations: bool,
ai_accelerator: bool,
},
IntelXe {
xe_thread_groups: usize,
xmx_acceleration: bool,
intel_gpu_gen: IntelGpuGeneration,
},
StandardCompute,
}
#[derive(Debug, Clone, PartialEq)]
pub enum TensorCorePrecision {
Float16,
BFloat16,
Int8,
Float8 { e4m3: bool, e5m2: bool },
Int4,
Mixed,
Adaptive,
}
#[derive(Debug, Clone, PartialEq)]
pub enum IntelGpuGeneration {
Alchemist,
Battlemage,
Celestial,
XeIntegrated,
}
#[derive(Debug, Clone, PartialEq)]
pub enum MemoryStrategy {
SharedMemoryTiling {
tile_size: usize,
bank_conflict_avoidance: bool,
},
BandwidthOptimized {
prefetch_distance: usize,
vectorization_factor: usize,
},
TextureMemory { cache_optimization: bool },
HbmOptimized {
memory_channels: usize,
interleaving: bool,
},
}
#[derive(Debug, Clone)]
pub struct OptimizationHints {
pub compute_intensity: ComputeIntensity,
pub tensor_shapes: Vec<Vec<usize>>,
pub is_repetitive: bool,
pub memory_pattern: MemoryPattern,
pub precision_requirements: PrecisionRequirements,
}
#[derive(Debug, Clone, PartialEq)]
pub enum ComputeIntensity {
MemoryBound,
ComputeBound,
Balanced,
}
#[derive(Debug, Clone, PartialEq)]
pub enum MemoryPattern {
Sequential,
Strided { stride: usize },
Random,
Coalesced,
}
#[derive(Debug, Clone, PartialEq)]
pub enum PrecisionRequirements {
HighPrecision,
StandardPrecision,
ReducedPrecision,
MinimalPrecision,
}
pub struct AdvancedKernelManager {
device_info: Arc<RwLock<DeviceCapabilities>>,
kernel_cache: Arc<RwLock<HashMap<String, CompiledKernel>>>,
performance_data: Arc<RwLock<HashMap<String, KernelPerformanceData>>>,
strategy: KernelStrategy,
}
#[derive(Debug, Clone)]
pub struct DeviceCapabilities {
pub vendor: GpuVendor,
pub compute_capability: String,
pub memory_bandwidth: f64,
pub compute_units: usize,
pub has_tensor_cores: bool,
pub max_threads_per_block: usize,
pub shared_memory_size: usize,
pub supports_fp16: bool,
pub supports_bf16: bool,
pub supports_coop_groups: bool,
}
#[derive(Debug, Clone, PartialEq)]
pub enum GpuVendor {
Nvidia,
AMD,
Apple,
Intel,
Unknown,
}
#[derive(Debug, Clone)]
pub struct CompiledKernel {
pub id: String,
pub strategy: KernelStrategy,
pub compiled_at: std::time::SystemTime,
pub parameters: KernelParameters,
pub handle: KernelHandle,
}
#[derive(Debug, Clone)]
pub enum KernelHandle {
#[cfg(feature = "cuda")]
Cuda {
module: String,
function: String,
},
#[cfg(feature = "metal")]
Metal {
library: String,
function: String,
},
#[cfg(feature = "rocm")]
ROCm {
module: String,
function: String,
},
WGPU {
shader: String,
entry_point: String,
},
}
#[derive(Debug, Clone)]
pub struct KernelParameters {
pub grid_size: (usize, usize, usize),
pub block_size: (usize, usize, usize),
pub shared_memory: usize,
pub register_count: usize,
}
#[derive(Debug, Clone)]
pub struct KernelPerformanceData {
pub avg_execution_time: f64,
pub memory_bandwidth_util: f64,
pub compute_utilization: f64,
pub execution_count: usize,
pub speedup_factor: f64,
}
impl AdvancedKernelManager {
pub fn new(device: &Device) -> Result<Self> {
let device_info = Self::detect_device_capabilities(device)?;
let strategy = Self::select_optimal_strategy(&device_info);
Ok(AdvancedKernelManager {
device_info: Arc::new(RwLock::new(device_info)),
kernel_cache: Arc::new(RwLock::new(HashMap::new())),
performance_data: Arc::new(RwLock::new(HashMap::new())),
strategy,
})
}
fn detect_device_capabilities(device: &Device) -> Result<DeviceCapabilities> {
match device {
#[cfg(feature = "gpu")]
Device::Gpu(gpu_device) => {
let caps = crate::device::get_gpu_adapter_capabilities(*gpu_device)?;
Ok(DeviceCapabilities {
vendor: Self::detect_gpu_vendor(&caps.info),
compute_capability: Self::query_compute_capability(&caps.info),
memory_bandwidth: Self::measure_memory_bandwidth()?,
compute_units: Self::query_compute_units()?,
has_tensor_cores: Self::detect_tensor_cores()?,
max_threads_per_block: Self::query_max_threads_per_block(&caps.limits),
shared_memory_size: Self::query_shared_memory_size(&caps.limits),
supports_fp16: Self::test_fp16_support(caps.features),
supports_bf16: Self::test_bf16_support()?,
supports_coop_groups: Self::test_cooperative_groups()?,
})
}
_ => Err(TensorError::InvalidArgument {
operation: "AdvancedKernelManager::detect_device_capabilities".to_string(),
reason: "Advanced kernels only supported on GPU devices".to_string(),
context: None,
}),
}
}
fn select_optimal_strategy(capabilities: &DeviceCapabilities) -> KernelStrategy {
match capabilities.vendor {
GpuVendor::Nvidia if capabilities.has_tensor_cores => {
KernelStrategy::TensorCore {
precision: if capabilities.supports_bf16 {
TensorCorePrecision::BFloat16
} else {
TensorCorePrecision::Float16
},
tile_size: 16, hopper_optimizations: capabilities.compute_capability.as_str() >= "9.0",
fp8_support: capabilities.compute_capability.as_str() >= "8.9",
}
}
GpuVendor::Apple => {
KernelStrategy::SIMDGroup {
group_size: 32, vectorization_width: 8, apple_neural_engine: true, memory_coalescing: true,
}
}
GpuVendor::AMD => {
KernelStrategy::Wavefront {
wavefront_size: 64, lds_optimization: true,
rdna3_optimizations: true, ai_accelerator: false, }
}
_ => KernelStrategy::StandardCompute,
}
}
pub fn optimized_matmul<T>(
&self,
a: &Tensor<T>,
b: &Tensor<T>,
hints: OptimizationHints,
) -> Result<Tensor<T>>
where
T: bytemuck::Pod + bytemuck::Zeroable + Clone + Default + Send + Sync + 'static,
{
let kernel_id = format!("matmul_{}x{}x{}", a.shape()[0], a.shape()[1], b.shape()[1]);
if let Some(kernel) = self.get_cached_kernel(&kernel_id)? {
return self.execute_cached_matmul(a, b, &kernel);
}
let kernel = self.compile_optimal_matmul_kernel(a, b, &hints)?;
self.cache_kernel(kernel_id.clone(), kernel.clone())?;
let result = self.execute_matmul_kernel(a, b, &kernel)?;
self.update_performance_data(&kernel_id, &kernel)?;
Ok(result)
}
fn compile_optimal_matmul_kernel<T: 'static>(
&self,
a: &Tensor<T>,
b: &Tensor<T>,
hints: &OptimizationHints,
) -> Result<CompiledKernel> {
match &self.strategy {
KernelStrategy::TensorCore {
precision,
tile_size,
..
} => self.compile_tensor_core_matmul(a, b, precision, *tile_size),
KernelStrategy::SIMDGroup {
group_size,
vectorization_width,
..
} => self.compile_simd_group_matmul(a, b, *group_size, *vectorization_width),
KernelStrategy::Wavefront {
wavefront_size,
lds_optimization,
..
} => self.compile_wavefront_matmul(a, b, *wavefront_size, *lds_optimization),
KernelStrategy::StandardCompute => self.compile_standard_matmul(a, b),
KernelStrategy::IntelXe {
xe_thread_groups,
xmx_acceleration,
intel_gpu_gen,
} => self.compile_intel_xe_matmul(
a,
b,
*xe_thread_groups,
*xmx_acceleration,
intel_gpu_gen,
),
}
}
#[cfg(feature = "cuda")]
fn compile_tensor_core_matmul<T: 'static>(
&self,
a: &Tensor<T>,
b: &Tensor<T>,
precision: &TensorCorePrecision,
tile_size: usize,
) -> Result<CompiledKernel> {
let kernel_source = match precision {
TensorCorePrecision::Float16 => {
include_str!("cuda_kernels/tensor_core_matmul.ptx")
}
TensorCorePrecision::BFloat16 => {
include_str!("cuda_kernels/tensor_core_matmul.ptx") }
TensorCorePrecision::Int8 => {
include_str!("cuda_kernels/tensor_core_matmul.ptx") }
TensorCorePrecision::Mixed => {
include_str!("cuda_kernels/tensor_core_matmul.ptx") }
TensorCorePrecision::Float8 { .. } => {
include_str!("cuda_kernels/tensor_core_matmul.ptx") }
TensorCorePrecision::Int4 => {
include_str!("cuda_kernels/tensor_core_matmul.ptx") }
TensorCorePrecision::Adaptive => {
include_str!("cuda_kernels/tensor_core_matmul.ptx") }
};
let m = a.shape()[0];
let n = b.shape()[1];
let grid_x = (m + tile_size - 1) / tile_size;
let grid_y = (n + tile_size - 1) / tile_size;
let block_x = 32; let block_y = 8;
Ok(CompiledKernel {
id: format!("tensor_core_{}_{:?}", tile_size, precision),
strategy: self.strategy.clone(),
compiled_at: std::time::SystemTime::now(),
parameters: KernelParameters {
grid_size: (grid_x, grid_y, 1),
block_size: (block_x, block_y, 1),
shared_memory: tile_size * tile_size * 4, register_count: 64, },
handle: KernelHandle::Cuda {
module: "tensor_core_matmul".to_string(),
function: match precision {
TensorCorePrecision::Float16 => "tensor_core_gemm_f16".to_string(),
TensorCorePrecision::BFloat16 => "tensor_core_gemm_bf16".to_string(),
TensorCorePrecision::Int8 => "tensor_core_gemm_int8".to_string(),
TensorCorePrecision::Mixed => "tensor_core_gemm_mixed".to_string(),
TensorCorePrecision::Float8 { .. } => "tensor_core_gemm_f8".to_string(),
TensorCorePrecision::Int4 => "tensor_core_gemm_int4".to_string(),
TensorCorePrecision::Adaptive => "tensor_core_gemm_adaptive".to_string(),
},
},
})
}
#[cfg(feature = "metal")]
fn compile_simd_group_matmul<T: 'static>(
&self,
a: &Tensor<T>,
b: &Tensor<T>,
group_size: usize,
vectorization_width: usize,
) -> Result<CompiledKernel> {
let kernel_source = include_str!("metal_shaders/simd_group_matmul.metal");
let m = a.shape()[0];
let n = b.shape()[1];
let tile_size = 32;
let threadgroup_x = (m + tile_size - 1) / tile_size;
let threadgroup_y = (n + tile_size - 1) / tile_size;
Ok(CompiledKernel {
id: format!("simd_group_{}_{}", group_size, vectorization_width),
strategy: self.strategy.clone(),
compiled_at: std::time::SystemTime::now(),
parameters: KernelParameters {
grid_size: (threadgroup_x, threadgroup_y, 1),
block_size: (group_size, 1, 1),
shared_memory: tile_size * tile_size * 8, register_count: 32, },
handle: KernelHandle::Metal {
library: "simd_group_matmul".to_string(),
function: match a.dtype() {
DType::Float32 => "simd_group_matmul_f32".to_string(),
DType::Float16 => "simd_group_matmul_f16".to_string(),
_ => {
return Err(TensorError::unsupported_operation_simple(format!(
"SIMD-group matmul: Unsupported dtype: {:?}",
a.dtype()
)))
}
},
},
})
}
#[cfg(feature = "rocm")]
fn compile_wavefront_matmul<T: 'static>(
&self,
a: &Tensor<T>,
b: &Tensor<T>,
wavefront_size: usize,
lds_optimization: bool,
) -> Result<CompiledKernel> {
let kernel_source = include_str!("rocm_kernels/wavefront_optimized_matmul.hip");
let m = a.shape()[0];
let n = b.shape()[1];
let tile_size = 64;
let grid_x = (m + tile_size - 1) / tile_size;
let grid_y = (n + tile_size - 1) / tile_size;
let block_size = wavefront_size * 4;
Ok(CompiledKernel {
id: format!("wavefront_{}_{}", wavefront_size, lds_optimization),
strategy: self.strategy.clone(),
compiled_at: std::time::SystemTime::now(),
parameters: KernelParameters {
grid_size: (grid_x, grid_y, 1),
block_size: (block_size, 1, 1),
shared_memory: if lds_optimization {
tile_size * tile_size * 8 } else {
0
},
register_count: 48, },
handle: KernelHandle::ROCm {
module: "wavefront_matmul".to_string(),
function: match a.dtype() {
DType::Float32 => "wavefront_gemm_f32".to_string(),
DType::Float16 => "wavefront_gemm_f16".to_string(),
_ => {
return Err(TensorError::unsupported_operation_simple(format!(
"Wavefront matmul: Unsupported dtype: {:?}",
a.dtype()
)))
}
},
},
})
}
fn compile_standard_matmul<T: 'static>(
&self,
a: &Tensor<T>,
b: &Tensor<T>,
) -> Result<CompiledKernel> {
let m = a.shape()[0];
let n = b.shape()[1];
let tile_size = 16;
let grid_x = (m + tile_size - 1) / tile_size;
let grid_y = (n + tile_size - 1) / tile_size;
Ok(CompiledKernel {
id: "standard_compute".to_string(),
strategy: self.strategy.clone(),
compiled_at: std::time::SystemTime::now(),
parameters: KernelParameters {
grid_size: (grid_x, grid_y, 1),
block_size: (tile_size, tile_size, 1),
shared_memory: 0,
register_count: 16,
},
handle: KernelHandle::WGPU {
shader: "matmul_ops.wgsl".to_string(),
entry_point: "matmul_kernel".to_string(),
},
})
}
fn detect_gpu_vendor(info: &wgpu::AdapterInfo) -> GpuVendor {
map_vendor(info)
}
fn query_compute_capability(info: &wgpu::AdapterInfo) -> String {
compute_capability_from_info(info)
}
fn measure_memory_bandwidth() -> Result<f64> {
Err(TensorError::unsupported_operation_simple(
"memory bandwidth cannot be queried through wgpu (no GB/s field exists on \
AdapterInfo/Limits/Features on any backend); a vendor runtime such as NVML or \
ROCm-SMI is required"
.to_string(),
))
}
fn query_compute_units() -> Result<usize> {
Err(TensorError::unsupported_operation_simple(
"compute unit / SM count has no wgpu API (AdapterInfo and Limits carry no such \
field on any backend); a vendor runtime such as NVML or ROCm-SMI is required"
.to_string(),
))
}
fn detect_tensor_cores() -> Result<bool> {
Err(TensorError::unsupported_operation_simple(
"tensor-core presence cannot be queried through wgpu; it exposes no matrix-\
accelerator feature flag on any backend"
.to_string(),
))
}
fn query_max_threads_per_block(limits: &wgpu::Limits) -> usize {
threads_from_limits(limits) as usize
}
fn query_shared_memory_size(limits: &wgpu::Limits) -> usize {
shared_mem_from_limits(limits) as usize
}
fn test_fp16_support(features: wgpu::Features) -> bool {
fp16_from_features(features)
}
fn test_bf16_support() -> Result<bool> {
Err(TensorError::unsupported_operation_simple(
"bf16 support cannot be queried through wgpu; no SHADER_BF16 (or equivalent) \
feature flag exists on any backend"
.to_string(),
))
}
fn test_cooperative_groups() -> Result<bool> {
Err(TensorError::unsupported_operation_simple(
"cooperative groups cannot be queried through wgpu; Features::SUBGROUP (warp/wave \
intrinsics) is a distinct, narrower capability and not a substitute"
.to_string(),
))
}
fn get_cached_kernel(&self, kernel_id: &str) -> Result<Option<CompiledKernel>> {
let cache = self
.kernel_cache
.read()
.map_err(|_| TensorError::InvalidArgument {
operation: "get_cached_kernel".to_string(),
reason: "Failed to acquire read lock".to_string(),
context: None,
})?;
Ok(cache.get(kernel_id).cloned())
}
fn cache_kernel(&self, kernel_id: String, kernel: CompiledKernel) -> Result<()> {
let mut cache = self
.kernel_cache
.write()
.map_err(|_| TensorError::InvalidArgument {
operation: "cache_kernel".to_string(),
reason: "Failed to acquire write lock".to_string(),
context: None,
})?;
cache.insert(kernel_id, kernel);
Ok(())
}
fn execute_cached_matmul<T>(
&self,
a: &Tensor<T>,
b: &Tensor<T>,
kernel: &CompiledKernel,
) -> Result<Tensor<T>>
where
T: bytemuck::Pod + bytemuck::Zeroable + Clone + Default + Send + Sync + 'static,
{
self.execute_matmul_kernel(a, b, kernel)
}
fn execute_matmul_kernel<T>(
&self,
a: &Tensor<T>,
b: &Tensor<T>,
kernel: &CompiledKernel,
) -> Result<Tensor<T>>
where
T: bytemuck::Pod + bytemuck::Zeroable + Clone + Default + Send + Sync + 'static,
{
match &kernel.handle {
#[cfg(feature = "cuda")]
KernelHandle::Cuda { module, function } => self.execute_cuda_kernel(a, b, kernel),
#[cfg(feature = "metal")]
KernelHandle::Metal { library, function } => self.execute_metal_kernel(a, b, kernel),
#[cfg(feature = "rocm")]
KernelHandle::ROCm { module, function } => self.execute_rocm_kernel(a, b, kernel),
KernelHandle::WGPU {
shader,
entry_point,
} => self.execute_wgpu_kernel(a, b, kernel),
}
}
#[cfg(feature = "cuda")]
fn execute_cuda_kernel<T>(
&self,
a: &Tensor<T>,
b: &Tensor<T>,
kernel: &CompiledKernel,
) -> Result<Tensor<T>> {
Err(TensorError::unsupported_operation_simple(
"CUDA kernel execution: CUDA kernel execution not yet implemented. CUDA feature is enabled but requires cuLaunchKernel integration.".to_string()
))
}
#[cfg(feature = "metal")]
fn execute_metal_kernel<T>(
&self,
a: &Tensor<T>,
b: &Tensor<T>,
_kernel: &CompiledKernel,
) -> Result<Tensor<T>>
where
T: bytemuck::Pod + bytemuck::Zeroable + Clone + Default + Send + Sync + 'static,
{
let wgpu_kernel = self.compile_standard_matmul(a, b)?;
self.execute_wgpu_kernel(a, b, &wgpu_kernel)
}
#[cfg(feature = "rocm")]
fn execute_rocm_kernel<T>(
&self,
a: &Tensor<T>,
b: &Tensor<T>,
kernel: &CompiledKernel,
) -> Result<Tensor<T>> {
Err(TensorError::unsupported_operation_simple(
"ROCm kernel execution: ROCm kernel execution not yet implemented. ROCm feature is enabled but requires HIP runtime integration.".to_string()
))
}
fn execute_wgpu_kernel<T>(
&self,
a: &Tensor<T>,
b: &Tensor<T>,
kernel: &CompiledKernel,
) -> Result<Tensor<T>>
where
T: bytemuck::Pod + bytemuck::Zeroable + Clone + Default + Send + Sync + 'static,
{
use crate::gpu::buffer::GpuBuffer;
use crate::tensor::TensorStorage;
if let (TensorStorage::Gpu(gpu_a), TensorStorage::Gpu(gpu_b)) = (&a.storage, &b.storage) {
let device_arc = Arc::clone(&gpu_a.device);
let queue_arc = Arc::clone(&gpu_a.queue);
let a_shape = a.shape().dims();
let b_shape = b.shape().dims();
let a_ndim = a_shape.len();
let b_ndim = b_shape.len();
let m = a_shape[a_ndim - 2];
let k = a_shape[a_ndim - 1];
let n = b_shape[b_ndim - 1];
let batch_size = kernel.parameters.grid_size.2.max(1);
let result_shape = vec![batch_size, m, n];
let output_size: usize = result_shape.iter().product();
let output_buffer = device_arc.create_buffer(&wgpu::BufferDescriptor {
label: Some("advanced_matmul_output"),
size: (output_size * 4) as u64, usage: wgpu::BufferUsages::STORAGE
| wgpu::BufferUsages::COPY_SRC
| wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
});
#[repr(C)]
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
struct MatMulParams {
m: u32,
k: u32,
n: u32,
batch_size: u32,
}
let params = MatMulParams {
m: m as u32,
k: k as u32,
n: n as u32,
batch_size: batch_size as u32,
};
let params_buffer = device_arc.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("advanced_matmul_params"),
contents: bytemuck::cast_slice(&[params]),
usage: wgpu::BufferUsages::UNIFORM,
});
let shader_source = match &kernel.handle {
KernelHandle::WGPU { shader, .. } => match shader.as_str() {
"matmul_ops.wgsl" => include_str!("shaders/matmul_ops.wgsl"),
_ => include_str!("shaders/matmul_ops.wgsl"), },
#[cfg(any(feature = "cuda", feature = "metal", feature = "rocm"))]
_ => {
return Err(TensorError::InvalidArgument {
operation: "execute_wgpu_kernel".to_string(),
reason: "Expected WGPU kernel handle".to_string(),
context: None,
})
}
};
let shader_module = device_arc.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some("advanced_matmul_shader"),
source: wgpu::ShaderSource::Wgsl(shader_source.into()),
});
let bind_group_layout =
device_arc.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: Some("advanced_matmul_bind_group_layout"),
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStages::COMPUTE,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Storage { read_only: true },
has_dynamic_offset: false,
min_binding_size: None,
},
count: None,
},
wgpu::BindGroupLayoutEntry {
binding: 1,
visibility: wgpu::ShaderStages::COMPUTE,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Storage { read_only: true },
has_dynamic_offset: false,
min_binding_size: None,
},
count: None,
},
wgpu::BindGroupLayoutEntry {
binding: 2,
visibility: wgpu::ShaderStages::COMPUTE,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Storage { read_only: false },
has_dynamic_offset: false,
min_binding_size: None,
},
count: None,
},
wgpu::BindGroupLayoutEntry {
binding: 3,
visibility: wgpu::ShaderStages::COMPUTE,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
min_binding_size: None,
},
count: None,
},
],
});
let bind_group = device_arc.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("advanced_matmul_bind_group"),
layout: &bind_group_layout,
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: gpu_a.buffer().as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 1,
resource: gpu_b.buffer().as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 2,
resource: output_buffer.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 3,
resource: params_buffer.as_entire_binding(),
},
],
});
let pipeline_layout =
device_arc.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("advanced_matmul_pipeline_layout"),
bind_group_layouts: &[Some(&bind_group_layout)],
immediate_size: 0,
});
let entry_point = match &kernel.handle {
KernelHandle::WGPU { entry_point, .. } => entry_point.as_str(),
#[cfg(any(feature = "cuda", feature = "metal", feature = "rocm"))]
_ => "matmul_kernel", };
let compute_pipeline =
device_arc.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
label: Some("advanced_matmul_pipeline"),
layout: Some(&pipeline_layout),
module: &shader_module,
entry_point: Some(entry_point),
cache: None,
compilation_options: Default::default(),
});
let mut encoder = device_arc.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("advanced_matmul_encoder"),
});
{
let mut compute_pass = encoder.begin_compute_pass(&wgpu::ComputePassDescriptor {
label: Some("advanced_matmul_pass"),
timestamp_writes: None,
});
compute_pass.set_pipeline(&compute_pipeline);
compute_pass.set_bind_group(0, &bind_group, &[]);
let grid_x = kernel.parameters.grid_size.0 as u32;
let grid_y = kernel.parameters.grid_size.1 as u32;
let grid_z = kernel.parameters.grid_size.2 as u32;
compute_pass.dispatch_workgroups(grid_x, grid_y, grid_z);
}
queue_arc.submit(std::iter::once(encoder.finish()));
device_arc.poll(wgpu::PollType::wait_indefinitely()).ok();
let device_id = match a.device() {
crate::Device::Gpu(id) => *id,
_ => {
return Err(TensorError::InvalidArgument {
operation: "execute_wgpu_kernel".to_string(),
reason: "Expected GPU device".to_string(),
context: None,
})
}
};
let result_gpu = GpuBuffer::from_wgpu_buffer(
output_buffer,
device_arc,
queue_arc,
crate::Device::Gpu(device_id),
output_size,
);
Ok(Tensor::from_gpu_buffer(
result_gpu,
crate::Shape::new(result_shape),
))
} else {
Err(TensorError::InvalidArgument {
operation: "execute_wgpu_kernel".to_string(),
reason: "Expected GPU tensors".to_string(),
context: None,
})
}
}
fn update_performance_data(&self, kernel_id: &str, kernel: &CompiledKernel) -> Result<()> {
let mut perf_data =
self.performance_data
.write()
.map_err(|_| TensorError::InvalidArgument {
operation: "update_performance_data".to_string(),
reason: "Failed to acquire write lock".to_string(),
context: None,
})?;
perf_data.insert(
kernel_id.to_string(),
KernelPerformanceData {
avg_execution_time: 0.0, memory_bandwidth_util: 0.0,
compute_utilization: 0.0,
execution_count: 1,
speedup_factor: 1.0,
},
);
Ok(())
}
}
impl AdvancedKernelManager {
pub fn enable_advanced_optimizations(&mut self) -> Result<()> {
self.benchmark_strategies()?;
Ok(())
}
fn benchmark_strategies(&mut self) -> Result<()> {
Ok(())
}
pub fn get_performance_stats(&self) -> Result<HashMap<String, KernelPerformanceData>> {
let perf_data = self
.performance_data
.read()
.map_err(|_| TensorError::InvalidArgument {
operation: "get_performance_stats".to_string(),
reason: "Failed to acquire read lock".to_string(),
context: None,
})?;
Ok(perf_data.clone())
}
pub fn clear_cache(&mut self) -> Result<()> {
let mut cache = self
.kernel_cache
.write()
.map_err(|_| TensorError::InvalidArgument {
operation: "clear_cache".to_string(),
reason: "Failed to acquire write lock".to_string(),
context: None,
})?;
cache.clear();
let mut perf_data =
self.performance_data
.write()
.map_err(|_| TensorError::InvalidArgument {
operation: "clear_cache".to_string(),
reason: "Failed to acquire write lock".to_string(),
context: None,
})?;
perf_data.clear();
Ok(())
}
#[cfg(not(feature = "cuda"))]
fn compile_tensor_core_matmul<T: 'static>(
&self,
a: &Tensor<T>,
b: &Tensor<T>,
_precision: &TensorCorePrecision,
_tile_size: usize,
) -> Result<CompiledKernel> {
self.compile_standard_matmul(a, b)
}
#[cfg(not(feature = "metal"))]
fn compile_simd_group_matmul<T: 'static>(
&self,
a: &Tensor<T>,
b: &Tensor<T>,
_group_size: usize,
_vectorization_width: usize,
) -> Result<CompiledKernel> {
self.compile_standard_matmul(a, b)
}
#[cfg(not(feature = "rocm"))]
fn compile_wavefront_matmul<T: 'static>(
&self,
a: &Tensor<T>,
b: &Tensor<T>,
_wavefront_size: usize,
_lds_optimization: bool,
) -> Result<CompiledKernel> {
self.compile_standard_matmul(a, b)
}
fn compile_intel_xe_matmul<T: 'static>(
&self,
a: &Tensor<T>,
b: &Tensor<T>,
_xe_thread_groups: usize,
_xmx_acceleration: bool,
_intel_gpu_gen: &IntelGpuGeneration,
) -> Result<CompiledKernel> {
self.compile_standard_matmul(a, b)
}
}
const PCI_VENDOR_NVIDIA: u32 = 0x10de;
const PCI_VENDOR_AMD: u32 = 0x1002;
const PCI_VENDOR_INTEL: u32 = 0x8086;
const PCI_VENDOR_APPLE: u32 = 0x106b;
fn map_vendor(info: &wgpu::AdapterInfo) -> GpuVendor {
match info.vendor {
PCI_VENDOR_NVIDIA => GpuVendor::Nvidia,
PCI_VENDOR_AMD => GpuVendor::AMD,
PCI_VENDOR_INTEL => GpuVendor::Intel,
PCI_VENDOR_APPLE => GpuVendor::Apple,
_ => vendor_from_name(&info.name),
}
}
fn vendor_from_name(name: &str) -> GpuVendor {
let lower = name.to_ascii_lowercase();
if lower.contains("nvidia") || lower.contains("geforce") || lower.contains("quadro") {
GpuVendor::Nvidia
} else if lower.contains("amd") || lower.contains("radeon") {
GpuVendor::AMD
} else if lower.contains("intel") {
GpuVendor::Intel
} else if lower.contains("apple") {
GpuVendor::Apple
} else {
GpuVendor::Unknown
}
}
fn compute_capability_from_info(info: &wgpu::AdapterInfo) -> String {
if info.name.is_empty() {
format!("{:?}", info.backend)
} else {
format!("{} ({:?})", info.name, info.backend)
}
}
fn threads_from_limits(limits: &wgpu::Limits) -> u32 {
limits.max_compute_workgroup_size_x
}
fn shared_mem_from_limits(limits: &wgpu::Limits) -> u32 {
limits.max_compute_workgroup_storage_size
}
fn fp16_from_features(features: wgpu::Features) -> bool {
features.contains(wgpu::Features::SHADER_F16)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn measure_memory_bandwidth_returns_honest_error_not_fabricated_literal() {
let result = AdvancedKernelManager::measure_memory_bandwidth();
assert!(
result.is_err(),
"measure_memory_bandwidth must not fabricate a measured value"
);
assert_ne!(
result.ok(),
Some(448.0),
"must not return the old fabricated 448.0 literal"
);
}
#[test]
fn query_compute_units_returns_honest_error_not_fabricated_literal() {
let result = AdvancedKernelManager::query_compute_units();
assert!(result.is_err());
assert_ne!(result.ok(), Some(46), "must not return the old 46 literal");
}
#[test]
fn detect_tensor_cores_returns_honest_error() {
assert!(AdvancedKernelManager::detect_tensor_cores().is_err());
}
#[test]
fn query_max_threads_per_block_reflects_real_limits_not_fabricated_literal() {
let limits = wgpu::Limits {
max_compute_workgroup_size_x: 777,
..Default::default()
};
assert_eq!(
AdvancedKernelManager::query_max_threads_per_block(&limits),
777
);
}
#[test]
fn query_shared_memory_size_reflects_real_limits_not_fabricated_literal() {
let limits = wgpu::Limits {
max_compute_workgroup_storage_size: 12345,
..Default::default()
};
assert_eq!(
AdvancedKernelManager::query_shared_memory_size(&limits),
12345
);
}
#[test]
fn test_fp16_support_reflects_real_features_not_fabricated_error() {
assert!(AdvancedKernelManager::test_fp16_support(
wgpu::Features::SHADER_F16
));
assert!(!AdvancedKernelManager::test_fp16_support(
wgpu::Features::empty()
));
}
#[test]
fn bf16_and_coop_group_queries_return_honest_errors() {
assert!(
AdvancedKernelManager::test_bf16_support().is_err(),
"bf16 support must not be fabricated"
);
assert!(
AdvancedKernelManager::test_cooperative_groups().is_err(),
"cooperative groups support must not be fabricated"
);
}
#[cfg(feature = "gpu")]
#[test]
fn detect_device_capabilities_propagates_honest_error_for_gpu() {
let result = AdvancedKernelManager::detect_device_capabilities(&Device::Gpu(0));
assert!(
result.is_err(),
"GPU capability detection must not fabricate a DeviceCapabilities struct"
);
}
fn test_adapter_info(vendor: u32, name: &str, backend: wgpu::Backend) -> wgpu::AdapterInfo {
wgpu::AdapterInfo {
name: name.to_string(),
vendor,
device: 0,
device_type: wgpu::DeviceType::Other,
device_pci_bus_id: String::new(),
driver: String::new(),
driver_info: String::new(),
backend,
subgroup_min_size: 0,
subgroup_max_size: 0,
transient_saves_memory: Some(false),
limit_bucket: None,
}
}
#[test]
fn map_vendor_detects_nvidia_by_pci_id() {
let info = test_adapter_info(
PCI_VENDOR_NVIDIA,
"NVIDIA GeForce RTX 4090",
wgpu::Backend::Vulkan,
);
assert_eq!(map_vendor(&info), GpuVendor::Nvidia);
}
#[test]
fn map_vendor_detects_amd_by_pci_id() {
let info = test_adapter_info(
PCI_VENDOR_AMD,
"AMD Radeon RX 7900 XTX",
wgpu::Backend::Vulkan,
);
assert_eq!(map_vendor(&info), GpuVendor::AMD);
}
#[test]
fn map_vendor_detects_intel_by_pci_id() {
let info = test_adapter_info(PCI_VENDOR_INTEL, "Intel Arc A770", wgpu::Backend::Vulkan);
assert_eq!(map_vendor(&info), GpuVendor::Intel);
}
#[test]
fn map_vendor_detects_apple_by_pci_id() {
let info = test_adapter_info(PCI_VENDOR_APPLE, "Apple GPU", wgpu::Backend::Metal);
assert_eq!(map_vendor(&info), GpuVendor::Apple);
}
#[test]
fn map_vendor_falls_back_to_name_when_pci_id_is_zero_apple() {
let info = test_adapter_info(0, "Apple M3 Max", wgpu::Backend::Metal);
assert_eq!(map_vendor(&info), GpuVendor::Apple);
}
#[test]
fn map_vendor_falls_back_to_name_for_nvidia_when_pci_id_unknown() {
let info = test_adapter_info(0, "NVIDIA GeForce RTX 3080", wgpu::Backend::Vulkan);
assert_eq!(map_vendor(&info), GpuVendor::Nvidia);
}
#[test]
fn map_vendor_falls_back_to_name_for_amd_when_pci_id_unknown() {
let info = test_adapter_info(0, "AMD Radeon Pro 5500M", wgpu::Backend::Vulkan);
assert_eq!(map_vendor(&info), GpuVendor::AMD);
}
#[test]
fn map_vendor_returns_unknown_for_unrecognized_adapter() {
let info = test_adapter_info(0, "llvmpipe (LLVM 17.0.0, 256 bits)", wgpu::Backend::Vulkan);
assert_eq!(map_vendor(&info), GpuVendor::Unknown);
}
#[test]
fn threads_from_limits_reads_workgroup_size_x() {
let limits_a = wgpu::Limits {
max_compute_workgroup_size_x: 1024,
..Default::default()
};
assert_eq!(threads_from_limits(&limits_a), 1024);
let limits_b = wgpu::Limits {
max_compute_workgroup_size_x: 256,
..Default::default()
};
assert_eq!(
threads_from_limits(&limits_b),
256,
"must track the real field, not a hardcoded constant"
);
}
#[test]
fn shared_mem_from_limits_reads_workgroup_storage_size() {
let limits_a = wgpu::Limits {
max_compute_workgroup_storage_size: 32768,
..Default::default()
};
assert_eq!(shared_mem_from_limits(&limits_a), 32768);
let limits_b = wgpu::Limits {
max_compute_workgroup_storage_size: 16384,
..Default::default()
};
assert_eq!(
shared_mem_from_limits(&limits_b),
16384,
"must track the real field, not a hardcoded constant"
);
}
#[test]
fn fp16_from_features_true_when_shader_f16_present() {
assert!(fp16_from_features(wgpu::Features::SHADER_F16));
}
#[test]
fn fp16_from_features_false_when_absent() {
assert!(!fp16_from_features(wgpu::Features::empty()));
}
#[test]
fn compute_capability_from_info_uses_real_name_not_fabricated_version() {
let info = test_adapter_info(
PCI_VENDOR_NVIDIA,
"NVIDIA GeForce RTX 4090",
wgpu::Backend::Vulkan,
);
let cap = compute_capability_from_info(&info);
assert!(
cap.contains("RTX 4090"),
"must reflect the real adapter name: {cap}"
);
assert_ne!(cap, "7.5");
}
#[test]
fn compute_capability_from_info_differs_across_real_devices() {
let a = compute_capability_from_info(&test_adapter_info(
PCI_VENDOR_NVIDIA,
"NVIDIA GeForce RTX 4090",
wgpu::Backend::Vulkan,
));
let b = compute_capability_from_info(&test_adapter_info(
PCI_VENDOR_NVIDIA,
"NVIDIA GeForce RTX 3050",
wgpu::Backend::Vulkan,
));
assert_ne!(
a, b,
"two different real NVIDIA cards must not collapse to the same fabricated literal"
);
}
#[test]
fn compute_capability_from_info_falls_back_to_backend_when_name_empty() {
let info = test_adapter_info(0, "", wgpu::Backend::Vulkan);
let cap = compute_capability_from_info(&info);
assert!(!cap.is_empty());
}
#[test]
fn detect_gpu_vendor_delegates_to_map_vendor() {
let info = test_adapter_info(
PCI_VENDOR_AMD,
"AMD Radeon RX 7900 XTX",
wgpu::Backend::Vulkan,
);
assert_eq!(
AdvancedKernelManager::detect_gpu_vendor(&info),
GpuVendor::AMD
);
}
#[test]
fn query_compute_capability_delegates_to_compute_capability_from_info() {
let info = test_adapter_info(PCI_VENDOR_APPLE, "Apple M2 Pro", wgpu::Backend::Metal);
let cap = AdvancedKernelManager::query_compute_capability(&info);
assert!(cap.contains("M2 Pro"));
}
#[cfg(feature = "gpu")]
fn gpu_adapter_available() -> bool {
crate::gpu::gpu_device_available()
}
#[cfg(feature = "gpu")]
#[test]
fn detect_device_capabilities_uses_real_adapter_when_available() {
if !gpu_adapter_available() {
eprintln!(
"GPU adapter not available, skipping detect_device_capabilities integration test"
);
return;
}
let caps = crate::device::get_gpu_adapter_capabilities(0).expect(
"test: a GPU adapter was just reported available, so fetching its capabilities \
must succeed",
);
assert!(
!caps.info.name.is_empty(),
"a real adapter must report a non-empty name"
);
let vendor = AdvancedKernelManager::detect_gpu_vendor(&caps.info);
let vendor_again = AdvancedKernelManager::detect_gpu_vendor(&caps.info);
assert_eq!(
vendor, vendor_again,
"vendor mapping must be a pure, deterministic function of real adapter info"
);
let result = AdvancedKernelManager::detect_device_capabilities(&Device::Gpu(0));
assert!(
result.is_err(),
"capability detection must still honestly error on the fields wgpu cannot \
answer, even with a real adapter available"
);
}
#[cfg(feature = "metal")]
#[test]
fn execute_metal_kernel_delegates_to_wgpu_and_succeeds() {
if !gpu_adapter_available() {
eprintln!("GPU adapter not available, skipping execute_metal_kernel test");
return;
}
let a_cpu = Tensor::<f32>::from_vec(vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0], &[2, 3])
.expect("test: create a");
let b_cpu = Tensor::<f32>::from_vec(vec![7.0, 8.0, 9.0, 10.0, 11.0, 12.0], &[3, 2])
.expect("test: create b");
let a_gpu = a_cpu
.to_device(Device::Gpu(0))
.expect("test: move a to GPU");
let b_gpu = b_cpu
.to_device(Device::Gpu(0))
.expect("test: move b to GPU");
let manager = AdvancedKernelManager {
device_info: Arc::new(RwLock::new(DeviceCapabilities {
vendor: GpuVendor::Apple,
compute_capability: "test".to_string(),
memory_bandwidth: 0.0,
compute_units: 0,
has_tensor_cores: false,
max_threads_per_block: 1024,
shared_memory_size: 0,
supports_fp16: false,
supports_bf16: false,
supports_coop_groups: false,
})),
kernel_cache: Arc::new(RwLock::new(HashMap::new())),
performance_data: Arc::new(RwLock::new(HashMap::new())),
strategy: KernelStrategy::StandardCompute,
};
let dummy_kernel = CompiledKernel {
id: "test".to_string(),
strategy: KernelStrategy::StandardCompute,
compiled_at: std::time::SystemTime::now(),
parameters: KernelParameters {
grid_size: (1, 1, 1),
block_size: (1, 1, 1),
shared_memory: 0,
register_count: 0,
},
handle: KernelHandle::Metal {
library: "test".to_string(),
function: "test".to_string(),
},
};
let result = manager
.execute_metal_kernel(&a_gpu, &b_gpu, &dummy_kernel)
.expect(
"test: execute_metal_kernel must now succeed by delegating to execute_wgpu_kernel",
);
let result_cpu = result.to_cpu().expect("test: move result to CPU");
assert_eq!(result_cpu.shape().dims(), &[1, 2, 2]);
let data = result_cpu.data();
let expected = [58.0f32, 64.0, 139.0, 154.0];
for (got, want) in data.iter().zip(expected.iter()) {
assert!(
(got - want).abs() < 1e-4,
"execute_metal_kernel result mismatch: got {got}, want {want}"
);
}
}
}