1use anyhow::Result;
9
10#[derive(Debug, Clone)]
12pub struct GpuDevice {
13 pub device_id: i32,
14 pub name: String,
15 pub compute_capability: (i32, i32),
16 pub total_memory: usize,
17 pub free_memory: usize,
18 pub max_threads_per_block: i32,
19 pub max_blocks_per_grid: i32,
20 pub warp_size: i32,
21 pub memory_bandwidth: f32,
22 pub peak_flops: f64,
23}
24
25impl GpuDevice {
26 fn simulated(device_id: i32) -> Self {
28 Self {
29 device_id,
30 name: format!("Simulated GPU {device_id}"),
31 compute_capability: (7, 5),
32 total_memory: 8 * 1024 * 1024 * 1024,
33 free_memory: 6 * 1024 * 1024 * 1024,
34 max_threads_per_block: 1024,
35 max_blocks_per_grid: 65535,
36 warp_size: 32,
37 memory_bandwidth: 900.0,
38 peak_flops: 14000.0,
39 }
40 }
41
42 pub fn get_device_info(device_id: i32) -> Result<Self> {
44 tracing::warn!("CUDA not available - using simulated GPU device");
47 Ok(Self::simulated(device_id))
48 }
49
50 pub fn get_all_devices() -> Result<Vec<Self>> {
52 tracing::warn!("CUDA not available - using simulated GPU devices");
55 Ok(vec![Self::get_device_info(0)?, Self::get_device_info(1)?])
56 }
57
58 pub fn supports_compute_capability(&self, major: i32, minor: i32) -> bool {
60 self.compute_capability.0 > major
61 || (self.compute_capability.0 == major && self.compute_capability.1 >= minor)
62 }
63
64 pub fn peak_memory_bandwidth(&self) -> f32 {
66 self.memory_bandwidth
67 }
68
69 pub fn peak_compute_performance(&self) -> f64 {
71 self.peak_flops
72 }
73
74 pub fn calculate_optimal_block_config(&self, problem_size: usize) -> (i32, i32) {
76 let optimal_threads = (self.max_threads_per_block as f32 * 0.75) as i32; let blocks_needed = ((problem_size as f32) / (optimal_threads as f32)).ceil() as i32;
78 let blocks = blocks_needed.min(self.max_blocks_per_grid);
79 (blocks, optimal_threads)
80 }
81}