1use crate::prelude::*;
4use std::str::FromStr;
5
6use mnn_sys::*;
7
8#[repr(transparent)]
13pub struct BackendConfig {
14 pub(crate) inner: *mut MNNBackendConfig,
15 __marker: core::marker::PhantomData<()>,
16}
17
18impl core::fmt::Debug for BackendConfig {
19 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20 f.debug_struct("BackendConfig")
21 .field("memory", &self.get_memory_mode())
22 .field("power", &self.get_power_mode())
23 .field("precision", &self.get_precision_mode())
24 .finish()
25 }
26}
27
28#[cfg(feature = "serde")]
29impl serde::Serialize for BackendConfig {
30 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
31 where
32 S: serde::ser::Serializer,
33 {
34 use serde::ser::SerializeStruct;
35 let mut state = serializer.serialize_struct("BackendConfig", 3)?;
36 state.serialize_field("memory", &self.get_memory_mode())?;
37 state.serialize_field("power", &self.get_power_mode())?;
38 state.serialize_field("precision", &self.get_precision_mode())?;
39 state.end()
40 }
41}
42
43impl Clone for BackendConfig {
44 fn clone(&self) -> Self {
45 unsafe {
46 let inner = mnn_sys::mnnbc_clone(self.inner);
47 Self {
48 inner,
49 __marker: core::marker::PhantomData,
50 }
51 }
52 }
53}
54
55impl Drop for BackendConfig {
56 fn drop(&mut self) {
57 unsafe {
58 mnn_sys::mnnbc_destroy(self.inner);
59 }
60 }
61}
62
63impl Default for BackendConfig {
64 fn default() -> Self {
65 Self::new()
66 }
67}
68
69#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
71#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
72pub enum PowerMode {
73 Low,
75 Normal,
77 High,
79}
80
81impl PowerMode {
82 fn to_mnn_sys(self) -> mnn_sys::PowerMode {
83 match self {
84 Self::Low => mnn_sys::PowerMode::Power_Low,
85 Self::Normal => mnn_sys::PowerMode::Power_Normal,
86 Self::High => mnn_sys::PowerMode::Power_High,
87 }
88 }
89
90 pub fn to_str(self) -> &'static str {
92 match self {
93 Self::Low => "low",
94 Self::Normal => "normal",
95 Self::High => "high",
96 }
97 }
98
99 fn from_mnn_sys(mode: mnn_sys::PowerMode) -> Self {
100 match mode {
101 mnn_sys::PowerMode::Power_Low => Self::Low,
102 mnn_sys::PowerMode::Power_Normal => Self::Normal,
103 mnn_sys::PowerMode::Power_High => Self::High,
104 _ => Self::Normal,
105 }
106 }
107}
108
109impl FromStr for PowerMode {
110 type Err = MNNError;
111 fn from_str(s: &str) -> Result<Self, Self::Err> {
112 match s {
113 "low" => Ok(Self::Low),
114 "normal" => Ok(Self::Normal),
115 "high" => Ok(Self::High),
116 _ => Err(error!(ErrorKind::ParseError).attach(format!("invalid power mode: {s}"))),
117 }
118 }
119}
120
121impl FromStr for MemoryMode {
122 type Err = MNNError;
123 fn from_str(s: &str) -> Result<Self, Self::Err> {
124 match s {
125 "low" => Ok(Self::Low),
126 "normal" => Ok(Self::Normal),
127 "high" => Ok(Self::High),
128 _ => Err(error!(ErrorKind::ParseError).attach(format!("invalid memory mode: {s}"))),
129 }
130 }
131}
132
133impl FromStr for PrecisionMode {
134 type Err = MNNError;
135 fn from_str(s: &str) -> Result<Self, Self::Err> {
136 match s {
137 "low" => Ok(Self::Low),
138 "normal" => Ok(Self::Normal),
139 "high" => Ok(Self::High),
140 "low_bf16" => Ok(Self::LowBf16),
141 _ => Err(error!(ErrorKind::ParseError).attach(format!("invalid precision mode: {s}"))),
142 }
143 }
144}
145
146#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
148#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
149pub enum MemoryMode {
150 Low,
152 Normal,
154 High,
156}
157
158impl MemoryMode {
159 fn to_mnn_sys(self) -> mnn_sys::MemoryMode {
160 match self {
161 Self::Low => mnn_sys::MemoryMode::Memory_Low,
162 Self::Normal => mnn_sys::MemoryMode::Memory_Normal,
163 Self::High => mnn_sys::MemoryMode::Memory_High,
164 }
165 }
166
167 pub fn to_str(self) -> &'static str {
169 match self {
170 Self::Low => "low",
171 Self::Normal => "normal",
172 Self::High => "high",
173 }
174 }
175
176 fn from_mnn_sys(mode: mnn_sys::MemoryMode) -> Self {
177 match mode {
178 mnn_sys::MemoryMode::Memory_Low => Self::Low,
179 mnn_sys::MemoryMode::Memory_Normal => Self::Normal,
180 mnn_sys::MemoryMode::Memory_High => Self::High,
181 _ => Self::Normal,
182 }
183 }
184}
185
186#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
188#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
189pub enum PrecisionMode {
190 Normal = 0,
192 High,
194 Low,
196 LowBf16,
198}
199impl PrecisionMode {
200 pub(crate) fn to_mnn_sys(self) -> mnn_sys::PrecisionMode {
201 match self {
202 Self::LowBf16 => mnn_sys::PrecisionMode::Precision_Low_BF16,
203 Self::Low => mnn_sys::PrecisionMode::Precision_Low,
204 Self::Normal => mnn_sys::PrecisionMode::Precision_Normal,
205 Self::High => mnn_sys::PrecisionMode::Precision_High,
206 }
207 }
208
209 pub fn to_str(self) -> &'static str {
211 match self {
212 Self::LowBf16 => "low_bf16",
213 Self::Low => "low",
214 Self::Normal => "normal",
215 Self::High => "high",
216 }
217 }
218
219 fn from_mnn_sys(mode: mnn_sys::PrecisionMode) -> Self {
220 match mode {
221 mnn_sys::PrecisionMode::Precision_Low_BF16 => Self::LowBf16,
222 mnn_sys::PrecisionMode::Precision_Low => Self::Low,
223 mnn_sys::PrecisionMode::Precision_Normal => Self::Normal,
224 mnn_sys::PrecisionMode::Precision_High => Self::High,
225 _ => Self::Normal,
226 }
227 }
228}
229
230impl BackendConfig {
231 pub fn new() -> Self {
233 unsafe {
234 let inner = mnnbc_create();
235 Self {
236 inner,
237 __marker: core::marker::PhantomData,
238 }
239 }
240 }
241
242 pub fn set_memory_mode(&mut self, mode: MemoryMode) {
244 unsafe {
245 mnn_sys::mnnbc_set_memory_mode(self.inner, mode.to_mnn_sys());
246 }
247 }
248
249 pub fn with_memory_mode(mut self, mode: MemoryMode) -> Self {
251 self.set_memory_mode(mode);
252 self
253 }
254
255 pub fn get_memory_mode(&self) -> MemoryMode {
257 unsafe { MemoryMode::from_mnn_sys(mnn_sys::mnnbc_get_memory_mode(self.inner)) }
258 }
259
260 pub fn set_power_mode(&mut self, mode: PowerMode) {
262 unsafe {
263 mnn_sys::mnnbc_set_power_mode(self.inner, mode.to_mnn_sys());
264 }
265 }
266
267 pub fn with_power_mode(mut self, mode: PowerMode) -> Self {
269 self.set_power_mode(mode);
270 self
271 }
272
273 pub fn get_power_mode(&self) -> PowerMode {
275 unsafe { PowerMode::from_mnn_sys(mnn_sys::mnnbc_get_power_mode(self.inner)) }
276 }
277
278 pub fn set_precision_mode(&mut self, mode: PrecisionMode) {
280 unsafe {
281 mnn_sys::mnnbc_set_precision_mode(self.inner, mode.to_mnn_sys());
282 }
283 }
284
285 pub fn with_precision_mode(mut self, mode: PrecisionMode) -> Self {
287 self.set_precision_mode(mode);
288 self
289 }
290
291 pub fn get_precision_mode(&self) -> PrecisionMode {
293 unsafe { PrecisionMode::from_mnn_sys(mnn_sys::mnnbc_get_precision_mode(self.inner)) }
294 }
295
296 pub fn set_flags(&mut self, flags: usize) {
299 unsafe {
300 mnn_sys::mnnbc_set_flags(self.inner, flags);
301 }
302 }
303
304 pub fn with_flags(mut self, flags: usize) -> Self {
306 self.set_flags(flags);
307 self
308 }
309
310 pub unsafe fn set_shared_context(&mut self, shared_context: *mut libc::c_void) {
314 unsafe {
315 mnn_sys::mnnbc_set_shared_context(self.inner, shared_context);
316 }
317 }
318
319 pub unsafe fn with_shared_context(mut self, shared_context: *mut libc::c_void) -> Self {
323 unsafe {
324 self.set_shared_context(shared_context);
325 }
326 self
327 }
328}
329
330#[test]
331fn test_backend_config() {
332 let mut config = BackendConfig::new();
333 config.set_memory_mode(MemoryMode::Low);
334 config.set_power_mode(PowerMode::Low);
335 config.set_precision_mode(PrecisionMode::Low);
336 let config = std::hint::black_box(config.clone());
337 assert_eq!(config.get_memory_mode(), MemoryMode::Low);
338 assert_eq!(config.get_power_mode(), PowerMode::Low);
339 assert_eq!(config.get_precision_mode(), PrecisionMode::Low);
340 let config = config
341 .with_memory_mode(MemoryMode::Normal)
342 .with_power_mode(PowerMode::Normal)
343 .with_precision_mode(PrecisionMode::Normal);
344 assert_eq!(config.get_memory_mode(), MemoryMode::Normal);
345 assert_eq!(config.get_power_mode(), PowerMode::Normal);
346 assert_eq!(config.get_precision_mode(), PrecisionMode::Normal);
347}