Skip to main content

oxirs_vec/gpu/
runtime.rs

1//! CUDA runtime types and utilities
2//!
3//! Pure-Rust handle types kept for API compatibility. Real CUDA streams and
4//! kernels live in the quarantined `oxirs-vec-adapter-cuda` crate
5//! (publish = false) per the COOLJAPAN Pure Rust Policy v2.
6
7use std::time::Duration;
8
9/// CUDA stream wrapper
10#[derive(Debug)]
11pub struct CudaStream {
12    pub handle: *mut std::ffi::c_void,
13    pub device_id: i32,
14}
15
16unsafe impl Send for CudaStream {}
17unsafe impl Sync for CudaStream {}
18
19impl CudaStream {
20    pub fn new(device_id: i32) -> anyhow::Result<Self> {
21        // Pure Rust build: placeholder handle. Real streams are created by
22        // oxirs-vec-adapter-cuda.
23        Ok(Self {
24            handle: std::ptr::null_mut(),
25            device_id,
26        })
27    }
28
29    pub fn synchronize(&self) -> anyhow::Result<()> {
30        // No-op in the Pure Rust build.
31        Ok(())
32    }
33}
34
35/// CUDA kernel wrapper
36#[derive(Debug)]
37pub struct CudaKernel {
38    pub function: *mut std::ffi::c_void,
39    pub module: *mut std::ffi::c_void,
40    pub name: String,
41}
42
43unsafe impl Send for CudaKernel {}
44unsafe impl Sync for CudaKernel {}
45
46impl CudaKernel {
47    pub fn load(_ptx_code: &str, function_name: &str) -> anyhow::Result<Self> {
48        // Pure Rust build: placeholder handle. Real PTX loading is provided by
49        // oxirs-vec-adapter-cuda.
50        Ok(Self {
51            function: std::ptr::null_mut(),
52            module: std::ptr::null_mut(),
53            name: function_name.to_string(),
54        })
55    }
56}
57
58/// GPU performance statistics
59#[derive(Debug, Default, Clone)]
60pub struct GpuPerformanceStats {
61    pub total_operations: u64,
62    pub total_compute_time: Duration,
63    pub total_memory_transfers: u64,
64    pub total_transfer_time: Duration,
65    pub peak_memory_usage: usize,
66    pub current_memory_usage: usize,
67}
68
69impl GpuPerformanceStats {
70    pub fn new() -> Self {
71        Self::default()
72    }
73
74    pub fn record_operation(&mut self, compute_time: Duration) {
75        self.total_operations += 1;
76        self.total_compute_time += compute_time;
77    }
78
79    pub fn record_transfer(&mut self, transfer_time: Duration) {
80        self.total_memory_transfers += 1;
81        self.total_transfer_time += transfer_time;
82    }
83
84    pub fn update_memory_usage(&mut self, current: usize) {
85        self.current_memory_usage = current;
86        if current > self.peak_memory_usage {
87            self.peak_memory_usage = current;
88        }
89    }
90
91    pub fn average_compute_time(&self) -> Duration {
92        if self.total_operations > 0 {
93            self.total_compute_time / self.total_operations as u32
94        } else {
95            Duration::ZERO
96        }
97    }
98
99    pub fn average_transfer_time(&self) -> Duration {
100        if self.total_memory_transfers > 0 {
101            self.total_transfer_time / self.total_memory_transfers as u32
102        } else {
103            Duration::ZERO
104        }
105    }
106
107    pub fn throughput_ops_per_sec(&self) -> f64 {
108        if !self.total_compute_time.is_zero() {
109            self.total_operations as f64 / self.total_compute_time.as_secs_f64()
110        } else {
111            0.0
112        }
113    }
114}