1use crate::{
6 Engine, QT_BF16, QT_F8_E4M3, QT_F32, QT_IQ3_S, QT_IQ4_XS, QT_NVFP4, QT_NVFP4_RP, QT_Q2_K,
7 QT_Q3_K, QT_Q4_0, QT_Q4_K, QT_Q5_K, QT_Q6_K, QT_Q8_0,
8};
9use cudarc::driver::CudaSlice;
10use memra_gguf::config::ModelConfig;
11use memra_gguf::source::{DiskExtent, GgufSource, TensorSource};
12use memra_gguf::{GgmlType, GgufFile, dequant};
13use std::collections::HashMap;
14use std::path::Path;
15
16static RESIDENCY_CENSUS: [(std::sync::atomic::AtomicUsize, std::sync::atomic::AtomicU64); 16] = {
24 #[allow(clippy::declare_interior_mutable_const)]
25 const Z: (std::sync::atomic::AtomicUsize, std::sync::atomic::AtomicU64) = (
26 std::sync::atomic::AtomicUsize::new(0),
27 std::sync::atomic::AtomicU64::new(0),
28 );
29 [Z; 16]
30};
31
32fn residency_census_note(qtype: i32, bytes: usize) {
33 use std::sync::atomic::Ordering::Relaxed;
34 if let Some(slot) = RESIDENCY_CENSUS.get(qtype as usize) {
35 slot.0.fetch_add(1, Relaxed);
36 slot.1.fetch_add(bytes as u64, Relaxed);
37 }
38}
39
40pub fn residency_census_report() -> String {
43 use std::sync::atomic::Ordering::Relaxed;
44 let name = |q: usize| -> &'static str {
45 match q as i32 {
46 QT_Q8_0 => "Q8_0",
47 QT_Q4_K => "Q4_K",
48 QT_Q6_K => "Q6_K",
49 QT_Q5_K => "Q5_K",
50 QT_Q3_K => "Q3_K",
51 QT_IQ4_XS => "IQ4_XS",
52 QT_IQ3_S => "IQ3_S",
53 QT_NVFP4 => "NVFP4",
54 QT_F32 => "F32",
55 QT_NVFP4_RP => "NVFP4_RP",
56 QT_F8_E4M3 => "F8_E4M3",
57 QT_BF16 => "BF16",
58 QT_Q4_0 => "Q4_0",
59 QT_Q2_K => "Q2_K",
60 crate::QT_F8_E4M3_BLK => "F8_E4M3_BLK",
61 _ => "?",
62 }
63 };
64 let mut out = String::from("residency census (2D matmul weights, resident container):\n");
65 let (mut tn, mut tb) = (0usize, 0u64);
66 for (q, slot) in RESIDENCY_CENSUS.iter().enumerate() {
67 let (n, b) = (slot.0.load(Relaxed), slot.1.load(Relaxed));
68 if n == 0 {
69 continue;
70 }
71 tn += n;
72 tb += b;
73 out += &format!(
74 " {:>9}: {:>4} tensors {:>9.3} MiB\n",
75 name(q),
76 n,
77 b as f64 / (1024.0 * 1024.0)
78 );
79 }
80 out += &format!(
81 " {:>9}: {:>4} tensors {:>9.3} MiB",
82 "TOTAL",
83 tn,
84 tb as f64 / (1024.0 * 1024.0)
85 );
86 out
87}
88
89fn ensure_repack_cache_dir(path: &Path) -> std::io::Result<()> {
97 match std::fs::symlink_metadata(path) {
98 Ok(meta) => {
99 if meta.file_type().is_symlink() || !meta.is_dir() {
100 return Err(std::io::Error::new(
101 std::io::ErrorKind::InvalidData,
102 format!("repack cache directory is not a real directory: {path:?}"),
103 ));
104 }
105 Ok(())
106 }
107 Err(error) if error.kind() == std::io::ErrorKind::NotFound => {
108 match std::fs::create_dir(path) {
109 Ok(()) => Ok(()),
110 Err(error) if error.kind() == std::io::ErrorKind::AlreadyExists => {
111 ensure_repack_cache_dir(path)
112 }
113 Err(error) => Err(error),
114 }
115 }
116 Err(error) => Err(error),
117 }
118}
119
120fn repack_cache_is_fresh(path: &Path, expected_len: usize) -> bool {
121 std::fs::symlink_metadata(path)
122 .is_ok_and(|meta| meta.file_type().is_file() && meta.len() == expected_len as u64)
123}
124
125#[cfg(unix)]
126fn open_repack_cache_dir(path: &Path) -> std::io::Result<std::fs::File> {
127 use std::os::unix::fs::OpenOptionsExt;
128 let mut options = std::fs::OpenOptions::new();
129 options
130 .read(true)
131 .custom_flags(libc::O_DIRECTORY | libc::O_NOFOLLOW);
132 options.open(path)
133}
134
135#[cfg(not(unix))]
136fn open_repack_cache_dir(path: &Path) -> std::io::Result<std::fs::File> {
137 std::fs::OpenOptions::new().read(true).open(path)
138}
139
140#[cfg(unix)]
141fn open_repack_cache(path: &Path, write: bool) -> std::io::Result<std::fs::File> {
142 use std::ffi::CString;
143 use std::os::unix::ffi::OsStrExt;
144 use std::os::unix::io::{AsRawFd, FromRawFd};
145
146 let parent = path.parent().ok_or_else(|| {
147 std::io::Error::new(
148 std::io::ErrorKind::InvalidInput,
149 "repack cache has no parent",
150 )
151 })?;
152 let name = path.file_name().ok_or_else(|| {
153 std::io::Error::new(
154 std::io::ErrorKind::InvalidInput,
155 "repack cache has no filename",
156 )
157 })?;
158 let name = CString::new(name.as_bytes()).map_err(|_| {
159 std::io::Error::new(
160 std::io::ErrorKind::InvalidInput,
161 "repack cache filename has NUL",
162 )
163 })?;
164 let dir = open_repack_cache_dir(parent)?;
165 let flags = if write {
166 libc::O_WRONLY | libc::O_CREAT | libc::O_EXCL | libc::O_NOFOLLOW
167 } else {
168 libc::O_RDONLY | libc::O_NOFOLLOW
169 };
170 let fd = unsafe { libc::openat(dir.as_raw_fd(), name.as_ptr(), flags, 0o600) };
171 if fd < 0 {
172 return Err(std::io::Error::last_os_error());
173 }
174 let file = unsafe { std::fs::File::from_raw_fd(fd) };
176 let metadata = file.metadata()?;
177 if !metadata.is_file() {
178 return Err(std::io::Error::new(
179 std::io::ErrorKind::InvalidData,
180 format!("repack cache is not a regular file: {path:?}"),
181 ));
182 }
183 if std::os::unix::fs::MetadataExt::nlink(&metadata) > 1 {
184 return Err(std::io::Error::new(
185 std::io::ErrorKind::InvalidData,
186 format!("repack cache refuses a multiply-linked file: {path:?}"),
187 ));
188 }
189 Ok(file)
190}
191
192#[cfg(not(unix))]
193fn open_repack_cache(path: &Path, write: bool) -> std::io::Result<std::fs::File> {
194 let metadata = std::fs::symlink_metadata(path)?;
195 if metadata.file_type().is_symlink() || !metadata.is_file() {
196 return Err(std::io::Error::new(
197 std::io::ErrorKind::InvalidData,
198 format!("repack cache is not a regular file: {path:?}"),
199 ));
200 }
201 let mut options = std::fs::OpenOptions::new();
202 options.read(!write).write(write);
203 options.open(path)
204}
205
206fn write_repack_cache<F>(path: &Path, write: F) -> std::io::Result<()>
212where
213 F: FnOnce(&mut std::io::BufWriter<std::fs::File>) -> std::io::Result<()>,
214{
215 use std::io::Write;
216
217 let parent = path.parent().ok_or_else(|| {
218 std::io::Error::new(
219 std::io::ErrorKind::InvalidInput,
220 "repack cache has no parent",
221 )
222 })?;
223 let name = path.file_name().ok_or_else(|| {
224 std::io::Error::new(
225 std::io::ErrorKind::InvalidInput,
226 "repack cache has no filename",
227 )
228 })?;
229 let dir = open_repack_cache_dir(parent)?;
230
231 #[cfg(unix)]
232 {
233 use std::ffi::CString;
234 use std::os::unix::ffi::OsStrExt;
235 use std::os::unix::io::{AsRawFd, FromRawFd};
236 static TEMP_COUNTER: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0);
237 let name = CString::new(name.as_bytes()).map_err(|_| {
238 std::io::Error::new(
239 std::io::ErrorKind::InvalidInput,
240 "repack cache filename has NUL",
241 )
242 })?;
243 let mut temp_name = None;
244 let mut temp_file = None;
245 for _ in 0..32 {
246 let suffix = TEMP_COUNTER.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
247 let candidate = CString::new(format!(
248 ".{}.tmp-{}-{suffix}",
249 name.to_string_lossy(),
250 std::process::id()
251 ))
252 .map_err(|_| {
253 std::io::Error::new(
254 std::io::ErrorKind::InvalidInput,
255 "temporary filename has NUL",
256 )
257 })?;
258 let fd = unsafe {
259 libc::openat(
260 dir.as_raw_fd(),
261 candidate.as_ptr(),
262 libc::O_WRONLY | libc::O_CREAT | libc::O_EXCL | libc::O_NOFOLLOW,
263 0o600,
264 )
265 };
266 if fd >= 0 {
267 temp_name = Some(candidate);
268 temp_file = Some(unsafe { std::fs::File::from_raw_fd(fd) });
270 break;
271 }
272 let error = std::io::Error::last_os_error();
273 if error.kind() != std::io::ErrorKind::AlreadyExists {
274 return Err(error);
275 }
276 }
277 let temp_name = temp_name.ok_or_else(|| {
278 std::io::Error::new(
279 std::io::ErrorKind::AlreadyExists,
280 "could not allocate a unique repack cache temporary",
281 )
282 })?;
283 let mut out = std::io::BufWriter::new(temp_file.expect("temporary file accompanies name"));
284 let result = write(&mut out).and_then(|()| {
285 out.flush()?;
286 out.get_ref().sync_all()?;
287 Ok(())
288 });
289 drop(out);
290 if let Err(error) = result {
291 unsafe {
292 libc::unlinkat(dir.as_raw_fd(), temp_name.as_ptr(), 0);
293 }
294 return Err(error);
295 }
296
297 if let Ok(metadata) = std::fs::symlink_metadata(path) {
301 if metadata.file_type().is_symlink()
302 || !metadata.is_file()
303 || std::os::unix::fs::MetadataExt::nlink(&metadata) > 1
304 {
305 unsafe {
306 libc::unlinkat(dir.as_raw_fd(), temp_name.as_ptr(), 0);
307 }
308 return Err(std::io::Error::new(
309 std::io::ErrorKind::InvalidData,
310 format!("repack cache target is not a private regular file: {path:?}"),
311 ));
312 }
313 }
314 let status = unsafe {
315 libc::renameat(
316 dir.as_raw_fd(),
317 temp_name.as_ptr(),
318 dir.as_raw_fd(),
319 name.as_ptr(),
320 )
321 };
322 if status != 0 {
323 unsafe {
324 libc::unlinkat(dir.as_raw_fd(), temp_name.as_ptr(), 0);
325 }
326 return Err(std::io::Error::last_os_error());
327 }
328 dir.sync_all()
329 }
330
331 #[cfg(not(unix))]
332 {
333 let temp = parent.join(format!(
334 ".{}.tmp-{}",
335 name.to_string_lossy(),
336 std::process::id()
337 ));
338 let mut out = std::io::BufWriter::new(
339 std::fs::OpenOptions::new()
340 .write(true)
341 .create_new(true)
342 .open(&temp)?,
343 );
344 write(&mut out)?;
345 out.flush()?;
346 out.get_ref().sync_all()?;
347 drop(out);
348 if let Ok(metadata) = std::fs::symlink_metadata(path) {
349 if metadata.file_type().is_symlink() || !metadata.is_file() {
350 std::fs::remove_file(&temp).ok();
351 return Err(std::io::Error::new(
352 std::io::ErrorKind::InvalidData,
353 format!("repack cache target is not a private regular file: {path:?}"),
354 ));
355 }
356 }
357 std::fs::rename(temp, path)
358 }
359}
360
361pub enum GpuTensor {
365 Quant {
366 bytes: CudaSlice<u8>,
367 qtype: i32,
368 row_bytes: usize,
369 ne: Vec<u64>,
370 scale: f32,
371 rp: bool,
379 #[cfg(memra_cutlass)]
383 cutlass: Option<CutlassWeight>,
384 fp8: Option<Fp8Weight>,
390 rp4: Option<CudaSlice<u8>>,
397 blk: Option<Fp8BlockScales>,
405 f16: Option<CudaSlice<u8>>,
410 },
411 Float {
412 data: CudaSlice<f32>,
413 ne: Vec<u64>,
414 },
415 FloatBf16 {
422 data: CudaSlice<u8>,
423 ne: Vec<u64>,
424 },
425}
426
427pub struct Fp8Weight {
433 pub bytes: CudaSlice<u8>,
434 pub scale: f32,
435 pub blk: Option<Fp8BlockScales>,
436}
437
438pub struct Fp8BlockScales {
455 pub scales: CudaSlice<f32>,
456 pub rows: usize, pub cols: usize, }
459
460pub fn repack_nvfp4_split(bytes: &[u8], out_f: usize) -> Vec<u8> {
464 let row_bytes = bytes.len() / out_f;
465 let nsb64 = row_bytes / 36;
466 debug_assert_eq!(
467 row_bytes % 36,
468 0,
469 "NVFP4 row_bytes must be a multiple of 36"
470 );
471 let qplane = out_f * nsb64 * 32;
472 let mut rp = vec![0u8; bytes.len()];
473 for o in 0..out_f {
474 for s in 0..nsb64 {
475 let src = &bytes[o * row_bytes + s * 36..o * row_bytes + s * 36 + 36];
476 rp[qplane + (o * nsb64 + s) * 4..qplane + (o * nsb64 + s) * 4 + 4]
477 .copy_from_slice(&src[0..4]);
478 rp[(o * nsb64 + s) * 32..(o * nsb64 + s) * 32 + 32].copy_from_slice(&src[4..36]);
479 }
480 }
481 rp
482}
483
484pub fn unpack_nvfp4_split(rp: &[u8], out_f: usize) -> Vec<u8> {
486 let row_bytes = rp.len() / out_f;
487 let nsb64 = row_bytes / 36;
488 let qplane = out_f * nsb64 * 32;
489 let mut back = vec![0u8; rp.len()];
490 for o in 0..out_f {
491 for s in 0..nsb64 {
492 back[o * row_bytes + s * 36..o * row_bytes + s * 36 + 4].copy_from_slice(
493 &rp[qplane + (o * nsb64 + s) * 4..qplane + (o * nsb64 + s) * 4 + 4],
494 );
495 back[o * row_bytes + s * 36 + 4..o * row_bytes + s * 36 + 36]
496 .copy_from_slice(&rp[(o * nsb64 + s) * 32..(o * nsb64 + s) * 32 + 32]);
497 }
498 }
499 back
500}
501
502pub fn rp_enabled() -> bool {
504 static ON: std::sync::OnceLock<bool> = std::sync::OnceLock::new();
505 *ON.get_or_init(|| std::env::var("MEMRA_RP").map(|v| v != "0").unwrap_or(true))
506}
507
508pub fn full_prec_enabled() -> bool {
517 static ON: std::sync::OnceLock<bool> = std::sync::OnceLock::new();
518 *ON.get_or_init(|| {
519 std::env::var("MEMRA_FULL_PREC")
520 .map(|v| v == "1")
521 .unwrap_or(false)
522 })
523}
524
525fn float_2d_audited(name: &str) -> bool {
535 name.ends_with("ffn_gate_inp.weight")
536}
537
538fn warn_float_2d_once(name: &str, ne: &[u64], src_type: GgmlType) {
541 use std::sync::{Mutex, OnceLock};
542 static SEEN: OnceLock<Mutex<std::collections::HashSet<String>>> = OnceLock::new();
543 let pat = match name.strip_prefix("blk.").and_then(|r| r.split_once('.')) {
544 Some((_, suffix)) => format!("blk.*.{suffix}"),
545 None => name.to_string(),
546 };
547 let mut seen = SEEN
548 .get_or_init(|| Mutex::new(std::collections::HashSet::new()))
549 .lock()
550 .unwrap();
551 if seen.insert(pat.clone()) {
552 eprintln!(
553 "[loader-law] WARNING: {pat} loads as 2D Float ne={ne:?} (src {src_type:?}) — \
554 a Float matmul weight rides cuBLAS f32 GEMV and poisons all-or-nothing q8-fast \
555 predicates (uses_q8_1_fast/mixer_in_q8_1_fast). If matmul-class: Q8_0-encode at \
556 load (model.rs ssm arm / source.rs BF16+F8 gates). If deliberately Float: add \
557 it to float_2d_audited with the audit rationale."
558 );
559 }
560}
561
562#[cfg(memra_cutlass)]
565pub struct CutlassWeight {
566 pub b_packed: CudaSlice<u8>,
568 pub sfb_swizzled: CudaSlice<u8>,
570}
571
572impl GpuTensor {
573 pub fn nvfp4_rp_from_raw(
580 e: &Engine,
581 raw: &[u8],
582 in_f: usize,
583 out_f: usize,
584 scale: f32,
585 ) -> Result<Self, Box<dyn std::error::Error>> {
586 assert_eq!(raw.len() % out_f, 0, "raw bytes must tile out_f rows");
587 let row_bytes = raw.len() / out_f;
588 assert_eq!(
589 row_bytes,
590 in_f / 64 * 36,
591 "NVFP4 row layout: 36B per 64 values"
592 );
593 let bytes = e.htod_bytes(&repack_nvfp4_split(raw, out_f))?;
594 Ok(GpuTensor::Quant {
595 bytes,
596 qtype: crate::QT_NVFP4,
597 row_bytes,
598 ne: vec![in_f as u64, out_f as u64],
599 scale,
600 rp: true,
601 #[cfg(memra_cutlass)]
602 cutlass: None,
603 fp8: None,
604 rp4: None,
605 blk: None,
606 f16: None,
607 })
608 }
609
610 pub fn ne(&self) -> &[u64] {
611 match self {
612 GpuTensor::Quant { ne, .. } => ne,
613 GpuTensor::Float { ne, .. } => ne,
614 GpuTensor::FloatBf16 { ne, .. } => ne,
615 }
616 }
617 pub fn in_features(&self) -> usize {
618 self.ne()[0] as usize
619 }
620 pub fn out_features(&self) -> usize {
621 self.ne()[1] as usize
622 }
623 pub fn scale(&self) -> f32 {
626 match self {
627 GpuTensor::Quant { scale, .. } => *scale,
628 GpuTensor::Float { .. } | GpuTensor::FloatBf16 { .. } => 1.0,
629 }
630 }
631
632 pub fn load(e: &Engine, g: &GgufFile, name: &str) -> Result<Self, Box<dyn std::error::Error>> {
635 Self::load_from_source(e, &GgufSource(g), name)
636 }
637
638 pub fn load_from_source(
647 e: &Engine,
648 src: &dyn TensorSource,
649 name: &str,
650 ) -> Result<Self, Box<dyn std::error::Error>> {
651 let t = Self::load_from_source_inner(e, src, name)?;
652 if let GpuTensor::Quant {
653 qtype, bytes, ne, ..
654 } = &t
655 {
656 if ne.len() == 2 {
657 residency_census_note(*qtype, bytes.len());
658 }
659 }
660 Ok(t)
661 }
662
663 fn load_from_source_inner(
664 e: &Engine,
665 src: &dyn TensorSource,
666 name: &str,
667 ) -> Result<Self, Box<dyn std::error::Error>> {
668 let cutlass_wants_raw = cfg!(memra_cutlass) && std::env::var("MEMRA_FP4_CUTLASS").is_ok();
676 let st_direct = std::env::var("MEMRA_ST_DIRECT")
677 .map(|v| v != "0")
678 .unwrap_or(true);
679 if rp_enabled() && st_direct && !cutlass_wants_raw {
680 if let Some(nv) = src.find_nvfp4_native(name) {
681 if nv.in_f % 64 == 0 && nv.out_f > 0 {
682 let stem = name.strip_suffix(".weight").unwrap_or(name);
684 let scale = match src.find(&format!("{stem}.scale")) {
685 Some(sv) => f32::from_le_bytes(sv.bytes[..4].try_into().unwrap()),
686 None => 1.0,
687 };
688 let bytes =
689 e.htod_bytes(&memra_gguf::nvfp4_repack::repack_modelopt_to_split(
690 nv.wbytes, nv.wscale, nv.out_f, nv.in_f,
691 ))?;
692 return Ok(GpuTensor::Quant {
693 bytes,
694 qtype: QT_NVFP4,
695 row_bytes: nv.in_f / 64 * 36,
696 ne: vec![nv.in_f as u64, nv.out_f as u64],
697 scale,
698 rp: true,
699 #[cfg(memra_cutlass)]
700 cutlass: None,
701 fp8: None,
702 blk: None,
703 f16: None,
704 rp4: None,
705 });
706 }
707 }
708 }
709 if crate::fp8_ffi::st_e4m3_enabled() {
724 if let Some(f8) = src.find_fp8_native(name) {
725 if f8.blk.is_none() && f8.in_f % 32 == 0 && f8.out_f > 0 {
726 return Ok(GpuTensor::Quant {
727 bytes: e.htod_bytes(&f8.bytes)?,
728 qtype: crate::QT_F8_E4M3,
729 row_bytes: f8.in_f,
730 ne: vec![f8.in_f as u64, f8.out_f as u64],
731 scale: f8.scale,
732 rp: false,
733 #[cfg(memra_cutlass)]
734 cutlass: None,
735 fp8: None,
736 blk: None,
737 f16: None,
738 rp4: None,
739 });
740 }
741 }
742 }
743 if crate::fp8_ffi::st_e4m3_blk_enabled() {
770 if let Some(f8) = src.find_fp8_native(name) {
771 if let Some(grid) = f8.blk.as_ref() {
772 let (in_f, out_f) = (f8.in_f, f8.out_f);
773 if in_f % 32 == 0
779 && out_f > 0
780 && f8.bytes.len() == out_f * in_f
781 && grid.rows == out_f.div_ceil(128)
782 && grid.cols == in_f.div_ceil(128)
783 && grid.scales.len() == grid.rows * grid.cols
784 && f8.scale == 1.0
785 {
786 let bytes = e.htod_bytes(&f8.bytes)?;
787 if e.fp8_blk_nan_count(&bytes)? == 0 {
788 let scales = e.htod(&grid.scales)?;
789 return Ok(GpuTensor::Quant {
790 bytes,
791 qtype: crate::QT_F8_E4M3_BLK,
792 row_bytes: in_f,
793 ne: vec![in_f as u64, out_f as u64],
794 scale: 1.0,
795 rp: false,
796 #[cfg(memra_cutlass)]
797 cutlass: None,
798 fp8: None,
799 blk: Some(Fp8BlockScales {
800 scales,
801 rows: grid.rows,
802 cols: grid.cols,
803 }),
804 f16: None,
805 rp4: None,
806 });
807 }
808 crate::fp8_ffi::note_blk_native_nan_refused();
809 }
810 }
811 }
812 }
813 if crate::fp8_ffi::fp8_blk_gpu_enabled() {
839 if let Some(f8) = src.find_fp8_native(name) {
840 if let Some(grid) = f8.blk.as_ref() {
841 let (in_f, out_f) = (f8.in_f, f8.out_f);
842 if in_f % 32 == 0 && out_f > 0 && f8.bytes.len() == out_f * in_f {
843 let bytes = e.fp8_blk_dequant_q8_0(&f8.bytes, &grid.scales, out_f, in_f)?;
844 return Ok(GpuTensor::Quant {
845 bytes,
846 qtype: QT_Q8_0,
847 row_bytes: in_f / 32 * 34,
848 ne: vec![in_f as u64, out_f as u64],
849 scale: 1.0,
850 rp: false,
851 #[cfg(memra_cutlass)]
852 cutlass: None,
853 fp8: None,
854 blk: None,
855 f16: None,
856 rp4: None,
857 });
858 }
859 }
860 }
861 }
862 let mut v = src
863 .find(name)
864 .unwrap_or_else(|| panic!("missing tensor {name}"));
865 let kq = std::env::var("MEMRA_KQ_NVFP4")
880 .ok()
881 .and_then(|x| x.parse::<u8>().ok())
882 .unwrap_or(0);
883 if (kq >= 1 && v.ggml_type == GgmlType::Q4_K || kq >= 2 && v.ggml_type == GgmlType::Q5_K)
884 && v.ne.len() == 2
885 && v.ne[0] % 64 == 0
886 && !name.starts_with("output")
887 {
888 let n: u64 = v.ne.iter().product();
889 let f32v = dequant::dequantize(v.ggml_type, &v.bytes, n as usize);
890 let packed = memra_gguf::nvfp4_repack::f32_to_nvfp4(&f32v);
891 v = memra_gguf::source::TensorView {
892 bytes: std::borrow::Cow::Owned(packed),
893 ggml_type: GgmlType::NVFP4,
894 ne: v.ne.clone(),
895 };
896 }
897 let qtype = match v.ggml_type {
898 GgmlType::Q8_0 => Some(QT_Q8_0),
899 GgmlType::Q4_K => Some(QT_Q4_K),
900 GgmlType::Q6_K => Some(QT_Q6_K),
901 GgmlType::Q5_K => Some(QT_Q5_K),
902 GgmlType::Q3_K => Some(QT_Q3_K),
903 GgmlType::IQ4_XS => Some(QT_IQ4_XS),
904 GgmlType::IQ3_S => Some(QT_IQ3_S),
905 GgmlType::NVFP4 => Some(QT_NVFP4),
906 GgmlType::Q4_0 => Some(QT_Q4_0),
907 _ => None,
909 };
910 match qtype {
911 Some(qt) => {
912 let out_f = v.ne[1] as usize;
913 let row_bytes = v.bytes.len() / out_f;
914 let scale = if qt == QT_NVFP4 {
919 let stem = name.strip_suffix(".weight").unwrap_or(name);
920 match src.find(&format!("{stem}.scale")) {
921 Some(sv) => f32::from_le_bytes(sv.bytes[..4].try_into().unwrap()),
922 None => 1.0,
923 }
924 } else {
925 1.0
926 };
927 let rp = qt == QT_NVFP4
931 && v.ne.len() == 2
932 && (v.ne[0] as usize) % 64 == 0
933 && v.bytes.len() % out_f == 0
934 && (v.bytes.len() / out_f) % 36 == 0
935 && rp_enabled();
936 let bytes = if rp {
937 e.htod_bytes(&repack_nvfp4_split(&v.bytes, out_f))?
938 } else {
939 e.htod_bytes(&v.bytes)?
940 };
941 #[cfg(memra_cutlass)]
946 let cutlass = {
947 let in_f = v.ne[0] as usize;
948 if qt == QT_NVFP4
951 && in_f % 64 == 0
952 && v.ne.len() == 2
953 && std::env::var("MEMRA_FP4_CUTLASS").is_ok()
954 && std::env::var("MEMRA_FP4_CUTLASS_OTF").is_err()
955 {
956 let raw_dev;
957 let src_dev = if rp {
958 raw_dev = e.htod_bytes(&v.bytes)?;
959 &raw_dev
960 } else {
961 &bytes
962 };
963 let (b_packed, sfb_swizzled) =
964 e.build_cutlass_weight(src_dev, out_f, in_f, row_bytes)?;
965 Some(CutlassWeight {
966 b_packed,
967 sfb_swizzled,
968 })
969 } else {
970 None
971 }
972 };
973 let fp8 = if qt == QT_Q8_0
993 && (crate::fp8_ffi::pp_fp8_enabled() || crate::fp8_ffi::fp8_mmq_enabled())
994 {
995 match src.find_fp8_native(name) {
996 Some(f8)
997 if v.ne.len() == 2
998 && f8.in_f as u64 == v.ne[0]
999 && f8.out_f as u64 == v.ne[1] =>
1000 {
1001 use std::sync::atomic::{AtomicUsize, Ordering};
1002 static FP8_SPENT: AtomicUsize = AtomicUsize::new(0);
1003 static FP8_BUDGET: std::sync::OnceLock<usize> =
1004 std::sync::OnceLock::new();
1005 let budget = *FP8_BUDGET.get_or_init(|| {
1006 std::env::var("MEMRA_PP_FP8_BUDGET_MB")
1007 .ok()
1008 .and_then(|v| v.parse::<usize>().ok())
1009 .unwrap_or(1536)
1010 << 20
1011 });
1012 let sz = f8.bytes.len();
1013 if FP8_SPENT.fetch_add(sz, Ordering::Relaxed) + sz <= budget {
1014 let blk = match f8.blk {
1019 Some(g) => Some(Fp8BlockScales {
1020 scales: e.htod(&g.scales)?,
1021 rows: g.rows,
1022 cols: g.cols,
1023 }),
1024 None => None,
1025 };
1026 Some(Fp8Weight {
1027 bytes: e.htod_bytes(&f8.bytes)?,
1028 scale: f8.scale,
1029 blk,
1030 })
1031 } else {
1032 FP8_SPENT.fetch_sub(sz, Ordering::Relaxed);
1033 None
1034 }
1035 }
1036 _ => None,
1037 }
1038 } else {
1039 None
1040 };
1041 Ok(GpuTensor::Quant {
1042 bytes,
1043 qtype: qt,
1044 row_bytes,
1045 ne: v.ne.clone(),
1046 scale,
1047 rp,
1048 #[cfg(memra_cutlass)]
1049 cutlass,
1050 fp8,
1051 blk: None,
1052 rp4: None,
1053 f16: None,
1054 })
1055 }
1056 None => {
1057 let n: u64 = v.ne.iter().product();
1058 if full_prec_enabled() || crate::Engine::bf16_mmv_on() {
1070 let threshold = if full_prec_enabled() {
1077 1_000_000
1078 } else {
1079 2_000_000
1080 };
1081 if v.ggml_type == GgmlType::BF16 && v.ne.len() == 2 && n >= threshold {
1082 let data = e.htod_bytes(&v.bytes)?; eprintln!(
1093 "[bf16-mmv] RESIDENT {name} ne={:?} n={n} admit={}",
1094 v.ne,
1095 if full_prec_enabled() {
1096 "full_prec"
1097 } else {
1098 "bf16_mmv"
1099 }
1100 );
1101 return Ok(GpuTensor::FloatBf16 {
1102 data,
1103 ne: v.ne.clone(),
1104 });
1105 }
1106 if full_prec_enabled() {
1107 let f32v = dequant::dequantize(v.ggml_type, &v.bytes, n as usize);
1108 return Ok(GpuTensor::Float {
1109 data: e.htod(&f32v)?,
1110 ne: v.ne.clone(),
1111 });
1112 }
1113 }
1114 let f32v = dequant::dequantize(v.ggml_type, &v.bytes, n as usize);
1115 if v.ne.len() == 2
1122 && v.ne[0] % 32 == 0
1123 && (name.ends_with("ssm_beta.weight") || name.ends_with("ssm_alpha.weight")
1124 || name.ends_with("per_layer_model_proj.weight"))
1130 {
1131 let q8 = memra_gguf::nvfp4_repack::f32_to_q8_0(&f32v);
1132 return GpuTensor::from_quant_bytes(
1133 e,
1134 &q8,
1135 GgmlType::Q8_0,
1136 v.ne[0],
1137 v.ne[1],
1138 1.0,
1139 );
1140 }
1141 if v.ne.len() == 2 && v.ne[0] >= 16 && v.ne[1] >= 16 && !float_2d_audited(name) {
1151 warn_float_2d_once(name, &v.ne, v.ggml_type);
1152 }
1153 Ok(GpuTensor::Float {
1155 data: e.htod(&f32v)?,
1156 ne: v.ne.clone(),
1157 })
1158 }
1159 }
1160 }
1161
1162 pub fn from_quant_bytes(
1166 e: &Engine,
1167 bytes: &[u8],
1168 ty: GgmlType,
1169 ne0: u64,
1170 ne1: u64,
1171 scale: f32,
1172 ) -> Result<Self, Box<dyn std::error::Error>> {
1173 let qt = match ty {
1174 GgmlType::Q8_0 => QT_Q8_0,
1175 GgmlType::Q4_K => QT_Q4_K,
1176 GgmlType::Q6_K => QT_Q6_K,
1177 GgmlType::Q5_K => QT_Q5_K,
1178 GgmlType::Q3_K => QT_Q3_K,
1179 GgmlType::IQ4_XS => QT_IQ4_XS,
1180 GgmlType::IQ3_S => QT_IQ3_S,
1181 GgmlType::NVFP4 => QT_NVFP4,
1182 GgmlType::Q4_0 => QT_Q4_0,
1183 other => panic!("from_quant_bytes: unsupported dtype {other:?}"),
1184 };
1185 let row_bytes = bytes.len() / ne1 as usize;
1186 let rp = qt == QT_NVFP4 && ne0 % 64 == 0 && row_bytes % 36 == 0 && rp_enabled();
1189 let dev = if rp {
1190 e.htod_bytes(&repack_nvfp4_split(bytes, ne1 as usize))?
1191 } else {
1192 e.htod_bytes(bytes)?
1193 };
1194 Ok(GpuTensor::Quant {
1195 bytes: dev,
1196 qtype: qt,
1197 row_bytes,
1198 ne: vec![ne0, ne1],
1199 scale,
1200 rp,
1201 #[cfg(memra_cutlass)]
1202 cutlass: None,
1203 fp8: None,
1204 blk: None,
1205 f16: None,
1206 rp4: None,
1207 })
1208 }
1209
1210 pub fn load_opt(
1211 e: &Engine,
1212 g: &GgufFile,
1213 name: &str,
1214 ) -> Result<Option<Self>, Box<dyn std::error::Error>> {
1215 Self::load_opt_from_source(e, &GgufSource(g), name)
1216 }
1217
1218 pub fn load_opt_from_source(
1219 e: &Engine,
1220 src: &dyn TensorSource,
1221 name: &str,
1222 ) -> Result<Option<Self>, Box<dyn std::error::Error>> {
1223 if src.has(name) {
1224 Ok(Some(Self::load_from_source(e, src, name)?))
1225 } else {
1226 Ok(None)
1227 }
1228 }
1229
1230 pub fn float_data(&self) -> &CudaSlice<f32> {
1232 match self {
1233 GpuTensor::Float { data, .. } => data,
1234 GpuTensor::Quant { .. } => panic!("expected float tensor (norm), got quantized"),
1235 GpuTensor::FloatBf16 { .. } => {
1236 panic!("expected f32 float tensor (norm), got bf16-resident matmul weight")
1237 }
1238 }
1239 }
1240}
1241
1242pub struct Layer {
1243 pub attn_norm: GpuTensor,
1244 pub wq: GpuTensor,
1245 pub wk: GpuTensor,
1246 pub wv: GpuTensor,
1247 pub wo: GpuTensor,
1248 pub q_norm: Option<GpuTensor>,
1249 pub k_norm: Option<GpuTensor>,
1250 pub ffn_norm: GpuTensor,
1251 pub ffn: crate::hybrid::Ffn,
1254}
1255
1256pub struct EmbedHost {
1258 pub raw: Vec<u8>,
1259 pub ggml_type: GgmlType,
1260 pub n_embd: usize,
1261}
1262impl EmbedHost {
1263 pub fn from_gguf(g: &GgufFile, name: &str) -> Self {
1264 Self::from_source(&GgufSource(g), name)
1265 }
1266 pub fn from_source(src: &dyn TensorSource, name: &str) -> Self {
1267 let v = src
1268 .find(name)
1269 .unwrap_or_else(|| panic!("missing embed {name}"));
1270 EmbedHost {
1271 raw: v.bytes.to_vec(),
1272 ggml_type: v.ggml_type,
1273 n_embd: v.ne[0] as usize,
1274 }
1275 }
1276 pub fn qt_and_row_bytes(&self, n_embd: usize) -> (i32, usize) {
1279 let (blk, tsize) = self.ggml_type.block_and_type_size();
1280 let row_bytes = (n_embd as u64 / blk * tsize) as usize;
1281 let qt = match self.ggml_type {
1282 GgmlType::Q8_0 => QT_Q8_0,
1283 GgmlType::Q4_K => QT_Q4_K,
1284 GgmlType::Q6_K => QT_Q6_K,
1285 GgmlType::Q5_K => QT_Q5_K,
1286 GgmlType::Q3_K => QT_Q3_K,
1287 GgmlType::IQ4_XS => QT_IQ4_XS,
1288 GgmlType::IQ3_S => QT_IQ3_S,
1289 GgmlType::NVFP4 => QT_NVFP4,
1290 GgmlType::F32 => QT_F32,
1291 GgmlType::BF16 => QT_BF16,
1294 other => panic!("embed_gather: unsupported dtype {other:?}"),
1295 };
1296 (qt, row_bytes)
1297 }
1298
1299 pub fn gather(&self, n_embd: usize, tokens: &[u32]) -> Vec<f32> {
1301 let (blk, tsize) = self.ggml_type.block_and_type_size();
1302 let row_bytes = (n_embd as u64 / blk * tsize) as usize;
1303 let mut x = vec![0f32; tokens.len() * n_embd];
1304 for (ti, &tok) in tokens.iter().enumerate() {
1305 let off = tok as usize * row_bytes;
1306 let row = dequant::dequantize(self.ggml_type, &self.raw[off..off + row_bytes], n_embd);
1307 x[ti * n_embd..ti * n_embd + n_embd].copy_from_slice(&row);
1308 }
1309 x
1310 }
1311}
1312
1313pub struct Model {
1314 pub cfg: ModelConfig,
1315 pub embd: EmbedHost,
1316 pub output_norm: GpuTensor,
1317 pub output: GpuTensor,
1318 pub layers: Vec<Layer>,
1319}
1320
1321impl Model {
1322 pub fn load_dense(e: &Engine, g: &GgufFile) -> Result<Self, Box<dyn std::error::Error>> {
1325 Self::load_dense_from_source(e, &GgufSource(g))
1326 }
1327
1328 pub fn load_dense_from_source(
1332 e: &Engine,
1333 src: &dyn TensorSource,
1334 ) -> Result<Self, Box<dyn std::error::Error>> {
1335 let cfg = src.try_config().map_err(std::io::Error::other)?;
1336 let plan = match memra_gguf::model_packs::for_config(&cfg) {
1337 Some(pack) => pack.compile_plan(&cfg)?,
1338 None => memra_gguf::model_plan::ModelPlan::compile(&cfg)?,
1339 };
1340 if plan.layers.iter().any(|layer| {
1341 !matches!(
1342 layer.attention,
1343 memra_gguf::model_plan::AttentionPlan::Full(_)
1344 )
1345 }) {
1346 return Err("plain executor requires full-attention ModelPlan layers".into());
1347 }
1348 crate::KV_FP8_FORCE.store(0, std::sync::atomic::Ordering::Relaxed);
1355
1356 let embd = EmbedHost::from_source(src, "token_embd.weight");
1357 let output_norm = GpuTensor::load_from_source(e, src, "output_norm.weight")?;
1358 let output = if src.has("output.weight") {
1360 GpuTensor::load_from_source(e, src, "output.weight")?
1361 } else {
1362 GpuTensor::load_from_source(e, src, "token_embd.weight")?
1363 };
1364 let mut resident = crate::hybrid::ResidentPlan::unsharded(e, src, &cfg);
1365 let mut step_runtimes = crate::hybrid::StepParallelRuntimeRegistry::default();
1366
1367 let mut layers = Vec::with_capacity(plan.layers.len());
1368 for (il, layer_plan) in plan.layers.iter().enumerate() {
1369 let il = il as u32;
1370 let p = |s: &str| format!("blk.{il}.{s}");
1371 let ffn = crate::hybrid::load_ffn(
1372 e,
1373 src,
1374 &cfg,
1375 &layer_plan.mlp,
1376 il,
1377 None,
1378 &mut resident,
1379 &mut step_runtimes,
1380 )?;
1381 layers.push(Layer {
1382 attn_norm: GpuTensor::load_from_source(e, src, &p("attn_norm.weight"))?,
1383 wq: GpuTensor::load_from_source(e, src, &p("attn_q.weight"))?,
1384 wk: GpuTensor::load_from_source(e, src, &p("attn_k.weight"))?,
1385 wv: GpuTensor::load_from_source(e, src, &p("attn_v.weight"))?,
1386 wo: GpuTensor::load_from_source(e, src, &p("attn_output.weight"))?,
1387 q_norm: GpuTensor::load_opt_from_source(e, src, &p("attn_q_norm.weight"))?,
1388 k_norm: GpuTensor::load_opt_from_source(e, src, &p("attn_k_norm.weight"))?,
1389 ffn_norm: GpuTensor::load_from_source(e, src, &p("ffn_norm.weight"))?,
1390 ffn,
1391 });
1392 }
1393 Ok(Model {
1394 cfg,
1395 embd,
1396 output_norm,
1397 output,
1398 layers,
1399 })
1400 }
1401
1402 pub(crate) fn max_moe_block(&self) -> usize {
1405 use crate::hybrid::Ffn;
1406 let mut mx = 0usize;
1407 for l in &self.layers {
1408 if let Ffn::Moe(m) = &l.ffn {
1409 mx = mx
1410 .max(m.gate_exps.max_expert_bytes())
1411 .max(m.up_exps.max_expert_bytes())
1412 .max(m.down_exps.max_expert_bytes());
1413 }
1414 }
1415 mx
1416 }
1417
1418 pub fn embed_tokens(
1421 &self,
1422 e: &Engine,
1423 tokens: &[u32],
1424 ) -> Result<CudaSlice<f32>, Box<dyn std::error::Error>> {
1425 let n_embd = self.cfg.n_embd as usize;
1426 let x = self.embd.gather(n_embd, tokens);
1427 Ok(e.htod(&x)?)
1428 }
1429}
1430
1431pub type TensorMap = HashMap<String, GpuTensor>;
1432
1433pub enum HostBuf {
1452 Paged(Vec<u8>),
1453 Pinned {
1456 slice: std::sync::Arc<cudarc::driver::PinnedHostSlice<u8>>,
1457 base: *const u8,
1458 len: usize,
1459 },
1460 PinnedAlias {
1463 owner: std::sync::Arc<HostBuf>,
1464 base: *const u8,
1465 len: usize,
1466 },
1467 Mmap {
1473 map: std::sync::Arc<memmap2::Mmap>,
1474 file: std::sync::Arc<std::fs::File>,
1477 off: usize,
1479 len: usize,
1480 },
1481}
1482unsafe impl Send for HostBuf {}
1487unsafe impl Sync for HostBuf {}
1488impl HostBuf {
1489 #[inline]
1490 pub fn as_bytes(&self) -> &[u8] {
1491 match self {
1492 HostBuf::Paged(v) => v.as_slice(),
1493 HostBuf::Pinned { base, len, .. } => unsafe { std::slice::from_raw_parts(*base, *len) },
1497 HostBuf::PinnedAlias { base, len, .. } => unsafe {
1498 std::slice::from_raw_parts(*base, *len)
1499 },
1500 HostBuf::Mmap { map, off, len, .. } => &map[*off..*off + *len],
1502 }
1503 }
1504 #[inline]
1505 pub fn len(&self) -> usize {
1506 match self {
1507 HostBuf::Paged(v) => v.len(),
1508 HostBuf::Pinned { len, .. } => *len,
1509 HostBuf::PinnedAlias { len, .. } => *len,
1510 HostBuf::Mmap { len, .. } => *len,
1511 }
1512 }
1513
1514 #[inline]
1519 pub fn advise_willneed(&self, rel_off: usize, len: usize) -> bool {
1520 let HostBuf::Mmap {
1521 map,
1522 off,
1523 len: extent,
1524 ..
1525 } = self
1526 else {
1527 return false;
1528 };
1529 if len == 0 || rel_off > *extent || len > *extent - rel_off {
1530 return false;
1531 }
1532 #[cfg(unix)]
1533 {
1534 map.advise_range(memmap2::Advice::WillNeed, *off + rel_off, len)
1535 .is_ok()
1536 }
1537 #[cfg(not(unix))]
1538 {
1539 let _ = (map, off);
1540 false
1541 }
1542 }
1543
1544 #[inline]
1545 fn expert_source(&self, rel_off: usize, len: usize) -> ExpertSource<'_> {
1546 debug_assert!(rel_off <= self.len() && len <= self.len() - rel_off);
1547 match self {
1548 HostBuf::Mmap { map, file, off, .. } => {
1549 let offset = *off + rel_off;
1550 ExpertSource::Disk {
1551 file,
1552 offset: offset as u64,
1553 len,
1554 fallback: &map[offset..offset + len],
1555 keepalive: ExpertKeepalive::Mmap(map.clone()),
1556 }
1557 }
1558 HostBuf::Pinned { slice, .. } => ExpertSource::Memory {
1559 bytes: &self.as_bytes()[rel_off..rel_off + len],
1560 keepalive: Some(ExpertKeepalive::Pinned(slice.clone())),
1561 },
1562 HostBuf::PinnedAlias { owner, .. } => ExpertSource::Memory {
1563 bytes: &self.as_bytes()[rel_off..rel_off + len],
1564 keepalive: Some(ExpertKeepalive::Buffer(owner.clone())),
1565 },
1566 HostBuf::Paged(_) => ExpertSource::Memory {
1567 bytes: &self.as_bytes()[rel_off..rel_off + len],
1568 keepalive: None,
1571 },
1572 }
1573 }
1574}
1575
1576#[allow(dead_code)]
1579pub(crate) enum ExpertKeepalive {
1580 Pinned(std::sync::Arc<cudarc::driver::PinnedHostSlice<u8>>),
1581 Buffer(std::sync::Arc<HostBuf>),
1582 Mmap(std::sync::Arc<memmap2::Mmap>),
1583}
1584
1585pub(crate) enum ExpertSource<'a> {
1588 Memory {
1589 bytes: &'a [u8],
1590 keepalive: Option<ExpertKeepalive>,
1591 },
1592 Disk {
1593 file: &'a std::sync::Arc<std::fs::File>,
1594 offset: u64,
1595 len: usize,
1596 fallback: &'a [u8],
1597 keepalive: ExpertKeepalive,
1598 },
1599}
1600
1601#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1613pub struct ExpertLayout {
1614 pub offset: usize,
1615 pub len: usize,
1616 pub qtype: i32,
1617 pub row_bytes: usize,
1618}
1619
1620fn staged_expert_qtype(ty: GgmlType) -> Option<i32> {
1621 Some(match ty {
1622 GgmlType::Q8_0 => QT_Q8_0,
1623 GgmlType::Q2_K => QT_Q2_K,
1624 GgmlType::Q4_K => QT_Q4_K,
1625 GgmlType::Q6_K => QT_Q6_K,
1626 GgmlType::Q5_K => QT_Q5_K,
1627 GgmlType::Q3_K => QT_Q3_K,
1628 GgmlType::IQ4_XS => QT_IQ4_XS,
1629 GgmlType::IQ3_S => QT_IQ3_S,
1630 GgmlType::NVFP4 => QT_NVFP4,
1631 GgmlType::F32 => QT_F32,
1632 GgmlType::BF16 => QT_BF16,
1633 _ => return None,
1634 })
1635}
1636
1637fn staged_expert_row_bytes(ty: GgmlType, in_f: usize) -> Option<usize> {
1638 staged_expert_qtype(ty)?;
1639 let (block, type_size) = ty.block_and_type_size();
1640 assert_eq!(
1641 in_f as u64 % block,
1642 0,
1643 "expert row width {in_f} is not divisible by {ty:?} block {block}"
1644 );
1645 Some((in_f as u64 / block * type_size) as usize)
1646}
1647
1648fn find_expert_disk_strict(
1649 src: &dyn TensorSource,
1650 name: &str,
1651) -> Result<Option<DiskExtent>, Box<dyn std::error::Error>> {
1652 if let Some(extent) = src.find_expert_disk(name) {
1653 return Ok(Some(extent));
1654 }
1655 if src.find_expert_mmap(name).is_some() {
1656 return Err(std::io::Error::new(
1657 std::io::ErrorKind::InvalidData,
1658 format!(
1659 "expert tensor {name} exposes legacy find_expert_mmap without find_expert_disk; \
1660 disk-backed expert loading requires a retained Arc<File>"
1661 ),
1662 )
1663 .into());
1664 }
1665 Ok(None)
1666}
1667
1668pub struct HostExps {
1669 pub bytes: HostBuf, pub tiers: Option<Vec<HostBuf>>,
1675 pub qtype: i32, pub in_f: usize, pub out_f: usize, pub n_expert: usize, pub row_bytes: usize, pub expert_stride: usize, pub layouts: Option<Vec<ExpertLayout>>,
1685 pub macros: Option<Vec<f32>>,
1690 pub fp8_blk: Option<HostExpertFp8BlockScales>,
1693}
1694
1695pub struct HostExpertFp8BlockScales {
1696 pub scales: Vec<f32>,
1697 pub rows: usize,
1698 pub cols: usize,
1699 pub expert_stride: usize,
1700}
1701
1702impl HostExps {
1703 pub fn load(e: &Engine, g: &GgufFile, name: &str) -> Result<Self, Box<dyn std::error::Error>> {
1707 Self::load_stacked_from_source(e, &GgufSource(g), name)
1708 }
1709
1710 pub fn load_stacked_split_from_source(
1717 e: &Engine,
1718 src: &dyn TensorSource,
1719 name: &str,
1720 row0: usize,
1721 row1: usize,
1722 ) -> Result<Self, Box<dyn std::error::Error>> {
1723 let t = src
1724 .find(name)
1725 .unwrap_or_else(|| panic!("missing exps tensor {name}"));
1726 assert_eq!(t.ne.len(), 3, "{name} is not 3D (ne={:?})", t.ne);
1727 let qtype = match t.ggml_type {
1728 GgmlType::Q8_0 => QT_Q8_0,
1729 GgmlType::Q4_K => QT_Q4_K,
1730 GgmlType::Q6_K => QT_Q6_K,
1731 GgmlType::Q5_K => QT_Q5_K,
1732 GgmlType::Q3_K => QT_Q3_K,
1733 GgmlType::IQ4_XS => QT_IQ4_XS,
1734 GgmlType::IQ3_S => QT_IQ3_S,
1735 GgmlType::NVFP4 => QT_NVFP4,
1736 GgmlType::Q4_0 => QT_Q4_0,
1737 other => panic!("exps {name} unsupported quant {other:?}"),
1738 };
1739 let raw: &[u8] = &t.bytes;
1740 let in_f = t.ne[0] as usize;
1741 let out_full = t.ne[1] as usize;
1742 let n_expert = t.ne[2] as usize;
1743 let full_stride = raw.len() / n_expert;
1744 let row_bytes = raw.len() / (out_full * n_expert);
1745 assert_eq!(full_stride, out_full * row_bytes, "{name} stride mismatch");
1746 let out_f = row1 - row0;
1747 let expert_stride = out_f * row_bytes;
1748 let mut buf = vec![0u8; n_expert * expert_stride];
1749 for ex in 0..n_expert {
1750 let s0 = ex * full_stride + row0 * row_bytes;
1751 buf[ex * expert_stride..(ex + 1) * expert_stride]
1752 .copy_from_slice(&raw[s0..s0 + expert_stride]);
1753 }
1754 let pinned = std::env::var("MEMRA_MOE_PINNED").is_ok()
1755 || std::env::var("MEMRA_MOE_CACHE").as_deref() != Ok("0");
1756 let bytes = if pinned {
1757 let mut pn = unsafe { e.ctx().alloc_pinned::<u8>(buf.len())? };
1758 {
1759 let dst = pn.as_mut_slice()?;
1760 dst.copy_from_slice(&buf);
1761 }
1762 let base = pn.as_ptr()? as *const u8;
1763 let len = buf.len();
1764 HostBuf::Pinned {
1765 slice: std::sync::Arc::new(pn),
1766 base,
1767 len,
1768 }
1769 } else {
1770 HostBuf::Paged(buf)
1771 };
1772 Ok(HostExps {
1773 bytes,
1774 tiers: None,
1775 qtype,
1776 in_f,
1777 out_f,
1778 n_expert,
1779 row_bytes,
1780 expert_stride,
1781 layouts: None,
1782 macros: None,
1783 fp8_blk: None,
1784 })
1785 }
1786
1787 fn stacked_macros(src: &dyn TensorSource, name: &str) -> Option<Vec<f32>> {
1793 let stem = name.strip_suffix(".weight")?;
1794 let sv = src.find(&format!("{stem}.scale"))?;
1795 if sv.ggml_type != GgmlType::F32 {
1796 return None;
1797 }
1798 let macros: Vec<f32> = sv
1799 .bytes
1800 .chunks_exact(4)
1801 .map(|c| f32::from_le_bytes(c.try_into().unwrap()))
1802 .collect();
1803 if macros.iter().all(|&m| m == 1.0) {
1804 None
1805 } else {
1806 Some(macros)
1807 }
1808 }
1809
1810 fn load_nvfp4_stacked_native(
1818 src: &dyn TensorSource,
1819 name: &str,
1820 ) -> Result<Option<Self>, Box<dyn std::error::Error>> {
1821 let Some(bank) = src.find_nvfp4_stacked_native(name) else {
1822 return Ok(None);
1823 };
1824 let (n_expert, out_f, in_f) = (bank.n_expert, bank.out_f, bank.in_f);
1825 if in_f % 64 != 0 {
1826 return Err(
1827 format!("{name} stacked NVFP4 in_features {in_f} is not 64-aligned").into(),
1828 );
1829 }
1830 let row_bytes = in_f / 64 * 36;
1831 let expert_stride = out_f * row_bytes;
1832 let total = n_expert * expert_stride;
1833 let code_stride = out_f * in_f / 2;
1834 let scale_stride = out_f * in_f / 16;
1835 let macros = bank.macros.clone();
1836 let cache_path = if let Some(dir) = src.st_dir() {
1837 let cache_dir = dir.join(".memra-repack");
1838 ensure_repack_cache_dir(&cache_dir)?;
1839 Some(cache_dir.join(format!(
1840 "{}-stacked-{n_expert}x{out_f}x{in_f}.nvfp4",
1841 name.replace(['.', '/'], "-")
1842 )))
1843 } else {
1844 None
1845 };
1846 let bytes = if let Some(cache) = cache_path.as_ref() {
1847 let fresh = repack_cache_is_fresh(cache, total);
1848 if !fresh {
1849 write_repack_cache(cache, |out| {
1850 for expert in 0..n_expert {
1851 use std::io::Write;
1852 out.write_all(&memra_gguf::nvfp4_repack::repack_modelopt_to_gguf(
1853 &bank.codes[expert * code_stride..(expert + 1) * code_stride],
1854 &bank.scales[expert * scale_stride..(expert + 1) * scale_stride],
1855 out_f,
1856 in_f,
1857 ))?;
1858 }
1859 Ok(())
1860 })?;
1861 }
1862 let file = std::sync::Arc::new(open_repack_cache(cache, false)?);
1863 let map = unsafe { memmap2::Mmap::map(file.as_ref())? };
1864 assert_eq!(map.len(), total, "repack cache {cache:?} size mismatch");
1865 let _ = memra_gguf::source::apply_expert_mmap_advice(&map);
1866 HostBuf::Mmap {
1867 map: std::sync::Arc::new(map),
1868 file,
1869 off: 0,
1870 len: total,
1871 }
1872 } else {
1873 let mut buf: Vec<u8> = Vec::with_capacity(total);
1874 for expert in 0..n_expert {
1875 buf.extend_from_slice(&memra_gguf::nvfp4_repack::repack_modelopt_to_gguf(
1876 &bank.codes[expert * code_stride..(expert + 1) * code_stride],
1877 &bank.scales[expert * scale_stride..(expert + 1) * scale_stride],
1878 out_f,
1879 in_f,
1880 ));
1881 }
1882 assert_eq!(buf.len(), total);
1883 HostBuf::Paged(buf)
1884 };
1885 let all_one = macros.iter().all(|&value| value == 1.0);
1886 Ok(Some(HostExps {
1887 bytes,
1888 tiers: None,
1889 qtype: QT_NVFP4,
1890 in_f,
1891 out_f,
1892 n_expert,
1893 row_bytes,
1894 expert_stride,
1895 layouts: None,
1896 macros: if all_one { None } else { Some(macros) },
1897 fp8_blk: None,
1898 }))
1899 }
1900
1901 fn load_fp8_stacked_native_with_policy(
1902 src: &dyn TensorSource,
1903 name: &str,
1904 native_enabled: bool,
1905 ) -> Result<Option<Self>, Box<dyn std::error::Error>> {
1906 let Some(f8) = src.find_fp8_stacked_native(name) else {
1907 return Ok(None);
1908 };
1909 if f8.scale_rows != f8.out_f.div_ceil(128) || f8.scale_cols != f8.in_f.div_ceil(128) {
1910 return Err(format!(
1911 "{name} FP8 scale geometry mismatch: got {}x{}, expected {}x{}",
1912 f8.scale_rows,
1913 f8.scale_cols,
1914 f8.out_f.div_ceil(128),
1915 f8.in_f.div_ceil(128)
1916 )
1917 .into());
1918 }
1919 if f8.bytes.iter().any(|code| code & 0x7f == 0x7f) {
1920 return Err(format!("{name} FP8 code slab contains non-finite E4M3 values").into());
1921 }
1922 let scale_stride = f8.scale_rows * f8.scale_cols;
1923 if !native_enabled {
1924 if f8.in_f % 32 != 0 {
1925 return Err(format!(
1926 "{name} FP8 rollback requires an input width divisible by 32, got {}",
1927 f8.in_f
1928 )
1929 .into());
1930 }
1931 let mut q8 = Vec::new();
1932 for expert in 0..f8.n_expert {
1933 let mut data = Vec::with_capacity(f8.out_f * f8.in_f);
1934 for output in 0..f8.out_f {
1935 let row = (expert * f8.out_f + output) * f8.in_f;
1936 for input in 0..f8.in_f {
1937 let scale = f8.scales
1938 [expert * scale_stride + (output / 128) * f8.scale_cols + input / 128];
1939 data.push(
1940 memra_gguf::nvfp4_repack::fp8_e4m3_to_f32(f8.bytes[row + input])
1941 * scale,
1942 );
1943 }
1944 }
1945 q8.extend_from_slice(&memra_gguf::nvfp4_repack::f32_to_q8_0(&data));
1946 }
1947 let row_bytes = f8.in_f / 32 * 34;
1948 let expert_stride = f8.out_f * row_bytes;
1949 assert_eq!(q8.len(), f8.n_expert * expert_stride);
1950 return Ok(Some(HostExps {
1951 bytes: HostBuf::Paged(q8),
1952 tiers: None,
1953 qtype: QT_Q8_0,
1954 in_f: f8.in_f,
1955 out_f: f8.out_f,
1956 n_expert: f8.n_expert,
1957 row_bytes,
1958 expert_stride,
1959 layouts: None,
1960 macros: None,
1961 fp8_blk: None,
1962 }));
1963 }
1964
1965 assert_eq!(
1966 f8.bytes.len(),
1967 f8.n_expert * f8.out_f * f8.in_f,
1968 "{name} FP8 code slab length mismatch"
1969 );
1970 assert_eq!(
1971 f8.scales.len(),
1972 f8.n_expert * scale_stride,
1973 "{name} FP8 scale slab length mismatch"
1974 );
1975 let expert_stride = f8.out_f * f8.in_f;
1976 let bytes = match find_expert_disk_strict(src, name)? {
1977 Some(extent) => {
1978 if extent.len != f8.bytes.len() {
1979 return Err(format!(
1980 "{name} FP8 mmap length mismatch: extent={} tensor={}",
1981 extent.len,
1982 f8.bytes.len()
1983 )
1984 .into());
1985 }
1986 let off = usize::try_from(extent.offset).map_err(|_| {
1987 format!(
1988 "{name} FP8 mmap offset {} does not fit usize",
1989 extent.offset
1990 )
1991 })?;
1992 HostBuf::Mmap {
1993 map: extent.map,
1994 file: extent.file,
1995 off,
1996 len: extent.len,
1997 }
1998 }
1999 None => HostBuf::Paged(f8.bytes.to_vec()),
2000 };
2001 Ok(Some(HostExps {
2002 bytes,
2003 tiers: None,
2004 qtype: crate::QT_F8_E4M3_BLK,
2005 in_f: f8.in_f,
2006 out_f: f8.out_f,
2007 n_expert: f8.n_expert,
2008 row_bytes: f8.in_f,
2009 expert_stride,
2010 layouts: None,
2011 macros: None,
2012 fp8_blk: Some(HostExpertFp8BlockScales {
2013 scales: f8.scales,
2014 rows: f8.scale_rows,
2015 cols: f8.scale_cols,
2016 expert_stride: scale_stride,
2017 }),
2018 }))
2019 }
2020
2021 pub fn load_stacked_from_source(
2022 e: &Engine,
2023 src: &dyn TensorSource,
2024 name: &str,
2025 ) -> Result<Self, Box<dyn std::error::Error>> {
2026 if let Some(exps) = Self::load_fp8_stacked_native_with_policy(
2027 src,
2028 name,
2029 crate::fp8_ffi::st_e4m3_blk_enabled(),
2030 )? {
2031 return Ok(exps);
2032 }
2033 if let Some(exps) = Self::load_nvfp4_stacked_native(src, name)? {
2034 return Ok(exps);
2035 }
2036
2037 let t = src
2038 .find(name)
2039 .unwrap_or_else(|| panic!("missing exps tensor {name}"));
2040 assert_eq!(
2041 t.ne.len(),
2042 3,
2043 "{name} is not a 3D stacked-expert tensor (ne={:?})",
2044 t.ne
2045 );
2046 if let Some(DiskExtent {
2056 map,
2057 file,
2058 offset,
2059 len,
2060 }) = find_expert_disk_strict(src, name)?
2061 {
2062 let off = usize::try_from(offset)
2063 .map_err(|_| format!("{name} disk offset {offset} does not fit usize"))?;
2064 let qtype = match t.ggml_type {
2065 GgmlType::Q8_0 => QT_Q8_0,
2066 GgmlType::Q4_K => QT_Q4_K,
2067 GgmlType::Q6_K => QT_Q6_K,
2068 GgmlType::Q5_K => QT_Q5_K,
2069 GgmlType::Q3_K => QT_Q3_K,
2070 GgmlType::IQ4_XS => QT_IQ4_XS,
2071 GgmlType::IQ3_S => QT_IQ3_S,
2072 GgmlType::NVFP4 => QT_NVFP4,
2073 GgmlType::Q4_0 => QT_Q4_0,
2074 other => panic!("exps {name} unsupported quant {other:?}"),
2075 };
2076 let in_f = t.ne[0] as usize;
2077 let out_f = t.ne[1] as usize;
2078 let n_expert = t.ne[2] as usize;
2079 let expert_stride = len / n_expert;
2080 let row_bytes = len / (out_f * n_expert);
2081 assert_eq!(
2082 expert_stride,
2083 out_f * row_bytes,
2084 "{name} stride mismatch: stride={expert_stride} out_f={out_f} row_bytes={row_bytes}"
2085 );
2086 assert_eq!(
2087 len,
2088 n_expert * expert_stride,
2089 "{name} mmap len != n_expert*stride"
2090 );
2091 return Ok(HostExps {
2092 bytes: HostBuf::Mmap {
2093 map,
2094 file,
2095 off,
2096 len,
2097 },
2098 tiers: None,
2099 qtype,
2100 in_f,
2101 out_f,
2102 n_expert,
2103 row_bytes,
2104 expert_stride,
2105 layouts: None,
2106 macros: Self::stacked_macros(src, name),
2107 fp8_blk: None,
2108 });
2109 }
2110 let raw: &[u8] = &t.bytes;
2111 let qtype = match t.ggml_type {
2113 GgmlType::Q8_0 => QT_Q8_0,
2114 GgmlType::Q4_K => QT_Q4_K,
2115 GgmlType::Q6_K => QT_Q6_K,
2116 GgmlType::Q5_K => QT_Q5_K,
2117 GgmlType::Q3_K => QT_Q3_K,
2118 GgmlType::IQ4_XS => QT_IQ4_XS,
2119 GgmlType::IQ3_S => QT_IQ3_S,
2120 GgmlType::NVFP4 => QT_NVFP4,
2121 GgmlType::Q4_0 => QT_Q4_0,
2122 other => panic!("exps {name} unsupported quant {other:?}"),
2123 };
2124 let in_f = t.ne[0] as usize;
2125 let out_f = t.ne[1] as usize;
2126 let n_expert = t.ne[2] as usize;
2127 let expert_stride = raw.len() / n_expert;
2130 let row_bytes = raw.len() / (out_f * n_expert);
2131 assert_eq!(
2133 expert_stride,
2134 out_f * row_bytes,
2135 "{name} stride mismatch: stride={expert_stride} out_f={out_f} row_bytes={row_bytes}"
2136 );
2137
2138 let pinned = std::env::var("MEMRA_MOE_PINNED").is_ok()
2139 || std::env::var("MEMRA_MOE_CACHE").as_deref() != Ok("0");
2140 let bytes = if pinned {
2141 let mut p = unsafe { e.ctx().alloc_pinned::<u8>(raw.len())? };
2143 {
2144 let dst = p.as_mut_slice()?;
2145 dst.copy_from_slice(raw);
2146 }
2147 let base = p.as_ptr()? as *const u8; let len = raw.len();
2149 HostBuf::Pinned {
2150 slice: std::sync::Arc::new(p),
2151 base,
2152 len,
2153 }
2154 } else {
2155 HostBuf::Paged(raw.to_vec())
2156 };
2157 Ok(HostExps {
2158 bytes,
2159 tiers: None,
2160 qtype,
2161 in_f,
2162 out_f,
2163 n_expert,
2164 row_bytes,
2165 expert_stride,
2166 layouts: None,
2167 macros: Self::stacked_macros(src, name),
2168 fp8_blk: None,
2169 })
2170 }
2171
2172 pub fn load_tiered(
2181 e: &Engine,
2182 g: &GgufFile,
2183 name: &str,
2184 ctx: &mut crate::spill::SpillCtx,
2185 ) -> Result<Self, Box<dyn std::error::Error>> {
2186 let t = g
2187 .find(name)
2188 .unwrap_or_else(|| panic!("missing exps tensor {name}"));
2189 assert_eq!(
2190 t.ne.len(),
2191 3,
2192 "{name} is not a 3D stacked-expert tensor (ne={:?})",
2193 t.ne
2194 );
2195 let raw = g.tensor_data(t);
2196 let qtype = match t.ggml_type {
2197 GgmlType::Q8_0 => QT_Q8_0,
2198 GgmlType::Q4_K => QT_Q4_K,
2199 GgmlType::Q6_K => QT_Q6_K,
2200 GgmlType::Q5_K => QT_Q5_K,
2201 GgmlType::Q3_K => QT_Q3_K,
2202 GgmlType::IQ4_XS => QT_IQ4_XS,
2203 GgmlType::IQ3_S => QT_IQ3_S,
2204 GgmlType::NVFP4 => QT_NVFP4,
2205 GgmlType::Q4_0 => QT_Q4_0,
2206 other => panic!("exps {name} unsupported quant {other:?}"),
2207 };
2208 let in_f = t.ne[0] as usize;
2209 let out_f = t.ne[1] as usize;
2210 let n_expert = t.ne[2] as usize;
2211 let expert_stride = raw.len() / n_expert;
2212 let row_bytes = raw.len() / (out_f * n_expert);
2213 assert_eq!(
2214 expert_stride,
2215 out_f * row_bytes,
2216 "{name} stride mismatch: stride={expert_stride} out_f={out_f} row_bytes={row_bytes}"
2217 );
2218
2219 let (file_start, _file_end) = g.tensor_file_range(t);
2223
2224 let mut tiers = Vec::with_capacity(n_expert);
2227 for ex in 0..n_expert {
2228 let blk = &raw[ex * expert_stride..(ex + 1) * expert_stride];
2229 let file_off = file_start + ex * expert_stride;
2230 tiers.push(crate::spill::place_expert(ctx, e, blk, file_off, t.shard)?);
2231 }
2232 Ok(HostExps {
2233 bytes: HostBuf::Paged(Vec::new()), tiers: Some(tiers),
2235 qtype,
2236 in_f,
2237 out_f,
2238 n_expert,
2239 row_bytes,
2240 expert_stride,
2241 layouts: None,
2242 macros: Self::stacked_macros(&GgufSource(g), name),
2243 fp8_blk: None,
2244 })
2245 }
2246
2247 pub fn load_from_source(
2262 e: &Engine,
2263 src: &dyn TensorSource,
2264 ggml_exps_name: &str,
2265 n_expert: usize,
2266 ) -> Result<Self, Box<dyn std::error::Error>> {
2267 let rest = ggml_exps_name
2269 .strip_prefix("blk.")
2270 .unwrap_or_else(|| panic!("not a blk.* name: {ggml_exps_name}"));
2271 let (il_s, suffix) = rest.split_once('.').unwrap();
2272 let il: u32 = il_s.parse().unwrap();
2273 let proj = match suffix {
2274 "ffn_gate_exps.weight" => "gate",
2275 "ffn_up_exps.weight" => "up",
2276 "ffn_down_exps.weight" => "down",
2277 other => panic!("not a *_exps suffix: {other}"),
2278 };
2279
2280 let mut signatures = Vec::with_capacity(n_expert);
2284 let active = src.active_experts(il);
2285 for ex in 0..n_expert {
2286 if active.is_some_and(|mask| !mask[ex]) {
2287 signatures.push((i32::MIN, 0));
2288 continue;
2289 }
2290 let name = format!("blk.{il}.ffn_{proj}_exps.{ex}.weight");
2291 if let Some(nv) = src.find_nvfp4_native(&name) {
2292 signatures.push((QT_NVFP4, nv.in_f / 64 * 36));
2293 } else {
2294 let v = src
2295 .find(&name)
2296 .unwrap_or_else(|| panic!("missing expert tensor {name}"));
2297 let in_f = v.ne[0] as usize;
2298 signatures.push(match staged_expert_row_bytes(v.ggml_type, in_f) {
2299 Some(row_bytes) => (staged_expert_qtype(v.ggml_type).unwrap(), row_bytes),
2300 None => (QT_F32, in_f * 4),
2301 });
2302 }
2303 }
2304 let mixed_layout = signatures.windows(2).any(|pair| pair[0] != pair[1]);
2305 if src.preserve_expert_encodings() && !mixed_layout {
2306 if let Some(uniform) = Self::load_uniform_mmap_from_source(src, il, proj, n_expert)? {
2307 return Ok(uniform);
2308 }
2309 }
2310 if src.preserve_expert_encodings() || mixed_layout {
2311 return Self::load_mixed_from_source(src, il, proj, n_expert);
2312 }
2313
2314 {
2321 let name0 = format!("blk.{il}.ffn_{proj}_exps.0.weight");
2322 if let Some(nv0) = src.find_nvfp4_native(&name0) {
2323 let (in_f, out_f) = (nv0.in_f, nv0.out_f);
2324 let row_bytes = in_f / 64 * 36;
2325 let expert_stride = out_f * row_bytes;
2326 let disk = std::env::var("MEMRA_ST_REPACK_DISK")
2333 .map(|v| v != "0")
2334 .unwrap_or(true)
2335 && src.st_dir().is_some();
2336 let cache_path = if let Some(dir) = src.st_dir() {
2337 let cache_dir = dir.join(".memra-repack");
2338 ensure_repack_cache_dir(&cache_dir)?;
2339 Some(cache_dir.join(format!("blk{il}-{proj}-{n_expert}x{out_f}x{in_f}.nvfp4")))
2340 } else {
2341 None
2342 };
2343 let total = n_expert * expert_stride;
2344 let mut macros = vec![1.0f32; n_expert];
2345 let read_macros = |macros: &mut Vec<f32>| {
2346 for ex in 0..n_expert {
2347 let stem = format!("blk.{il}.ffn_{proj}_exps.{ex}");
2348 if let Some(sv) = src.find(&format!("{stem}.scale")) {
2349 macros[ex] = f32::from_le_bytes(sv.bytes[..4].try_into().unwrap());
2350 }
2351 }
2352 };
2353 let bytes = if disk {
2354 let cp = cache_path.as_ref().unwrap();
2355 let fresh = repack_cache_is_fresh(cp, total);
2356 if !fresh {
2357 write_repack_cache(cp, |out| {
2359 for ex in 0..n_expert {
2360 use std::io::Write;
2361 let name = format!("blk.{il}.ffn_{proj}_exps.{ex}.weight");
2362 let nv = src.find_nvfp4_native(&name).unwrap_or_else(|| {
2363 panic!("expert {name} lost NVFP4-native mid-gather")
2364 });
2365 assert_eq!(
2366 (nv.in_f, nv.out_f),
2367 (in_f, out_f),
2368 "expert {ex} dims ({},{}) != expert 0 ({in_f},{out_f})",
2369 nv.in_f,
2370 nv.out_f
2371 );
2372 out.write_all(&memra_gguf::nvfp4_repack::repack_modelopt_to_gguf(
2373 nv.wbytes, nv.wscale, out_f, in_f,
2374 ))?;
2375 }
2376 Ok(())
2377 })?;
2378 }
2379 read_macros(&mut macros);
2380 let file = std::sync::Arc::new(open_repack_cache(cp, false)?);
2381 let map = unsafe { memmap2::Mmap::map(file.as_ref())? };
2382 assert_eq!(map.len(), total, "repack cache {cp:?} size mismatch");
2383 let _ = memra_gguf::source::apply_expert_mmap_advice(&map);
2386 let map = std::sync::Arc::new(map);
2387 let tiers = if std::env::var("MEMRA_ST_PINNED")
2400 .map(|v| v == "1")
2401 .unwrap_or(false)
2402 {
2403 static PIN_BUDGET: std::sync::OnceLock<std::sync::Mutex<usize>> =
2404 std::sync::OnceLock::new();
2405 let budget = PIN_BUDGET.get_or_init(|| {
2406 let b = crate::spill::MemBudget::probe(e)
2407 .map(|b| b.free_pinnable_ram)
2408 .unwrap_or(0);
2409 eprintln!("[st-spill] free_pinnable_ram={} MiB", b >> 20);
2410 std::sync::Mutex::new(b)
2411 });
2412 let mut rem = budget.lock().unwrap();
2413 let n_pin = (*rem / expert_stride).min(n_expert);
2417 if n_pin == 0 {
2418 None
2419 } else {
2420 let slab_len = n_pin * expert_stride;
2421 let mut pn = unsafe { e.ctx().alloc_pinned::<u8>(slab_len)? };
2422 {
2423 let dst = pn.as_mut_slice()?;
2424 dst.copy_from_slice(&map[..slab_len]);
2425 }
2426 let base = pn.as_ptr()? as *const u8;
2427 *rem -= slab_len;
2428 let slab = std::sync::Arc::new(HostBuf::Pinned {
2429 slice: std::sync::Arc::new(pn),
2430 base,
2431 len: slab_len,
2432 });
2433 let mut tiers: Vec<HostBuf> = Vec::with_capacity(n_expert);
2434 for ex in 0..n_expert {
2435 let off = ex * expert_stride;
2436 if ex < n_pin {
2437 tiers.push(HostBuf::PinnedAlias {
2438 owner: slab.clone(),
2439 base: unsafe { base.add(off) },
2440 len: expert_stride,
2441 });
2442 } else {
2443 tiers.push(HostBuf::Mmap {
2444 map: map.clone(),
2445 file: file.clone(),
2446 off,
2447 len: expert_stride,
2448 });
2449 }
2450 }
2451 Some(tiers)
2452 }
2453 } else {
2454 None
2455 };
2456 if let Some(tiers) = tiers {
2457 let all_one = macros.iter().all(|&m| m == 1.0);
2458 return Ok(HostExps {
2459 bytes: HostBuf::Mmap {
2460 map,
2461 file,
2462 off: 0,
2463 len: total,
2464 },
2465 tiers: Some(tiers),
2466 qtype: QT_NVFP4,
2467 in_f,
2468 out_f,
2469 n_expert,
2470 row_bytes,
2471 expert_stride,
2472 layouts: None,
2473 macros: if all_one { None } else { Some(macros) },
2474 fp8_blk: None,
2475 });
2476 }
2477 HostBuf::Mmap {
2478 map,
2479 file,
2480 off: 0,
2481 len: total,
2482 }
2483 } else {
2484 let mut buf: Vec<u8> = Vec::with_capacity(total);
2485 for ex in 0..n_expert {
2486 let name = format!("blk.{il}.ffn_{proj}_exps.{ex}.weight");
2487 let nv = src.find_nvfp4_native(&name).unwrap_or_else(|| {
2488 panic!("expert {name} lost NVFP4-native mid-gather")
2489 });
2490 assert_eq!(
2491 (nv.in_f, nv.out_f),
2492 (in_f, out_f),
2493 "expert {ex} dims ({},{}) != expert 0 ({in_f},{out_f})",
2494 nv.in_f,
2495 nv.out_f
2496 );
2497 buf.extend_from_slice(&memra_gguf::nvfp4_repack::repack_modelopt_to_gguf(
2498 nv.wbytes, nv.wscale, out_f, in_f,
2499 ));
2500 }
2501 assert_eq!(buf.len(), total);
2502 read_macros(&mut macros);
2503 let pinned = std::env::var("MEMRA_MOE_PINNED").is_ok()
2504 || std::env::var("MEMRA_MOE_CACHE").as_deref() != Ok("0");
2505 if pinned {
2506 let mut p = unsafe { e.ctx().alloc_pinned::<u8>(buf.len())? };
2507 {
2508 let dst = p.as_mut_slice()?;
2509 dst.copy_from_slice(&buf);
2510 }
2511 let base = p.as_ptr()? as *const u8;
2512 let len = buf.len();
2513 HostBuf::Pinned {
2514 slice: std::sync::Arc::new(p),
2515 base,
2516 len,
2517 }
2518 } else {
2519 HostBuf::Paged(buf)
2520 }
2521 };
2522 let all_one = macros.iter().all(|&m| m == 1.0);
2523 return Ok(HostExps {
2524 bytes,
2525 tiers: None,
2526 qtype: QT_NVFP4,
2527 in_f,
2528 out_f,
2529 n_expert,
2530 row_bytes,
2531 expert_stride,
2532 layouts: None,
2533 macros: if all_one { None } else { Some(macros) },
2534 fp8_blk: None,
2535 });
2536 }
2537 }
2538
2539 let mut buf: Vec<u8> = Vec::new();
2541 let mut in_f = 0usize;
2542 let mut out_f = 0usize;
2543 for ex in 0..n_expert {
2544 let name = format!("blk.{il}.ffn_{proj}_exps.{ex}.weight");
2546 let v = src
2547 .find(&name)
2548 .unwrap_or_else(|| panic!("missing expert tensor {name}"));
2549 assert_eq!(v.ne.len(), 2, "expert {name} is not 2D (ne={:?})", v.ne);
2550 let (cur_in, cur_out) = (v.ne[0] as usize, v.ne[1] as usize);
2551 if ex == 0 {
2552 in_f = cur_in;
2553 out_f = cur_out;
2554 } else {
2555 assert_eq!(
2556 (cur_in, cur_out),
2557 (in_f, out_f),
2558 "expert {ex} dims {:?} != expert 0 [{in_f},{out_f}]",
2559 (cur_in, cur_out)
2560 );
2561 }
2562 let n = cur_in * cur_out;
2565 let f32v = dequant::dequantize(v.ggml_type, &v.bytes, n);
2566 buf.reserve(n * 4);
2567 for f in &f32v {
2568 buf.extend_from_slice(&f.to_le_bytes());
2569 }
2570 }
2571 let row_bytes = in_f * 4; let expert_stride = out_f * row_bytes;
2573 assert_eq!(
2574 buf.len(),
2575 n_expert * expert_stride,
2576 "{ggml_exps_name} gather size {} != n_expert*stride {}",
2577 buf.len(),
2578 n_expert * expert_stride
2579 );
2580 assert_eq!(
2582 expert_stride,
2583 out_f * row_bytes,
2584 "{ggml_exps_name} stride mismatch: stride={expert_stride} out_f={out_f} row_bytes={row_bytes}"
2585 );
2586
2587 let pinned = std::env::var("MEMRA_MOE_PINNED").is_ok()
2589 || std::env::var("MEMRA_MOE_CACHE").as_deref() != Ok("0");
2590 let bytes = if pinned {
2591 let mut p = unsafe { e.ctx().alloc_pinned::<u8>(buf.len())? };
2592 {
2593 let dst = p.as_mut_slice()?;
2594 dst.copy_from_slice(&buf);
2595 }
2596 let base = p.as_ptr()? as *const u8;
2597 let len = buf.len();
2598 HostBuf::Pinned {
2599 slice: std::sync::Arc::new(p),
2600 base,
2601 len,
2602 }
2603 } else {
2604 HostBuf::Paged(buf)
2605 };
2606 Ok(HostExps {
2607 bytes,
2608 tiers: None,
2609 qtype: QT_F32,
2610 in_f,
2611 out_f,
2612 n_expert,
2613 row_bytes,
2614 expert_stride,
2615 layouts: None,
2616 macros: None,
2617 fp8_blk: None,
2618 })
2619 }
2620
2621 fn load_uniform_mmap_from_source(
2626 src: &dyn TensorSource,
2627 il: u32,
2628 proj: &str,
2629 n_expert: usize,
2630 ) -> Result<Option<Self>, Box<dyn std::error::Error>> {
2631 if src
2632 .active_experts(il)
2633 .is_some_and(|mask| mask.iter().any(|&active| !active))
2634 {
2635 return Ok(None);
2636 }
2637 let mut first_map = None;
2638 let mut first_file = None;
2639 let mut base_offset = 0u64;
2640 let mut expert_stride = 0usize;
2641 let mut in_f = 0usize;
2642 let mut out_f = 0usize;
2643 let mut qtype = 0i32;
2644 let mut row_bytes = 0usize;
2645 let mut macros = vec![1.0f32; n_expert];
2646 for ex in 0..n_expert {
2647 let stem = format!("blk.{il}.ffn_{proj}_exps.{ex}");
2648 let name = format!("{stem}.weight");
2649 let Some(DiskExtent {
2650 map,
2651 file,
2652 offset,
2653 len,
2654 }) = find_expert_disk_strict(src, &name)?
2655 else {
2656 return Ok(None);
2657 };
2658 let Some(v) = src.find(&name) else {
2659 return Ok(None);
2660 };
2661 if v.ne.len() != 2 {
2662 return Ok(None);
2663 }
2664 let (cur_in, cur_out) = (v.ne[0] as usize, v.ne[1] as usize);
2665 let Some(cur_row_bytes) = staged_expert_row_bytes(v.ggml_type, cur_in) else {
2666 return Ok(None);
2667 };
2668 let cur_qtype = staged_expert_qtype(v.ggml_type).unwrap();
2669 if ex == 0 {
2670 base_offset = offset;
2671 expert_stride = len;
2672 in_f = cur_in;
2673 out_f = cur_out;
2674 qtype = cur_qtype;
2675 row_bytes = cur_row_bytes;
2676 first_map = Some(map);
2677 first_file = Some(file);
2678 } else if !std::sync::Arc::ptr_eq(first_map.as_ref().unwrap(), &map)
2679 || !std::sync::Arc::ptr_eq(first_file.as_ref().unwrap(), &file)
2680 || offset != base_offset + (ex * expert_stride) as u64
2681 || len != expert_stride
2682 || (cur_in, cur_out, cur_qtype, cur_row_bytes) != (in_f, out_f, qtype, row_bytes)
2683 {
2684 return Ok(None);
2685 }
2686 if let Some(scale) = src.find(&format!("{stem}.scale")) {
2687 macros[ex] = f32::from_le_bytes(scale.bytes[..4].try_into().unwrap());
2688 }
2689 }
2690 assert_eq!(expert_stride, out_f * row_bytes);
2691 let total = n_expert * expert_stride;
2692 let off = usize::try_from(base_offset)
2693 .map_err(|_| format!("uniform expert disk offset {base_offset} does not fit usize"))?;
2694 let all_one = macros.iter().all(|&scale| scale == 1.0);
2695 Ok(Some(HostExps {
2696 bytes: HostBuf::Mmap {
2697 map: first_map.unwrap(),
2698 file: first_file.unwrap(),
2699 off,
2700 len: total,
2701 },
2702 tiers: None,
2703 qtype,
2704 in_f,
2705 out_f,
2706 n_expert,
2707 row_bytes,
2708 expert_stride,
2709 layouts: None,
2710 macros: if all_one { None } else { Some(macros) },
2711 fp8_blk: None,
2712 }))
2713 }
2714
2715 fn load_mixed_from_source(
2716 src: &dyn TensorSource,
2717 il: u32,
2718 proj: &str,
2719 n_expert: usize,
2720 ) -> Result<Self, Box<dyn std::error::Error>> {
2721 let mut tiers = Vec::with_capacity(n_expert);
2722 let mut layouts = Vec::with_capacity(n_expert);
2723 let mut macros = vec![1.0f32; n_expert];
2724 let mut in_f = 0usize;
2725 let mut out_f = 0usize;
2726 let active = src.active_experts(il);
2727 let mut first_active = None;
2728
2729 for ex in 0..n_expert {
2730 if active.is_some_and(|mask| !mask[ex]) {
2731 layouts.push(ExpertLayout {
2732 offset: 0,
2733 len: 0,
2734 qtype: QT_F32,
2735 row_bytes: 0,
2736 });
2737 tiers.push(HostBuf::Paged(Vec::new()));
2738 continue;
2739 }
2740 let name = format!("blk.{il}.ffn_{proj}_exps.{ex}.weight");
2741 let stem = format!("blk.{il}.ffn_{proj}_exps.{ex}");
2742 if let Some(scale) = src.find(&format!("{stem}.scale")) {
2743 macros[ex] = f32::from_le_bytes(scale.bytes[..4].try_into().unwrap());
2744 }
2745 let (host, byte_len, qtype, row_bytes, cur_in, cur_out) = if let Some(DiskExtent {
2746 map,
2747 file,
2748 offset,
2749 len,
2750 }) =
2751 find_expert_disk_strict(src, &name)?
2752 {
2753 let v = src
2754 .find(&name)
2755 .unwrap_or_else(|| panic!("missing expert tensor {name}"));
2756 assert_eq!(v.ne.len(), 2, "expert {name} is not 2D (ne={:?})", v.ne);
2757 let (cur_in, cur_out) = (v.ne[0] as usize, v.ne[1] as usize);
2758 let row_bytes = staged_expert_row_bytes(v.ggml_type, cur_in).ok_or_else(|| {
2759 format!("mmap expert {name} has unsupported qtype {:?}", v.ggml_type)
2760 })?;
2761 let off = usize::try_from(offset).map_err(|_| {
2762 format!("expert {name} disk offset {offset} does not fit usize")
2763 })?;
2764 (
2765 HostBuf::Mmap {
2766 map,
2767 file,
2768 off,
2769 len,
2770 },
2771 len,
2772 staged_expert_qtype(v.ggml_type).unwrap(),
2773 row_bytes,
2774 cur_in,
2775 cur_out,
2776 )
2777 } else if let Some(nv) = src.find_nvfp4_native(&name) {
2778 let bytes = memra_gguf::nvfp4_repack::repack_modelopt_to_gguf(
2779 nv.wbytes, nv.wscale, nv.out_f, nv.in_f,
2780 );
2781 let row_bytes = nv.in_f / 64 * 36;
2782 let byte_len = bytes.len();
2783 (
2784 HostBuf::Paged(bytes),
2785 byte_len,
2786 QT_NVFP4,
2787 row_bytes,
2788 nv.in_f,
2789 nv.out_f,
2790 )
2791 } else {
2792 let v = src
2793 .find(&name)
2794 .unwrap_or_else(|| panic!("missing expert tensor {name}"));
2795 assert_eq!(v.ne.len(), 2, "expert {name} is not 2D (ne={:?})", v.ne);
2796 let (cur_in, cur_out) = (v.ne[0] as usize, v.ne[1] as usize);
2797 if let Some(row_bytes) = staged_expert_row_bytes(v.ggml_type, cur_in) {
2798 let bytes = v.bytes.into_owned();
2799 let byte_len = bytes.len();
2800 (
2801 HostBuf::Paged(bytes),
2802 byte_len,
2803 staged_expert_qtype(v.ggml_type).unwrap(),
2804 row_bytes,
2805 cur_in,
2806 cur_out,
2807 )
2808 } else {
2809 let f32v = dequant::dequantize(v.ggml_type, &v.bytes, cur_in * cur_out);
2810 let mut bytes = Vec::with_capacity(f32v.len() * 4);
2811 for f in f32v {
2812 bytes.extend_from_slice(&f.to_le_bytes());
2813 }
2814 let byte_len = bytes.len();
2815 (
2816 HostBuf::Paged(bytes),
2817 byte_len,
2818 QT_F32,
2819 cur_in * 4,
2820 cur_in,
2821 cur_out,
2822 )
2823 }
2824 };
2825
2826 if first_active.is_none() {
2827 in_f = cur_in;
2828 out_f = cur_out;
2829 first_active = Some(ex);
2830 } else {
2831 assert_eq!(
2832 (cur_in, cur_out),
2833 (in_f, out_f),
2834 "expert {ex} dims ({cur_in},{cur_out}) != first active expert ({in_f},{out_f})"
2835 );
2836 }
2837 assert_eq!(
2838 byte_len,
2839 cur_out * row_bytes,
2840 "expert {name} bytes {byte_len} != out_f*row_bytes {}",
2841 cur_out * row_bytes
2842 );
2843 layouts.push(ExpertLayout {
2844 offset: 0,
2845 len: byte_len,
2846 qtype,
2847 row_bytes,
2848 });
2849 tiers.push(host);
2850 }
2851
2852 let first = layouts[*first_active
2853 .as_ref()
2854 .expect("expert mask pruned every expert")];
2855 let expert_stride = layouts.iter().map(|layout| layout.len).max().unwrap_or(0);
2856 let all_one = macros.iter().all(|&scale| scale == 1.0);
2857 Ok(HostExps {
2858 bytes: HostBuf::Paged(Vec::new()),
2859 tiers: Some(tiers),
2860 qtype: first.qtype,
2861 in_f,
2862 out_f,
2863 n_expert,
2864 row_bytes: first.row_bytes,
2865 expert_stride,
2866 layouts: Some(layouts),
2867 macros: if all_one { None } else { Some(macros) },
2868 fp8_blk: None,
2869 })
2870 }
2871
2872 #[inline]
2876 pub fn macro_scale(&self, e: usize) -> f32 {
2877 self.macros.as_ref().map(|m| m[e]).unwrap_or(1.0)
2878 }
2879
2880 #[inline]
2881 pub fn is_uniform_layout(&self) -> bool {
2882 self.layouts.is_none()
2883 }
2884
2885 #[inline]
2886 pub fn expert_layout(&self, e: usize) -> ExpertLayout {
2887 debug_assert!(
2888 e < self.n_expert,
2889 "expert index {e} >= n_expert {}",
2890 self.n_expert
2891 );
2892 self.layouts
2893 .as_ref()
2894 .map(|layouts| layouts[e])
2895 .unwrap_or(ExpertLayout {
2896 offset: e * self.expert_stride,
2897 len: self.expert_stride,
2898 qtype: self.qtype,
2899 row_bytes: self.row_bytes,
2900 })
2901 }
2902
2903 #[inline]
2904 pub fn max_expert_bytes(&self) -> usize {
2905 self.layouts
2906 .as_ref()
2907 .and_then(|layouts| layouts.iter().map(|layout| layout.len).max())
2908 .unwrap_or(self.expert_stride)
2909 }
2910
2911 #[inline]
2913 pub fn expert_bytes(&self, e: usize) -> &[u8] {
2914 let layout = self.expert_layout(e);
2915 match &self.tiers {
2916 Some(tiers) => {
2917 debug_assert_eq!(tiers[e].len(), layout.len);
2918 tiers[e].as_bytes()
2919 }
2920 None => &self.bytes.as_bytes()[layout.offset..layout.offset + layout.len],
2921 }
2922 }
2923
2924 #[inline]
2928 pub(crate) fn expert_source(&self, e: usize) -> ExpertSource<'_> {
2929 let layout = self.expert_layout(e);
2930 match &self.tiers {
2931 Some(tiers) => tiers[e].expert_source(0, layout.len),
2932 None => self.bytes.expert_source(layout.offset, layout.len),
2933 }
2934 }
2935
2936 #[inline]
2940 pub fn prefetch_expert_pages(&self, e: usize) -> bool {
2941 let layout = self.expert_layout(e);
2942 match &self.tiers {
2943 Some(tiers) => tiers[e].advise_willneed(0, layout.len),
2944 None => self.bytes.advise_willneed(layout.offset, layout.len),
2945 }
2946 }
2947}
2948
2949#[cfg(test)]
2950mod tests {
2951 use super::{
2952 ExpertKeepalive, ExpertSource, HostBuf, HostExps, QT_BF16, QT_NVFP4, QT_Q2_K, QT_Q4_K,
2953 ensure_repack_cache_dir, open_repack_cache, repack_cache_is_fresh, repack_nvfp4_split,
2954 unpack_nvfp4_split, write_repack_cache,
2955 };
2956 use memra_gguf::nvfp4_repack::{repack_modelopt_to_gguf, repack_modelopt_to_split};
2957 use memra_gguf::source::{DiskExtent, Fp8StackedNative, TensorSource, TensorView};
2958 use memra_gguf::{GgmlType, config::ModelConfig};
2959 use std::borrow::Cow;
2960
2961 #[cfg(unix)]
2962 #[test]
2963 fn repack_cache_refuses_symlinked_directory_and_file() {
2964 use std::os::unix::fs::symlink;
2965
2966 let root = std::env::temp_dir().join(format!("memra-repack-links-{}", std::process::id()));
2967 std::fs::create_dir_all(&root).unwrap();
2968 let target_dir = root.join("target-dir");
2969 std::fs::create_dir(&target_dir).unwrap();
2970 let cache_dir = root.join(".memra-repack");
2971 symlink(&target_dir, &cache_dir).unwrap();
2972 let error = ensure_repack_cache_dir(&cache_dir).unwrap_err();
2973 assert_eq!(error.kind(), std::io::ErrorKind::InvalidData);
2974
2975 std::fs::remove_file(&cache_dir).unwrap();
2976 std::fs::create_dir(&cache_dir).unwrap();
2977 let target = root.join("outside.bin");
2978 std::fs::write(&target, b"keep").unwrap();
2979 let cache_file = cache_dir.join("artifact.nvfp4");
2980 symlink(&target, &cache_file).unwrap();
2981 assert!(!repack_cache_is_fresh(&cache_file, 4));
2982 let error = open_repack_cache(&cache_file, true).unwrap_err();
2983 assert_ne!(error.kind(), std::io::ErrorKind::NotFound);
2984 assert_eq!(std::fs::read(&target).unwrap(), b"keep");
2985
2986 let hardlink = cache_dir.join("hardlink.nvfp4");
2987 std::fs::hard_link(&target, &hardlink).unwrap();
2988 let error = write_repack_cache(&hardlink, |out| {
2989 use std::io::Write;
2990 out.write_all(b"replacement")
2991 })
2992 .unwrap_err();
2993 assert_eq!(error.kind(), std::io::ErrorKind::InvalidData);
2994 assert_eq!(std::fs::read(&target).unwrap(), b"keep");
2995 std::fs::remove_dir_all(root).ok();
2996 }
2997
2998 struct MixedExpertSource {
2999 bf16: Vec<u8>,
3000 q4k: Vec<u8>,
3001 }
3002
3003 impl TensorSource for MixedExpertSource {
3004 fn config(&self) -> ModelConfig {
3005 panic!("unused by HostExps mixed-loader test")
3006 }
3007
3008 fn find(&self, name: &str) -> Option<TensorView<'_>> {
3009 let (bytes, ggml_type) = if name == "blk.0.ffn_gate_exps.0.weight" {
3010 (&self.bf16, GgmlType::BF16)
3011 } else if name == "blk.0.ffn_gate_exps.1.weight" {
3012 (&self.q4k, GgmlType::Q4_K)
3013 } else {
3014 return None;
3015 };
3016 Some(TensorView {
3017 bytes: Cow::Borrowed(bytes),
3018 ggml_type,
3019 ne: vec![256, 2],
3020 })
3021 }
3022 }
3023
3024 struct PrunedExpertSource {
3025 q2k: Vec<u8>,
3026 nvfp4: Vec<u8>,
3027 active: Vec<bool>,
3028 }
3029
3030 struct MmapExpertSource {
3031 file: std::sync::Arc<std::fs::File>,
3032 map: std::sync::Arc<memmap2::Mmap>,
3033 base_offset: usize,
3034 expert_len: usize,
3035 }
3036
3037 struct LegacyMmapExpertSource {
3038 map: std::sync::Arc<memmap2::Mmap>,
3039 expert_len: usize,
3040 }
3041
3042 struct StackedFp8Source {
3043 file: std::sync::Arc<std::fs::File>,
3044 map: std::sync::Arc<memmap2::Mmap>,
3045 offset: usize,
3046 len: usize,
3047 scales: Vec<f32>,
3048 }
3049
3050 impl TensorSource for StackedFp8Source {
3051 fn config(&self) -> ModelConfig {
3052 panic!("unused by stacked FP8 ownership test")
3053 }
3054
3055 fn find(&self, _name: &str) -> Option<TensorView<'_>> {
3056 None
3057 }
3058
3059 fn find_fp8_stacked_native(&self, name: &str) -> Option<Fp8StackedNative<'_>> {
3060 (name == "blk.0.ffn_gate_exps.weight").then(|| Fp8StackedNative {
3061 bytes: &self.map[self.offset..self.offset + self.len],
3062 scales: self.scales.clone(),
3063 n_expert: 2,
3064 out_f: 2,
3065 in_f: 32,
3066 scale_rows: 1,
3067 scale_cols: 1,
3068 })
3069 }
3070
3071 fn find_expert_disk(&self, name: &str) -> Option<DiskExtent> {
3072 (name == "blk.0.ffn_gate_exps.weight").then(|| DiskExtent {
3073 map: self.map.clone(),
3074 file: self.file.clone(),
3075 offset: self.offset as u64,
3076 len: self.len,
3077 })
3078 }
3079 }
3080
3081 impl TensorSource for MmapExpertSource {
3082 fn config(&self) -> ModelConfig {
3083 panic!("unused by HostExps mmap-loader test")
3084 }
3085 fn preserve_expert_encodings(&self) -> bool {
3086 true
3087 }
3088 fn find(&self, name: &str) -> Option<TensorView<'_>> {
3089 let ex = match name {
3090 "blk.0.ffn_gate_exps.0.weight" => 0,
3091 "blk.0.ffn_gate_exps.1.weight" => 1,
3092 _ => return None,
3093 };
3094 let off = self.base_offset + ex * self.expert_len;
3095 Some(TensorView {
3096 bytes: Cow::Borrowed(&self.map[off..off + self.expert_len]),
3097 ggml_type: GgmlType::Q2_K,
3098 ne: vec![256, 2],
3099 })
3100 }
3101 fn find_expert_disk(&self, name: &str) -> Option<DiskExtent> {
3102 let ex = match name {
3103 "blk.0.ffn_gate_exps.0.weight" => 0,
3104 "blk.0.ffn_gate_exps.1.weight" => 1,
3105 _ => return None,
3106 };
3107 Some(DiskExtent {
3108 map: self.map.clone(),
3109 file: self.file.clone(),
3110 offset: (self.base_offset + ex * self.expert_len) as u64,
3111 len: self.expert_len,
3112 })
3113 }
3114 }
3115
3116 impl TensorSource for LegacyMmapExpertSource {
3117 fn config(&self) -> ModelConfig {
3118 panic!("unused by legacy mmap guard test")
3119 }
3120 fn preserve_expert_encodings(&self) -> bool {
3121 true
3122 }
3123 fn find(&self, name: &str) -> Option<TensorView<'_>> {
3124 let ex = match name {
3125 "blk.0.ffn_gate_exps.0.weight" => 0,
3126 "blk.0.ffn_gate_exps.1.weight" => 1,
3127 _ => return None,
3128 };
3129 let off = ex * self.expert_len;
3130 Some(TensorView {
3131 bytes: Cow::Borrowed(&self.map[off..off + self.expert_len]),
3132 ggml_type: GgmlType::Q2_K,
3133 ne: vec![256, 2],
3134 })
3135 }
3136 fn find_expert_mmap(
3137 &self,
3138 name: &str,
3139 ) -> Option<(std::sync::Arc<memmap2::Mmap>, usize, usize)> {
3140 let ex = match name {
3141 "blk.0.ffn_gate_exps.0.weight" => 0,
3142 "blk.0.ffn_gate_exps.1.weight" => 1,
3143 _ => return None,
3144 };
3145 Some((self.map.clone(), ex * self.expert_len, self.expert_len))
3146 }
3147 }
3148
3149 impl TensorSource for PrunedExpertSource {
3150 fn config(&self) -> ModelConfig {
3151 panic!("unused by HostExps pruned-loader test")
3152 }
3153 fn active_experts(&self, layer: u32) -> Option<&[bool]> {
3154 (layer == 0).then_some(self.active.as_slice())
3155 }
3156 fn find(&self, name: &str) -> Option<TensorView<'_>> {
3157 let (bytes, ggml_type) = match name {
3158 "blk.0.ffn_gate_exps.0.weight" => (&self.q2k, GgmlType::Q2_K),
3159 "blk.0.ffn_gate_exps.2.weight" => (&self.nvfp4, GgmlType::NVFP4),
3160 _ => return None,
3161 };
3162 Some(TensorView {
3163 bytes: Cow::Borrowed(bytes),
3164 ggml_type,
3165 ne: vec![256, 2],
3166 })
3167 }
3168 }
3169
3170 #[test]
3171 fn stacked_fp8_experts_retain_owned_mmap_and_scale_geometry() {
3172 let path = std::env::temp_dir().join(format!("memra-stacked-fp8-{}", std::process::id()));
3173 let offset = 11usize;
3174 let len = 2 * 2 * 32;
3175 let mut file_bytes = vec![0xA5; offset];
3176 file_bytes.extend((0..len).map(|i| (i % 127) as u8));
3177 std::fs::write(&path, &file_bytes).unwrap();
3178 let file = std::sync::Arc::new(std::fs::File::open(&path).unwrap());
3179 let map = std::sync::Arc::new(unsafe { memmap2::Mmap::map(file.as_ref()).unwrap() });
3180 let source = StackedFp8Source {
3181 file,
3182 map,
3183 offset,
3184 len,
3185 scales: vec![0.5, 0.25],
3186 };
3187
3188 let exps = HostExps::load_fp8_stacked_native_with_policy(
3189 &source,
3190 "blk.0.ffn_gate_exps.weight",
3191 true,
3192 )
3193 .unwrap()
3194 .unwrap();
3195 assert_eq!(exps.qtype, crate::QT_F8_E4M3_BLK);
3196 assert_eq!((exps.n_expert, exps.out_f, exps.in_f), (2, 2, 32));
3197 assert_eq!(exps.expert_stride, 64);
3198 assert!(matches!(exps.bytes, HostBuf::Mmap { .. }));
3199 assert_eq!(exps.expert_bytes(0), &file_bytes[offset..offset + 64]);
3200 assert_eq!(exps.expert_bytes(1), &file_bytes[offset + 64..offset + len]);
3201 let fp8 = exps.fp8_blk.as_ref().unwrap();
3202 assert_eq!((fp8.rows, fp8.cols, fp8.expert_stride), (1, 1, 1));
3203 assert_eq!(fp8.scales, vec![0.5, 0.25]);
3204
3205 drop(source);
3206 assert_eq!(exps.expert_bytes(1), &file_bytes[offset + 64..offset + len]);
3207 std::fs::remove_file(path).ok();
3208 }
3209
3210 #[test]
3211 fn stacked_fp8_experts_reject_non_finite_codes() {
3212 let path =
3213 std::env::temp_dir().join(format!("memra-stacked-fp8-nan-{}", std::process::id()));
3214 let len = 2 * 2 * 32;
3215 let mut file_bytes = vec![0x12; len];
3216 file_bytes[73] = 0x7f;
3217 std::fs::write(&path, &file_bytes).unwrap();
3218 let file = std::sync::Arc::new(std::fs::File::open(&path).unwrap());
3219 let map = std::sync::Arc::new(unsafe { memmap2::Mmap::map(file.as_ref()).unwrap() });
3220 let source = StackedFp8Source {
3221 file,
3222 map,
3223 offset: 0,
3224 len,
3225 scales: vec![0.5, 0.25],
3226 };
3227
3228 let err = match HostExps::load_fp8_stacked_native_with_policy(
3229 &source,
3230 "blk.0.ffn_gate_exps.weight",
3231 true,
3232 ) {
3233 Ok(_) => panic!("non-finite E4M3 code was accepted"),
3234 Err(err) => err,
3235 };
3236 assert!(err.to_string().contains("non-finite E4M3"));
3237 std::fs::remove_file(path).ok();
3238 }
3239
3240 #[test]
3244 fn direct_split_equals_chained() {
3245 for (out_f, in_f) in [(1usize, 64usize), (3, 128), (5, 320), (8, 1024)] {
3246 let mut w = vec![0u8; out_f * in_f / 2];
3247 let mut s = vec![0u8; out_f * in_f / 16];
3248 for (i, b) in w.iter_mut().enumerate() {
3249 *b = ((i * 41 + 7) & 0xFF) as u8;
3250 }
3251 for (i, b) in s.iter_mut().enumerate() {
3252 *b = (0x20 + ((i * 11 + 5) % 0x50)) as u8;
3253 }
3254 let gguf = repack_modelopt_to_gguf(&w, &s, out_f, in_f);
3255 let chained = repack_nvfp4_split(&gguf, out_f);
3256 let direct = repack_modelopt_to_split(&w, &s, out_f, in_f);
3257 assert_eq!(
3258 direct, chained,
3259 "fused != chained at out_f={out_f} in_f={in_f}"
3260 );
3261 assert_eq!(
3262 unpack_nvfp4_split(&direct, out_f),
3263 gguf,
3264 "split roundtrip broken at out_f={out_f} in_f={in_f}"
3265 );
3266 }
3267 }
3268
3269 #[test]
3270 fn mixed_expert_loader_keeps_each_encoding_and_extent() {
3271 let source = MixedExpertSource {
3272 bf16: vec![0x5a; 256 * 2 * 2],
3273 q4k: vec![0xa5; 2 * 144],
3274 };
3275 let exps = HostExps::load_mixed_from_source(&source, 0, "gate", 2).unwrap();
3276 assert!(!exps.is_uniform_layout());
3277 assert_eq!(exps.max_expert_bytes(), 1024);
3278 assert_eq!(exps.expert_layout(0).qtype, QT_BF16);
3279 assert_eq!(exps.expert_layout(0).row_bytes, 512);
3280 assert_eq!(exps.expert_layout(0).len, 1024);
3281 assert_eq!(exps.expert_layout(1).qtype, QT_Q4_K);
3282 assert_eq!(exps.expert_layout(1).row_bytes, 144);
3283 assert_eq!(exps.expert_layout(1).len, 288);
3284 assert_eq!(exps.expert_bytes(0), source.bf16);
3285 assert_eq!(exps.expert_bytes(1), source.q4k);
3286 match exps.expert_source(1) {
3287 ExpertSource::Memory { bytes, .. } => assert_eq!(bytes, source.q4k),
3288 ExpertSource::Disk { .. } => panic!("paged expert unexpectedly became disk-backed"),
3289 }
3290 }
3291
3292 #[test]
3293 fn mixed_expert_loader_omits_masked_expert_bytes() {
3294 let source = PrunedExpertSource {
3295 q2k: vec![0x22; 2 * 84],
3296 nvfp4: vec![0x44; 2 * 4 * 36],
3297 active: vec![true, false, true],
3298 };
3299 let exps = HostExps::load_mixed_from_source(&source, 0, "gate", 3).unwrap();
3300 assert_eq!(exps.expert_layout(0).qtype, QT_Q2_K);
3301 assert_eq!(exps.expert_layout(0).row_bytes, 84);
3302 assert_eq!(exps.expert_layout(1).len, 0);
3303 assert_eq!(exps.expert_bytes(1), &[]);
3304 assert_eq!(exps.expert_layout(2).qtype, QT_NVFP4);
3305 assert_eq!(exps.expert_layout(2).row_bytes, 4 * 36);
3306 }
3307
3308 #[test]
3309 fn mixed_expert_loader_keeps_mmap_backing_zero_copy() {
3310 let path = std::env::temp_dir().join(format!("memra-mixed-mmap-{}", std::process::id()));
3311 let base_offset = 3usize;
3312 let expert_len = 2 * 84;
3313 let mut bytes = vec![0xE1; base_offset];
3314 bytes.extend(vec![0x31; expert_len]);
3315 bytes.extend(vec![0x72; expert_len]);
3316 std::fs::write(&path, &bytes).unwrap();
3317 let file = std::sync::Arc::new(std::fs::File::open(&path).unwrap());
3318 let map = std::sync::Arc::new(unsafe { memmap2::Mmap::map(file.as_ref()).unwrap() });
3319 let source = MmapExpertSource {
3320 file: file.clone(),
3321 map,
3322 base_offset,
3323 expert_len,
3324 };
3325 let exps = HostExps::load_mixed_from_source(&source, 0, "gate", 2).unwrap();
3326 assert!(matches!(
3327 exps.tiers.as_ref().unwrap()[0],
3328 HostBuf::Mmap { .. }
3329 ));
3330 assert!(matches!(
3331 exps.tiers.as_ref().unwrap()[1],
3332 HostBuf::Mmap { .. }
3333 ));
3334 assert_eq!(
3335 exps.expert_bytes(0),
3336 &bytes[base_offset..base_offset + expert_len]
3337 );
3338 assert_eq!(exps.expert_bytes(1), &bytes[base_offset + expert_len..]);
3339 match exps.expert_source(1) {
3340 ExpertSource::Disk {
3341 file: got_file,
3342 offset,
3343 len,
3344 fallback,
3345 keepalive,
3346 } => {
3347 assert!(std::sync::Arc::ptr_eq(got_file, &file));
3348 assert_eq!(offset, (base_offset + expert_len) as u64);
3349 assert_eq!(len, expert_len);
3350 assert_eq!(fallback, &bytes[base_offset + expert_len..]);
3351 match keepalive {
3352 ExpertKeepalive::Mmap(owner) => {
3353 assert!(std::sync::Arc::ptr_eq(&owner, &source.map));
3354 }
3355 _ => panic!("mmap expert did not retain its mmap owner"),
3356 }
3357 }
3358 ExpertSource::Memory { .. } => panic!("mixed mmap tier lost its disk extent"),
3359 }
3360 #[cfg(unix)]
3361 assert!(exps.prefetch_expert_pages(1));
3362 std::fs::remove_file(path).ok();
3363 }
3364
3365 #[test]
3366 fn tiered_expert_source_does_not_double_apply_layout_offset() {
3367 let path =
3368 std::env::temp_dir().join(format!("memra-tiered-source-offset-{}", std::process::id()));
3369 let base_offset = 7usize;
3370 let expert_len = 2 * 84;
3371 let mut bytes = vec![0xE3; base_offset];
3372 bytes.extend(vec![0x41; expert_len]);
3373 bytes.extend(vec![0x82; expert_len]);
3374 std::fs::write(&path, &bytes).unwrap();
3375 let file = std::sync::Arc::new(std::fs::File::open(&path).unwrap());
3376 let map = std::sync::Arc::new(unsafe { memmap2::Mmap::map(file.as_ref()).unwrap() });
3377 let exps = HostExps {
3378 bytes: HostBuf::Paged(Vec::new()),
3379 tiers: Some(vec![
3380 HostBuf::Mmap {
3381 map: map.clone(),
3382 file: file.clone(),
3383 off: base_offset,
3384 len: expert_len,
3385 },
3386 HostBuf::Mmap {
3387 map,
3388 file: file.clone(),
3389 off: base_offset + expert_len,
3390 len: expert_len,
3391 },
3392 ]),
3393 qtype: QT_Q2_K,
3394 in_f: 256,
3395 out_f: 2,
3396 n_expert: 2,
3397 row_bytes: 84,
3398 expert_stride: expert_len,
3399 layouts: None,
3400 macros: None,
3401 fp8_blk: None,
3402 };
3403
3404 assert_eq!(exps.expert_layout(1).offset, expert_len);
3406 match exps.expert_source(1) {
3407 ExpertSource::Disk {
3408 offset,
3409 len,
3410 fallback,
3411 ..
3412 } => {
3413 assert_eq!(offset, (base_offset + expert_len) as u64);
3414 assert_eq!(len, expert_len);
3415 assert_eq!(fallback, &bytes[base_offset + expert_len..]);
3416 }
3417 ExpertSource::Memory { .. } => panic!("tiered mmap expert lost its disk extent"),
3418 }
3419 std::fs::remove_file(path).ok();
3420 }
3421
3422 #[test]
3423 fn legacy_mmap_source_requires_retained_file_extent() {
3424 let path =
3425 std::env::temp_dir().join(format!("memra-legacy-mmap-source-{}", std::process::id()));
3426 let expert_len = 2 * 84;
3427 std::fs::write(&path, vec![0x64; 2 * expert_len]).unwrap();
3428 let file = std::fs::File::open(&path).unwrap();
3429 let map = std::sync::Arc::new(unsafe { memmap2::Mmap::map(&file).unwrap() });
3430 let source = LegacyMmapExpertSource { map, expert_len };
3431
3432 let err = match HostExps::load_uniform_mmap_from_source(&source, 0, "gate", 2) {
3433 Ok(_) => panic!("legacy mmap-only source silently fell back instead of failing"),
3434 Err(err) => err,
3435 };
3436 let message = err.to_string();
3437 assert!(
3438 message.contains("legacy find_expert_mmap without find_expert_disk"),
3439 "{message}"
3440 );
3441 assert!(message.contains("retained Arc<File>"), "{message}");
3442 std::fs::remove_file(path).ok();
3443 }
3444
3445 #[test]
3446 fn uniform_expert_loader_coalesces_contiguous_mmap() {
3447 let path = std::env::temp_dir().join(format!("memra-uniform-mmap-{}", std::process::id()));
3448 let base_offset = 5usize;
3449 let expert_len = 2 * 84;
3450 let mut bytes = vec![0xE2; base_offset];
3451 bytes.extend(vec![0x19; expert_len]);
3452 bytes.extend(vec![0x91; expert_len]);
3453 std::fs::write(&path, &bytes).unwrap();
3454 let file = std::sync::Arc::new(std::fs::File::open(&path).unwrap());
3455 let map = std::sync::Arc::new(unsafe { memmap2::Mmap::map(file.as_ref()).unwrap() });
3456 let source = MmapExpertSource {
3457 file: file.clone(),
3458 map,
3459 base_offset,
3460 expert_len,
3461 };
3462 let exps = HostExps::load_uniform_mmap_from_source(&source, 0, "gate", 2)
3463 .unwrap()
3464 .expect("contiguous mmap should coalesce");
3465 assert!(exps.is_uniform_layout());
3466 assert!(matches!(&exps.bytes, HostBuf::Mmap { .. }));
3467 assert_eq!(exps.expert_stride, expert_len);
3468 assert_eq!(
3469 exps.expert_bytes(0),
3470 &bytes[base_offset..base_offset + expert_len]
3471 );
3472 assert_eq!(exps.expert_bytes(1), &bytes[base_offset + expert_len..]);
3473 match exps.expert_source(1) {
3474 ExpertSource::Disk {
3475 file: got_file,
3476 offset,
3477 len,
3478 fallback,
3479 ..
3480 } => {
3481 assert!(std::sync::Arc::ptr_eq(got_file, &file));
3482 assert_eq!(offset, (base_offset + expert_len) as u64);
3483 assert_eq!(len, expert_len);
3484 assert_eq!(fallback, &bytes[base_offset + expert_len..]);
3485 }
3486 ExpertSource::Memory { .. } => panic!("uniform mmap slab lost its disk extent"),
3487 }
3488 #[cfg(unix)]
3489 assert!(exps.prefetch_expert_pages(1));
3490 std::fs::remove_file(path).ok();
3491 }
3492}