cubecl_runtime/throughput/
cache.rs1#[cfg(std_io)]
2use cubecl_environment::persistence::{Namespace, Store, StoreOptions};
3
4use crate::throughput::{ThroughputKey, ThroughputValue};
5use alloc::string::{String, ToString};
6use alloc::sync::Arc;
7use cubecl_environment::collections::HashMap;
8use cubecl_environment::sync::Mutex;
9
10static GLOBAL_CACHE: Mutex<Option<HashMap<String, Arc<Mutex<ThroughputCache>>>>> = Mutex::new(None);
11
12pub struct ThroughputCache {
17 #[cfg(not(std_io))]
18 cache: HashMap<ThroughputKey, ThroughputValue>,
19 #[cfg(std_io)]
20 cache: Store<ThroughputKey, ThroughputValue>,
21}
22
23impl ThroughputCache {
24 pub fn get_for_device(name: &str) -> Arc<Mutex<Self>> {
26 let mut cache_map = GLOBAL_CACHE.lock();
27 let cache_map = cache_map.get_or_insert_with(HashMap::new);
28
29 cache_map
30 .entry(name.to_string())
31 .or_insert_with(|| Arc::new(Mutex::new(Self::new(name))))
32 .clone()
33 }
34
35 pub fn new(#[cfg_attr(not(std_io), allow(unused_variables))] name: &str) -> Self {
37 #[cfg(not(std_io))]
38 {
39 ThroughputCache {
40 cache: HashMap::new(),
41 }
42 }
43
44 #[cfg(std_io)]
45 {
46 let namespace = Namespace::scoped("throughput", name);
47
48 Self {
49 cache: Store::new(StoreOptions::new().storage(namespace)),
50 }
51 }
52 }
53
54 pub fn insert(&mut self, key: ThroughputKey, value: ThroughputValue) {
60 #[cfg(std_io)]
61 if let Err(err) = self.cache.insert(key, value) {
62 log::warn!("Concurrent throughput measurement, keeping the existing value: {err}");
63 }
64
65 #[cfg(not(std_io))]
66 self.cache.insert(key, value);
67 }
68
69 pub fn get(&self, key: &ThroughputKey) -> Option<&ThroughputValue> {
71 self.cache.get(key)
72 }
73}