1#[allow(unused_imports)]
10use lazy_static::lazy_static;
11
12#[cfg(feature = "cuda")]
15pub extern crate cust;
16
17pub use ulib_derive::UniversalCopy;
18
19#[cfg(feature = "cuda")]
20use cust::memory::{ DeviceCopy, DeviceSlice };
21
22#[cfg(feature = "cuda")]
23pub const MAX_NUM_CUDA_DEVICES: usize = 4;
24#[cfg(feature = "cuda")]
25pub const MAX_DEVICES: usize = MAX_NUM_CUDA_DEVICES + 1;
26
27#[cfg(not(feature = "cuda"))]
28pub const MAX_DEVICES: usize = 1;
29
30#[derive(Copy, Clone, Debug, PartialEq, Eq)]
32pub enum Device {
33 CPU,
34 #[cfg(feature = "cuda")]
35 CUDA(u8 )
36}
37
38pub struct DeviceContext {
40 #[cfg(feature = "cuda")]
41 #[allow(dead_code)]
42 cuda_context: Option<cust::context::Context>,
43}
44
45impl Device {
46 #[inline]
47 fn to_id(self) -> usize {
48 use Device::*;
49 match self {
50 CPU => 0,
51 #[cfg(feature = "cuda")]
52 CUDA(c) => {
53 assert!((c as usize) < MAX_NUM_CUDA_DEVICES,
54 "invalid cuda device id");
55 c as usize + 1
56 }
57 }
58 }
59
60 #[inline]
61 fn from_id(id: usize) -> Device {
62 use Device::*;
63 match id {
64 0 => CPU,
65 #[cfg(feature = "cuda")]
66 c @ 1..=MAX_NUM_CUDA_DEVICES => CUDA(c as u8 - 1),
67 id @ _ => panic!("device id {} is invalid.", id)
68 }
69 }
70
71 #[inline]
72 pub fn get_context(self) -> DeviceContext {
73 use Device::*;
74 match self {
75 CPU => DeviceContext {
76 #[cfg(feature = "cuda")]
77 cuda_context: None
78 },
79 #[cfg(feature = "cuda")]
80 CUDA(c) => DeviceContext {
81 cuda_context: Some(cust::context::Context::new(
82 CUDA_DEVICES[c as usize].0).unwrap())
83 }
84 }
85 }
86
87 #[inline]
88 pub fn synchronize(self) {
89 use Device::*;
90 match self {
91 CPU => {},
92 #[cfg(feature = "cuda")]
93 CUDA(c) => {
94 let _context = cust::context::Context::new(
95 CUDA_DEVICES[c as usize].0).unwrap();
96 cust::context::CurrentContext::synchronize().unwrap();
97 }
98 }
99 }
100}
101
102#[cfg(feature = "cuda")]
117pub trait UniversalCopy: Copy + DeviceCopy { }
118#[cfg(feature = "cuda")]
119impl<T: Copy + DeviceCopy> UniversalCopy for T { }
120
121#[cfg(not(feature = "cuda"))]
136pub trait UniversalCopy: Copy { }
137#[cfg(not(feature = "cuda"))]
138impl<T: Copy> UniversalCopy for T { }
139
140#[cfg(feature = "cuda")]
141lazy_static! {
142 static ref CUDA_DEVICES: Vec<(cust::device::Device, cust::context::Context)> = {
147 cust::init(cust::CudaFlags::empty()).unwrap();
149 let mut ret = cust::device::Device::devices().unwrap()
150 .map(|d| {
151 let d = d.unwrap();
152 (d, cust::context::Context::new(d).unwrap())
153 })
154 .collect::<Vec<_>>();
155 if ret.len() > MAX_NUM_CUDA_DEVICES as usize {
156 clilog::warn!(ULIB_CUDA_TRUNC,
157 "the number of available cuda gpus {} \
158 exceed max supported {}, truncated.",
159 ret.len(), MAX_NUM_CUDA_DEVICES);
160 ret.truncate(MAX_NUM_CUDA_DEVICES as usize);
161 }
162 ret
163 };
164
165 pub static ref NUM_CUDA_DEVICES: usize = CUDA_DEVICES.len();
167}
168
169#[cfg(feature = "cuda")]
171pub trait AsCUDASlice<T: UniversalCopy> {
172 fn as_cuda_slice(&self, cuda_device: Device) -> DeviceSlice<T>;
182}
183
184#[cfg(feature = "cuda")]
186pub trait AsCUDASliceMut<T: UniversalCopy> {
187 fn as_cuda_slice_mut(&mut self, cuda_device: Device) ->
189 DeviceSlice<T>;
190}
191
192pub trait AsUPtr<T: UniversalCopy> {
194 fn as_uptr(&self, device: Device) -> *const T;
196}
197
198pub trait AsUPtrMut<T: UniversalCopy> {
200 fn as_mut_uptr(&mut self, device: Device) -> *mut T;
202}
203
204mod uvec;
205pub use uvec::UVec;