collenchyma/frameworks/cuda/
device.rs

1//! Provides a Rust wrapper around Cuda's device.
2
3use hardware::{IHardware, HardwareType};
4use super::api::{Driver, DriverFFI};
5use std::io::Cursor;
6use byteorder::{ByteOrder, LittleEndian, ReadBytesExt};
7
8#[derive(Debug, Clone)]
9/// Defines a Cuda Device.
10///
11/// [hardware]: ../../hardware/index.html
12pub struct Device {
13    id: isize,
14    name: Option<String>,
15    device_type: Option<HardwareType>,
16    compute_units: Option<isize>,
17}
18
19impl Default for Device {
20    fn default() -> Self {
21        Device {
22            id: -1,
23            name: None,
24            device_type: None,
25            compute_units: None,
26        }
27    }
28}
29
30impl Device {
31    /// Initializes a new Cuda device.
32    pub fn from_isize(id: isize) -> Device {
33        Device { id: id, ..Device::default() }
34    }
35
36    /// Initializes a new Cuda device from its C type.
37    pub fn from_c(id: DriverFFI::CUdevice) -> Device {
38        Device { id: id as isize, ..Device::default() }
39    }
40
41    /// Returns the id as its C type.
42    pub fn id_c(&self) -> DriverFFI::CUdevice {
43        self.id as DriverFFI::CUdevice
44    }
45
46    /// Loads the name of the device via a foreign Cuda call.
47    pub fn load_name(&mut self) -> Self {
48        self.name = match Driver::load_device_info(self, DriverFFI::CUdevice_attribute::CU_DEVICE_NAME) {
49            Ok(result) => Some(result.to_string()),
50            Err(_) => None
51        };
52        self.clone()
53    }
54
55    /// Loads the device type via a foreign Cuda call.
56    pub fn load_device_type(&mut self) -> Self {
57        self.device_type = Some(HardwareType::GPU);
58        self.clone()
59    }
60
61    /// Loads the compute units of the device via a foreign Cuda call.
62    pub fn load_compute_units(&mut self) -> Self {
63        self.compute_units = match Driver::load_device_info(self, DriverFFI::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT) {
64            Ok(result) => Some(result.to_isize()),
65            Err(_) => None
66        };
67        self.clone()
68    }
69}
70
71impl IHardware for Device {
72    fn id(&self) -> isize {
73        self.id
74    }
75
76    fn name(&self) -> Option<String> {
77        self.name.clone()
78    }
79
80    fn set_name(&mut self, name: Option<String>) -> Self {
81        self.name = name;
82        self.clone()
83    }
84
85    fn hardware_type(&self) -> Option<HardwareType> {
86        self.device_type
87    }
88
89    fn set_hardware_type(&mut self, hardware_type: Option<HardwareType>) -> Self {
90        self.device_type = hardware_type;
91        self.clone()
92    }
93
94    fn compute_units(&self) -> Option<isize> {
95        self.compute_units
96    }
97
98    fn set_compute_units(&mut self, compute_units: Option<isize>) -> Self {
99        self.compute_units = compute_units;
100        self.clone()
101    }
102
103    #[allow(missing_docs)]
104    fn build(self) -> Device {
105        Device {
106            id: self.id(),
107            name: self.name(),
108            device_type: self.hardware_type(),
109            compute_units: self.compute_units(),
110        }
111    }
112}
113
114impl PartialEq for Device {
115    fn eq(&self, other: &Self) -> bool {
116        self.id() == other.id()
117    }
118}
119
120#[derive(Debug, Clone)]
121/// Defines a generic DeviceInfo container.
122///
123/// Can be used to transform the info to different outputs.
124pub struct DeviceInfo {
125    info: Vec<u8>,
126}
127
128impl DeviceInfo {
129
130    /// Initializes a new Device Info
131    pub fn new(info: Vec<u8>) -> DeviceInfo {
132        DeviceInfo { info: info }
133    }
134
135    #[allow(missing_docs)]
136    pub fn to_string(self) -> String {
137        unsafe { String::from_utf8_unchecked(self.info) }
138    }
139
140    #[allow(missing_docs)]
141    pub fn to_isize(self) -> isize {
142        let mut bytes = Cursor::new(&self.info);
143        bytes.read_u32::<LittleEndian>().unwrap() as isize
144    }
145}