cubecl_runtime/config/
base.rs1use crate::config::memory::MemoryConfig;
2use crate::config::streaming::StreamingConfig;
3
4use super::{
5 autotune::AutotuneConfig, compilation::CompilationConfig, profiling::ProfilingConfig,
6 throughput::ThroughputConfig,
7};
8use alloc::format;
9use alloc::string::{String, ToString};
10use alloc::sync::Arc;
11use cubecl_environment::config::RuntimeConfig;
12use cubecl_environment::sync::Mutex;
13
14static CUBE_GLOBAL_CONFIG: Mutex<Option<Arc<CubeClRuntimeConfig>>> = Mutex::new(None);
16
17#[derive(Default, Clone, Debug, serde::Serialize, serde::Deserialize)]
19pub struct CubeClRuntimeConfig {
20 #[serde(default)]
22 pub profiling: ProfilingConfig,
23
24 #[serde(default)]
26 pub autotune: AutotuneConfig,
27
28 #[serde(default)]
30 pub throughput: ThroughputConfig,
31
32 #[serde(default)]
34 pub compilation: CompilationConfig,
35
36 #[serde(default)]
38 pub streaming: StreamingConfig,
39
40 #[serde(default)]
42 pub memory: MemoryConfig,
43
44 #[serde(default)]
46 pub environment: super::environment::EnvironmentConfig,
47}
48
49impl RuntimeConfig for CubeClRuntimeConfig {
50 fn storage() -> &'static Mutex<Option<Arc<Self>>> {
51 &CUBE_GLOBAL_CONFIG
52 }
53
54 fn on_loaded(&self) {
55 cubecl_environment::stream::set_policy_from_config(self.streaming.policy);
56 cubecl_environment::records::configure(self.environment.records);
57 cubecl_environment::environment::activate(&self.environment.name);
60 #[cfg(std_io)]
61 cubecl_environment::environment::set_root(self.environment.path.root());
62 }
63
64 fn file_names() -> &'static [&'static str] {
65 &["cubecl.toml", "CubeCL.toml"]
66 }
67
68 fn section_file_names() -> &'static [(&'static str, &'static str)] {
69 &[("burn.toml", "cubecl"), ("Burn.toml", "cubecl")]
70 }
71
72 #[cfg(std_io)]
73 fn override_from_env(mut self) -> Self {
74 use super::compilation::{CompilationLogLevel, F16Evaluation};
75 use crate::config::{
76 autotune::{AutotuneLevel, AutotuneLogLevel},
77 profiling::ProfilingLogLevel,
78 };
79
80 if let Ok(val) = std::env::var("CUBECL_DEBUG_LOG") {
81 self.compilation.logger.level = CompilationLogLevel::Full;
82 self.profiling.logger.level = ProfilingLogLevel::Medium;
83 self.autotune.logger.level = AutotuneLogLevel::Full;
84
85 match val.as_str() {
86 "stdout" => {
87 self.compilation.logger.stdout = true;
88 self.profiling.logger.stdout = true;
89 self.autotune.logger.stdout = true;
90 }
91 "stderr" => {
92 self.compilation.logger.stderr = true;
93 self.profiling.logger.stderr = true;
94 self.autotune.logger.stderr = true;
95 }
96 "1" | "true" => {
97 let file_path = "/tmp/cubecl.log";
98 self.compilation.logger.file = Some(file_path.into());
99 self.profiling.logger.file = Some(file_path.into());
100 self.autotune.logger.file = Some(file_path.into());
101 }
102 "0" | "false" => {
103 self.compilation.logger.level = CompilationLogLevel::Disabled;
104 self.profiling.logger.level = ProfilingLogLevel::Disabled;
105 self.autotune.logger.level = AutotuneLogLevel::Disabled;
106 }
107 file_path => {
108 self.compilation.logger.file = Some(file_path.into());
109 self.profiling.logger.file = Some(file_path.into());
110 self.autotune.logger.file = Some(file_path.into());
111 }
112 }
113 };
114
115 if let Ok(val) = std::env::var("CUBECL_DEBUG_OPTION") {
116 match val.as_str() {
117 "debug" => {
118 self.compilation.logger.level = CompilationLogLevel::Full;
119 self.profiling.logger.level = ProfilingLogLevel::Medium;
120 self.autotune.logger.level = AutotuneLogLevel::Full;
121 }
122 "debug-full" => {
123 self.compilation.logger.level = CompilationLogLevel::Full;
124 self.profiling.logger.level = ProfilingLogLevel::Full;
125 self.autotune.logger.level = AutotuneLogLevel::Full;
126 }
127 "profile" => {
128 self.profiling.logger.level = ProfilingLogLevel::Basic;
129 }
130 "profile-medium" => {
131 self.profiling.logger.level = ProfilingLogLevel::Medium;
132 }
133 "profile-full" => {
134 self.profiling.logger.level = ProfilingLogLevel::Full;
135 }
136 _ => {}
137 }
138 };
139
140 if let Ok(val) = std::env::var("CUBECL_AUTOTUNE_LEVEL") {
141 match val.as_str() {
142 "minimal" | "0" => {
143 self.autotune.level = AutotuneLevel::Minimal;
144 }
145 "balanced" | "1" => {
146 self.autotune.level = AutotuneLevel::Balanced;
147 }
148 "extensive" | "2" => {
149 self.autotune.level = AutotuneLevel::Extensive;
150 }
151 "full" | "3" => {
152 self.autotune.level = AutotuneLevel::Full;
153 }
154 _ => {}
155 }
156 }
157
158 if let Ok(val) = std::env::var("CUBECL_CPU_F16_EVAL") {
159 match val.as_str() {
160 "per-operation" => {
161 self.compilation.f16_evaluation = Some(F16Evaluation::PerOperation);
162 }
163 "chain" => {
164 self.compilation.f16_evaluation = Some(F16Evaluation::Chain);
165 }
166 "accumulators" => {
167 self.compilation.f16_evaluation = Some(F16Evaluation::Accumulators);
168 }
169 _ => {}
170 }
171 }
172
173 if let Ok(dir) = std::env::var("CUBECL_DEBUG_PLIRON") {
174 self.compilation.dump_dir = Some(dir.into());
175 }
176
177 if let Some(enabled) = env_bool("CUBECL_TIME_PASSES") {
178 self.compilation.time_passes = enabled;
179 }
180
181 if let Some(level) = env_variant("CUBECL_DEBUG_INFO") {
182 self.compilation.debug_info = Some(level);
183 }
184
185 if let Some(format) = env_variant("CUBECL_SPIRV_DEBUG_FORMAT") {
186 self.compilation.spirv_debug_format = format;
187 }
188
189 if let Ok(dir) = std::env::var("CUBECL_SOURCE_CACHE") {
190 self.compilation.source_cache = Some(dir.into());
191 }
192
193 if let Some(enabled) = env_bool("CUBECL_THROUGHPUT_CACHE") {
194 self.throughput.disable_cache = !enabled;
195 }
196
197 if let Ok(val) = std::env::var("CUBECL_ENVIRONMENT") {
198 self.environment.name = val;
199 }
200
201 if let Ok(val) = std::env::var("CUBECL_ENVIRONMENT_RECORDS") {
202 use cubecl_environment::records::RecordLevel;
203
204 match val.as_str() {
205 "off" | "0" => self.environment.records.level = RecordLevel::Off,
206 "basic" | "1" => self.environment.records.level = RecordLevel::Basic,
207 "full" | "2" => self.environment.records.level = RecordLevel::Full,
208 _ => {}
209 }
210 }
211
212 if let Some(enabled) = env_bool("CUBECL_AUTOTUNE_CACHE") {
213 self.autotune.disable_cache = !enabled;
214 }
215
216 if let Some(enabled) = env_bool("CUBECL_AUTOTUNE_SHORT_CIRCUIT") {
217 self.autotune.disable_short_circuit = !enabled;
218 }
219
220 if let Some(enabled) = env_bool("CUBECL_AUTOTUNE_BENCH_ADAPTIVE") {
221 self.autotune.bench.adaptive = enabled;
222 }
223
224 self
225 }
226}
227
228#[cfg(std_io)]
231fn env_variant<T: serde::de::DeserializeOwned>(name: &str) -> Option<T> {
232 variant(&std::env::var(name).ok()?)
233}
234
235#[cfg(std_io)]
237fn variant<T: serde::de::DeserializeOwned>(value: &str) -> Option<T> {
238 use serde::de::{IntoDeserializer, value::Error};
239
240 T::deserialize(IntoDeserializer::<Error>::into_deserializer(value)).ok()
241}
242
243#[cfg(std_io)]
248fn env_bool(name: &str) -> Option<bool> {
249 match std::env::var(name).ok()?.as_str() {
250 "true" | "1" | "on" => Some(true),
251 "false" | "0" | "off" => Some(false),
252 _ => None,
253 }
254}
255
256#[derive(Clone, Copy, Debug)]
257pub enum TypeNameFormatLevel {
259 Full,
261 Short,
263 Balanced,
265}
266
267pub fn type_name_format(name: &str, level: TypeNameFormatLevel) -> String {
269 match level {
270 TypeNameFormatLevel::Full => name.to_string(),
271 TypeNameFormatLevel::Short => {
272 if let Some(val) = name.split("<").next() {
273 val.split("::").last().unwrap_or(name).to_string()
274 } else {
275 name.to_string()
276 }
277 }
278 TypeNameFormatLevel::Balanced => {
279 let mut split = name.split("<");
280 let before_generic = split.next();
281 let after_generic = split.next();
282
283 let before_generic = match before_generic {
284 None => return name.to_string(),
285 Some(val) => val
286 .split("::")
287 .last()
288 .unwrap_or(val)
289 .trim()
290 .replace(">", "")
291 .to_string(),
292 };
293 let inside_generic = match after_generic {
294 None => return before_generic.to_string(),
295 Some(val) => {
296 let mut val = val.to_string();
297 for s in split {
298 val += "<";
299 val += s;
300 }
301 val
302 }
303 };
304
305 let inside = type_name_list_format(&inside_generic, level);
306
307 format!("{before_generic}{inside}")
308 }
309 }
310}
311
312fn type_name_list_format(name: &str, level: TypeNameFormatLevel) -> String {
313 let mut acc = String::new();
314 let splits = name.split(", ");
315
316 for a in splits {
317 acc += " | ";
318 acc += &type_name_format(a, level);
319 }
320
321 acc
322}
323
324#[cfg(test)]
325mod test {
326 use super::*;
327
328 #[test_log::test]
329 fn test_format_name() {
330 let full_name = "burn_cubecl::kernel::unary_numeric::unary_numeric::UnaryNumeric<f32, burn_cubecl::tensor::base::CubeTensor<_>::copy::Copy, cubecl_cuda::runtime::CudaRuntime>";
331 let name = type_name_format(full_name, TypeNameFormatLevel::Balanced);
332
333 assert_eq!(name, "UnaryNumeric | f32 | CubeTensor | Copy | CudaRuntime");
334 }
335}