Skip to main content

oxicuda_dnn/
error.rs

1//! Error types for the DNN crate.
2//!
3//! [`DnnError`] unifies failures from the CUDA driver, BLAS layer, PTX
4//! generation, and DNN-specific validation into a single error enum.
5//! All public DNN functions return [`DnnResult<T>`].
6
7use oxicuda_blas::BlasError;
8use oxicuda_driver::CudaError;
9use thiserror::Error;
10
11/// Errors that can arise during DNN operations.
12#[derive(Debug, Error)]
13pub enum DnnError {
14    /// A low-level CUDA driver call failed.
15    #[error("CUDA driver error: {0}")]
16    Cuda(#[from] CudaError),
17
18    /// A BLAS operation failed (e.g. during convolution via im2col + GEMM).
19    #[error("BLAS error: {0}")]
20    Blas(#[from] BlasError),
21
22    /// PTX kernel generation or compilation failed.
23    #[error("PTX generation error: {0}")]
24    PtxGeneration(String),
25
26    /// Tensor dimensions are invalid (e.g. zero-sized, negative, or
27    /// inconsistent with the expected layout).
28    #[error("invalid tensor dimensions: {0}")]
29    InvalidDimension(String),
30
31    /// The supplied device buffer is too small for the described tensor.
32    #[error("buffer too small: expected {expected} bytes, got {actual} bytes")]
33    BufferTooSmall {
34        /// Minimum required buffer size in bytes.
35        expected: usize,
36        /// Actual buffer size in bytes.
37        actual: usize,
38    },
39
40    /// The requested operation is not supported for the given configuration
41    /// (e.g. unsupported data type or algorithm on a particular SM version).
42    #[error("unsupported operation: {0}")]
43    UnsupportedOperation(String),
44
45    /// A function argument failed validation.
46    #[error("invalid argument: {0}")]
47    InvalidArgument(String),
48
49    /// The operation requires a workspace buffer of at least the given size,
50    /// but none (or too small) was provided.
51    #[error("workspace required: need at least {0} bytes")]
52    WorkspaceRequired(usize),
53
54    /// A GPU kernel launch failed.
55    #[error("kernel launch failed: {0}")]
56    LaunchFailed(String),
57
58    /// An I/O error occurred (e.g. when reading/writing the PTX cache).
59    #[error("I/O error: {0}")]
60    Io(#[from] std::io::Error),
61}
62
63impl From<oxicuda_ptx::PtxGenError> for DnnError {
64    fn from(e: oxicuda_ptx::PtxGenError) -> Self {
65        Self::PtxGeneration(e.to_string())
66    }
67}
68
69/// Convenience alias for `Result<T, DnnError>`.
70pub type DnnResult<T> = Result<T, DnnError>;
71
72#[cfg(test)]
73mod tests {
74    use super::*;
75
76    #[test]
77    fn display_buffer_too_small() {
78        let e = DnnError::BufferTooSmall {
79            expected: 4096,
80            actual: 1024,
81        };
82        assert!(e.to_string().contains("4096"));
83        assert!(e.to_string().contains("1024"));
84    }
85
86    #[test]
87    fn display_workspace_required() {
88        let e = DnnError::WorkspaceRequired(8192);
89        assert!(e.to_string().contains("8192"));
90    }
91
92    #[test]
93    fn from_cuda_error() {
94        let cuda_err = CudaError::InvalidValue;
95        let dnn_err: DnnError = cuda_err.into();
96        assert!(matches!(dnn_err, DnnError::Cuda(_)));
97    }
98}