axonml_core/backends/
mod.rs

1//! Backends - Device-Specific Implementations
2//!
3//! This module contains backend implementations for different compute devices.
4//! Each backend provides device-specific memory operations and kernel execution.
5//!
6//! # Available Backends
7//! - `cpu` - CPU backend (always available)
8//! - `cuda` - NVIDIA CUDA backend (requires `cuda` feature)
9//! - `vulkan` - Vulkan backend (requires `vulkan` feature)
10//! - `metal` - Apple Metal backend (requires `metal` feature)
11//! - `wgpu` - WebGPU backend (requires `wgpu` feature)
12//!
13//! # Backend Trait
14//!
15//! All backends implement the `Backend` trait which provides a common interface
16//! for tensor operations. This enables device-agnostic code.
17//!
18//! @version 0.1.0
19//! @author `AutomataNexus` Development Team
20
21use crate::device::DeviceCapabilities;
22
23// =============================================================================
24// Backend Modules
25// =============================================================================
26
27pub mod cpu;
28
29#[cfg(feature = "cuda")]
30pub mod cuda;
31
32#[cfg(feature = "vulkan")]
33pub mod vulkan;
34
35#[cfg(feature = "metal")]
36pub mod metal;
37
38#[cfg(feature = "wgpu")]
39pub mod wgpu_backend;
40
41// =============================================================================
42// Re-exports
43// =============================================================================
44
45pub use cpu::CpuBackend;
46
47#[cfg(feature = "cuda")]
48pub use cuda::CudaBackend;
49
50#[cfg(feature = "vulkan")]
51pub use vulkan::VulkanBackend;
52
53#[cfg(feature = "metal")]
54pub use metal::MetalBackend;
55
56#[cfg(feature = "wgpu")]
57pub use wgpu_backend::WgpuBackend;
58
59// =============================================================================
60// Backend Trait
61// =============================================================================
62
63/// Common trait for all compute backends.
64///
65/// This trait defines the interface that all backends must implement,
66/// enabling device-agnostic tensor operations.
67pub trait Backend: Send + Sync {
68    /// Returns the name of this backend.
69    fn name(&self) -> &'static str;
70
71    /// Returns whether this backend is available on the current system.
72    fn is_available(&self) -> bool;
73
74    /// Returns the device capabilities.
75    fn capabilities(&self) -> DeviceCapabilities;
76
77    /// Allocates memory on this backend.
78    fn allocate(&self, size: usize) -> *mut u8;
79
80    /// Deallocates memory on this backend.
81    fn deallocate(&self, ptr: *mut u8, size: usize);
82
83    /// Copies data from host to device.
84    fn copy_to_device(&self, dst: *mut u8, src: *const u8, size: usize);
85
86    /// Copies data from device to host.
87    fn copy_to_host(&self, dst: *mut u8, src: *const u8, size: usize);
88
89    /// Copies data within the device.
90    fn copy_device_to_device(&self, dst: *mut u8, src: *const u8, size: usize);
91
92    /// Synchronizes the device (waits for all operations to complete).
93    fn synchronize(&self);
94}
95
96// =============================================================================
97// GPU Memory Management
98// =============================================================================
99
100/// GPU memory handle for safe memory management.
101#[derive(Debug)]
102pub struct GpuMemory {
103    ptr: *mut u8,
104    size: usize,
105    device_index: usize,
106    backend_type: BackendType,
107}
108
109/// Type of backend for a GPU memory allocation.
110#[derive(Debug, Clone, Copy, PartialEq, Eq)]
111pub enum BackendType {
112    /// CPU backend.
113    Cpu,
114    /// CUDA backend.
115    #[cfg(feature = "cuda")]
116    Cuda,
117    /// Vulkan backend.
118    #[cfg(feature = "vulkan")]
119    Vulkan,
120    /// Metal backend.
121    #[cfg(feature = "metal")]
122    Metal,
123    /// WebGPU backend.
124    #[cfg(feature = "wgpu")]
125    Wgpu,
126}
127
128impl GpuMemory {
129    /// Creates a new GPU memory handle.
130    pub fn new(ptr: *mut u8, size: usize, device_index: usize, backend_type: BackendType) -> Self {
131        Self {
132            ptr,
133            size,
134            device_index,
135            backend_type,
136        }
137    }
138
139    /// Returns the raw pointer.
140    #[must_use] pub fn ptr(&self) -> *mut u8 {
141        self.ptr
142    }
143
144    /// Returns the size in bytes.
145    #[must_use] pub fn size(&self) -> usize {
146        self.size
147    }
148
149    /// Returns the device index.
150    #[must_use] pub fn device_index(&self) -> usize {
151        self.device_index
152    }
153
154    /// Returns the backend type.
155    #[must_use] pub fn backend_type(&self) -> BackendType {
156        self.backend_type
157    }
158}
159
160// =============================================================================
161// GPU Stream/Queue Abstraction
162// =============================================================================
163
164/// GPU execution stream for async operations.
165#[derive(Debug)]
166pub struct GpuStream {
167    /// Stream handle (backend-specific).
168    handle: usize,
169    /// Device index.
170    device_index: usize,
171    /// Backend type.
172    backend_type: BackendType,
173}
174
175impl GpuStream {
176    /// Creates a new GPU stream.
177    #[must_use] pub fn new(handle: usize, device_index: usize, backend_type: BackendType) -> Self {
178        Self {
179            handle,
180            device_index,
181            backend_type,
182        }
183    }
184
185    /// Returns the stream handle.
186    #[must_use] pub fn handle(&self) -> usize {
187        self.handle
188    }
189
190    /// Returns the device index.
191    #[must_use] pub fn device_index(&self) -> usize {
192        self.device_index
193    }
194
195    /// Synchronizes this stream (waits for all operations to complete).
196    pub fn synchronize(&self) {
197        match self.backend_type {
198            BackendType::Cpu => {} // No-op for CPU
199            #[cfg(feature = "cuda")]
200            BackendType::Cuda => cuda::stream_synchronize(self.handle),
201            #[cfg(feature = "vulkan")]
202            BackendType::Vulkan => vulkan::queue_wait_idle(self.handle),
203            #[cfg(feature = "metal")]
204            BackendType::Metal => metal::command_buffer_wait(self.handle),
205            #[cfg(feature = "wgpu")]
206            BackendType::Wgpu => wgpu_backend::queue_submit(self.handle),
207        }
208    }
209}
210
211// =============================================================================
212// Device Selection Utilities
213// =============================================================================
214
215/// Returns the best available GPU backend.
216#[must_use] pub fn best_available_backend() -> BackendType {
217    #[cfg(feature = "cuda")]
218    if cuda::is_available() {
219        return BackendType::Cuda;
220    }
221
222    #[cfg(feature = "metal")]
223    if metal::is_available() {
224        return BackendType::Metal;
225    }
226
227    #[cfg(feature = "vulkan")]
228    if vulkan::is_available() {
229        return BackendType::Vulkan;
230    }
231
232    #[cfg(feature = "wgpu")]
233    if wgpu_backend::is_available() {
234        return BackendType::Wgpu;
235    }
236
237    BackendType::Cpu
238}
239
240/// Returns the number of available GPUs across all backends.
241#[must_use] pub fn gpu_count() -> usize {
242    #[allow(unused_mut)]
243    let mut count = 0_usize;
244
245    #[cfg(feature = "cuda")]
246    {
247        count += cuda::device_count();
248    }
249
250    #[cfg(feature = "vulkan")]
251    {
252        count += vulkan::device_count();
253    }
254
255    #[cfg(feature = "metal")]
256    {
257        count += metal::device_count();
258    }
259
260    #[cfg(feature = "wgpu")]
261    {
262        count += wgpu_backend::device_count();
263    }
264
265    count
266}