hive_gpu/monitoring/
vram_monitor.rs

1//! VRAM Monitoring and Validation
2//!
3//! This module provides VRAM usage monitoring, validation, and optimization
4//! for GPU operations.
5
6use crate::error::{Result, HiveGpuError};
7use crate::traits::{GpuMonitor, VramStats, VramBufferInfo};
8use std::collections::HashMap;
9use std::time::{SystemTime, UNIX_EPOCH};
10
11/// VRAM Monitor for tracking GPU memory usage
12pub struct VramMonitor {
13    /// Total VRAM capacity in bytes
14    total_vram: usize,
15    /// Currently allocated VRAM in bytes
16    allocated_vram: usize,
17    /// Buffer information map
18    buffers: HashMap<usize, VramBufferInfo>,
19    /// Next buffer ID
20    next_buffer_id: usize,
21}
22
23impl VramMonitor {
24    /// Create a new VRAM monitor
25    pub fn new(total_vram: usize) -> Self {
26        Self {
27            total_vram,
28            allocated_vram: 0,
29            buffers: HashMap::new(),
30            next_buffer_id: 0,
31        }
32    }
33
34    /// Allocate VRAM for a buffer
35    pub fn allocate_buffer(&mut self, size: usize, buffer_type: crate::traits::BufferType) -> Result<usize> {
36        if self.allocated_vram + size > self.total_vram {
37            return Err(HiveGpuError::VramLimitExceeded {
38                requested: self.allocated_vram + size,
39                limit: self.total_vram,
40            });
41        }
42
43        let buffer_id = self.next_buffer_id;
44        self.next_buffer_id += 1;
45
46        let buffer_info = VramBufferInfo {
47            buffer_id,
48            size,
49            buffer_type,
50            allocated_at: SystemTime::now()
51                .duration_since(UNIX_EPOCH)
52                .unwrap()
53                .as_secs(),
54        };
55
56        self.buffers.insert(buffer_id, buffer_info);
57        self.allocated_vram += size;
58
59        Ok(buffer_id)
60    }
61
62    /// Deallocate VRAM for a buffer
63    pub fn deallocate_buffer(&mut self, buffer_id: usize) -> Result<()> {
64        if let Some(buffer_info) = self.buffers.remove(&buffer_id) {
65            self.allocated_vram = self.allocated_vram.saturating_sub(buffer_info.size);
66            Ok(())
67        } else {
68            Err(HiveGpuError::Other(format!("Buffer {} not found", buffer_id)))
69        }
70    }
71
72    /// Get current VRAM statistics
73    pub fn get_vram_stats(&self) -> VramStats {
74        VramStats {
75            total_vram: self.total_vram,
76            allocated_vram: self.allocated_vram,
77            available_vram: self.total_vram - self.allocated_vram,
78            utilization: self.allocated_vram as f32 / self.total_vram as f32,
79            buffer_count: self.buffers.len(),
80        }
81    }
82
83    /// Validate that all operations are in VRAM
84    pub fn validate_all_vram(&self) -> Result<()> {
85        let stats = self.get_vram_stats();
86        
87        if stats.utilization > 0.95 {
88            return Err(HiveGpuError::VramLimitExceeded {
89                requested: stats.allocated_vram,
90                limit: (self.total_vram as f32 * 0.95) as usize,
91            });
92        }
93
94        Ok(())
95    }
96
97    /// Generate detailed VRAM report
98    pub fn generate_vram_report(&self) -> String {
99        let stats = self.get_vram_stats();
100        let mut report = String::new();
101        
102        report.push_str(&format!("VRAM Report:\n"));
103        report.push_str(&format!("  Total VRAM: {:.2} MB\n", stats.total_vram as f64 / 1024.0 / 1024.0));
104        report.push_str(&format!("  Allocated: {:.2} MB\n", stats.allocated_vram as f64 / 1024.0 / 1024.0));
105        report.push_str(&format!("  Available: {:.2} MB\n", stats.available_vram as f64 / 1024.0 / 1024.0));
106        report.push_str(&format!("  Utilization: {:.1}%\n", stats.utilization * 100.0));
107        report.push_str(&format!("  Buffer Count: {}\n", stats.buffer_count));
108        
109        // Buffer breakdown by type
110        let mut type_counts: HashMap<crate::traits::BufferType, (usize, usize)> = HashMap::new();
111        for buffer in self.buffers.values() {
112            let entry = type_counts.entry(buffer.buffer_type).or_insert((0, 0));
113            entry.0 += 1;
114            entry.1 += buffer.size;
115        }
116        
117        report.push_str("\nBuffer Breakdown:\n");
118        for (buffer_type, (count, size)) in type_counts {
119            report.push_str(&format!("  {:?}: {} buffers, {:.2} MB\n", 
120                buffer_type, count, size as f64 / 1024.0 / 1024.0));
121        }
122        
123        report
124    }
125}
126
127impl GpuMonitor for VramMonitor {
128    fn get_vram_stats(&self) -> VramStats {
129        self.get_vram_stats()
130    }
131
132    fn validate_all_vram(&self) -> Result<()> {
133        self.validate_all_vram()
134    }
135
136    fn generate_vram_report(&self) -> String {
137        self.generate_vram_report()
138    }
139}
140
141/// VRAM Validator for ensuring VRAM-only operations
142pub struct VramValidator {
143    monitor: VramMonitor,
144    max_utilization: f32,
145}
146
147impl VramValidator {
148    /// Create a new VRAM validator
149    pub fn new(total_vram: usize, max_utilization: f32) -> Self {
150        Self {
151            monitor: VramMonitor::new(total_vram),
152            max_utilization,
153        }
154    }
155
156    /// Validate VRAM allocation request
157    pub fn validate_allocation(&self, size: usize) -> Result<()> {
158        let stats = self.monitor.get_vram_stats();
159        let new_utilization = (stats.allocated_vram + size) as f32 / stats.total_vram as f32;
160        
161        if new_utilization > self.max_utilization {
162            return Err(HiveGpuError::VramLimitExceeded {
163                requested: stats.allocated_vram + size,
164                limit: (stats.total_vram as f32 * self.max_utilization) as usize,
165            });
166        }
167
168        Ok(())
169    }
170}
171
172/// VRAM Benchmark Result
173#[derive(Debug, Clone)]
174pub struct VramBenchmarkResult {
175    /// Operation name
176    pub operation: String,
177    /// Duration in milliseconds
178    pub duration_ms: f64,
179    /// Memory allocated in bytes
180    pub memory_allocated: usize,
181    /// Memory utilization percentage
182    pub utilization: f32,
183    /// Throughput (operations per second)
184    pub throughput: f64,
185}