use super::logger::{LogLevel, LoggerConfig};
use cubecl_ir::settings::DebugInfo;
pub const PROFILE_DEBUG_INFO: DebugInfo = if cfg!(cubecl_debug_info) {
DebugInfo::LineTables
} else {
DebugInfo::None
};
pub fn effective_debug_info(requested: DebugInfo) -> DebugInfo {
use super::{CubeClRuntimeConfig, RuntimeConfig};
use core::sync::atomic::{AtomicU8, Ordering};
const UNREAD: u8 = u8::MAX;
const NO_LIMIT: u8 = u8::MAX - 1;
static LIMIT: AtomicU8 = AtomicU8::new(UNREAD);
let mut limit = LIMIT.load(Ordering::Relaxed);
if limit == UNREAD {
limit = CubeClRuntimeConfig::get()
.compilation
.debug_info
.map_or(NO_LIMIT, |level| level as u8);
LIMIT.store(limit, Ordering::Relaxed);
}
let limit = [DebugInfo::None, DebugInfo::LineTables, DebugInfo::Full]
.into_iter()
.find(|level| *level as u8 == limit);
resolve_debug_info(requested, limit)
}
fn resolve_debug_info(requested: DebugInfo, limit: Option<DebugInfo>) -> DebugInfo {
let level = requested.max(PROFILE_DEBUG_INFO);
limit.map_or(level, |limit| level.min(limit))
}
#[derive(Default, Clone, Debug, serde::Serialize, serde::Deserialize)]
pub struct CompilationConfig {
#[serde(default)]
pub logger: LoggerConfig<CompilationLogLevel>,
#[serde(default)]
#[cfg(persistence)]
pub cache: bool,
#[serde(default)]
pub check_mode: BoundsCheckMode,
#[serde(default)]
pub f16_evaluation: Option<F16Evaluation>,
#[serde(default)]
#[cfg(feature = "std")]
pub dump_dir: Option<std::path::PathBuf>,
#[serde(default)]
pub time_passes: bool,
#[serde(default)]
pub debug_info: Option<DebugInfo>,
#[serde(default)]
pub spirv_debug_format: SpirvDebugFormat,
#[serde(default)]
#[cfg(feature = "std")]
pub source_cache: Option<std::path::PathBuf>,
#[serde(default)]
pub parallelism: Option<usize>,
}
impl CompilationConfig {
#[must_use]
pub fn resolve_debug_info(&self, requested: DebugInfo) -> DebugInfo {
resolve_debug_info(requested, self.debug_info)
}
pub fn parallelism(&self) -> usize {
#[cfg(all(feature = "std", not(target_family = "wasm")))]
let threads = self
.parallelism
.unwrap_or_else(|| std::thread::available_parallelism().map_or(1, |cores| cores.get()));
#[cfg(any(not(feature = "std"), target_family = "wasm"))]
let threads = 1;
threads.max(1)
}
}
#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum F16Evaluation {
#[serde(rename = "per-operation")]
PerOperation,
#[default]
#[serde(rename = "chain")]
Chain,
#[serde(rename = "accumulators")]
Accumulators,
}
impl F16Evaluation {
pub fn for_native_f16(native: bool) -> Self {
match native {
true => Self::PerOperation,
false => Self::Chain,
}
}
}
impl core::fmt::Display for F16Evaluation {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str(match self {
Self::PerOperation => "per-operation",
Self::Chain => "chain",
Self::Accumulators => "accumulators",
})
}
}
#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum SpirvDebugFormat {
#[default]
#[serde(rename = "auto")]
Auto,
#[serde(rename = "op-line")]
OpLine,
#[serde(rename = "non-semantic")]
NonSemantic,
}
#[derive(Default, Clone, Copy, Debug, serde::Serialize, serde::Deserialize)]
pub enum BoundsCheckMode {
#[serde(rename = "enforce")]
Enforce,
#[serde(rename = "validate")]
Validate,
#[default]
#[serde(rename = "auto")]
Auto,
}
#[derive(Default, Clone, Copy, Debug, serde::Serialize, serde::Deserialize)]
pub enum CompilationLogLevel {
#[default]
#[serde(rename = "disabled")]
Disabled,
#[serde(rename = "basic")]
Basic,
#[serde(rename = "full")]
Full,
}
impl LogLevel for CompilationLogLevel {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn debug_info_follows_the_profile_and_the_kernel() {
let config = CompilationConfig::default();
assert_eq!(
config.resolve_debug_info(DebugInfo::None),
PROFILE_DEBUG_INFO
);
assert_eq!(config.resolve_debug_info(DebugInfo::Full), DebugInfo::Full);
}
#[test]
fn debug_info_limit_only_lowers() {
let config = CompilationConfig {
debug_info: Some(DebugInfo::LineTables),
..Default::default()
};
assert_eq!(
config.resolve_debug_info(DebugInfo::Full),
DebugInfo::LineTables
);
let config = CompilationConfig {
debug_info: Some(DebugInfo::Full),
..Default::default()
};
assert_eq!(
config.resolve_debug_info(DebugInfo::None),
PROFILE_DEBUG_INFO
);
}
}