1use std::sync::OnceLock;
32
33#[cfg(all(target_arch = "aarch64", target_vendor = "apple"))]
39const PLATFORM_CACHE_LINE: usize = 128; #[cfg(all(target_arch = "aarch64", not(target_vendor = "apple")))]
42const PLATFORM_CACHE_LINE: usize = 64; #[cfg(not(target_arch = "aarch64"))]
45const PLATFORM_CACHE_LINE: usize = 64; #[cfg(all(target_arch = "aarch64", target_vendor = "apple"))]
52const PLATFORM_PAR_THRESHOLD: usize = 16_384; #[cfg(not(all(target_arch = "aarch64", target_vendor = "apple")))]
55const PLATFORM_PAR_THRESHOLD: usize = 30_000;
56
57struct HwInfo {
61 total_cpus: usize,
62 perf_cores: usize, l1d_cache: usize, l2_cache: usize, cache_line: usize, }
67
68impl HwInfo {
69 fn detect() -> Self {
70 let total = std::thread::available_parallelism()
71 .map(|n| n.get())
72 .unwrap_or(2);
73
74 #[allow(unused_mut)]
77 let mut info = HwInfo {
78 total_cpus: total,
79 perf_cores: 0,
80 l1d_cache: 0,
81 l2_cache: 0,
82 cache_line: 0,
83 };
84
85 #[cfg(target_vendor = "apple")]
86 {
87 info.perf_cores = sysctl_usize("hw.perflevel0.physicalcpu").unwrap_or(0);
88 info.l1d_cache = sysctl_usize("hw.l1dcachesize").unwrap_or(0);
89 info.l2_cache = sysctl_usize("hw.l2cachesize").unwrap_or(0);
90 info.cache_line = sysctl_usize("hw.cachelinesize").unwrap_or(0);
91 }
92
93 #[cfg(target_os = "linux")]
94 {
95 if let Ok(v) = std::fs::read_to_string(
97 "/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size",
98 ) {
99 info.cache_line = v.trim().parse().unwrap_or(0);
100 }
101 if let Ok(v) = std::fs::read_to_string("/sys/devices/system/cpu/cpu0/cache/index0/size")
102 {
103 let s = v.trim().to_uppercase();
105 if s.ends_with('K') {
106 info.l1d_cache = s[..s.len() - 1].parse::<usize>().unwrap_or(0) * 1024;
107 } else {
108 info.l1d_cache = s.parse().unwrap_or(0);
109 }
110 }
111 }
112
113 info
114 }
115
116 fn optimal_workers(&self) -> usize {
118 let base = if self.perf_cores > 0 {
119 self.perf_cores / 2 } else {
121 self.total_cpus / 2 };
123 base.clamp(1, 15)
124 }
125
126 fn cache_line(&self) -> usize {
128 if self.cache_line > 0 {
129 self.cache_line
130 } else {
131 PLATFORM_CACHE_LINE
132 }
133 }
134
135 #[allow(dead_code)]
137 fn fuse_attn_threshold(&self) -> usize {
138 if self.l1d_cache > 0 {
139 64
145 } else {
146 64
147 }
148 }
149}
150
151#[cfg(target_vendor = "apple")]
152fn sysctl_usize(name: &str) -> Option<usize> {
153 use std::ffi::CString;
154 let cname = CString::new(name).ok()?;
155 let mut val: u64 = 0;
156 let mut len = std::mem::size_of::<u64>();
157 unsafe {
158 unsafe extern "C" {
159 fn sysctlbyname(
160 name: *const i8,
161 oldp: *mut u8,
162 oldlenp: *mut usize,
163 newp: *const u8,
164 newlen: usize,
165 ) -> i32;
166 }
167 let ret = sysctlbyname(
168 cname.as_ptr(),
169 &mut val as *mut u64 as *mut u8,
170 &mut len,
171 std::ptr::null(),
172 0,
173 );
174 if ret == 0 { Some(val as usize) } else { None }
175 }
176}
177
178#[derive(Debug, Clone)]
180pub struct RuntimeConfig {
181 pub pool_workers: usize,
183
184 pub par_threshold: usize,
186 pub min_rows_per_thread: usize,
187
188 pub sdpa_seq_threshold: usize,
190
191 pub arena_alignment: usize,
193
194 pub ln_eps_default: f32,
196 pub attn_mask_neg_inf: f32,
197 pub score_skip_threshold: f32,
198 pub mask_binary_threshold: f32,
199
200 pub verbose: u8,
202}
203
204impl Default for RuntimeConfig {
205 fn default() -> Self {
206 Self::auto_detect()
207 }
208}
209
210impl RuntimeConfig {
211 pub fn auto_detect() -> Self {
213 let hw = HwInfo::detect();
214
215 Self {
216 pool_workers: hw.optimal_workers(),
217 par_threshold: PLATFORM_PAR_THRESHOLD,
218 min_rows_per_thread: 4,
219 sdpa_seq_threshold: 32,
220 arena_alignment: hw.cache_line(),
221 ln_eps_default: 1e-12,
222 attn_mask_neg_inf: -1e9,
223 score_skip_threshold: 1e-8,
224 mask_binary_threshold: 0.5,
225 verbose: 0,
226 }
227 }
228
229 pub fn from_env() -> Self {
231 let mut cfg = Self::auto_detect();
232
233 if let Some(v) = rlx_ir::env::var("RLX_WORKERS")
234 && let Ok(n) = v.parse::<usize>()
235 {
236 cfg.pool_workers = if n == 0 { cfg.pool_workers } else { n.min(15) };
237 }
238 if let Some(v) = rlx_ir::env::var("RLX_PAR_THRESHOLD")
239 && let Ok(n) = v.parse()
240 {
241 cfg.par_threshold = n;
242 }
243 if let Some(v) = rlx_ir::env::var("RLX_SDPA_THRESHOLD")
244 && let Ok(n) = v.parse()
245 {
246 cfg.sdpa_seq_threshold = n;
247 }
248 if let Some(v) = rlx_ir::env::var("RLX_ARENA_ALIGN")
249 && let Ok(n) = v.parse()
250 {
251 cfg.arena_alignment = n;
252 }
253 if let Some(v) = rlx_ir::env::var("RLX_VERBOSE")
254 && let Ok(n) = v.parse()
255 {
256 cfg.verbose = n;
257 }
258
259 if cfg.verbose >= 1 {
260 let hw = HwInfo::detect();
261 eprintln!(
262 "[rlx] hw: {} CPUs ({} P-cores), L1={}KB, L2={}KB, cacheline={}B",
263 hw.total_cpus,
264 hw.perf_cores,
265 hw.l1d_cache / 1024,
266 hw.l2_cache / 1024,
267 hw.cache_line()
268 );
269 eprintln!(
270 "[rlx] config: workers={}, par_thr={}, sdpa_thr={}, align={}",
271 cfg.pool_workers, cfg.par_threshold, cfg.sdpa_seq_threshold, cfg.arena_alignment
272 );
273 }
274
275 cfg
276 }
277
278 pub fn install(&self) {
281 rlx_ir::env::set("RLX_WORKERS", self.pool_workers.to_string());
282 rlx_ir::env::set("RLX_PAR_THRESHOLD", self.par_threshold.to_string());
283 rlx_ir::env::set("RLX_SDPA_THRESHOLD", self.sdpa_seq_threshold.to_string());
284 rlx_ir::env::set("RLX_ARENA_ALIGN", self.arena_alignment.to_string());
285 rlx_ir::env::set("RLX_VERBOSE", self.verbose.to_string());
286 }
287
288 pub fn global() -> &'static RuntimeConfig {
290 static CONFIG: OnceLock<RuntimeConfig> = OnceLock::new();
291 CONFIG.get_or_init(RuntimeConfig::from_env)
292 }
293}
294
295#[cfg(test)]
296mod tests {
297 use super::*;
298
299 #[test]
300 fn auto_detect_sane_defaults() {
301 let cfg = RuntimeConfig::auto_detect();
302 assert!(cfg.pool_workers >= 1);
303 assert!(cfg.pool_workers <= 15);
304 assert!(cfg.arena_alignment >= 64);
306 assert!(cfg.verbose == 0);
307 }
308
309 #[test]
310 fn global_is_consistent() {
311 let a = RuntimeConfig::global();
312 let b = RuntimeConfig::global();
313 assert_eq!(a.pool_workers, b.pool_workers);
314 }
315
316 #[test]
317 fn hw_detection() {
318 let hw = HwInfo::detect();
319 assert!(hw.total_cpus >= 1);
320 #[cfg(target_vendor = "apple")]
322 assert!(
323 hw.cache_line > 0,
324 "expected sysctl to return cache line size"
325 );
326 }
327}