feat(ml): add gpu module with DeviceConfig enum

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jgrusewski
2026-02-23 11:11:20 +01:00
parent 17727d5db9
commit 985b0f73d6
4 changed files with 99 additions and 0 deletions

View File

View File

98
ml/src/gpu/mod.rs Normal file
View File

@@ -0,0 +1,98 @@
//! GPU device management for ML training
//!
//! Provides centralized device selection, GPU capability detection,
//! and per-model batch size optimization.
pub mod capabilities;
pub mod memory_profile;
use candle_core::Device;
use serde::{Deserialize, Serialize};
use crate::MLError;
/// Device configuration for ML training and inference.
///
/// Use `Auto` for production — it detects CUDA if available, falls back to CPU.
/// Use `Cuda(id)` to pin to a specific GPU. Use `Cpu` to force CPU mode.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum DeviceConfig {
Cpu,
Cuda(usize),
Auto,
}
impl DeviceConfig {
/// Resolve this config into a concrete candle `Device`.
///
/// - `Cpu` → always `Device::Cpu`
/// - `Cuda(id)` → `Device::new_cuda(id)`, errors if unavailable
/// - `Auto` → CUDA device 0 if available, else CPU
pub fn resolve(&self) -> Result<Device, MLError> {
match self {
DeviceConfig::Cpu => Ok(Device::Cpu),
DeviceConfig::Cuda(id) => Device::new_cuda(*id).map_err(|e| {
MLError::ConfigurationError(format!(
"CUDA device {} required but unavailable: {}",
id, e
))
}),
DeviceConfig::Auto => {
match Device::new_cuda(0) {
Ok(dev) => Ok(dev),
Err(_) => Ok(Device::Cpu),
}
}
}
}
/// Returns true if this config will attempt to use a GPU.
pub fn is_gpu(&self) -> bool {
matches!(self, DeviceConfig::Cuda(_) | DeviceConfig::Auto)
}
}
impl Default for DeviceConfig {
fn default() -> Self {
DeviceConfig::Auto
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_cpu_always_resolves() {
let device = DeviceConfig::Cpu.resolve().unwrap();
assert!(!device.is_cuda());
}
#[test]
fn test_auto_resolves_without_error() {
let device = DeviceConfig::Auto.resolve().unwrap();
let _ = device;
}
#[test]
fn test_is_gpu() {
assert!(!DeviceConfig::Cpu.is_gpu());
assert!(DeviceConfig::Cuda(0).is_gpu());
assert!(DeviceConfig::Auto.is_gpu());
}
#[test]
fn test_default_is_auto() {
assert_eq!(DeviceConfig::default(), DeviceConfig::Auto);
}
#[test]
fn test_serde_roundtrip() {
let configs = vec![DeviceConfig::Cpu, DeviceConfig::Cuda(0), DeviceConfig::Auto];
for config in configs {
let json = serde_json::to_string(&config).unwrap();
let deserialized: DeviceConfig = serde_json::from_str(&json).unwrap();
assert_eq!(config, deserialized);
}
}
}

View File

@@ -687,6 +687,7 @@ pub mod data_loaders; // Data loaders for ML training
pub mod dqn;
pub mod gradient_accumulation; // Gradient accumulation for mini-batch training
pub mod gradient_utils; // Gradient utilities (clipping, monitoring)
pub mod gpu;
pub mod diffusion;
pub mod ensemble;
pub mod evaluation; // DQN evaluation engine (backtest metrics, Sharpe ratio)