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 && (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 let status = unsafe {
314 libc::renameat(
315 dir.as_raw_fd(),
316 temp_name.as_ptr(),
317 dir.as_raw_fd(),
318 name.as_ptr(),
319 )
320 };
321 if status != 0 {
322 unsafe {
323 libc::unlinkat(dir.as_raw_fd(), temp_name.as_ptr(), 0);
324 }
325 return Err(std::io::Error::last_os_error());
326 }
327 dir.sync_all()
328 }
329
330 #[cfg(not(unix))]
331 {
332 let temp = parent.join(format!(
333 ".{}.tmp-{}",
334 name.to_string_lossy(),
335 std::process::id()
336 ));
337 let mut out = std::io::BufWriter::new(
338 std::fs::OpenOptions::new()
339 .write(true)
340 .create_new(true)
341 .open(&temp)?,
342 );
343 write(&mut out)?;
344 out.flush()?;
345 out.get_ref().sync_all()?;
346 drop(out);
347 if let Ok(metadata) = std::fs::symlink_metadata(path) {
348 if metadata.file_type().is_symlink() || !metadata.is_file() {
349 std::fs::remove_file(&temp).ok();
350 return Err(std::io::Error::new(
351 std::io::ErrorKind::InvalidData,
352 format!("repack cache target is not a private regular file: {path:?}"),
353 ));
354 }
355 }
356 std::fs::rename(temp, path)
357 }
358}
359
360#[allow(clippy::large_enum_variant)] pub 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 || name.ends_with("hc_attn_fn")
542 || name.ends_with("hc_ffn_fn")
543}
544
545fn warn_float_2d_once(name: &str, ne: &[u64], src_type: GgmlType) {
548 use std::sync::{Mutex, OnceLock};
549 static SEEN: OnceLock<Mutex<std::collections::HashSet<String>>> = OnceLock::new();
550 let pat = match name.strip_prefix("blk.").and_then(|r| r.split_once('.')) {
551 Some((_, suffix)) => format!("blk.*.{suffix}"),
552 None => name.to_string(),
553 };
554 let mut seen = SEEN
555 .get_or_init(|| Mutex::new(std::collections::HashSet::new()))
556 .lock()
557 .unwrap();
558 if seen.insert(pat.clone()) {
559 eprintln!(
560 "[loader-law] WARNING: {pat} loads as 2D Float ne={ne:?} (src {src_type:?}) — \
561 a Float matmul weight rides cuBLAS f32 GEMV and poisons all-or-nothing q8-fast \
562 predicates (uses_q8_1_fast/mixer_in_q8_1_fast). If matmul-class: Q8_0-encode at \
563 load (model.rs ssm arm / source.rs BF16+F8 gates). If deliberately Float: add \
564 it to float_2d_audited with the audit rationale."
565 );
566 }
567}
568
569#[cfg(memra_cutlass)]
572pub struct CutlassWeight {
573 pub b_packed: CudaSlice<u8>,
575 pub sfb_swizzled: CudaSlice<u8>,
577}
578
579impl GpuTensor {
580 pub fn nvfp4_rp_from_raw(
587 e: &Engine,
588 raw: &[u8],
589 in_f: usize,
590 out_f: usize,
591 scale: f32,
592 ) -> Result<Self, Box<dyn std::error::Error>> {
593 assert_eq!(raw.len() % out_f, 0, "raw bytes must tile out_f rows");
594 let row_bytes = raw.len() / out_f;
595 assert_eq!(
596 row_bytes,
597 in_f / 64 * 36,
598 "NVFP4 row layout: 36B per 64 values"
599 );
600 let bytes = e.htod_bytes(&repack_nvfp4_split(raw, out_f))?;
601 Ok(GpuTensor::Quant {
602 bytes,
603 qtype: crate::QT_NVFP4,
604 row_bytes,
605 ne: vec![in_f as u64, out_f as u64],
606 scale,
607 rp: true,
608 #[cfg(memra_cutlass)]
609 cutlass: None,
610 fp8: None,
611 rp4: None,
612 blk: None,
613 f16: None,
614 })
615 }
616
617 pub fn ne(&self) -> &[u64] {
618 match self {
619 GpuTensor::Quant { ne, .. } => ne,
620 GpuTensor::Float { ne, .. } => ne,
621 GpuTensor::FloatBf16 { ne, .. } => ne,
622 }
623 }
624 pub fn in_features(&self) -> usize {
625 self.ne()[0] as usize
626 }
627 pub fn out_features(&self) -> usize {
628 self.ne()[1] as usize
629 }
630 pub fn scale(&self) -> f32 {
633 match self {
634 GpuTensor::Quant { scale, .. } => *scale,
635 GpuTensor::Float { .. } | GpuTensor::FloatBf16 { .. } => 1.0,
636 }
637 }
638
639 pub fn ordinal(&self) -> usize {
641 match self {
642 GpuTensor::Quant { bytes, .. } => bytes.ordinal(),
643 GpuTensor::Float { data, .. } => data.ordinal(),
644 GpuTensor::FloatBf16 { data, .. } => data.ordinal(),
645 }
646 }
647
648 pub fn load(e: &Engine, g: &GgufFile, name: &str) -> Result<Self, Box<dyn std::error::Error>> {
651 Self::load_from_source(e, &GgufSource(g), name)
652 }
653
654 pub fn load_from_source(
663 e: &Engine,
664 src: &dyn TensorSource,
665 name: &str,
666 ) -> Result<Self, Box<dyn std::error::Error>> {
667 let t = Self::load_from_source_inner(e, src, name)?;
668 if let GpuTensor::Quant {
669 qtype, bytes, ne, ..
670 } = &t
671 && ne.len() == 2
672 {
673 residency_census_note(*qtype, bytes.len());
674 }
675 Ok(t)
676 }
677
678 #[allow(clippy::manual_is_multiple_of)] fn load_from_source_inner(
680 e: &Engine,
681 src: &dyn TensorSource,
682 name: &str,
683 ) -> Result<Self, Box<dyn std::error::Error>> {
684 let cutlass_wants_raw = cfg!(memra_cutlass) && std::env::var("MEMRA_FP4_CUTLASS").is_ok();
692 let st_direct = std::env::var("MEMRA_ST_DIRECT")
693 .map(|v| v != "0")
694 .unwrap_or(true);
695 if rp_enabled()
696 && st_direct
697 && !cutlass_wants_raw
698 && let Some(nv) = src.find_nvfp4_native(name)
699 && nv.in_f % 64 == 0
700 && nv.out_f > 0
701 {
702 let stem = name.strip_suffix(".weight").unwrap_or(name);
704 let scale = match src.find(&format!("{stem}.scale")) {
705 Some(sv) => f32::from_le_bytes(sv.bytes[..4].try_into().unwrap()),
706 None => 1.0,
707 };
708 let bytes = e.htod_bytes(&memra_gguf::nvfp4_repack::repack_modelopt_to_split(
709 nv.wbytes, &nv.wscale, nv.out_f, nv.in_f,
710 ))?;
711 return Ok(GpuTensor::Quant {
712 bytes,
713 qtype: QT_NVFP4,
714 row_bytes: nv.in_f / 64 * 36,
715 ne: vec![nv.in_f as u64, nv.out_f as u64],
716 scale,
717 rp: true,
718 #[cfg(memra_cutlass)]
719 cutlass: None,
720 fp8: None,
721 blk: None,
722 f16: None,
723 rp4: None,
724 });
725 }
726 if crate::fp8_ffi::st_e4m3_enabled()
741 && let Some(f8) = src.find_fp8_native(name)
742 && f8.blk.is_none()
743 && f8.in_f % 32 == 0
744 && f8.out_f > 0
745 {
746 return Ok(GpuTensor::Quant {
747 bytes: e.htod_bytes(&f8.bytes)?,
748 qtype: crate::QT_F8_E4M3,
749 row_bytes: f8.in_f,
750 ne: vec![f8.in_f as u64, f8.out_f as u64],
751 scale: f8.scale,
752 rp: false,
753 #[cfg(memra_cutlass)]
754 cutlass: None,
755 fp8: None,
756 blk: None,
757 f16: None,
758 rp4: None,
759 });
760 }
761 if crate::fp8_ffi::st_e4m3_blk_enabled()
788 && let Some(f8) = src.find_fp8_native(name)
789 && let Some(grid) = f8.blk.as_ref()
790 {
791 let (in_f, out_f) = (f8.in_f, f8.out_f);
792 if in_f % 32 == 0
798 && out_f > 0
799 && f8.bytes.len() == out_f * in_f
800 && grid.rows == out_f.div_ceil(128)
801 && grid.cols == in_f.div_ceil(128)
802 && grid.scales.len() == grid.rows * grid.cols
803 && f8.scale == 1.0
804 {
805 let bytes = e.htod_bytes(&f8.bytes)?;
806 if e.fp8_blk_nan_count(&bytes)? == 0 {
807 let scales = e.htod(&grid.scales)?;
808 return Ok(GpuTensor::Quant {
809 bytes,
810 qtype: crate::QT_F8_E4M3_BLK,
811 row_bytes: in_f,
812 ne: vec![in_f as u64, out_f as u64],
813 scale: 1.0,
814 rp: false,
815 #[cfg(memra_cutlass)]
816 cutlass: None,
817 fp8: None,
818 blk: Some(Fp8BlockScales {
819 scales,
820 rows: grid.rows,
821 cols: grid.cols,
822 }),
823 f16: None,
824 rp4: None,
825 });
826 }
827 crate::fp8_ffi::note_blk_native_nan_refused();
828 }
829 }
830 if crate::fp8_ffi::fp8_blk_gpu_enabled()
856 && let Some(f8) = src.find_fp8_native(name)
857 && let Some(grid) = f8.blk.as_ref()
858 {
859 let (in_f, out_f) = (f8.in_f, f8.out_f);
860 if in_f % 32 == 0 && out_f > 0 && f8.bytes.len() == out_f * in_f {
861 let bytes = e.fp8_blk_dequant_q8_0(&f8.bytes, &grid.scales, out_f, in_f)?;
862 return Ok(GpuTensor::Quant {
863 bytes,
864 qtype: QT_Q8_0,
865 row_bytes: in_f / 32 * 34,
866 ne: vec![in_f as u64, out_f as u64],
867 scale: 1.0,
868 rp: false,
869 #[cfg(memra_cutlass)]
870 cutlass: None,
871 fp8: None,
872 blk: None,
873 f16: None,
874 rp4: None,
875 });
876 }
877 }
878 let v = src
879 .find(name)
880 .unwrap_or_else(|| panic!("missing tensor {name}"));
881 let qtype = match v.ggml_type {
882 GgmlType::Q8_0 => Some(QT_Q8_0),
883 GgmlType::Q4_K => Some(QT_Q4_K),
884 GgmlType::Q6_K => Some(QT_Q6_K),
885 GgmlType::Q5_K => Some(QT_Q5_K),
886 GgmlType::Q3_K => Some(QT_Q3_K),
887 GgmlType::IQ4_XS => Some(QT_IQ4_XS),
888 GgmlType::IQ3_S => Some(QT_IQ3_S),
889 GgmlType::NVFP4 => Some(QT_NVFP4),
890 GgmlType::Q4_0 => Some(QT_Q4_0),
891 _ => None,
893 };
894 match qtype {
895 Some(qt) => {
896 if v.ne.len() != 2 {
909 return Err(format!(
910 "{name}: quantized tensor (qtype {qt}) has {}-D ne {:?}, but every \
911 quantized resident layout in this engine is 2-D — row_bytes is derived \
912 from ne[1] as the out-feature count and would be wrong here. A 3-D \
913 operand must be dequantized at the source (see TensorTransform::\
914 SplitMlaKv) or split per head before it reaches the loader.",
915 v.ne.len(),
916 v.ne
917 )
918 .into());
919 }
920 let out_f = v.ne[1] as usize;
921 let row_bytes = v.bytes.len() / out_f;
922 let scale = if qt == QT_NVFP4 {
927 let stem = name.strip_suffix(".weight").unwrap_or(name);
928 match src.find(&format!("{stem}.scale")) {
929 Some(sv) => f32::from_le_bytes(sv.bytes[..4].try_into().unwrap()),
930 None => 1.0,
931 }
932 } else {
933 1.0
934 };
935 let rp = qt == QT_NVFP4
939 && v.ne.len() == 2
940 && (v.ne[0] as usize).is_multiple_of(64)
941 && v.bytes.len() % out_f == 0
942 && (v.bytes.len() / out_f).is_multiple_of(36)
943 && rp_enabled();
944 let bytes = if rp {
945 e.htod_bytes(&repack_nvfp4_split(&v.bytes, out_f))?
946 } else {
947 e.htod_bytes(&v.bytes)?
948 };
949 #[cfg(memra_cutlass)]
954 let cutlass = {
955 let in_f = v.ne[0] as usize;
956 if qt == QT_NVFP4
959 && in_f % 64 == 0
960 && v.ne.len() == 2
961 && std::env::var("MEMRA_FP4_CUTLASS").is_ok()
962 && std::env::var("MEMRA_FP4_CUTLASS_OTF").is_err()
963 {
964 let raw_dev;
965 let src_dev = if rp {
966 raw_dev = e.htod_bytes(&v.bytes)?;
967 &raw_dev
968 } else {
969 &bytes
970 };
971 let (b_packed, sfb_swizzled) =
972 e.build_cutlass_weight(src_dev, out_f, in_f, row_bytes)?;
973 Some(CutlassWeight {
974 b_packed,
975 sfb_swizzled,
976 })
977 } else {
978 None
979 }
980 };
981 let fp8 = if qt == QT_Q8_0
1001 && (crate::fp8_ffi::pp_fp8_enabled() || crate::fp8_ffi::fp8_mmq_enabled())
1002 {
1003 match src.find_fp8_native(name) {
1004 Some(f8)
1005 if v.ne.len() == 2
1006 && f8.in_f as u64 == v.ne[0]
1007 && f8.out_f as u64 == v.ne[1] =>
1008 {
1009 use std::sync::atomic::{AtomicUsize, Ordering};
1010 static FP8_SPENT: AtomicUsize = AtomicUsize::new(0);
1011 static FP8_BUDGET: std::sync::OnceLock<usize> =
1012 std::sync::OnceLock::new();
1013 let budget = *FP8_BUDGET.get_or_init(|| {
1014 std::env::var("MEMRA_PP_FP8_BUDGET_MB")
1015 .ok()
1016 .and_then(|v| v.parse::<usize>().ok())
1017 .unwrap_or(1536)
1018 << 20
1019 });
1020 let sz = f8.bytes.len();
1021 if FP8_SPENT.fetch_add(sz, Ordering::Relaxed) + sz <= budget {
1022 let blk = match f8.blk {
1027 Some(g) => Some(Fp8BlockScales {
1028 scales: e.htod(&g.scales)?,
1029 rows: g.rows,
1030 cols: g.cols,
1031 }),
1032 None => None,
1033 };
1034 Some(Fp8Weight {
1035 bytes: e.htod_bytes(&f8.bytes)?,
1036 scale: f8.scale,
1037 blk,
1038 })
1039 } else {
1040 FP8_SPENT.fetch_sub(sz, Ordering::Relaxed);
1041 None
1042 }
1043 }
1044 _ => None,
1045 }
1046 } else {
1047 None
1048 };
1049 Ok(GpuTensor::Quant {
1050 bytes,
1051 qtype: qt,
1052 row_bytes,
1053 ne: v.ne.clone(),
1054 scale,
1055 rp,
1056 #[cfg(memra_cutlass)]
1057 cutlass,
1058 fp8,
1059 blk: None,
1060 rp4: None,
1061 f16: None,
1062 })
1063 }
1064 None => {
1065 let n: u64 = v.ne.iter().product();
1066 if full_prec_enabled() || crate::Engine::bf16_mmv_on() {
1078 let threshold = if full_prec_enabled() {
1085 1_000_000
1086 } else {
1087 2_000_000
1088 };
1089 if v.ggml_type == GgmlType::BF16 && v.ne.len() == 2 && n >= threshold {
1090 let data = e.htod_bytes(&v.bytes)?; eprintln!(
1101 "[bf16-mmv] RESIDENT {name} ne={:?} n={n} admit={}",
1102 v.ne,
1103 if full_prec_enabled() {
1104 "full_prec"
1105 } else {
1106 "bf16_mmv"
1107 }
1108 );
1109 return Ok(GpuTensor::FloatBf16 {
1110 data,
1111 ne: v.ne.clone(),
1112 });
1113 }
1114 if full_prec_enabled() {
1115 let f32v = dequant::dequantize(v.ggml_type, &v.bytes, n as usize);
1116 return Ok(GpuTensor::Float {
1117 data: e.htod(&f32v)?,
1118 ne: v.ne.clone(),
1119 });
1120 }
1121 }
1122 let f32v = dequant::dequantize(v.ggml_type, &v.bytes, n as usize);
1123 if v.ne.len() == 2
1130 && v.ne[0].is_multiple_of(32)
1131 && (name.ends_with("ssm_beta.weight") || name.ends_with("ssm_alpha.weight")
1132 || name.ends_with("per_layer_model_proj.weight"))
1138 {
1139 let q8 = memra_gguf::nvfp4_repack::f32_to_q8_0(&f32v);
1140 return GpuTensor::from_quant_bytes(
1141 e,
1142 &q8,
1143 GgmlType::Q8_0,
1144 v.ne[0],
1145 v.ne[1],
1146 1.0,
1147 );
1148 }
1149 if v.ne.len() == 2 && v.ne[0] >= 16 && v.ne[1] >= 16 && !float_2d_audited(name) {
1159 warn_float_2d_once(name, &v.ne, v.ggml_type);
1160 }
1161 Ok(GpuTensor::Float {
1163 data: e.htod(&f32v)?,
1164 ne: v.ne.clone(),
1165 })
1166 }
1167 }
1168 }
1169
1170 pub fn from_quant_bytes(
1174 e: &Engine,
1175 bytes: &[u8],
1176 ty: GgmlType,
1177 ne0: u64,
1178 ne1: u64,
1179 scale: f32,
1180 ) -> Result<Self, Box<dyn std::error::Error>> {
1181 let qt = match ty {
1182 GgmlType::Q8_0 => QT_Q8_0,
1183 GgmlType::Q4_K => QT_Q4_K,
1184 GgmlType::Q6_K => QT_Q6_K,
1185 GgmlType::Q5_K => QT_Q5_K,
1186 GgmlType::Q3_K => QT_Q3_K,
1187 GgmlType::IQ4_XS => QT_IQ4_XS,
1188 GgmlType::IQ3_S => QT_IQ3_S,
1189 GgmlType::NVFP4 => QT_NVFP4,
1190 GgmlType::Q4_0 => QT_Q4_0,
1191 other => panic!("from_quant_bytes: unsupported dtype {other:?}"),
1192 };
1193 let row_bytes = bytes.len() / ne1 as usize;
1194 let rp = qt == QT_NVFP4
1197 && ne0.is_multiple_of(64)
1198 && row_bytes.is_multiple_of(36)
1199 && rp_enabled();
1200 let dev = if rp {
1201 e.htod_bytes(&repack_nvfp4_split(bytes, ne1 as usize))?
1202 } else {
1203 e.htod_bytes(bytes)?
1204 };
1205 Ok(GpuTensor::Quant {
1206 bytes: dev,
1207 qtype: qt,
1208 row_bytes,
1209 ne: vec![ne0, ne1],
1210 scale,
1211 rp,
1212 #[cfg(memra_cutlass)]
1213 cutlass: None,
1214 fp8: None,
1215 blk: None,
1216 f16: None,
1217 rp4: None,
1218 })
1219 }
1220
1221 pub fn load_opt(
1222 e: &Engine,
1223 g: &GgufFile,
1224 name: &str,
1225 ) -> Result<Option<Self>, Box<dyn std::error::Error>> {
1226 Self::load_opt_from_source(e, &GgufSource(g), name)
1227 }
1228
1229 pub fn load_opt_from_source(
1230 e: &Engine,
1231 src: &dyn TensorSource,
1232 name: &str,
1233 ) -> Result<Option<Self>, Box<dyn std::error::Error>> {
1234 if src.has(name) {
1235 Ok(Some(Self::load_from_source(e, src, name)?))
1236 } else {
1237 Ok(None)
1238 }
1239 }
1240
1241 pub fn float_data(&self) -> &CudaSlice<f32> {
1243 match self {
1244 GpuTensor::Float { data, .. } => data,
1245 GpuTensor::Quant { .. } => panic!("expected float tensor (norm), got quantized"),
1246 GpuTensor::FloatBf16 { .. } => {
1247 panic!("expected f32 float tensor (norm), got bf16-resident matmul weight")
1248 }
1249 }
1250 }
1251}
1252
1253pub struct Layer {
1254 pub attn_norm: GpuTensor,
1255 pub wq: GpuTensor,
1256 pub wk: GpuTensor,
1257 pub wv: GpuTensor,
1258 pub wo: GpuTensor,
1259 pub q_norm: Option<GpuTensor>,
1260 pub k_norm: Option<GpuTensor>,
1261 pub ffn_norm: GpuTensor,
1262 pub ffn: crate::hybrid::Ffn,
1265}
1266
1267pub struct EmbedHost {
1269 pub raw: Vec<u8>,
1270 pub ggml_type: GgmlType,
1271 pub n_embd: usize,
1272}
1273impl EmbedHost {
1274 pub fn from_gguf(g: &GgufFile, name: &str) -> Self {
1275 Self::from_source(&GgufSource(g), name)
1276 }
1277 pub fn from_source(src: &dyn TensorSource, name: &str) -> Self {
1278 let v = src
1279 .find(name)
1280 .unwrap_or_else(|| panic!("missing embed {name}"));
1281 EmbedHost {
1282 raw: v.bytes.to_vec(),
1283 ggml_type: v.ggml_type,
1284 n_embd: v.ne[0] as usize,
1285 }
1286 }
1287 pub fn qt_and_row_bytes(&self, n_embd: usize) -> (i32, usize) {
1290 let (blk, tsize) = self.ggml_type.block_and_type_size();
1291 let row_bytes = (n_embd as u64 / blk * tsize) as usize;
1292 let qt = match self.ggml_type {
1293 GgmlType::Q8_0 => QT_Q8_0,
1294 GgmlType::Q4_K => QT_Q4_K,
1295 GgmlType::Q6_K => QT_Q6_K,
1296 GgmlType::Q5_K => QT_Q5_K,
1297 GgmlType::Q3_K => QT_Q3_K,
1298 GgmlType::IQ4_XS => QT_IQ4_XS,
1299 GgmlType::IQ3_S => QT_IQ3_S,
1300 GgmlType::NVFP4 => QT_NVFP4,
1301 GgmlType::F32 => QT_F32,
1302 GgmlType::BF16 => QT_BF16,
1305 other => panic!("embed_gather: unsupported dtype {other:?}"),
1306 };
1307 (qt, row_bytes)
1308 }
1309
1310 pub fn rows(&self, n_embd: usize) -> usize {
1313 let (blk, tsize) = self.ggml_type.block_and_type_size();
1314 let row_bytes = (n_embd as u64 / blk * tsize) as usize;
1315 self.raw.len().checked_div(row_bytes).unwrap_or(0)
1316 }
1317
1318 pub fn try_gather(&self, n_embd: usize, tokens: &[u32]) -> Result<Vec<f32>, String> {
1332 let (blk, tsize) = self.ggml_type.block_and_type_size();
1333 let row_bytes = (n_embd as u64 / blk * tsize) as usize;
1334 let rows = self.rows(n_embd);
1335 let mut x = vec![0f32; tokens.len() * n_embd];
1336 for (ti, &tok) in tokens.iter().enumerate() {
1337 if tok as usize >= rows {
1338 return Err(format!(
1339 "embed gather: token id {tok} at position {ti} is outside this table's {rows} rows ({} raw bytes / {row_bytes} B per row, dtype {:?}). An out-of-range id is produced UPSTREAM — corrupt logits, a sampler reading a stale or non-finite row, or a tokenizer/vocab mismatch — so fix it there; this refusal exists so the worker does not die on the slice",
1340 self.raw.len(),
1341 self.ggml_type,
1342 ));
1343 }
1344 let off = tok as usize * row_bytes;
1345 let row = dequant::dequantize(self.ggml_type, &self.raw[off..off + row_bytes], n_embd);
1346 x[ti * n_embd..ti * n_embd + n_embd].copy_from_slice(&row);
1347 }
1348 Ok(x)
1349 }
1350
1351 pub fn gather(&self, n_embd: usize, tokens: &[u32]) -> Vec<f32> {
1354 self.try_gather(n_embd, tokens)
1355 .unwrap_or_else(|err| panic!("{err}"))
1356 }
1357}
1358
1359pub struct Model {
1360 pub cfg: ModelConfig,
1361 pub embd: EmbedHost,
1362 pub output_norm: GpuTensor,
1363 pub output: GpuTensor,
1364 pub layers: Vec<Layer>,
1365}
1366
1367impl Model {
1368 pub fn load_dense(e: &Engine, g: &GgufFile) -> Result<Self, Box<dyn std::error::Error>> {
1371 Self::load_dense_from_source(e, &GgufSource(g))
1372 }
1373
1374 pub fn load_dense_from_source(
1378 e: &Engine,
1379 src: &dyn TensorSource,
1380 ) -> Result<Self, Box<dyn std::error::Error>> {
1381 let cfg = src.try_config().map_err(std::io::Error::other)?;
1382 let plan = match memra_gguf::model_packs::for_config(&cfg) {
1383 Some(pack) => pack.compile_plan(&cfg)?,
1384 None => memra_gguf::model_plan::ModelPlan::compile(&cfg)?,
1385 };
1386 if plan.layers.iter().any(|layer| {
1387 !matches!(
1388 layer.attention,
1389 memra_gguf::model_plan::AttentionPlan::Full(_)
1390 )
1391 }) {
1392 return Err("plain executor requires full-attention ModelPlan layers".into());
1393 }
1394 let embd = EmbedHost::from_source(src, "token_embd.weight");
1395 let output_norm = GpuTensor::load_from_source(e, src, "output_norm.weight")?;
1396 let output = if src.has("output.weight") {
1398 GpuTensor::load_from_source(e, src, "output.weight")?
1399 } else {
1400 GpuTensor::load_from_source(e, src, "token_embd.weight")?
1401 };
1402 let mut resident = crate::hybrid::ResidentPlan::unsharded(e, src, &cfg);
1403 let mut step_runtimes = crate::hybrid::StepParallelRuntimeRegistry::default();
1404
1405 let mut layers = Vec::with_capacity(plan.layers.len());
1406 for (il, layer_plan) in plan.layers.iter().enumerate() {
1407 let il = il as u32;
1408 let p = |s: &str| format!("blk.{il}.{s}");
1409 let ffn = crate::hybrid::load_ffn(
1410 e,
1411 src,
1412 &cfg,
1413 &layer_plan.mlp,
1414 il,
1415 None,
1416 &mut resident,
1417 &mut step_runtimes,
1418 )?;
1419 layers.push(Layer {
1420 attn_norm: GpuTensor::load_from_source(e, src, &p("attn_norm.weight"))?,
1421 wq: GpuTensor::load_from_source(e, src, &p("attn_q.weight"))?,
1422 wk: GpuTensor::load_from_source(e, src, &p("attn_k.weight"))?,
1423 wv: GpuTensor::load_from_source(e, src, &p("attn_v.weight"))?,
1424 wo: GpuTensor::load_from_source(e, src, &p("attn_output.weight"))?,
1425 q_norm: GpuTensor::load_opt_from_source(e, src, &p("attn_q_norm.weight"))?,
1426 k_norm: GpuTensor::load_opt_from_source(e, src, &p("attn_k_norm.weight"))?,
1427 ffn_norm: GpuTensor::load_from_source(e, src, &p("ffn_norm.weight"))?,
1428 ffn,
1429 });
1430 }
1431 Ok(Model {
1432 cfg,
1433 embd,
1434 output_norm,
1435 output,
1436 layers,
1437 })
1438 }
1439
1440 pub(crate) fn max_moe_block(&self) -> usize {
1443 use crate::hybrid::Ffn;
1444 let mut mx = 0usize;
1445 for l in &self.layers {
1446 if let Ffn::Moe(m) = &l.ffn {
1447 mx = mx
1448 .max(m.gate_exps.max_expert_bytes())
1449 .max(m.up_exps.max_expert_bytes())
1450 .max(m.down_exps.max_expert_bytes());
1451 }
1452 }
1453 mx
1454 }
1455
1456 pub fn embed_tokens(
1459 &self,
1460 e: &Engine,
1461 tokens: &[u32],
1462 ) -> Result<CudaSlice<f32>, Box<dyn std::error::Error>> {
1463 let n_embd = self.cfg.n_embd as usize;
1464 let x = self.embd.try_gather(n_embd, tokens)?;
1465 e.htod(&x)
1466 }
1467}
1468
1469pub type TensorMap = HashMap<String, GpuTensor>;
1470
1471pub enum HostBuf {
1490 Paged(Vec<u8>),
1491 Pinned {
1494 slice: std::sync::Arc<cudarc::driver::PinnedHostSlice<u8>>,
1495 base: *const u8,
1496 len: usize,
1497 },
1498 PinnedAlias {
1501 owner: std::sync::Arc<HostBuf>,
1502 base: *const u8,
1503 len: usize,
1504 },
1505 Mmap {
1511 map: std::sync::Arc<memmap2::Mmap>,
1512 file: std::sync::Arc<std::fs::File>,
1515 off: usize,
1517 len: usize,
1518 },
1519}
1520unsafe impl Send for HostBuf {}
1525unsafe impl Sync for HostBuf {}
1526impl HostBuf {
1527 #[inline]
1528 pub fn as_bytes(&self) -> &[u8] {
1529 match self {
1530 HostBuf::Paged(v) => v.as_slice(),
1531 HostBuf::Pinned { base, len, .. } => unsafe { std::slice::from_raw_parts(*base, *len) },
1535 HostBuf::PinnedAlias { base, len, .. } => unsafe {
1536 std::slice::from_raw_parts(*base, *len)
1537 },
1538 HostBuf::Mmap { map, off, len, .. } => &map[*off..*off + *len],
1540 }
1541 }
1542 #[inline]
1543 #[allow(clippy::len_without_is_empty)] pub fn len(&self) -> usize {
1545 match self {
1546 HostBuf::Paged(v) => v.len(),
1547 HostBuf::Pinned { len, .. } => *len,
1548 HostBuf::PinnedAlias { len, .. } => *len,
1549 HostBuf::Mmap { len, .. } => *len,
1550 }
1551 }
1552
1553 #[inline]
1558 pub fn advise_willneed(&self, rel_off: usize, len: usize) -> bool {
1559 let HostBuf::Mmap {
1560 map,
1561 off,
1562 len: extent,
1563 ..
1564 } = self
1565 else {
1566 return false;
1567 };
1568 if len == 0 || rel_off > *extent || len > *extent - rel_off {
1569 return false;
1570 }
1571 #[cfg(unix)]
1572 {
1573 map.advise_range(memmap2::Advice::WillNeed, *off + rel_off, len)
1574 .is_ok()
1575 }
1576 #[cfg(not(unix))]
1577 {
1578 let _ = (map, off);
1579 false
1580 }
1581 }
1582
1583 #[inline]
1584 fn expert_source(&self, rel_off: usize, len: usize) -> ExpertSource<'_> {
1585 debug_assert!(rel_off <= self.len() && len <= self.len() - rel_off);
1586 match self {
1587 HostBuf::Mmap { map, file, off, .. } => {
1588 let offset = *off + rel_off;
1589 ExpertSource::Disk {
1590 file,
1591 offset: offset as u64,
1592 len,
1593 fallback: &map[offset..offset + len],
1594 keepalive: ExpertKeepalive::Mmap(map.clone()),
1595 }
1596 }
1597 HostBuf::Pinned { slice, .. } => ExpertSource::Memory {
1598 bytes: &self.as_bytes()[rel_off..rel_off + len],
1599 keepalive: Some(ExpertKeepalive::Pinned(slice.clone())),
1600 },
1601 HostBuf::PinnedAlias { owner, .. } => ExpertSource::Memory {
1602 bytes: &self.as_bytes()[rel_off..rel_off + len],
1603 keepalive: Some(ExpertKeepalive::Buffer(owner.clone())),
1604 },
1605 HostBuf::Paged(_) => ExpertSource::Memory {
1606 bytes: &self.as_bytes()[rel_off..rel_off + len],
1607 keepalive: None,
1610 },
1611 }
1612 }
1613}
1614
1615#[allow(dead_code)]
1618pub(crate) enum ExpertKeepalive {
1619 Pinned(std::sync::Arc<cudarc::driver::PinnedHostSlice<u8>>),
1620 Buffer(std::sync::Arc<HostBuf>),
1621 Mmap(std::sync::Arc<memmap2::Mmap>),
1622}
1623
1624pub(crate) enum ExpertSource<'a> {
1627 Memory {
1628 bytes: &'a [u8],
1629 keepalive: Option<ExpertKeepalive>,
1630 },
1631 Disk {
1632 file: &'a std::sync::Arc<std::fs::File>,
1633 offset: u64,
1634 len: usize,
1635 fallback: &'a [u8],
1636 keepalive: ExpertKeepalive,
1637 },
1638}
1639
1640#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1652pub struct ExpertLayout {
1653 pub offset: usize,
1654 pub len: usize,
1655 pub qtype: i32,
1656 pub row_bytes: usize,
1657}
1658
1659fn staged_expert_qtype(ty: GgmlType) -> Option<i32> {
1660 Some(match ty {
1661 GgmlType::Q8_0 => QT_Q8_0,
1662 GgmlType::Q2_K => QT_Q2_K,
1663 GgmlType::Q4_K => QT_Q4_K,
1664 GgmlType::Q6_K => QT_Q6_K,
1665 GgmlType::Q5_K => QT_Q5_K,
1666 GgmlType::Q3_K => QT_Q3_K,
1667 GgmlType::IQ4_XS => QT_IQ4_XS,
1668 GgmlType::IQ3_S => QT_IQ3_S,
1669 GgmlType::NVFP4 => QT_NVFP4,
1670 GgmlType::F32 => QT_F32,
1671 GgmlType::BF16 => QT_BF16,
1672 _ => return None,
1673 })
1674}
1675
1676fn staged_expert_row_bytes(ty: GgmlType, in_f: usize) -> Option<usize> {
1677 staged_expert_qtype(ty)?;
1678 let (block, type_size) = ty.block_and_type_size();
1679 assert_eq!(
1680 in_f as u64 % block,
1681 0,
1682 "expert row width {in_f} is not divisible by {ty:?} block {block}"
1683 );
1684 Some((in_f as u64 / block * type_size) as usize)
1685}
1686
1687fn find_expert_disk_strict(
1688 src: &dyn TensorSource,
1689 name: &str,
1690) -> Result<Option<DiskExtent>, Box<dyn std::error::Error>> {
1691 if let Some(extent) = src.find_expert_disk(name) {
1692 return Ok(Some(extent));
1693 }
1694 if src.find_expert_mmap(name).is_some() {
1695 return Err(std::io::Error::new(
1696 std::io::ErrorKind::InvalidData,
1697 format!(
1698 "expert tensor {name} exposes legacy find_expert_mmap without find_expert_disk; \
1699 disk-backed expert loading requires a retained Arc<File>"
1700 ),
1701 )
1702 .into());
1703 }
1704 Ok(None)
1705}
1706
1707pub struct HostExps {
1708 pub bytes: HostBuf, pub tiers: Option<Vec<HostBuf>>,
1714 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>>,
1724 pub macros: Option<Vec<f32>>,
1729 pub fp8_blk: Option<HostExpertFp8BlockScales>,
1732}
1733
1734pub struct HostExpertFp8BlockScales {
1735 pub scales: Vec<f32>,
1736 pub rows: usize,
1737 pub cols: usize,
1738 pub expert_stride: usize,
1739}
1740
1741impl HostExps {
1742 pub fn load(e: &Engine, g: &GgufFile, name: &str) -> Result<Self, Box<dyn std::error::Error>> {
1746 Self::load_stacked_from_source(e, &GgufSource(g), name)
1747 }
1748
1749 pub fn load_stacked_split_from_source(
1756 e: &Engine,
1757 src: &dyn TensorSource,
1758 name: &str,
1759 row0: usize,
1760 row1: usize,
1761 ) -> Result<Self, Box<dyn std::error::Error>> {
1762 let t = src
1763 .find(name)
1764 .unwrap_or_else(|| panic!("missing exps tensor {name}"));
1765 assert_eq!(t.ne.len(), 3, "{name} is not 3D (ne={:?})", t.ne);
1766 let qtype = match t.ggml_type {
1767 GgmlType::Q8_0 => QT_Q8_0,
1768 GgmlType::Q4_K => QT_Q4_K,
1769 GgmlType::Q6_K => QT_Q6_K,
1770 GgmlType::Q5_K => QT_Q5_K,
1771 GgmlType::Q3_K => QT_Q3_K,
1772 GgmlType::IQ4_XS => QT_IQ4_XS,
1773 GgmlType::IQ3_S => QT_IQ3_S,
1774 GgmlType::NVFP4 => QT_NVFP4,
1775 GgmlType::Q4_0 => QT_Q4_0,
1776 other => panic!("exps {name} unsupported quant {other:?}"),
1777 };
1778 let raw: &[u8] = &t.bytes;
1779 let in_f = t.ne[0] as usize;
1780 let out_full = t.ne[1] as usize;
1781 let n_expert = t.ne[2] as usize;
1782 let full_stride = raw.len() / n_expert;
1783 let row_bytes = raw.len() / (out_full * n_expert);
1784 assert_eq!(full_stride, out_full * row_bytes, "{name} stride mismatch");
1785 let out_f = row1 - row0;
1786 let expert_stride = out_f * row_bytes;
1787 let mut buf = vec![0u8; n_expert * expert_stride];
1788 for ex in 0..n_expert {
1789 let s0 = ex * full_stride + row0 * row_bytes;
1790 buf[ex * expert_stride..(ex + 1) * expert_stride]
1791 .copy_from_slice(&raw[s0..s0 + expert_stride]);
1792 }
1793 let pinned = std::env::var("MEMRA_MOE_PINNED").is_ok()
1794 || std::env::var("MEMRA_MOE_CACHE").as_deref() != Ok("0");
1795 let bytes = if pinned {
1796 let mut pn = unsafe { e.ctx().alloc_pinned::<u8>(buf.len())? };
1797 {
1798 let dst = pn.as_mut_slice()?;
1799 dst.copy_from_slice(&buf);
1800 }
1801 let base = pn.as_ptr()?;
1802 let len = buf.len();
1803 HostBuf::Pinned {
1804 slice: std::sync::Arc::new(pn),
1805 base,
1806 len,
1807 }
1808 } else {
1809 HostBuf::Paged(buf)
1810 };
1811 Ok(HostExps {
1812 bytes,
1813 tiers: None,
1814 qtype,
1815 in_f,
1816 out_f,
1817 n_expert,
1818 row_bytes,
1819 expert_stride,
1820 layouts: None,
1821 macros: None,
1822 fp8_blk: None,
1823 })
1824 }
1825
1826 fn stacked_macros(src: &dyn TensorSource, name: &str) -> Option<Vec<f32>> {
1832 let stem = name.strip_suffix(".weight")?;
1833 let sv = src.find(&format!("{stem}.scale"))?;
1834 if sv.ggml_type != GgmlType::F32 {
1835 return None;
1836 }
1837 let macros: Vec<f32> = sv
1838 .bytes
1839 .chunks_exact(4)
1840 .map(|c| f32::from_le_bytes(c.try_into().unwrap()))
1841 .collect();
1842 if macros.iter().all(|&m| m == 1.0) {
1843 None
1844 } else {
1845 Some(macros)
1846 }
1847 }
1848
1849 fn load_nvfp4_stacked_native(
1857 src: &dyn TensorSource,
1858 name: &str,
1859 ) -> Result<Option<Self>, Box<dyn std::error::Error>> {
1860 let Some(bank) = src.find_nvfp4_stacked_native(name) else {
1861 return Ok(None);
1862 };
1863 let (n_expert, out_f, in_f) = (bank.n_expert, bank.out_f, bank.in_f);
1864 if in_f % 64 != 0 {
1865 return Err(
1866 format!("{name} stacked NVFP4 in_features {in_f} is not 64-aligned").into(),
1867 );
1868 }
1869 let row_bytes = in_f / 64 * 36;
1870 let expert_stride = out_f * row_bytes;
1871 let total = n_expert * expert_stride;
1872 let code_stride = out_f * in_f / 2;
1873 let scale_stride = out_f * in_f / 16;
1874 let macros = bank.macros.clone();
1875 let cache_path = if let Some(dir) = src.st_dir() {
1876 let cache_dir = dir.join(".memra-repack");
1877 ensure_repack_cache_dir(&cache_dir)?;
1878 Some(cache_dir.join(format!(
1879 "{}-stacked-{n_expert}x{out_f}x{in_f}{}.nvfp4",
1880 name.replace(['.', '/'], "-"),
1881 src.nvfp4_cache_tag()
1882 )))
1883 } else {
1884 None
1885 };
1886 let bytes = if let Some(cache) = cache_path.as_ref() {
1887 let fresh = repack_cache_is_fresh(cache, total);
1888 if !fresh {
1889 write_repack_cache(cache, |out| {
1890 for expert in 0..n_expert {
1891 use std::io::Write;
1892 out.write_all(&memra_gguf::nvfp4_repack::repack_modelopt_to_gguf(
1893 &bank.codes[expert * code_stride..(expert + 1) * code_stride],
1894 &bank.scales[expert * scale_stride..(expert + 1) * scale_stride],
1895 out_f,
1896 in_f,
1897 ))?;
1898 }
1899 Ok(())
1900 })?;
1901 }
1902 let file = std::sync::Arc::new(open_repack_cache(cache, false)?);
1903 let map = unsafe { memmap2::Mmap::map(file.as_ref())? };
1904 assert_eq!(map.len(), total, "repack cache {cache:?} size mismatch");
1905 let _ = memra_gguf::source::apply_expert_mmap_advice(&map);
1906 memra_gguf::source::populate_expert_slab(&file, total, name);
1907 HostBuf::Mmap {
1908 map: std::sync::Arc::new(map),
1909 file,
1910 off: 0,
1911 len: total,
1912 }
1913 } else {
1914 let mut buf: Vec<u8> = Vec::with_capacity(total);
1915 for expert in 0..n_expert {
1916 buf.extend_from_slice(&memra_gguf::nvfp4_repack::repack_modelopt_to_gguf(
1917 &bank.codes[expert * code_stride..(expert + 1) * code_stride],
1918 &bank.scales[expert * scale_stride..(expert + 1) * scale_stride],
1919 out_f,
1920 in_f,
1921 ));
1922 }
1923 assert_eq!(buf.len(), total);
1924 HostBuf::Paged(buf)
1925 };
1926 let all_one = macros.iter().all(|&value| value == 1.0);
1927 Ok(Some(HostExps {
1928 bytes,
1929 tiers: None,
1930 qtype: QT_NVFP4,
1931 in_f,
1932 out_f,
1933 n_expert,
1934 row_bytes,
1935 expert_stride,
1936 layouts: None,
1937 macros: if all_one { None } else { Some(macros) },
1938 fp8_blk: None,
1939 }))
1940 }
1941
1942 fn load_fp8_stacked_native_with_policy(
1943 src: &dyn TensorSource,
1944 name: &str,
1945 native_enabled: bool,
1946 ) -> Result<Option<Self>, Box<dyn std::error::Error>> {
1947 let Some(f8) = src.find_fp8_stacked_native(name) else {
1948 return Ok(None);
1949 };
1950 if f8.scale_rows != f8.out_f.div_ceil(128) || f8.scale_cols != f8.in_f.div_ceil(128) {
1951 return Err(format!(
1952 "{name} FP8 scale geometry mismatch: got {}x{}, expected {}x{}",
1953 f8.scale_rows,
1954 f8.scale_cols,
1955 f8.out_f.div_ceil(128),
1956 f8.in_f.div_ceil(128)
1957 )
1958 .into());
1959 }
1960 if f8.bytes.iter().any(|code| code & 0x7f == 0x7f) {
1961 return Err(format!("{name} FP8 code slab contains non-finite E4M3 values").into());
1962 }
1963 let scale_stride = f8.scale_rows * f8.scale_cols;
1964 if !native_enabled {
1965 if f8.in_f % 32 != 0 {
1966 return Err(format!(
1967 "{name} FP8 rollback requires an input width divisible by 32, got {}",
1968 f8.in_f
1969 )
1970 .into());
1971 }
1972 let mut q8 = Vec::new();
1973 for expert in 0..f8.n_expert {
1974 let mut data = Vec::with_capacity(f8.out_f * f8.in_f);
1975 for output in 0..f8.out_f {
1976 let row = (expert * f8.out_f + output) * f8.in_f;
1977 for input in 0..f8.in_f {
1978 let scale = f8.scales
1979 [expert * scale_stride + (output / 128) * f8.scale_cols + input / 128];
1980 data.push(
1981 memra_gguf::nvfp4_repack::fp8_e4m3_to_f32(f8.bytes[row + input])
1982 * scale,
1983 );
1984 }
1985 }
1986 q8.extend_from_slice(&memra_gguf::nvfp4_repack::f32_to_q8_0(&data));
1987 }
1988 let row_bytes = f8.in_f / 32 * 34;
1989 let expert_stride = f8.out_f * row_bytes;
1990 assert_eq!(q8.len(), f8.n_expert * expert_stride);
1991 return Ok(Some(HostExps {
1992 bytes: HostBuf::Paged(q8),
1993 tiers: None,
1994 qtype: QT_Q8_0,
1995 in_f: f8.in_f,
1996 out_f: f8.out_f,
1997 n_expert: f8.n_expert,
1998 row_bytes,
1999 expert_stride,
2000 layouts: None,
2001 macros: None,
2002 fp8_blk: None,
2003 }));
2004 }
2005
2006 assert_eq!(
2007 f8.bytes.len(),
2008 f8.n_expert * f8.out_f * f8.in_f,
2009 "{name} FP8 code slab length mismatch"
2010 );
2011 assert_eq!(
2012 f8.scales.len(),
2013 f8.n_expert * scale_stride,
2014 "{name} FP8 scale slab length mismatch"
2015 );
2016 let expert_stride = f8.out_f * f8.in_f;
2017 let bytes = match find_expert_disk_strict(src, name)? {
2018 Some(extent) => {
2019 if extent.len != f8.bytes.len() {
2020 return Err(format!(
2021 "{name} FP8 mmap length mismatch: extent={} tensor={}",
2022 extent.len,
2023 f8.bytes.len()
2024 )
2025 .into());
2026 }
2027 let off = usize::try_from(extent.offset).map_err(|_| {
2028 format!(
2029 "{name} FP8 mmap offset {} does not fit usize",
2030 extent.offset
2031 )
2032 })?;
2033 HostBuf::Mmap {
2034 map: extent.map,
2035 file: extent.file,
2036 off,
2037 len: extent.len,
2038 }
2039 }
2040 None => HostBuf::Paged(f8.bytes.to_vec()),
2041 };
2042 Ok(Some(HostExps {
2043 bytes,
2044 tiers: None,
2045 qtype: crate::QT_F8_E4M3_BLK,
2046 in_f: f8.in_f,
2047 out_f: f8.out_f,
2048 n_expert: f8.n_expert,
2049 row_bytes: f8.in_f,
2050 expert_stride,
2051 layouts: None,
2052 macros: None,
2053 fp8_blk: Some(HostExpertFp8BlockScales {
2054 scales: f8.scales,
2055 rows: f8.scale_rows,
2056 cols: f8.scale_cols,
2057 expert_stride: scale_stride,
2058 }),
2059 }))
2060 }
2061
2062 pub fn load_stacked_from_source(
2063 e: &Engine,
2064 src: &dyn TensorSource,
2065 name: &str,
2066 ) -> Result<Self, Box<dyn std::error::Error>> {
2067 if let Some(exps) = Self::load_fp8_stacked_native_with_policy(
2068 src,
2069 name,
2070 crate::fp8_ffi::st_e4m3_blk_enabled(),
2071 )? {
2072 return Ok(exps);
2073 }
2074 if let Some(exps) = Self::load_nvfp4_stacked_native(src, name)? {
2075 return Ok(exps);
2076 }
2077
2078 let t = src
2079 .find(name)
2080 .unwrap_or_else(|| panic!("missing exps tensor {name}"));
2081 assert_eq!(
2082 t.ne.len(),
2083 3,
2084 "{name} is not a 3D stacked-expert tensor (ne={:?})",
2085 t.ne
2086 );
2087 if let Some(DiskExtent {
2097 map,
2098 file,
2099 offset,
2100 len,
2101 }) = find_expert_disk_strict(src, name)?
2102 {
2103 let off = usize::try_from(offset)
2104 .map_err(|_| format!("{name} disk offset {offset} does not fit usize"))?;
2105 let qtype = match t.ggml_type {
2106 GgmlType::Q8_0 => QT_Q8_0,
2107 GgmlType::Q4_K => QT_Q4_K,
2108 GgmlType::Q6_K => QT_Q6_K,
2109 GgmlType::Q5_K => QT_Q5_K,
2110 GgmlType::Q3_K => QT_Q3_K,
2111 GgmlType::IQ4_XS => QT_IQ4_XS,
2112 GgmlType::IQ3_S => QT_IQ3_S,
2113 GgmlType::NVFP4 => QT_NVFP4,
2114 GgmlType::Q4_0 => QT_Q4_0,
2115 other => panic!("exps {name} unsupported quant {other:?}"),
2116 };
2117 let in_f = t.ne[0] as usize;
2118 let out_f = t.ne[1] as usize;
2119 let n_expert = t.ne[2] as usize;
2120 let expert_stride = len / n_expert;
2121 let row_bytes = len / (out_f * n_expert);
2122 assert_eq!(
2123 expert_stride,
2124 out_f * row_bytes,
2125 "{name} stride mismatch: stride={expert_stride} out_f={out_f} row_bytes={row_bytes}"
2126 );
2127 assert_eq!(
2128 len,
2129 n_expert * expert_stride,
2130 "{name} mmap len != n_expert*stride"
2131 );
2132 return Ok(HostExps {
2133 bytes: HostBuf::Mmap {
2134 map,
2135 file,
2136 off,
2137 len,
2138 },
2139 tiers: None,
2140 qtype,
2141 in_f,
2142 out_f,
2143 n_expert,
2144 row_bytes,
2145 expert_stride,
2146 layouts: None,
2147 macros: Self::stacked_macros(src, name),
2148 fp8_blk: None,
2149 });
2150 }
2151 let raw: &[u8] = &t.bytes;
2152 let qtype = match t.ggml_type {
2154 GgmlType::Q8_0 => QT_Q8_0,
2155 GgmlType::Q4_K => QT_Q4_K,
2156 GgmlType::Q6_K => QT_Q6_K,
2157 GgmlType::Q5_K => QT_Q5_K,
2158 GgmlType::Q3_K => QT_Q3_K,
2159 GgmlType::IQ4_XS => QT_IQ4_XS,
2160 GgmlType::IQ3_S => QT_IQ3_S,
2161 GgmlType::NVFP4 => QT_NVFP4,
2162 GgmlType::Q4_0 => QT_Q4_0,
2163 other => panic!("exps {name} unsupported quant {other:?}"),
2164 };
2165 let in_f = t.ne[0] as usize;
2166 let out_f = t.ne[1] as usize;
2167 let n_expert = t.ne[2] as usize;
2168 let expert_stride = raw.len() / n_expert;
2171 let row_bytes = raw.len() / (out_f * n_expert);
2172 assert_eq!(
2174 expert_stride,
2175 out_f * row_bytes,
2176 "{name} stride mismatch: stride={expert_stride} out_f={out_f} row_bytes={row_bytes}"
2177 );
2178
2179 let pinned = std::env::var("MEMRA_MOE_PINNED").is_ok()
2180 || std::env::var("MEMRA_MOE_CACHE").as_deref() != Ok("0");
2181 let bytes = if pinned {
2182 let mut p = unsafe { e.ctx().alloc_pinned::<u8>(raw.len())? };
2184 {
2185 let dst = p.as_mut_slice()?;
2186 dst.copy_from_slice(raw);
2187 }
2188 let base = p.as_ptr()?; let len = raw.len();
2190 HostBuf::Pinned {
2191 slice: std::sync::Arc::new(p),
2192 base,
2193 len,
2194 }
2195 } else {
2196 HostBuf::Paged(raw.to_vec())
2197 };
2198 Ok(HostExps {
2199 bytes,
2200 tiers: None,
2201 qtype,
2202 in_f,
2203 out_f,
2204 n_expert,
2205 row_bytes,
2206 expert_stride,
2207 layouts: None,
2208 macros: Self::stacked_macros(src, name),
2209 fp8_blk: None,
2210 })
2211 }
2212
2213 pub fn load_tiered(
2222 e: &Engine,
2223 g: &GgufFile,
2224 name: &str,
2225 ctx: &mut crate::spill::SpillCtx,
2226 ) -> Result<Self, Box<dyn std::error::Error>> {
2227 let t = g
2228 .find(name)
2229 .unwrap_or_else(|| panic!("missing exps tensor {name}"));
2230 assert_eq!(
2231 t.ne.len(),
2232 3,
2233 "{name} is not a 3D stacked-expert tensor (ne={:?})",
2234 t.ne
2235 );
2236 let raw = g.tensor_data(t);
2237 let qtype = match t.ggml_type {
2238 GgmlType::Q8_0 => QT_Q8_0,
2239 GgmlType::Q4_K => QT_Q4_K,
2240 GgmlType::Q6_K => QT_Q6_K,
2241 GgmlType::Q5_K => QT_Q5_K,
2242 GgmlType::Q3_K => QT_Q3_K,
2243 GgmlType::IQ4_XS => QT_IQ4_XS,
2244 GgmlType::IQ3_S => QT_IQ3_S,
2245 GgmlType::NVFP4 => QT_NVFP4,
2246 GgmlType::Q4_0 => QT_Q4_0,
2247 other => panic!("exps {name} unsupported quant {other:?}"),
2248 };
2249 let in_f = t.ne[0] as usize;
2250 let out_f = t.ne[1] as usize;
2251 let n_expert = t.ne[2] as usize;
2252 let expert_stride = raw.len() / n_expert;
2253 let row_bytes = raw.len() / (out_f * n_expert);
2254 assert_eq!(
2255 expert_stride,
2256 out_f * row_bytes,
2257 "{name} stride mismatch: stride={expert_stride} out_f={out_f} row_bytes={row_bytes}"
2258 );
2259
2260 let (file_start, _file_end) = g.tensor_file_range(t);
2264
2265 let mut tiers = Vec::with_capacity(n_expert);
2268 for ex in 0..n_expert {
2269 let blk = &raw[ex * expert_stride..(ex + 1) * expert_stride];
2270 let file_off = file_start + ex * expert_stride;
2271 tiers.push(crate::spill::place_expert(ctx, e, blk, file_off, t.shard)?);
2272 }
2273 Ok(HostExps {
2274 bytes: HostBuf::Paged(Vec::new()), tiers: Some(tiers),
2276 qtype,
2277 in_f,
2278 out_f,
2279 n_expert,
2280 row_bytes,
2281 expert_stride,
2282 layouts: None,
2283 macros: Self::stacked_macros(&GgufSource(g), name),
2284 fp8_blk: None,
2285 })
2286 }
2287
2288 pub fn load_from_source(
2303 e: &Engine,
2304 src: &dyn TensorSource,
2305 ggml_exps_name: &str,
2306 n_expert: usize,
2307 ) -> Result<Self, Box<dyn std::error::Error>> {
2308 let rest = ggml_exps_name
2310 .strip_prefix("blk.")
2311 .unwrap_or_else(|| panic!("not a blk.* name: {ggml_exps_name}"));
2312 let (il_s, suffix) = rest.split_once('.').unwrap();
2313 let il: u32 = il_s.parse().unwrap();
2314 let proj = match suffix {
2315 "ffn_gate_exps.weight" => "gate",
2316 "ffn_up_exps.weight" => "up",
2317 "ffn_down_exps.weight" => "down",
2318 other => panic!("not a *_exps suffix: {other}"),
2319 };
2320
2321 let mut signatures = Vec::with_capacity(n_expert);
2325 let active = src.active_experts(il);
2326 for ex in 0..n_expert {
2327 if active.is_some_and(|mask| !mask[ex]) {
2328 signatures.push((i32::MIN, 0));
2329 continue;
2330 }
2331 let name = format!("blk.{il}.ffn_{proj}_exps.{ex}.weight");
2332 if let Some(nv) = src.find_nvfp4_native(&name) {
2333 signatures.push((QT_NVFP4, nv.in_f / 64 * 36));
2334 } else {
2335 let v = src
2336 .find(&name)
2337 .unwrap_or_else(|| panic!("missing expert tensor {name}"));
2338 let in_f = v.ne[0] as usize;
2339 signatures.push(match staged_expert_row_bytes(v.ggml_type, in_f) {
2340 Some(row_bytes) => (staged_expert_qtype(v.ggml_type).unwrap(), row_bytes),
2341 None => (QT_F32, in_f * 4),
2342 });
2343 }
2344 }
2345 let mixed_layout = signatures.windows(2).any(|pair| pair[0] != pair[1]);
2346 if src.preserve_expert_encodings()
2347 && !mixed_layout
2348 && let Some(uniform) = Self::load_uniform_mmap_from_source(src, il, proj, n_expert)?
2349 {
2350 return Ok(uniform);
2351 }
2352 if src.preserve_expert_encodings() || mixed_layout {
2353 return Self::load_mixed_from_source(src, il, proj, n_expert);
2354 }
2355
2356 {
2363 let name0 = format!("blk.{il}.ffn_{proj}_exps.0.weight");
2364 if let Some(nv0) = src.find_nvfp4_native(&name0) {
2365 let (in_f, out_f) = (nv0.in_f, nv0.out_f);
2366 let row_bytes = in_f / 64 * 36;
2367 let expert_stride = out_f * row_bytes;
2368 let disk = std::env::var("MEMRA_ST_REPACK_DISK")
2375 .map(|v| v != "0")
2376 .unwrap_or(true)
2377 && src.st_dir().is_some();
2378 let cache_path = if let Some(dir) = src.st_dir() {
2379 let cache_dir = dir.join(".memra-repack");
2380 ensure_repack_cache_dir(&cache_dir)?;
2381 Some(cache_dir.join(format!(
2382 "blk{il}-{proj}-{n_expert}x{out_f}x{in_f}{}.nvfp4",
2383 src.nvfp4_cache_tag()
2384 )))
2385 } else {
2386 None
2387 };
2388 let total = n_expert * expert_stride;
2389 let mut macros = vec![1.0f32; n_expert];
2390 let read_macros = |macros: &mut Vec<f32>| {
2391 #[allow(clippy::needless_range_loop)]
2392 for ex in 0..n_expert {
2394 let stem = format!("blk.{il}.ffn_{proj}_exps.{ex}");
2395 if let Some(sv) = src.find(&format!("{stem}.scale")) {
2396 macros[ex] = f32::from_le_bytes(sv.bytes[..4].try_into().unwrap());
2397 }
2398 }
2399 };
2400 let bytes = if disk {
2401 let cp = cache_path.as_ref().unwrap();
2402 let fresh = repack_cache_is_fresh(cp, total);
2403 if !fresh {
2404 write_repack_cache(cp, |out| {
2406 for ex in 0..n_expert {
2407 use std::io::Write;
2408 let name = format!("blk.{il}.ffn_{proj}_exps.{ex}.weight");
2409 let nv = src.find_nvfp4_native(&name).unwrap_or_else(|| {
2410 panic!("expert {name} lost NVFP4-native mid-gather")
2411 });
2412 assert_eq!(
2413 (nv.in_f, nv.out_f),
2414 (in_f, out_f),
2415 "expert {ex} dims ({},{}) != expert 0 ({in_f},{out_f})",
2416 nv.in_f,
2417 nv.out_f
2418 );
2419 out.write_all(&memra_gguf::nvfp4_repack::repack_modelopt_to_gguf(
2420 nv.wbytes, &nv.wscale, out_f, in_f,
2421 ))?;
2422 }
2423 Ok(())
2424 })?;
2425 }
2426 read_macros(&mut macros);
2427 let file = std::sync::Arc::new(open_repack_cache(cp, false)?);
2428 let map = unsafe { memmap2::Mmap::map(file.as_ref())? };
2429 assert_eq!(map.len(), total, "repack cache {cp:?} size mismatch");
2430 let _ = memra_gguf::source::apply_expert_mmap_advice(&map);
2433 memra_gguf::source::populate_expert_slab(
2434 &file,
2435 total,
2436 &format!("blk{il}-{proj}"),
2437 );
2438 let map = std::sync::Arc::new(map);
2439 let tiers = if std::env::var("MEMRA_ST_PINNED")
2452 .map(|v| v == "1")
2453 .unwrap_or(false)
2454 {
2455 static PIN_BUDGET: std::sync::OnceLock<std::sync::Mutex<usize>> =
2456 std::sync::OnceLock::new();
2457 let budget = PIN_BUDGET.get_or_init(|| {
2458 let b = crate::spill::MemBudget::probe(e)
2459 .map(|b| b.free_pinnable_ram)
2460 .unwrap_or(0);
2461 eprintln!("[st-spill] free_pinnable_ram={} MiB", b >> 20);
2462 std::sync::Mutex::new(b)
2463 });
2464 let mut rem = budget.lock().unwrap();
2465 let n_pin = (*rem / expert_stride).min(n_expert);
2469 if n_pin == 0 {
2470 None
2471 } else {
2472 let slab_len = n_pin * expert_stride;
2473 let mut pn = unsafe { e.ctx().alloc_pinned::<u8>(slab_len)? };
2474 {
2475 let dst = pn.as_mut_slice()?;
2476 dst.copy_from_slice(&map[..slab_len]);
2477 }
2478 let base = pn.as_ptr()?;
2479 *rem -= slab_len;
2480 let slab = std::sync::Arc::new(HostBuf::Pinned {
2481 slice: std::sync::Arc::new(pn),
2482 base,
2483 len: slab_len,
2484 });
2485 let mut tiers: Vec<HostBuf> = Vec::with_capacity(n_expert);
2486 for ex in 0..n_expert {
2487 let off = ex * expert_stride;
2488 if ex < n_pin {
2489 tiers.push(HostBuf::PinnedAlias {
2490 owner: slab.clone(),
2491 base: unsafe { base.add(off) },
2492 len: expert_stride,
2493 });
2494 } else {
2495 tiers.push(HostBuf::Mmap {
2496 map: map.clone(),
2497 file: file.clone(),
2498 off,
2499 len: expert_stride,
2500 });
2501 }
2502 }
2503 Some(tiers)
2504 }
2505 } else {
2506 None
2507 };
2508 if let Some(tiers) = tiers {
2509 let all_one = macros.iter().all(|&m| m == 1.0);
2510 return Ok(HostExps {
2511 bytes: HostBuf::Mmap {
2512 map,
2513 file,
2514 off: 0,
2515 len: total,
2516 },
2517 tiers: Some(tiers),
2518 qtype: QT_NVFP4,
2519 in_f,
2520 out_f,
2521 n_expert,
2522 row_bytes,
2523 expert_stride,
2524 layouts: None,
2525 macros: if all_one { None } else { Some(macros) },
2526 fp8_blk: None,
2527 });
2528 }
2529 HostBuf::Mmap {
2530 map,
2531 file,
2532 off: 0,
2533 len: total,
2534 }
2535 } else {
2536 let mut buf: Vec<u8> = Vec::with_capacity(total);
2537 for ex in 0..n_expert {
2538 let name = format!("blk.{il}.ffn_{proj}_exps.{ex}.weight");
2539 let nv = src.find_nvfp4_native(&name).unwrap_or_else(|| {
2540 panic!("expert {name} lost NVFP4-native mid-gather")
2541 });
2542 assert_eq!(
2543 (nv.in_f, nv.out_f),
2544 (in_f, out_f),
2545 "expert {ex} dims ({},{}) != expert 0 ({in_f},{out_f})",
2546 nv.in_f,
2547 nv.out_f
2548 );
2549 buf.extend_from_slice(&memra_gguf::nvfp4_repack::repack_modelopt_to_gguf(
2550 nv.wbytes, &nv.wscale, out_f, in_f,
2551 ));
2552 }
2553 assert_eq!(buf.len(), total);
2554 read_macros(&mut macros);
2555 let pinned = std::env::var("MEMRA_MOE_PINNED").is_ok()
2556 || std::env::var("MEMRA_MOE_CACHE").as_deref() != Ok("0");
2557 if pinned {
2558 let mut p = unsafe { e.ctx().alloc_pinned::<u8>(buf.len())? };
2559 {
2560 let dst = p.as_mut_slice()?;
2561 dst.copy_from_slice(&buf);
2562 }
2563 let base = p.as_ptr()?;
2564 let len = buf.len();
2565 HostBuf::Pinned {
2566 slice: std::sync::Arc::new(p),
2567 base,
2568 len,
2569 }
2570 } else {
2571 HostBuf::Paged(buf)
2572 }
2573 };
2574 let all_one = macros.iter().all(|&m| m == 1.0);
2575 return Ok(HostExps {
2576 bytes,
2577 tiers: None,
2578 qtype: QT_NVFP4,
2579 in_f,
2580 out_f,
2581 n_expert,
2582 row_bytes,
2583 expert_stride,
2584 layouts: None,
2585 macros: if all_one { None } else { Some(macros) },
2586 fp8_blk: None,
2587 });
2588 }
2589 }
2590
2591 let mut buf: Vec<u8> = Vec::new();
2593 let mut in_f = 0usize;
2594 let mut out_f = 0usize;
2595 for ex in 0..n_expert {
2596 let name = format!("blk.{il}.ffn_{proj}_exps.{ex}.weight");
2598 let v = src
2599 .find(&name)
2600 .unwrap_or_else(|| panic!("missing expert tensor {name}"));
2601 assert_eq!(v.ne.len(), 2, "expert {name} is not 2D (ne={:?})", v.ne);
2602 let (cur_in, cur_out) = (v.ne[0] as usize, v.ne[1] as usize);
2603 if ex == 0 {
2604 in_f = cur_in;
2605 out_f = cur_out;
2606 } else {
2607 assert_eq!(
2608 (cur_in, cur_out),
2609 (in_f, out_f),
2610 "expert {ex} dims {:?} != expert 0 [{in_f},{out_f}]",
2611 (cur_in, cur_out)
2612 );
2613 }
2614 let n = cur_in * cur_out;
2617 let f32v = dequant::dequantize(v.ggml_type, &v.bytes, n);
2618 buf.reserve(n * 4);
2619 for f in &f32v {
2620 buf.extend_from_slice(&f.to_le_bytes());
2621 }
2622 }
2623 let row_bytes = in_f * 4; let expert_stride = out_f * row_bytes;
2625 assert_eq!(
2626 buf.len(),
2627 n_expert * expert_stride,
2628 "{ggml_exps_name} gather size {} != n_expert*stride {}",
2629 buf.len(),
2630 n_expert * expert_stride
2631 );
2632 assert_eq!(
2634 expert_stride,
2635 out_f * row_bytes,
2636 "{ggml_exps_name} stride mismatch: stride={expert_stride} out_f={out_f} row_bytes={row_bytes}"
2637 );
2638
2639 let pinned = std::env::var("MEMRA_MOE_PINNED").is_ok()
2641 || std::env::var("MEMRA_MOE_CACHE").as_deref() != Ok("0");
2642 let bytes = if pinned {
2643 let mut p = unsafe { e.ctx().alloc_pinned::<u8>(buf.len())? };
2644 {
2645 let dst = p.as_mut_slice()?;
2646 dst.copy_from_slice(&buf);
2647 }
2648 let base = p.as_ptr()?;
2649 let len = buf.len();
2650 HostBuf::Pinned {
2651 slice: std::sync::Arc::new(p),
2652 base,
2653 len,
2654 }
2655 } else {
2656 HostBuf::Paged(buf)
2657 };
2658 Ok(HostExps {
2659 bytes,
2660 tiers: None,
2661 qtype: QT_F32,
2662 in_f,
2663 out_f,
2664 n_expert,
2665 row_bytes,
2666 expert_stride,
2667 layouts: None,
2668 macros: None,
2669 fp8_blk: None,
2670 })
2671 }
2672
2673 fn load_uniform_mmap_from_source(
2678 src: &dyn TensorSource,
2679 il: u32,
2680 proj: &str,
2681 n_expert: usize,
2682 ) -> Result<Option<Self>, Box<dyn std::error::Error>> {
2683 if src
2684 .active_experts(il)
2685 .is_some_and(|mask| mask.iter().any(|&active| !active))
2686 {
2687 return Ok(None);
2688 }
2689 let mut first_map = None;
2690 let mut first_file = None;
2691 let mut base_offset = 0u64;
2692 let mut expert_stride = 0usize;
2693 let mut in_f = 0usize;
2694 let mut out_f = 0usize;
2695 let mut qtype = 0i32;
2696 let mut row_bytes = 0usize;
2697 let mut macros = vec![1.0f32; n_expert];
2698 #[allow(clippy::needless_range_loop)]
2699 for ex in 0..n_expert {
2701 let stem = format!("blk.{il}.ffn_{proj}_exps.{ex}");
2702 let name = format!("{stem}.weight");
2703 let Some(DiskExtent {
2704 map,
2705 file,
2706 offset,
2707 len,
2708 }) = find_expert_disk_strict(src, &name)?
2709 else {
2710 return Ok(None);
2711 };
2712 let Some(v) = src.find(&name) else {
2713 return Ok(None);
2714 };
2715 if v.ne.len() != 2 {
2716 return Ok(None);
2717 }
2718 let (cur_in, cur_out) = (v.ne[0] as usize, v.ne[1] as usize);
2719 let Some(cur_row_bytes) = staged_expert_row_bytes(v.ggml_type, cur_in) else {
2720 return Ok(None);
2721 };
2722 let cur_qtype = staged_expert_qtype(v.ggml_type).unwrap();
2723 if ex == 0 {
2724 base_offset = offset;
2725 expert_stride = len;
2726 in_f = cur_in;
2727 out_f = cur_out;
2728 qtype = cur_qtype;
2729 row_bytes = cur_row_bytes;
2730 first_map = Some(map);
2731 first_file = Some(file);
2732 } else if !std::sync::Arc::ptr_eq(first_map.as_ref().unwrap(), &map)
2733 || !std::sync::Arc::ptr_eq(first_file.as_ref().unwrap(), &file)
2734 || offset != base_offset + (ex * expert_stride) as u64
2735 || len != expert_stride
2736 || (cur_in, cur_out, cur_qtype, cur_row_bytes) != (in_f, out_f, qtype, row_bytes)
2737 {
2738 return Ok(None);
2739 }
2740 if let Some(scale) = src.find(&format!("{stem}.scale")) {
2741 macros[ex] = f32::from_le_bytes(scale.bytes[..4].try_into().unwrap());
2742 }
2743 }
2744 assert_eq!(expert_stride, out_f * row_bytes);
2745 let total = n_expert * expert_stride;
2746 let off = usize::try_from(base_offset)
2747 .map_err(|_| format!("uniform expert disk offset {base_offset} does not fit usize"))?;
2748 let all_one = macros.iter().all(|&scale| scale == 1.0);
2749 Ok(Some(HostExps {
2750 bytes: HostBuf::Mmap {
2751 map: first_map.unwrap(),
2752 file: first_file.unwrap(),
2753 off,
2754 len: total,
2755 },
2756 tiers: None,
2757 qtype,
2758 in_f,
2759 out_f,
2760 n_expert,
2761 row_bytes,
2762 expert_stride,
2763 layouts: None,
2764 macros: if all_one { None } else { Some(macros) },
2765 fp8_blk: None,
2766 }))
2767 }
2768
2769 fn load_mixed_from_source(
2770 src: &dyn TensorSource,
2771 il: u32,
2772 proj: &str,
2773 n_expert: usize,
2774 ) -> Result<Self, Box<dyn std::error::Error>> {
2775 let mut tiers = Vec::with_capacity(n_expert);
2776 let mut layouts = Vec::with_capacity(n_expert);
2777 let mut macros = vec![1.0f32; n_expert];
2778 let mut in_f = 0usize;
2779 let mut out_f = 0usize;
2780 let active = src.active_experts(il);
2781 let mut first_active = None;
2782
2783 for ex in 0..n_expert {
2784 if active.is_some_and(|mask| !mask[ex]) {
2785 layouts.push(ExpertLayout {
2786 offset: 0,
2787 len: 0,
2788 qtype: QT_F32,
2789 row_bytes: 0,
2790 });
2791 tiers.push(HostBuf::Paged(Vec::new()));
2792 continue;
2793 }
2794 let name = format!("blk.{il}.ffn_{proj}_exps.{ex}.weight");
2795 let stem = format!("blk.{il}.ffn_{proj}_exps.{ex}");
2796 if let Some(scale) = src.find(&format!("{stem}.scale")) {
2797 macros[ex] = f32::from_le_bytes(scale.bytes[..4].try_into().unwrap());
2798 }
2799 let (host, byte_len, qtype, row_bytes, cur_in, cur_out) = if let Some(DiskExtent {
2800 map,
2801 file,
2802 offset,
2803 len,
2804 }) =
2805 find_expert_disk_strict(src, &name)?
2806 {
2807 let v = src
2808 .find(&name)
2809 .unwrap_or_else(|| panic!("missing expert tensor {name}"));
2810 assert_eq!(v.ne.len(), 2, "expert {name} is not 2D (ne={:?})", v.ne);
2811 let (cur_in, cur_out) = (v.ne[0] as usize, v.ne[1] as usize);
2812 let row_bytes = staged_expert_row_bytes(v.ggml_type, cur_in).ok_or_else(|| {
2813 format!("mmap expert {name} has unsupported qtype {:?}", v.ggml_type)
2814 })?;
2815 let off = usize::try_from(offset).map_err(|_| {
2816 format!("expert {name} disk offset {offset} does not fit usize")
2817 })?;
2818 (
2819 HostBuf::Mmap {
2820 map,
2821 file,
2822 off,
2823 len,
2824 },
2825 len,
2826 staged_expert_qtype(v.ggml_type).unwrap(),
2827 row_bytes,
2828 cur_in,
2829 cur_out,
2830 )
2831 } else if let Some(nv) = src.find_nvfp4_native(&name) {
2832 let bytes = memra_gguf::nvfp4_repack::repack_modelopt_to_gguf(
2833 nv.wbytes, &nv.wscale, nv.out_f, nv.in_f,
2834 );
2835 let row_bytes = nv.in_f / 64 * 36;
2836 let byte_len = bytes.len();
2837 (
2838 HostBuf::Paged(bytes),
2839 byte_len,
2840 QT_NVFP4,
2841 row_bytes,
2842 nv.in_f,
2843 nv.out_f,
2844 )
2845 } else {
2846 let v = src
2847 .find(&name)
2848 .unwrap_or_else(|| panic!("missing expert tensor {name}"));
2849 assert_eq!(v.ne.len(), 2, "expert {name} is not 2D (ne={:?})", v.ne);
2850 let (cur_in, cur_out) = (v.ne[0] as usize, v.ne[1] as usize);
2851 if let Some(row_bytes) = staged_expert_row_bytes(v.ggml_type, cur_in) {
2852 let bytes = v.bytes.into_owned();
2853 let byte_len = bytes.len();
2854 (
2855 HostBuf::Paged(bytes),
2856 byte_len,
2857 staged_expert_qtype(v.ggml_type).unwrap(),
2858 row_bytes,
2859 cur_in,
2860 cur_out,
2861 )
2862 } else {
2863 let f32v = dequant::dequantize(v.ggml_type, &v.bytes, cur_in * cur_out);
2864 let mut bytes = Vec::with_capacity(f32v.len() * 4);
2865 for f in f32v {
2866 bytes.extend_from_slice(&f.to_le_bytes());
2867 }
2868 let byte_len = bytes.len();
2869 (
2870 HostBuf::Paged(bytes),
2871 byte_len,
2872 QT_F32,
2873 cur_in * 4,
2874 cur_in,
2875 cur_out,
2876 )
2877 }
2878 };
2879
2880 if first_active.is_none() {
2881 in_f = cur_in;
2882 out_f = cur_out;
2883 first_active = Some(ex);
2884 } else {
2885 assert_eq!(
2886 (cur_in, cur_out),
2887 (in_f, out_f),
2888 "expert {ex} dims ({cur_in},{cur_out}) != first active expert ({in_f},{out_f})"
2889 );
2890 }
2891 assert_eq!(
2892 byte_len,
2893 cur_out * row_bytes,
2894 "expert {name} bytes {byte_len} != out_f*row_bytes {}",
2895 cur_out * row_bytes
2896 );
2897 layouts.push(ExpertLayout {
2898 offset: 0,
2899 len: byte_len,
2900 qtype,
2901 row_bytes,
2902 });
2903 tiers.push(host);
2904 }
2905
2906 let first = layouts[*first_active
2907 .as_ref()
2908 .expect("expert mask pruned every expert")];
2909 let expert_stride = layouts.iter().map(|layout| layout.len).max().unwrap_or(0);
2910 let all_one = macros.iter().all(|&scale| scale == 1.0);
2911 Ok(HostExps {
2912 bytes: HostBuf::Paged(Vec::new()),
2913 tiers: Some(tiers),
2914 qtype: first.qtype,
2915 in_f,
2916 out_f,
2917 n_expert,
2918 row_bytes: first.row_bytes,
2919 expert_stride,
2920 layouts: Some(layouts),
2921 macros: if all_one { None } else { Some(macros) },
2922 fp8_blk: None,
2923 })
2924 }
2925
2926 #[inline]
2930 pub fn macro_scale(&self, e: usize) -> f32 {
2931 self.macros.as_ref().map(|m| m[e]).unwrap_or(1.0)
2932 }
2933
2934 #[inline]
2935 pub fn is_uniform_layout(&self) -> bool {
2936 self.layouts.is_none()
2937 }
2938
2939 #[inline]
2940 pub fn expert_layout(&self, e: usize) -> ExpertLayout {
2941 debug_assert!(
2942 e < self.n_expert,
2943 "expert index {e} >= n_expert {}",
2944 self.n_expert
2945 );
2946 self.layouts
2947 .as_ref()
2948 .map(|layouts| layouts[e])
2949 .unwrap_or(ExpertLayout {
2950 offset: e * self.expert_stride,
2951 len: self.expert_stride,
2952 qtype: self.qtype,
2953 row_bytes: self.row_bytes,
2954 })
2955 }
2956
2957 #[inline]
2958 pub fn max_expert_bytes(&self) -> usize {
2959 self.layouts
2960 .as_ref()
2961 .and_then(|layouts| layouts.iter().map(|layout| layout.len).max())
2962 .unwrap_or(self.expert_stride)
2963 }
2964
2965 #[inline]
2967 pub fn expert_bytes(&self, e: usize) -> &[u8] {
2968 let layout = self.expert_layout(e);
2969 match &self.tiers {
2970 Some(tiers) => {
2971 debug_assert_eq!(tiers[e].len(), layout.len);
2972 tiers[e].as_bytes()
2973 }
2974 None => &self.bytes.as_bytes()[layout.offset..layout.offset + layout.len],
2975 }
2976 }
2977
2978 #[inline]
2982 pub(crate) fn expert_source(&self, e: usize) -> ExpertSource<'_> {
2983 let layout = self.expert_layout(e);
2984 match &self.tiers {
2985 Some(tiers) => tiers[e].expert_source(0, layout.len),
2986 None => self.bytes.expert_source(layout.offset, layout.len),
2987 }
2988 }
2989
2990 #[inline]
2994 pub fn prefetch_expert_pages(&self, e: usize) -> bool {
2995 let layout = self.expert_layout(e);
2996 match &self.tiers {
2997 Some(tiers) => tiers[e].advise_willneed(0, layout.len),
2998 None => self.bytes.advise_willneed(layout.offset, layout.len),
2999 }
3000 }
3001}
3002
3003#[cfg(test)]
3004mod tests {
3005 use super::{
3006 ExpertKeepalive, ExpertSource, HostBuf, HostExps, QT_BF16, QT_NVFP4, QT_Q2_K, QT_Q4_K,
3007 ensure_repack_cache_dir, open_repack_cache, repack_cache_is_fresh, repack_nvfp4_split,
3008 unpack_nvfp4_split, write_repack_cache,
3009 };
3010 use memra_gguf::nvfp4_repack::{repack_modelopt_to_gguf, repack_modelopt_to_split};
3011 use memra_gguf::source::{DiskExtent, Fp8StackedNative, TensorSource, TensorView};
3012 use memra_gguf::{GgmlType, config::ModelConfig};
3013 use std::borrow::Cow;
3014
3015 #[cfg(unix)]
3016 #[test]
3017 fn repack_cache_refuses_symlinked_directory_and_file() {
3018 use std::os::unix::fs::symlink;
3019
3020 let root = std::env::temp_dir().join(format!("memra-repack-links-{}", std::process::id()));
3021 std::fs::create_dir_all(&root).unwrap();
3022 let target_dir = root.join("target-dir");
3023 std::fs::create_dir(&target_dir).unwrap();
3024 let cache_dir = root.join(".memra-repack");
3025 symlink(&target_dir, &cache_dir).unwrap();
3026 let error = ensure_repack_cache_dir(&cache_dir).unwrap_err();
3027 assert_eq!(error.kind(), std::io::ErrorKind::InvalidData);
3028
3029 std::fs::remove_file(&cache_dir).unwrap();
3030 std::fs::create_dir(&cache_dir).unwrap();
3031 let target = root.join("outside.bin");
3032 std::fs::write(&target, b"keep").unwrap();
3033 let cache_file = cache_dir.join("artifact.nvfp4");
3034 symlink(&target, &cache_file).unwrap();
3035 assert!(!repack_cache_is_fresh(&cache_file, 4));
3036 let error = open_repack_cache(&cache_file, true).unwrap_err();
3037 assert_ne!(error.kind(), std::io::ErrorKind::NotFound);
3038 assert_eq!(std::fs::read(&target).unwrap(), b"keep");
3039
3040 let hardlink = cache_dir.join("hardlink.nvfp4");
3041 std::fs::hard_link(&target, &hardlink).unwrap();
3042 let error = write_repack_cache(&hardlink, |out| {
3043 use std::io::Write;
3044 out.write_all(b"replacement")
3045 })
3046 .unwrap_err();
3047 assert_eq!(error.kind(), std::io::ErrorKind::InvalidData);
3048 assert_eq!(std::fs::read(&target).unwrap(), b"keep");
3049 std::fs::remove_dir_all(root).ok();
3050 }
3051
3052 struct MixedExpertSource {
3053 bf16: Vec<u8>,
3054 q4k: Vec<u8>,
3055 }
3056
3057 impl TensorSource for MixedExpertSource {
3058 fn config(&self) -> ModelConfig {
3059 panic!("unused by HostExps mixed-loader test")
3060 }
3061
3062 fn find(&self, name: &str) -> Option<TensorView<'_>> {
3063 let (bytes, ggml_type) = if name == "blk.0.ffn_gate_exps.0.weight" {
3064 (&self.bf16, GgmlType::BF16)
3065 } else if name == "blk.0.ffn_gate_exps.1.weight" {
3066 (&self.q4k, GgmlType::Q4_K)
3067 } else {
3068 return None;
3069 };
3070 Some(TensorView {
3071 bytes: Cow::Borrowed(bytes),
3072 ggml_type,
3073 ne: vec![256, 2],
3074 })
3075 }
3076 }
3077
3078 struct PrunedExpertSource {
3079 q2k: Vec<u8>,
3080 nvfp4: Vec<u8>,
3081 active: Vec<bool>,
3082 }
3083
3084 struct MmapExpertSource {
3085 file: std::sync::Arc<std::fs::File>,
3086 map: std::sync::Arc<memmap2::Mmap>,
3087 base_offset: usize,
3088 expert_len: usize,
3089 }
3090
3091 struct LegacyMmapExpertSource {
3092 map: std::sync::Arc<memmap2::Mmap>,
3093 expert_len: usize,
3094 }
3095
3096 struct StackedFp8Source {
3097 file: std::sync::Arc<std::fs::File>,
3098 map: std::sync::Arc<memmap2::Mmap>,
3099 offset: usize,
3100 len: usize,
3101 scales: Vec<f32>,
3102 }
3103
3104 impl TensorSource for StackedFp8Source {
3105 fn config(&self) -> ModelConfig {
3106 panic!("unused by stacked FP8 ownership test")
3107 }
3108
3109 fn find(&self, _name: &str) -> Option<TensorView<'_>> {
3110 None
3111 }
3112
3113 fn find_fp8_stacked_native(&self, name: &str) -> Option<Fp8StackedNative<'_>> {
3114 (name == "blk.0.ffn_gate_exps.weight").then(|| Fp8StackedNative {
3115 bytes: &self.map[self.offset..self.offset + self.len],
3116 scales: self.scales.clone(),
3117 n_expert: 2,
3118 out_f: 2,
3119 in_f: 32,
3120 scale_rows: 1,
3121 scale_cols: 1,
3122 })
3123 }
3124
3125 fn find_expert_disk(&self, name: &str) -> Option<DiskExtent> {
3126 (name == "blk.0.ffn_gate_exps.weight").then(|| DiskExtent {
3127 map: self.map.clone(),
3128 file: self.file.clone(),
3129 offset: self.offset as u64,
3130 len: self.len,
3131 })
3132 }
3133 }
3134
3135 impl TensorSource for MmapExpertSource {
3136 fn config(&self) -> ModelConfig {
3137 panic!("unused by HostExps mmap-loader test")
3138 }
3139 fn preserve_expert_encodings(&self) -> bool {
3140 true
3141 }
3142 fn find(&self, name: &str) -> Option<TensorView<'_>> {
3143 let ex = match name {
3144 "blk.0.ffn_gate_exps.0.weight" => 0,
3145 "blk.0.ffn_gate_exps.1.weight" => 1,
3146 _ => return None,
3147 };
3148 let off = self.base_offset + ex * self.expert_len;
3149 Some(TensorView {
3150 bytes: Cow::Borrowed(&self.map[off..off + self.expert_len]),
3151 ggml_type: GgmlType::Q2_K,
3152 ne: vec![256, 2],
3153 })
3154 }
3155 fn find_expert_disk(&self, name: &str) -> Option<DiskExtent> {
3156 let ex = match name {
3157 "blk.0.ffn_gate_exps.0.weight" => 0,
3158 "blk.0.ffn_gate_exps.1.weight" => 1,
3159 _ => return None,
3160 };
3161 Some(DiskExtent {
3162 map: self.map.clone(),
3163 file: self.file.clone(),
3164 offset: (self.base_offset + ex * self.expert_len) as u64,
3165 len: self.expert_len,
3166 })
3167 }
3168 }
3169
3170 impl TensorSource for LegacyMmapExpertSource {
3171 fn config(&self) -> ModelConfig {
3172 panic!("unused by legacy mmap guard test")
3173 }
3174 fn preserve_expert_encodings(&self) -> bool {
3175 true
3176 }
3177 fn find(&self, name: &str) -> Option<TensorView<'_>> {
3178 let ex = match name {
3179 "blk.0.ffn_gate_exps.0.weight" => 0,
3180 "blk.0.ffn_gate_exps.1.weight" => 1,
3181 _ => return None,
3182 };
3183 let off = ex * self.expert_len;
3184 Some(TensorView {
3185 bytes: Cow::Borrowed(&self.map[off..off + self.expert_len]),
3186 ggml_type: GgmlType::Q2_K,
3187 ne: vec![256, 2],
3188 })
3189 }
3190 fn find_expert_mmap(
3191 &self,
3192 name: &str,
3193 ) -> Option<(std::sync::Arc<memmap2::Mmap>, usize, usize)> {
3194 let ex = match name {
3195 "blk.0.ffn_gate_exps.0.weight" => 0,
3196 "blk.0.ffn_gate_exps.1.weight" => 1,
3197 _ => return None,
3198 };
3199 Some((self.map.clone(), ex * self.expert_len, self.expert_len))
3200 }
3201 }
3202
3203 impl TensorSource for PrunedExpertSource {
3204 fn config(&self) -> ModelConfig {
3205 panic!("unused by HostExps pruned-loader test")
3206 }
3207 fn active_experts(&self, layer: u32) -> Option<&[bool]> {
3208 (layer == 0).then_some(self.active.as_slice())
3209 }
3210 fn find(&self, name: &str) -> Option<TensorView<'_>> {
3211 let (bytes, ggml_type) = match name {
3212 "blk.0.ffn_gate_exps.0.weight" => (&self.q2k, GgmlType::Q2_K),
3213 "blk.0.ffn_gate_exps.2.weight" => (&self.nvfp4, GgmlType::NVFP4),
3214 _ => return None,
3215 };
3216 Some(TensorView {
3217 bytes: Cow::Borrowed(bytes),
3218 ggml_type,
3219 ne: vec![256, 2],
3220 })
3221 }
3222 }
3223
3224 #[test]
3225 fn stacked_fp8_experts_retain_owned_mmap_and_scale_geometry() {
3226 let path = std::env::temp_dir().join(format!("memra-stacked-fp8-{}", std::process::id()));
3227 let offset = 11usize;
3228 let len = 2 * 2 * 32;
3229 let mut file_bytes = vec![0xA5; offset];
3230 file_bytes.extend((0..len).map(|i| (i % 127) as u8));
3231 std::fs::write(&path, &file_bytes).unwrap();
3232 let file = std::sync::Arc::new(std::fs::File::open(&path).unwrap());
3233 let map = std::sync::Arc::new(unsafe { memmap2::Mmap::map(file.as_ref()).unwrap() });
3234 let source = StackedFp8Source {
3235 file,
3236 map,
3237 offset,
3238 len,
3239 scales: vec![0.5, 0.25],
3240 };
3241
3242 let exps = HostExps::load_fp8_stacked_native_with_policy(
3243 &source,
3244 "blk.0.ffn_gate_exps.weight",
3245 true,
3246 )
3247 .unwrap()
3248 .unwrap();
3249 assert_eq!(exps.qtype, crate::QT_F8_E4M3_BLK);
3250 assert_eq!((exps.n_expert, exps.out_f, exps.in_f), (2, 2, 32));
3251 assert_eq!(exps.expert_stride, 64);
3252 assert!(matches!(exps.bytes, HostBuf::Mmap { .. }));
3253 assert_eq!(exps.expert_bytes(0), &file_bytes[offset..offset + 64]);
3254 assert_eq!(exps.expert_bytes(1), &file_bytes[offset + 64..offset + len]);
3255 let fp8 = exps.fp8_blk.as_ref().unwrap();
3256 assert_eq!((fp8.rows, fp8.cols, fp8.expert_stride), (1, 1, 1));
3257 assert_eq!(fp8.scales, vec![0.5, 0.25]);
3258
3259 drop(source);
3260 assert_eq!(exps.expert_bytes(1), &file_bytes[offset + 64..offset + len]);
3261 std::fs::remove_file(path).ok();
3262 }
3263
3264 #[test]
3265 fn stacked_fp8_experts_reject_non_finite_codes() {
3266 let path =
3267 std::env::temp_dir().join(format!("memra-stacked-fp8-nan-{}", std::process::id()));
3268 let len = 2 * 2 * 32;
3269 let mut file_bytes = vec![0x12; len];
3270 file_bytes[73] = 0x7f;
3271 std::fs::write(&path, &file_bytes).unwrap();
3272 let file = std::sync::Arc::new(std::fs::File::open(&path).unwrap());
3273 let map = std::sync::Arc::new(unsafe { memmap2::Mmap::map(file.as_ref()).unwrap() });
3274 let source = StackedFp8Source {
3275 file,
3276 map,
3277 offset: 0,
3278 len,
3279 scales: vec![0.5, 0.25],
3280 };
3281
3282 let err = match HostExps::load_fp8_stacked_native_with_policy(
3283 &source,
3284 "blk.0.ffn_gate_exps.weight",
3285 true,
3286 ) {
3287 Ok(_) => panic!("non-finite E4M3 code was accepted"),
3288 Err(err) => err,
3289 };
3290 assert!(err.to_string().contains("non-finite E4M3"));
3291 std::fs::remove_file(path).ok();
3292 }
3293
3294 #[test]
3298 fn direct_split_equals_chained() {
3299 for (out_f, in_f) in [(1usize, 64usize), (3, 128), (5, 320), (8, 1024)] {
3300 let mut w = vec![0u8; out_f * in_f / 2];
3301 let mut s = vec![0u8; out_f * in_f / 16];
3302 for (i, b) in w.iter_mut().enumerate() {
3303 *b = ((i * 41 + 7) & 0xFF) as u8;
3304 }
3305 for (i, b) in s.iter_mut().enumerate() {
3306 *b = (0x20 + ((i * 11 + 5) % 0x50)) as u8;
3307 }
3308 let gguf = repack_modelopt_to_gguf(&w, &s, out_f, in_f);
3309 let chained = repack_nvfp4_split(&gguf, out_f);
3310 let direct = repack_modelopt_to_split(&w, &s, out_f, in_f);
3311 assert_eq!(
3312 direct, chained,
3313 "fused != chained at out_f={out_f} in_f={in_f}"
3314 );
3315 assert_eq!(
3316 unpack_nvfp4_split(&direct, out_f),
3317 gguf,
3318 "split roundtrip broken at out_f={out_f} in_f={in_f}"
3319 );
3320 }
3321 }
3322
3323 #[test]
3324 fn mixed_expert_loader_keeps_each_encoding_and_extent() {
3325 let source = MixedExpertSource {
3326 bf16: vec![0x5a; 256 * 2 * 2],
3327 q4k: vec![0xa5; 2 * 144],
3328 };
3329 let exps = HostExps::load_mixed_from_source(&source, 0, "gate", 2).unwrap();
3330 assert!(!exps.is_uniform_layout());
3331 assert_eq!(exps.max_expert_bytes(), 1024);
3332 assert_eq!(exps.expert_layout(0).qtype, QT_BF16);
3333 assert_eq!(exps.expert_layout(0).row_bytes, 512);
3334 assert_eq!(exps.expert_layout(0).len, 1024);
3335 assert_eq!(exps.expert_layout(1).qtype, QT_Q4_K);
3336 assert_eq!(exps.expert_layout(1).row_bytes, 144);
3337 assert_eq!(exps.expert_layout(1).len, 288);
3338 assert_eq!(exps.expert_bytes(0), source.bf16);
3339 assert_eq!(exps.expert_bytes(1), source.q4k);
3340 match exps.expert_source(1) {
3341 ExpertSource::Memory { bytes, .. } => assert_eq!(bytes, source.q4k),
3342 ExpertSource::Disk { .. } => panic!("paged expert unexpectedly became disk-backed"),
3343 }
3344 }
3345
3346 #[test]
3347 fn mixed_expert_loader_omits_masked_expert_bytes() {
3348 let source = PrunedExpertSource {
3349 q2k: vec![0x22; 2 * 84],
3350 nvfp4: vec![0x44; 2 * 4 * 36],
3351 active: vec![true, false, true],
3352 };
3353 let exps = HostExps::load_mixed_from_source(&source, 0, "gate", 3).unwrap();
3354 assert_eq!(exps.expert_layout(0).qtype, QT_Q2_K);
3355 assert_eq!(exps.expert_layout(0).row_bytes, 84);
3356 assert_eq!(exps.expert_layout(1).len, 0);
3357 assert_eq!(exps.expert_bytes(1), &[]);
3358 assert_eq!(exps.expert_layout(2).qtype, QT_NVFP4);
3359 assert_eq!(exps.expert_layout(2).row_bytes, 4 * 36);
3360 }
3361
3362 #[test]
3363 fn mixed_expert_loader_keeps_mmap_backing_zero_copy() {
3364 let path = std::env::temp_dir().join(format!("memra-mixed-mmap-{}", std::process::id()));
3365 let base_offset = 3usize;
3366 let expert_len = 2 * 84;
3367 let mut bytes = vec![0xE1; base_offset];
3368 bytes.extend(vec![0x31; expert_len]);
3369 bytes.extend(vec![0x72; expert_len]);
3370 std::fs::write(&path, &bytes).unwrap();
3371 let file = std::sync::Arc::new(std::fs::File::open(&path).unwrap());
3372 let map = std::sync::Arc::new(unsafe { memmap2::Mmap::map(file.as_ref()).unwrap() });
3373 let source = MmapExpertSource {
3374 file: file.clone(),
3375 map,
3376 base_offset,
3377 expert_len,
3378 };
3379 let exps = HostExps::load_mixed_from_source(&source, 0, "gate", 2).unwrap();
3380 assert!(matches!(
3381 exps.tiers.as_ref().unwrap()[0],
3382 HostBuf::Mmap { .. }
3383 ));
3384 assert!(matches!(
3385 exps.tiers.as_ref().unwrap()[1],
3386 HostBuf::Mmap { .. }
3387 ));
3388 assert_eq!(
3389 exps.expert_bytes(0),
3390 &bytes[base_offset..base_offset + expert_len]
3391 );
3392 assert_eq!(exps.expert_bytes(1), &bytes[base_offset + expert_len..]);
3393 match exps.expert_source(1) {
3394 ExpertSource::Disk {
3395 file: got_file,
3396 offset,
3397 len,
3398 fallback,
3399 keepalive,
3400 } => {
3401 assert!(std::sync::Arc::ptr_eq(got_file, &file));
3402 assert_eq!(offset, (base_offset + expert_len) as u64);
3403 assert_eq!(len, expert_len);
3404 assert_eq!(fallback, &bytes[base_offset + expert_len..]);
3405 match keepalive {
3406 ExpertKeepalive::Mmap(owner) => {
3407 assert!(std::sync::Arc::ptr_eq(&owner, &source.map));
3408 }
3409 _ => panic!("mmap expert did not retain its mmap owner"),
3410 }
3411 }
3412 ExpertSource::Memory { .. } => panic!("mixed mmap tier lost its disk extent"),
3413 }
3414 #[cfg(unix)]
3415 assert!(exps.prefetch_expert_pages(1));
3416 std::fs::remove_file(path).ok();
3417 }
3418
3419 #[test]
3420 fn tiered_expert_source_does_not_double_apply_layout_offset() {
3421 let path =
3422 std::env::temp_dir().join(format!("memra-tiered-source-offset-{}", std::process::id()));
3423 let base_offset = 7usize;
3424 let expert_len = 2 * 84;
3425 let mut bytes = vec![0xE3; base_offset];
3426 bytes.extend(vec![0x41; expert_len]);
3427 bytes.extend(vec![0x82; expert_len]);
3428 std::fs::write(&path, &bytes).unwrap();
3429 let file = std::sync::Arc::new(std::fs::File::open(&path).unwrap());
3430 let map = std::sync::Arc::new(unsafe { memmap2::Mmap::map(file.as_ref()).unwrap() });
3431 let exps = HostExps {
3432 bytes: HostBuf::Paged(Vec::new()),
3433 tiers: Some(vec![
3434 HostBuf::Mmap {
3435 map: map.clone(),
3436 file: file.clone(),
3437 off: base_offset,
3438 len: expert_len,
3439 },
3440 HostBuf::Mmap {
3441 map,
3442 file: file.clone(),
3443 off: base_offset + expert_len,
3444 len: expert_len,
3445 },
3446 ]),
3447 qtype: QT_Q2_K,
3448 in_f: 256,
3449 out_f: 2,
3450 n_expert: 2,
3451 row_bytes: 84,
3452 expert_stride: expert_len,
3453 layouts: None,
3454 macros: None,
3455 fp8_blk: None,
3456 };
3457
3458 assert_eq!(exps.expert_layout(1).offset, expert_len);
3460 match exps.expert_source(1) {
3461 ExpertSource::Disk {
3462 offset,
3463 len,
3464 fallback,
3465 ..
3466 } => {
3467 assert_eq!(offset, (base_offset + expert_len) as u64);
3468 assert_eq!(len, expert_len);
3469 assert_eq!(fallback, &bytes[base_offset + expert_len..]);
3470 }
3471 ExpertSource::Memory { .. } => panic!("tiered mmap expert lost its disk extent"),
3472 }
3473 std::fs::remove_file(path).ok();
3474 }
3475
3476 #[test]
3477 fn legacy_mmap_source_requires_retained_file_extent() {
3478 let path =
3479 std::env::temp_dir().join(format!("memra-legacy-mmap-source-{}", std::process::id()));
3480 let expert_len = 2 * 84;
3481 std::fs::write(&path, vec![0x64; 2 * expert_len]).unwrap();
3482 let file = std::fs::File::open(&path).unwrap();
3483 let map = std::sync::Arc::new(unsafe { memmap2::Mmap::map(&file).unwrap() });
3484 let source = LegacyMmapExpertSource { map, expert_len };
3485
3486 let err = match HostExps::load_uniform_mmap_from_source(&source, 0, "gate", 2) {
3487 Ok(_) => panic!("legacy mmap-only source silently fell back instead of failing"),
3488 Err(err) => err,
3489 };
3490 let message = err.to_string();
3491 assert!(
3492 message.contains("legacy find_expert_mmap without find_expert_disk"),
3493 "{message}"
3494 );
3495 assert!(message.contains("retained Arc<File>"), "{message}");
3496 std::fs::remove_file(path).ok();
3497 }
3498
3499 #[test]
3500 fn uniform_expert_loader_coalesces_contiguous_mmap() {
3501 let path = std::env::temp_dir().join(format!("memra-uniform-mmap-{}", std::process::id()));
3502 let base_offset = 5usize;
3503 let expert_len = 2 * 84;
3504 let mut bytes = vec![0xE2; base_offset];
3505 bytes.extend(vec![0x19; expert_len]);
3506 bytes.extend(vec![0x91; expert_len]);
3507 std::fs::write(&path, &bytes).unwrap();
3508 let file = std::sync::Arc::new(std::fs::File::open(&path).unwrap());
3509 let map = std::sync::Arc::new(unsafe { memmap2::Mmap::map(file.as_ref()).unwrap() });
3510 let source = MmapExpertSource {
3511 file: file.clone(),
3512 map,
3513 base_offset,
3514 expert_len,
3515 };
3516 let exps = HostExps::load_uniform_mmap_from_source(&source, 0, "gate", 2)
3517 .unwrap()
3518 .expect("contiguous mmap should coalesce");
3519 assert!(exps.is_uniform_layout());
3520 assert!(matches!(&exps.bytes, HostBuf::Mmap { .. }));
3521 assert_eq!(exps.expert_stride, expert_len);
3522 assert_eq!(
3523 exps.expert_bytes(0),
3524 &bytes[base_offset..base_offset + expert_len]
3525 );
3526 assert_eq!(exps.expert_bytes(1), &bytes[base_offset + expert_len..]);
3527 match exps.expert_source(1) {
3528 ExpertSource::Disk {
3529 file: got_file,
3530 offset,
3531 len,
3532 fallback,
3533 ..
3534 } => {
3535 assert!(std::sync::Arc::ptr_eq(got_file, &file));
3536 assert_eq!(offset, (base_offset + expert_len) as u64);
3537 assert_eq!(len, expert_len);
3538 assert_eq!(fallback, &bytes[base_offset + expert_len..]);
3539 }
3540 ExpertSource::Memory { .. } => panic!("uniform mmap slab lost its disk extent"),
3541 }
3542 #[cfg(unix)]
3543 assert!(exps.prefetch_expert_pages(1));
3544 std::fs::remove_file(path).ok();
3545 }
3546}