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 {
122 let base = if self.perf_cores > 0 {
123 self.perf_cores / 2
124 } else if cfg!(all(target_arch = "aarch64", target_vendor = "apple")) {
125 self.total_cpus / 2
126 } else {
127 self.total_cpus.saturating_mul(3) / 4
128 };
129 base.clamp(1, 32)
130 }
131
132 fn cache_line(&self) -> usize {
134 if self.cache_line > 0 {
135 self.cache_line
136 } else {
137 PLATFORM_CACHE_LINE
138 }
139 }
140
141 #[allow(dead_code)]
143 fn fuse_attn_threshold(&self) -> usize {
144 if self.l1d_cache > 0 {
145 64
151 } else {
152 64
153 }
154 }
155}
156
157#[cfg(target_vendor = "apple")]
158fn sysctl_usize(name: &str) -> Option<usize> {
159 use std::ffi::CString;
160 let cname = CString::new(name).ok()?;
161 let mut val: u64 = 0;
162 let mut len = std::mem::size_of::<u64>();
163 unsafe {
164 unsafe extern "C" {
165 fn sysctlbyname(
166 name: *const i8,
167 oldp: *mut u8,
168 oldlenp: *mut usize,
169 newp: *const u8,
170 newlen: usize,
171 ) -> i32;
172 }
173 let ret = sysctlbyname(
174 cname.as_ptr(),
175 &mut val as *mut u64 as *mut u8,
176 &mut len,
177 std::ptr::null(),
178 0,
179 );
180 if ret == 0 { Some(val as usize) } else { None }
181 }
182}
183
184#[derive(Debug, Clone)]
186pub struct RuntimeConfig {
187 pub pool_workers: usize,
189
190 pub par_threshold: usize,
192 pub min_rows_per_thread: usize,
193
194 pub sdpa_seq_threshold: usize,
196
197 pub arena_alignment: usize,
199
200 pub ln_eps_default: f32,
202 pub attn_mask_neg_inf: f32,
203 pub score_skip_threshold: f32,
204 pub mask_binary_threshold: f32,
205
206 pub verbose: u8,
208}
209
210impl Default for RuntimeConfig {
211 fn default() -> Self {
212 Self::auto_detect()
213 }
214}
215
216impl RuntimeConfig {
217 pub fn auto_detect() -> Self {
219 let hw = HwInfo::detect();
220
221 Self {
222 pool_workers: hw.optimal_workers(),
223 par_threshold: PLATFORM_PAR_THRESHOLD,
224 min_rows_per_thread: 4,
225 sdpa_seq_threshold: 32,
226 arena_alignment: hw.cache_line(),
227 ln_eps_default: 1e-12,
228 attn_mask_neg_inf: -1e9,
229 score_skip_threshold: 1e-8,
230 mask_binary_threshold: 0.5,
231 verbose: 0,
232 }
233 }
234
235 pub fn from_env() -> Self {
237 let mut cfg = Self::auto_detect();
238
239 if let Some(v) = rlx_ir::env::var("RLX_WORKERS")
240 && let Ok(n) = v.parse::<usize>()
241 {
242 cfg.pool_workers = if n == 0 { cfg.pool_workers } else { n.min(32) };
243 }
244 if let Some(v) = rlx_ir::env::var("RLX_PAR_THRESHOLD")
245 && let Ok(n) = v.parse()
246 {
247 cfg.par_threshold = n;
248 }
249 if let Some(v) = rlx_ir::env::var("RLX_SDPA_THRESHOLD")
250 && let Ok(n) = v.parse()
251 {
252 cfg.sdpa_seq_threshold = n;
253 }
254 if let Some(v) = rlx_ir::env::var("RLX_ARENA_ALIGN")
255 && let Ok(n) = v.parse()
256 {
257 cfg.arena_alignment = n;
258 }
259 if let Some(v) = rlx_ir::env::var("RLX_VERBOSE")
260 && let Ok(n) = v.parse()
261 {
262 cfg.verbose = n;
263 }
264
265 if cfg.verbose >= 1 {
266 let hw = HwInfo::detect();
267 eprintln!(
268 "[rlx] hw: {} CPUs ({} P-cores), L1={}KB, L2={}KB, cacheline={}B",
269 hw.total_cpus,
270 hw.perf_cores,
271 hw.l1d_cache / 1024,
272 hw.l2_cache / 1024,
273 hw.cache_line()
274 );
275 eprintln!(
276 "[rlx] config: workers={}, par_thr={}, sdpa_thr={}, align={}",
277 cfg.pool_workers, cfg.par_threshold, cfg.sdpa_seq_threshold, cfg.arena_alignment
278 );
279 }
280
281 cfg
282 }
283
284 pub fn install(&self) {
287 rlx_ir::env::set("RLX_WORKERS", self.pool_workers.to_string());
288 rlx_ir::env::set("RLX_PAR_THRESHOLD", self.par_threshold.to_string());
289 rlx_ir::env::set("RLX_SDPA_THRESHOLD", self.sdpa_seq_threshold.to_string());
290 rlx_ir::env::set("RLX_ARENA_ALIGN", self.arena_alignment.to_string());
291 rlx_ir::env::set("RLX_VERBOSE", self.verbose.to_string());
292 }
293
294 pub fn global() -> &'static RuntimeConfig {
296 static CONFIG: OnceLock<RuntimeConfig> = OnceLock::new();
297 CONFIG.get_or_init(RuntimeConfig::from_env)
298 }
299}
300
301#[cfg(test)]
302mod tests {
303 use super::*;
304
305 #[test]
306 fn auto_detect_sane_defaults() {
307 let cfg = RuntimeConfig::auto_detect();
308 assert!(cfg.pool_workers >= 1);
309 assert!(cfg.pool_workers <= 32);
310 assert!(cfg.arena_alignment >= 64);
312 assert!(cfg.verbose == 0);
313 }
314
315 #[test]
316 fn global_is_consistent() {
317 let a = RuntimeConfig::global();
318 let b = RuntimeConfig::global();
319 assert_eq!(a.pool_workers, b.pool_workers);
320 }
321
322 #[test]
323 fn hw_detection() {
324 let hw = HwInfo::detect();
325 assert!(hw.total_cpus >= 1);
326 #[cfg(target_vendor = "apple")]
328 assert!(
329 hw.cache_line > 0,
330 "expected sysctl to return cache line size"
331 );
332 }
333}