1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use cuda::cudaError_enum as DeviceError;
use std::path::PathBuf;
pub type Result<T> = ::std::result::Result<T, AccelError>;
#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq, Hash)]
pub enum AccelError {
#[error("CUDA Device API Error: {api_name}, {error:?}")]
CUDAError {
api_name: String,
error: DeviceError,
},
#[error("Async operations issues previously have not completed yet")]
AsyncOperationNotReady,
#[error("Assertion in device code has failed")]
DeviceAssertionFailed,
#[error("No device found for given ID")]
DeviceNotFound { id: usize, count: usize },
#[error("File not found: {path:?}")]
FileNotFound { path: PathBuf },
}
pub(crate) fn check(error: DeviceError, api_name: &str) -> Result<()> {
match error {
DeviceError::CUDA_SUCCESS => Ok(()),
DeviceError::CUDA_ERROR_ASSERT => Err(AccelError::DeviceAssertionFailed),
DeviceError::CUDA_ERROR_NOT_READY => Err(AccelError::AsyncOperationNotReady),
_ => Err(AccelError::CUDAError {
api_name: api_name.into(),
error,
}),
}
}
#[macro_export]
macro_rules! ffi_call {
($ffi:path $(,$args:expr)*) => {
{
$crate::error::check($ffi($($args),*), stringify!($ffi))
}
};
}
#[macro_export]
macro_rules! ffi_new {
($ffi:path $(,$args:expr)*) => {
{
let mut value = ::std::mem::MaybeUninit::uninit();
$crate::error::check($ffi(value.as_mut_ptr(), $($args),*), stringify!($ffi)).map(|_| value.assume_init())
}
};
}
#[macro_export]
macro_rules! contexted_call {
($ctx:expr, $ffi:path $(,$args:expr)*) => {
{
let _g = $crate::Contexted::guard_context($ctx);
$crate::ffi_call!($ffi $(,$args)*)
}
};
}
#[macro_export]
macro_rules! contexted_new {
($ctx:expr, $ffi:path $(,$args:expr)*) => {
{
let _g = $crate::Contexted::guard_context($ctx);
$crate::ffi_new!($ffi $(,$args)*)
}
};
}