trustformers_core/
device.rs1use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
10pub enum Device {
11 #[default]
13 CPU,
14 CUDA(usize),
16 Metal(usize),
18 ROCm(usize),
20 WebGPU,
22}
23
24impl Device {
25 pub fn is_gpu(&self) -> bool {
27 !matches!(self, Device::CPU)
28 }
29
30 pub fn is_metal(&self) -> bool {
32 matches!(self, Device::Metal(_))
33 }
34
35 pub fn is_cuda(&self) -> bool {
37 matches!(self, Device::CUDA(_))
38 }
39
40 pub fn is_cpu(&self) -> bool {
42 matches!(self, Device::CPU)
43 }
44
45 pub fn device_id(&self) -> Option<usize> {
47 match self {
48 Device::CUDA(id) | Device::Metal(id) | Device::ROCm(id) => Some(*id),
49 _ => None,
50 }
51 }
52
53 #[cfg(all(target_os = "macos", feature = "metal"))]
55 pub fn metal_if_available(device_id: usize) -> Device {
56 #[cfg(all(target_os = "macos", feature = "metal"))]
59 {
60 use metal::Device as MetalDevice;
61 if MetalDevice::system_default().is_some() {
62 Device::Metal(device_id)
63 } else {
64 Device::CPU
65 }
66 }
67
68 #[cfg(not(all(target_os = "macos", feature = "metal")))]
69 Device::CPU
70 }
71
72 #[cfg(not(all(target_os = "macos", feature = "metal")))]
73 pub fn metal_if_available(_device_id: usize) -> Device {
74 Device::CPU
75 }
76
77 #[cfg(feature = "cuda")]
87 pub fn cuda_if_available(device_id: usize) -> Device {
88 if crate::gpu_ops::cuda::oxicuda_cuda_available() {
89 Device::CUDA(device_id)
90 } else {
91 Device::CPU
92 }
93 }
94
95 #[cfg(not(feature = "cuda"))]
96 pub fn cuda_if_available(_device_id: usize) -> Device {
97 Device::CPU
98 }
99
100 pub fn best_available() -> Device {
109 #[cfg(feature = "cuda")]
110 if crate::gpu_ops::cuda::oxicuda_cuda_available() {
111 return Device::CUDA(0);
112 }
113
114 #[cfg(all(target_os = "macos", feature = "metal"))]
115 {
116 use metal::Device as MetalDevice;
117 if MetalDevice::system_default().is_some() {
118 return Device::Metal(0);
119 }
120 }
121
122 Device::CPU
123 }
124}
125
126impl std::fmt::Display for Device {
127 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
128 match self {
129 Device::CPU => write!(f, "CPU"),
130 Device::CUDA(id) => write!(f, "CUDA:{}", id),
131 Device::Metal(id) => write!(f, "Metal:{}", id),
132 Device::ROCm(id) => write!(f, "ROCm:{}", id),
133 Device::WebGPU => write!(f, "WebGPU"),
134 }
135 }
136}
137
138#[cfg(test)]
139mod tests {
140 use super::*;
141
142 #[test]
143 fn test_device_checks() {
144 assert!(Device::CPU.is_cpu());
145 assert!(!Device::CPU.is_gpu());
146 assert!(!Device::CPU.is_metal());
147
148 assert!(Device::Metal(0).is_metal());
149 assert!(Device::Metal(0).is_gpu());
150 assert!(!Device::Metal(0).is_cpu());
151
152 assert!(Device::CUDA(0).is_cuda());
153 assert!(Device::CUDA(0).is_gpu());
154 }
155
156 #[test]
157 fn test_device_id() {
158 assert_eq!(Device::CPU.device_id(), None);
159 assert_eq!(Device::Metal(0).device_id(), Some(0));
160 assert_eq!(Device::CUDA(1).device_id(), Some(1));
161 }
162
163 #[test]
164 fn test_device_display() {
165 assert_eq!(Device::CPU.to_string(), "CPU");
166 assert_eq!(Device::Metal(0).to_string(), "Metal:0");
167 assert_eq!(Device::CUDA(1).to_string(), "CUDA:1");
168 }
169
170 #[test]
175 fn test_cuda_if_available_does_not_panic() {
176 let device = Device::cuda_if_available(0);
177 assert!(matches!(device, Device::CPU | Device::CUDA(0)));
178 }
179
180 #[test]
183 fn test_metal_if_available_does_not_panic() {
184 let device = Device::metal_if_available(0);
185 assert!(matches!(device, Device::CPU | Device::Metal(0)));
186 }
187
188 #[test]
192 fn test_best_available_does_not_panic() {
193 let device = Device::best_available();
194 assert!(matches!(
195 device,
196 Device::CPU | Device::CUDA(0) | Device::Metal(0)
197 ));
198 }
199}