|
| 1 | +// Copyright 2025 Lablup Inc. and Jeongkyu Shin |
| 2 | +// |
| 3 | +// Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | +// you may not use this file except in compliance with the License. |
| 5 | +// You may obtain a copy of the License at |
| 6 | +// |
| 7 | +// http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | +// |
| 9 | +// Unless required by applicable law or agreed to in writing, software |
| 10 | +// distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | +// See the License for the specific language governing permissions and |
| 13 | +// limitations under the License. |
| 14 | + |
| 15 | +//! Example demonstrating the all-smi library API. |
| 16 | +//! |
| 17 | +//! This example shows how to use the high-level AllSmi API to query |
| 18 | +//! GPU, CPU, memory, and process information. |
| 19 | +//! |
| 20 | +//! Run with: `cargo run --example library_usage` |
| 21 | +
|
| 22 | +use all_smi::prelude::*; |
| 23 | + |
| 24 | +fn main() -> Result<()> { |
| 25 | + println!("=== all-smi Library Usage Example ===\n"); |
| 26 | + |
| 27 | + // Initialize AllSmi with default configuration |
| 28 | + let smi = AllSmi::new()?; |
| 29 | + |
| 30 | + // ========================================================================== |
| 31 | + // GPU / NPU Information |
| 32 | + // ========================================================================== |
| 33 | + println!("--- GPU/NPU Information ---"); |
| 34 | + let gpus = smi.get_gpu_info(); |
| 35 | + |
| 36 | + if gpus.is_empty() { |
| 37 | + println!("No GPUs/NPUs detected on this system."); |
| 38 | + } else { |
| 39 | + println!("Found {} GPU(s)/NPU(s):\n", gpus.len()); |
| 40 | + |
| 41 | + for (i, gpu) in gpus.iter().enumerate() { |
| 42 | + println!(" [{}] {}", i, gpu.name); |
| 43 | + println!(" Type: {}", gpu.device_type); |
| 44 | + println!(" Utilization: {:.1}%", gpu.utilization); |
| 45 | + println!( |
| 46 | + " Memory: {} MB / {} MB ({:.1}%)", |
| 47 | + gpu.used_memory / 1024 / 1024, |
| 48 | + gpu.total_memory / 1024 / 1024, |
| 49 | + if gpu.total_memory > 0 { |
| 50 | + (gpu.used_memory as f64 / gpu.total_memory as f64) * 100.0 |
| 51 | + } else { |
| 52 | + 0.0 |
| 53 | + } |
| 54 | + ); |
| 55 | + println!(" Temperature: {}C", gpu.temperature); |
| 56 | + println!(" Power: {:.1}W", gpu.power_consumption); |
| 57 | + println!(" Frequency: {} MHz", gpu.frequency); |
| 58 | + |
| 59 | + if let Some(cores) = gpu.gpu_core_count { |
| 60 | + println!(" GPU Cores: {}", cores); |
| 61 | + } |
| 62 | + |
| 63 | + println!(); |
| 64 | + } |
| 65 | + } |
| 66 | + |
| 67 | + // ========================================================================== |
| 68 | + // GPU/NPU Process Information |
| 69 | + // ========================================================================== |
| 70 | + println!("--- GPU/NPU Processes ---"); |
| 71 | + let processes = smi.get_process_info(); |
| 72 | + |
| 73 | + if processes.is_empty() { |
| 74 | + println!("No GPU/NPU processes running."); |
| 75 | + } else { |
| 76 | + println!("Found {} GPU process(es):\n", processes.len()); |
| 77 | + |
| 78 | + for proc in processes.iter().take(5) { |
| 79 | + println!( |
| 80 | + " PID {}: {} ({} MB GPU memory)", |
| 81 | + proc.pid, |
| 82 | + proc.process_name, |
| 83 | + proc.used_memory / 1024 / 1024 |
| 84 | + ); |
| 85 | + } |
| 86 | + |
| 87 | + if processes.len() > 5 { |
| 88 | + println!(" ... and {} more", processes.len() - 5); |
| 89 | + } |
| 90 | + } |
| 91 | + println!(); |
| 92 | + |
| 93 | + // ========================================================================== |
| 94 | + // CPU Information |
| 95 | + // ========================================================================== |
| 96 | + println!("--- CPU Information ---"); |
| 97 | + let cpus = smi.get_cpu_info(); |
| 98 | + |
| 99 | + if cpus.is_empty() { |
| 100 | + println!("CPU information not available."); |
| 101 | + } else { |
| 102 | + for cpu in &cpus { |
| 103 | + println!(" Model: {}", cpu.cpu_model); |
| 104 | + println!(" Architecture: {}", cpu.architecture); |
| 105 | + println!( |
| 106 | + " Cores: {} (Threads: {})", |
| 107 | + cpu.total_cores, cpu.total_threads |
| 108 | + ); |
| 109 | + println!(" Sockets: {}", cpu.socket_count); |
| 110 | + println!(" Utilization: {:.1}%", cpu.utilization); |
| 111 | + println!( |
| 112 | + " Frequency: {} MHz (Max: {} MHz)", |
| 113 | + cpu.base_frequency_mhz, cpu.max_frequency_mhz |
| 114 | + ); |
| 115 | + |
| 116 | + if let Some(temp) = cpu.temperature { |
| 117 | + println!(" Temperature: {}C", temp); |
| 118 | + } |
| 119 | + |
| 120 | + if let Some(power) = cpu.power_consumption { |
| 121 | + println!(" Power: {:.1}W", power); |
| 122 | + } |
| 123 | + |
| 124 | + // Apple Silicon specific info |
| 125 | + if let Some(ref apple_info) = cpu.apple_silicon_info { |
| 126 | + println!(" Apple Silicon Details:"); |
| 127 | + println!( |
| 128 | + " P-cores: {} ({:.1}% utilization)", |
| 129 | + apple_info.p_core_count, apple_info.p_core_utilization |
| 130 | + ); |
| 131 | + println!( |
| 132 | + " E-cores: {} ({:.1}% utilization)", |
| 133 | + apple_info.e_core_count, apple_info.e_core_utilization |
| 134 | + ); |
| 135 | + println!(" GPU cores: {}", apple_info.gpu_core_count); |
| 136 | + |
| 137 | + if let Some(p_freq) = apple_info.p_cluster_frequency_mhz { |
| 138 | + println!(" P-cluster frequency: {} MHz", p_freq); |
| 139 | + } |
| 140 | + if let Some(e_freq) = apple_info.e_cluster_frequency_mhz { |
| 141 | + println!(" E-cluster frequency: {} MHz", e_freq); |
| 142 | + } |
| 143 | + } |
| 144 | + } |
| 145 | + } |
| 146 | + println!(); |
| 147 | + |
| 148 | + // ========================================================================== |
| 149 | + // Memory Information |
| 150 | + // ========================================================================== |
| 151 | + println!("--- Memory Information ---"); |
| 152 | + let memory = smi.get_memory_info(); |
| 153 | + |
| 154 | + if memory.is_empty() { |
| 155 | + println!("Memory information not available."); |
| 156 | + } else { |
| 157 | + for mem in &memory { |
| 158 | + let total_gb = mem.total_bytes as f64 / 1024.0 / 1024.0 / 1024.0; |
| 159 | + let used_gb = mem.used_bytes as f64 / 1024.0 / 1024.0 / 1024.0; |
| 160 | + let available_gb = mem.available_bytes as f64 / 1024.0 / 1024.0 / 1024.0; |
| 161 | + |
| 162 | + println!(" Total: {:.1} GB", total_gb); |
| 163 | + println!(" Used: {:.1} GB ({:.1}%)", used_gb, mem.utilization); |
| 164 | + println!(" Available: {:.1} GB", available_gb); |
| 165 | + |
| 166 | + if mem.swap_total_bytes > 0 { |
| 167 | + let swap_total_gb = mem.swap_total_bytes as f64 / 1024.0 / 1024.0 / 1024.0; |
| 168 | + let swap_used_gb = mem.swap_used_bytes as f64 / 1024.0 / 1024.0 / 1024.0; |
| 169 | + println!(" Swap: {:.1} GB / {:.1} GB", swap_used_gb, swap_total_gb); |
| 170 | + } |
| 171 | + |
| 172 | + // Linux-specific metrics |
| 173 | + if mem.buffers_bytes > 0 || mem.cached_bytes > 0 { |
| 174 | + let buffers_mb = mem.buffers_bytes as f64 / 1024.0 / 1024.0; |
| 175 | + let cached_mb = mem.cached_bytes as f64 / 1024.0 / 1024.0; |
| 176 | + println!( |
| 177 | + " Buffers: {:.1} MB, Cached: {:.1} MB", |
| 178 | + buffers_mb, cached_mb |
| 179 | + ); |
| 180 | + } |
| 181 | + } |
| 182 | + } |
| 183 | + println!(); |
| 184 | + |
| 185 | + // ========================================================================== |
| 186 | + // Chassis Information |
| 187 | + // ========================================================================== |
| 188 | + println!("--- Chassis Information ---"); |
| 189 | + if let Some(chassis) = smi.get_chassis_info() { |
| 190 | + if let Some(power) = chassis.total_power_watts { |
| 191 | + println!(" Total System Power: {:.1}W", power); |
| 192 | + } |
| 193 | + |
| 194 | + if let Some(ref pressure) = chassis.thermal_pressure { |
| 195 | + println!(" Thermal Pressure: {}", pressure); |
| 196 | + } |
| 197 | + |
| 198 | + if let Some(inlet) = chassis.inlet_temperature { |
| 199 | + println!(" Inlet Temperature: {:.1}C", inlet); |
| 200 | + } |
| 201 | + |
| 202 | + if let Some(outlet) = chassis.outlet_temperature { |
| 203 | + println!(" Outlet Temperature: {:.1}C", outlet); |
| 204 | + } |
| 205 | + |
| 206 | + if !chassis.fan_speeds.is_empty() { |
| 207 | + println!(" Fans:"); |
| 208 | + for fan in &chassis.fan_speeds { |
| 209 | + println!( |
| 210 | + " {}: {} RPM / {} RPM", |
| 211 | + fan.name, fan.speed_rpm, fan.max_rpm |
| 212 | + ); |
| 213 | + } |
| 214 | + } |
| 215 | + |
| 216 | + if !chassis.psu_status.is_empty() { |
| 217 | + println!(" PSUs:"); |
| 218 | + for psu in &chassis.psu_status { |
| 219 | + println!(" {}: {:?}", psu.name, psu.status); |
| 220 | + } |
| 221 | + } |
| 222 | + } else { |
| 223 | + println!(" Chassis information not available on this platform."); |
| 224 | + } |
| 225 | + println!(); |
| 226 | + |
| 227 | + // ========================================================================== |
| 228 | + // Summary |
| 229 | + // ========================================================================== |
| 230 | + println!("--- Summary ---"); |
| 231 | + println!(" GPU readers: {}", smi.gpu_reader_count()); |
| 232 | + println!(" Has GPUs: {}", smi.has_gpus()); |
| 233 | + println!(" Has CPU monitoring: {}", smi.has_cpu_monitoring()); |
| 234 | + println!(" Has memory monitoring: {}", smi.has_memory_monitoring()); |
| 235 | + |
| 236 | + Ok(()) |
| 237 | +} |
0 commit comments