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 mut v = src
879 .find(name)
880 .unwrap_or_else(|| panic!("missing tensor {name}"));
881 let kq = std::env::var("MEMRA_KQ_NVFP4")
896 .ok()
897 .and_then(|x| x.parse::<u8>().ok())
898 .unwrap_or(0);
899 if (kq >= 1 && v.ggml_type == GgmlType::Q4_K || kq >= 2 && v.ggml_type == GgmlType::Q5_K)
900 && v.ne.len() == 2
901 && v.ne[0].is_multiple_of(64)
902 && !name.starts_with("output")
903 {
904 let n: u64 = v.ne.iter().product();
905 let f32v = dequant::dequantize(v.ggml_type, &v.bytes, n as usize);
906 let packed = memra_gguf::nvfp4_repack::f32_to_nvfp4(&f32v);
907 v = memra_gguf::source::TensorView {
908 bytes: std::borrow::Cow::Owned(packed),
909 ggml_type: GgmlType::NVFP4,
910 ne: v.ne.clone(),
911 };
912 }
913 let qtype = match v.ggml_type {
914 GgmlType::Q8_0 => Some(QT_Q8_0),
915 GgmlType::Q4_K => Some(QT_Q4_K),
916 GgmlType::Q6_K => Some(QT_Q6_K),
917 GgmlType::Q5_K => Some(QT_Q5_K),
918 GgmlType::Q3_K => Some(QT_Q3_K),
919 GgmlType::IQ4_XS => Some(QT_IQ4_XS),
920 GgmlType::IQ3_S => Some(QT_IQ3_S),
921 GgmlType::NVFP4 => Some(QT_NVFP4),
922 GgmlType::Q4_0 => Some(QT_Q4_0),
923 _ => None,
925 };
926 match qtype {
927 Some(qt) => {
928 if v.ne.len() != 2 {
941 return Err(format!(
942 "{name}: quantized tensor (qtype {qt}) has {}-D ne {:?}, but every \
943 quantized resident layout in this engine is 2-D — row_bytes is derived \
944 from ne[1] as the out-feature count and would be wrong here. A 3-D \
945 operand must be dequantized at the source (see TensorTransform::\
946 SplitMlaKv) or split per head before it reaches the loader.",
947 v.ne.len(),
948 v.ne
949 )
950 .into());
951 }
952 let out_f = v.ne[1] as usize;
953 let row_bytes = v.bytes.len() / out_f;
954 let scale = if qt == QT_NVFP4 {
959 let stem = name.strip_suffix(".weight").unwrap_or(name);
960 match src.find(&format!("{stem}.scale")) {
961 Some(sv) => f32::from_le_bytes(sv.bytes[..4].try_into().unwrap()),
962 None => 1.0,
963 }
964 } else {
965 1.0
966 };
967 let rp = qt == QT_NVFP4
971 && v.ne.len() == 2
972 && (v.ne[0] as usize).is_multiple_of(64)
973 && v.bytes.len() % out_f == 0
974 && (v.bytes.len() / out_f).is_multiple_of(36)
975 && rp_enabled();
976 let bytes = if rp {
977 e.htod_bytes(&repack_nvfp4_split(&v.bytes, out_f))?
978 } else {
979 e.htod_bytes(&v.bytes)?
980 };
981 #[cfg(memra_cutlass)]
986 let cutlass = {
987 let in_f = v.ne[0] as usize;
988 if qt == QT_NVFP4
991 && in_f % 64 == 0
992 && v.ne.len() == 2
993 && std::env::var("MEMRA_FP4_CUTLASS").is_ok()
994 && std::env::var("MEMRA_FP4_CUTLASS_OTF").is_err()
995 {
996 let raw_dev;
997 let src_dev = if rp {
998 raw_dev = e.htod_bytes(&v.bytes)?;
999 &raw_dev
1000 } else {
1001 &bytes
1002 };
1003 let (b_packed, sfb_swizzled) =
1004 e.build_cutlass_weight(src_dev, out_f, in_f, row_bytes)?;
1005 Some(CutlassWeight {
1006 b_packed,
1007 sfb_swizzled,
1008 })
1009 } else {
1010 None
1011 }
1012 };
1013 let fp8 = if qt == QT_Q8_0
1033 && (crate::fp8_ffi::pp_fp8_enabled() || crate::fp8_ffi::fp8_mmq_enabled())
1034 {
1035 match src.find_fp8_native(name) {
1036 Some(f8)
1037 if v.ne.len() == 2
1038 && f8.in_f as u64 == v.ne[0]
1039 && f8.out_f as u64 == v.ne[1] =>
1040 {
1041 use std::sync::atomic::{AtomicUsize, Ordering};
1042 static FP8_SPENT: AtomicUsize = AtomicUsize::new(0);
1043 static FP8_BUDGET: std::sync::OnceLock<usize> =
1044 std::sync::OnceLock::new();
1045 let budget = *FP8_BUDGET.get_or_init(|| {
1046 std::env::var("MEMRA_PP_FP8_BUDGET_MB")
1047 .ok()
1048 .and_then(|v| v.parse::<usize>().ok())
1049 .unwrap_or(1536)
1050 << 20
1051 });
1052 let sz = f8.bytes.len();
1053 if FP8_SPENT.fetch_add(sz, Ordering::Relaxed) + sz <= budget {
1054 let blk = match f8.blk {
1059 Some(g) => Some(Fp8BlockScales {
1060 scales: e.htod(&g.scales)?,
1061 rows: g.rows,
1062 cols: g.cols,
1063 }),
1064 None => None,
1065 };
1066 Some(Fp8Weight {
1067 bytes: e.htod_bytes(&f8.bytes)?,
1068 scale: f8.scale,
1069 blk,
1070 })
1071 } else {
1072 FP8_SPENT.fetch_sub(sz, Ordering::Relaxed);
1073 None
1074 }
1075 }
1076 _ => None,
1077 }
1078 } else {
1079 None
1080 };
1081 Ok(GpuTensor::Quant {
1082 bytes,
1083 qtype: qt,
1084 row_bytes,
1085 ne: v.ne.clone(),
1086 scale,
1087 rp,
1088 #[cfg(memra_cutlass)]
1089 cutlass,
1090 fp8,
1091 blk: None,
1092 rp4: None,
1093 f16: None,
1094 })
1095 }
1096 None => {
1097 let n: u64 = v.ne.iter().product();
1098 if full_prec_enabled() || crate::Engine::bf16_mmv_on() {
1110 let threshold = if full_prec_enabled() {
1117 1_000_000
1118 } else {
1119 2_000_000
1120 };
1121 if v.ggml_type == GgmlType::BF16 && v.ne.len() == 2 && n >= threshold {
1122 let data = e.htod_bytes(&v.bytes)?; eprintln!(
1133 "[bf16-mmv] RESIDENT {name} ne={:?} n={n} admit={}",
1134 v.ne,
1135 if full_prec_enabled() {
1136 "full_prec"
1137 } else {
1138 "bf16_mmv"
1139 }
1140 );
1141 return Ok(GpuTensor::FloatBf16 {
1142 data,
1143 ne: v.ne.clone(),
1144 });
1145 }
1146 if full_prec_enabled() {
1147 let f32v = dequant::dequantize(v.ggml_type, &v.bytes, n as usize);
1148 return Ok(GpuTensor::Float {
1149 data: e.htod(&f32v)?,
1150 ne: v.ne.clone(),
1151 });
1152 }
1153 }
1154 let f32v = dequant::dequantize(v.ggml_type, &v.bytes, n as usize);
1155 if v.ne.len() == 2
1162 && v.ne[0].is_multiple_of(32)
1163 && (name.ends_with("ssm_beta.weight") || name.ends_with("ssm_alpha.weight")
1164 || name.ends_with("per_layer_model_proj.weight"))
1170 {
1171 let q8 = memra_gguf::nvfp4_repack::f32_to_q8_0(&f32v);
1172 return GpuTensor::from_quant_bytes(
1173 e,
1174 &q8,
1175 GgmlType::Q8_0,
1176 v.ne[0],
1177 v.ne[1],
1178 1.0,
1179 );
1180 }
1181 if v.ne.len() == 2 && v.ne[0] >= 16 && v.ne[1] >= 16 && !float_2d_audited(name) {
1191 warn_float_2d_once(name, &v.ne, v.ggml_type);
1192 }
1193 Ok(GpuTensor::Float {
1195 data: e.htod(&f32v)?,
1196 ne: v.ne.clone(),
1197 })
1198 }
1199 }
1200 }
1201
1202 pub fn from_quant_bytes(
1206 e: &Engine,
1207 bytes: &[u8],
1208 ty: GgmlType,
1209 ne0: u64,
1210 ne1: u64,
1211 scale: f32,
1212 ) -> Result<Self, Box<dyn std::error::Error>> {
1213 let qt = match ty {
1214 GgmlType::Q8_0 => QT_Q8_0,
1215 GgmlType::Q4_K => QT_Q4_K,
1216 GgmlType::Q6_K => QT_Q6_K,
1217 GgmlType::Q5_K => QT_Q5_K,
1218 GgmlType::Q3_K => QT_Q3_K,
1219 GgmlType::IQ4_XS => QT_IQ4_XS,
1220 GgmlType::IQ3_S => QT_IQ3_S,
1221 GgmlType::NVFP4 => QT_NVFP4,
1222 GgmlType::Q4_0 => QT_Q4_0,
1223 other => panic!("from_quant_bytes: unsupported dtype {other:?}"),
1224 };
1225 let row_bytes = bytes.len() / ne1 as usize;
1226 let rp = qt == QT_NVFP4
1229 && ne0.is_multiple_of(64)
1230 && row_bytes.is_multiple_of(36)
1231 && rp_enabled();
1232 let dev = if rp {
1233 e.htod_bytes(&repack_nvfp4_split(bytes, ne1 as usize))?
1234 } else {
1235 e.htod_bytes(bytes)?
1236 };
1237 Ok(GpuTensor::Quant {
1238 bytes: dev,
1239 qtype: qt,
1240 row_bytes,
1241 ne: vec![ne0, ne1],
1242 scale,
1243 rp,
1244 #[cfg(memra_cutlass)]
1245 cutlass: None,
1246 fp8: None,
1247 blk: None,
1248 f16: None,
1249 rp4: None,
1250 })
1251 }
1252
1253 pub fn load_opt(
1254 e: &Engine,
1255 g: &GgufFile,
1256 name: &str,
1257 ) -> Result<Option<Self>, Box<dyn std::error::Error>> {
1258 Self::load_opt_from_source(e, &GgufSource(g), name)
1259 }
1260
1261 pub fn load_opt_from_source(
1262 e: &Engine,
1263 src: &dyn TensorSource,
1264 name: &str,
1265 ) -> Result<Option<Self>, Box<dyn std::error::Error>> {
1266 if src.has(name) {
1267 Ok(Some(Self::load_from_source(e, src, name)?))
1268 } else {
1269 Ok(None)
1270 }
1271 }
1272
1273 pub fn float_data(&self) -> &CudaSlice<f32> {
1275 match self {
1276 GpuTensor::Float { data, .. } => data,
1277 GpuTensor::Quant { .. } => panic!("expected float tensor (norm), got quantized"),
1278 GpuTensor::FloatBf16 { .. } => {
1279 panic!("expected f32 float tensor (norm), got bf16-resident matmul weight")
1280 }
1281 }
1282 }
1283}
1284
1285pub struct Layer {
1286 pub attn_norm: GpuTensor,
1287 pub wq: GpuTensor,
1288 pub wk: GpuTensor,
1289 pub wv: GpuTensor,
1290 pub wo: GpuTensor,
1291 pub q_norm: Option<GpuTensor>,
1292 pub k_norm: Option<GpuTensor>,
1293 pub ffn_norm: GpuTensor,
1294 pub ffn: crate::hybrid::Ffn,
1297}
1298
1299pub struct EmbedHost {
1301 pub raw: Vec<u8>,
1302 pub ggml_type: GgmlType,
1303 pub n_embd: usize,
1304}
1305impl EmbedHost {
1306 pub fn from_gguf(g: &GgufFile, name: &str) -> Self {
1307 Self::from_source(&GgufSource(g), name)
1308 }
1309 pub fn from_source(src: &dyn TensorSource, name: &str) -> Self {
1310 let v = src
1311 .find(name)
1312 .unwrap_or_else(|| panic!("missing embed {name}"));
1313 EmbedHost {
1314 raw: v.bytes.to_vec(),
1315 ggml_type: v.ggml_type,
1316 n_embd: v.ne[0] as usize,
1317 }
1318 }
1319 pub fn qt_and_row_bytes(&self, n_embd: usize) -> (i32, usize) {
1322 let (blk, tsize) = self.ggml_type.block_and_type_size();
1323 let row_bytes = (n_embd as u64 / blk * tsize) as usize;
1324 let qt = match self.ggml_type {
1325 GgmlType::Q8_0 => QT_Q8_0,
1326 GgmlType::Q4_K => QT_Q4_K,
1327 GgmlType::Q6_K => QT_Q6_K,
1328 GgmlType::Q5_K => QT_Q5_K,
1329 GgmlType::Q3_K => QT_Q3_K,
1330 GgmlType::IQ4_XS => QT_IQ4_XS,
1331 GgmlType::IQ3_S => QT_IQ3_S,
1332 GgmlType::NVFP4 => QT_NVFP4,
1333 GgmlType::F32 => QT_F32,
1334 GgmlType::BF16 => QT_BF16,
1337 other => panic!("embed_gather: unsupported dtype {other:?}"),
1338 };
1339 (qt, row_bytes)
1340 }
1341
1342 pub fn rows(&self, n_embd: usize) -> usize {
1345 let (blk, tsize) = self.ggml_type.block_and_type_size();
1346 let row_bytes = (n_embd as u64 / blk * tsize) as usize;
1347 self.raw.len().checked_div(row_bytes).unwrap_or(0)
1348 }
1349
1350 pub fn try_gather(&self, n_embd: usize, tokens: &[u32]) -> Result<Vec<f32>, String> {
1364 let (blk, tsize) = self.ggml_type.block_and_type_size();
1365 let row_bytes = (n_embd as u64 / blk * tsize) as usize;
1366 let rows = self.rows(n_embd);
1367 let mut x = vec![0f32; tokens.len() * n_embd];
1368 for (ti, &tok) in tokens.iter().enumerate() {
1369 if tok as usize >= rows {
1370 return Err(format!(
1371 "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",
1372 self.raw.len(),
1373 self.ggml_type,
1374 ));
1375 }
1376 let off = tok as usize * row_bytes;
1377 let row = dequant::dequantize(self.ggml_type, &self.raw[off..off + row_bytes], n_embd);
1378 x[ti * n_embd..ti * n_embd + n_embd].copy_from_slice(&row);
1379 }
1380 Ok(x)
1381 }
1382
1383 pub fn gather(&self, n_embd: usize, tokens: &[u32]) -> Vec<f32> {
1386 self.try_gather(n_embd, tokens)
1387 .unwrap_or_else(|err| panic!("{err}"))
1388 }
1389}
1390
1391pub struct Model {
1392 pub cfg: ModelConfig,
1393 pub embd: EmbedHost,
1394 pub output_norm: GpuTensor,
1395 pub output: GpuTensor,
1396 pub layers: Vec<Layer>,
1397}
1398
1399impl Model {
1400 pub fn load_dense(e: &Engine, g: &GgufFile) -> Result<Self, Box<dyn std::error::Error>> {
1403 Self::load_dense_from_source(e, &GgufSource(g))
1404 }
1405
1406 pub fn load_dense_from_source(
1410 e: &Engine,
1411 src: &dyn TensorSource,
1412 ) -> Result<Self, Box<dyn std::error::Error>> {
1413 let cfg = src.try_config().map_err(std::io::Error::other)?;
1414 let plan = match memra_gguf::model_packs::for_config(&cfg) {
1415 Some(pack) => pack.compile_plan(&cfg)?,
1416 None => memra_gguf::model_plan::ModelPlan::compile(&cfg)?,
1417 };
1418 if plan.layers.iter().any(|layer| {
1419 !matches!(
1420 layer.attention,
1421 memra_gguf::model_plan::AttentionPlan::Full(_)
1422 )
1423 }) {
1424 return Err("plain executor requires full-attention ModelPlan layers".into());
1425 }
1426 crate::KV_FP8_FORCE.store(0, std::sync::atomic::Ordering::Relaxed);
1433
1434 let embd = EmbedHost::from_source(src, "token_embd.weight");
1435 let output_norm = GpuTensor::load_from_source(e, src, "output_norm.weight")?;
1436 let output = if src.has("output.weight") {
1438 GpuTensor::load_from_source(e, src, "output.weight")?
1439 } else {
1440 GpuTensor::load_from_source(e, src, "token_embd.weight")?
1441 };
1442 let mut resident = crate::hybrid::ResidentPlan::unsharded(e, src, &cfg);
1443 let mut step_runtimes = crate::hybrid::StepParallelRuntimeRegistry::default();
1444
1445 let mut layers = Vec::with_capacity(plan.layers.len());
1446 for (il, layer_plan) in plan.layers.iter().enumerate() {
1447 let il = il as u32;
1448 let p = |s: &str| format!("blk.{il}.{s}");
1449 let ffn = crate::hybrid::load_ffn(
1450 e,
1451 src,
1452 &cfg,
1453 &layer_plan.mlp,
1454 il,
1455 None,
1456 &mut resident,
1457 &mut step_runtimes,
1458 )?;
1459 layers.push(Layer {
1460 attn_norm: GpuTensor::load_from_source(e, src, &p("attn_norm.weight"))?,
1461 wq: GpuTensor::load_from_source(e, src, &p("attn_q.weight"))?,
1462 wk: GpuTensor::load_from_source(e, src, &p("attn_k.weight"))?,
1463 wv: GpuTensor::load_from_source(e, src, &p("attn_v.weight"))?,
1464 wo: GpuTensor::load_from_source(e, src, &p("attn_output.weight"))?,
1465 q_norm: GpuTensor::load_opt_from_source(e, src, &p("attn_q_norm.weight"))?,
1466 k_norm: GpuTensor::load_opt_from_source(e, src, &p("attn_k_norm.weight"))?,
1467 ffn_norm: GpuTensor::load_from_source(e, src, &p("ffn_norm.weight"))?,
1468 ffn,
1469 });
1470 }
1471 Ok(Model {
1472 cfg,
1473 embd,
1474 output_norm,
1475 output,
1476 layers,
1477 })
1478 }
1479
1480 pub(crate) fn max_moe_block(&self) -> usize {
1483 use crate::hybrid::Ffn;
1484 let mut mx = 0usize;
1485 for l in &self.layers {
1486 if let Ffn::Moe(m) = &l.ffn {
1487 mx = mx
1488 .max(m.gate_exps.max_expert_bytes())
1489 .max(m.up_exps.max_expert_bytes())
1490 .max(m.down_exps.max_expert_bytes());
1491 }
1492 }
1493 mx
1494 }
1495
1496 pub fn embed_tokens(
1499 &self,
1500 e: &Engine,
1501 tokens: &[u32],
1502 ) -> Result<CudaSlice<f32>, Box<dyn std::error::Error>> {
1503 let n_embd = self.cfg.n_embd as usize;
1504 let x = self.embd.try_gather(n_embd, tokens)?;
1505 e.htod(&x)
1506 }
1507}
1508
1509pub type TensorMap = HashMap<String, GpuTensor>;
1510
1511pub enum HostBuf {
1530 Paged(Vec<u8>),
1531 Pinned {
1534 slice: std::sync::Arc<cudarc::driver::PinnedHostSlice<u8>>,
1535 base: *const u8,
1536 len: usize,
1537 },
1538 PinnedAlias {
1541 owner: std::sync::Arc<HostBuf>,
1542 base: *const u8,
1543 len: usize,
1544 },
1545 Mmap {
1551 map: std::sync::Arc<memmap2::Mmap>,
1552 file: std::sync::Arc<std::fs::File>,
1555 off: usize,
1557 len: usize,
1558 },
1559}
1560unsafe impl Send for HostBuf {}
1565unsafe impl Sync for HostBuf {}
1566impl HostBuf {
1567 #[inline]
1568 pub fn as_bytes(&self) -> &[u8] {
1569 match self {
1570 HostBuf::Paged(v) => v.as_slice(),
1571 HostBuf::Pinned { base, len, .. } => unsafe { std::slice::from_raw_parts(*base, *len) },
1575 HostBuf::PinnedAlias { base, len, .. } => unsafe {
1576 std::slice::from_raw_parts(*base, *len)
1577 },
1578 HostBuf::Mmap { map, off, len, .. } => &map[*off..*off + *len],
1580 }
1581 }
1582 #[inline]
1583 #[allow(clippy::len_without_is_empty)] pub fn len(&self) -> usize {
1585 match self {
1586 HostBuf::Paged(v) => v.len(),
1587 HostBuf::Pinned { len, .. } => *len,
1588 HostBuf::PinnedAlias { len, .. } => *len,
1589 HostBuf::Mmap { len, .. } => *len,
1590 }
1591 }
1592
1593 #[inline]
1598 pub fn advise_willneed(&self, rel_off: usize, len: usize) -> bool {
1599 let HostBuf::Mmap {
1600 map,
1601 off,
1602 len: extent,
1603 ..
1604 } = self
1605 else {
1606 return false;
1607 };
1608 if len == 0 || rel_off > *extent || len > *extent - rel_off {
1609 return false;
1610 }
1611 #[cfg(unix)]
1612 {
1613 map.advise_range(memmap2::Advice::WillNeed, *off + rel_off, len)
1614 .is_ok()
1615 }
1616 #[cfg(not(unix))]
1617 {
1618 let _ = (map, off);
1619 false
1620 }
1621 }
1622
1623 #[inline]
1624 fn expert_source(&self, rel_off: usize, len: usize) -> ExpertSource<'_> {
1625 debug_assert!(rel_off <= self.len() && len <= self.len() - rel_off);
1626 match self {
1627 HostBuf::Mmap { map, file, off, .. } => {
1628 let offset = *off + rel_off;
1629 ExpertSource::Disk {
1630 file,
1631 offset: offset as u64,
1632 len,
1633 fallback: &map[offset..offset + len],
1634 keepalive: ExpertKeepalive::Mmap(map.clone()),
1635 }
1636 }
1637 HostBuf::Pinned { slice, .. } => ExpertSource::Memory {
1638 bytes: &self.as_bytes()[rel_off..rel_off + len],
1639 keepalive: Some(ExpertKeepalive::Pinned(slice.clone())),
1640 },
1641 HostBuf::PinnedAlias { owner, .. } => ExpertSource::Memory {
1642 bytes: &self.as_bytes()[rel_off..rel_off + len],
1643 keepalive: Some(ExpertKeepalive::Buffer(owner.clone())),
1644 },
1645 HostBuf::Paged(_) => ExpertSource::Memory {
1646 bytes: &self.as_bytes()[rel_off..rel_off + len],
1647 keepalive: None,
1650 },
1651 }
1652 }
1653}
1654
1655#[allow(dead_code)]
1658pub(crate) enum ExpertKeepalive {
1659 Pinned(std::sync::Arc<cudarc::driver::PinnedHostSlice<u8>>),
1660 Buffer(std::sync::Arc<HostBuf>),
1661 Mmap(std::sync::Arc<memmap2::Mmap>),
1662}
1663
1664pub(crate) enum ExpertSource<'a> {
1667 Memory {
1668 bytes: &'a [u8],
1669 keepalive: Option<ExpertKeepalive>,
1670 },
1671 Disk {
1672 file: &'a std::sync::Arc<std::fs::File>,
1673 offset: u64,
1674 len: usize,
1675 fallback: &'a [u8],
1676 keepalive: ExpertKeepalive,
1677 },
1678}
1679
1680#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1692pub struct ExpertLayout {
1693 pub offset: usize,
1694 pub len: usize,
1695 pub qtype: i32,
1696 pub row_bytes: usize,
1697}
1698
1699fn staged_expert_qtype(ty: GgmlType) -> Option<i32> {
1700 Some(match ty {
1701 GgmlType::Q8_0 => QT_Q8_0,
1702 GgmlType::Q2_K => QT_Q2_K,
1703 GgmlType::Q4_K => QT_Q4_K,
1704 GgmlType::Q6_K => QT_Q6_K,
1705 GgmlType::Q5_K => QT_Q5_K,
1706 GgmlType::Q3_K => QT_Q3_K,
1707 GgmlType::IQ4_XS => QT_IQ4_XS,
1708 GgmlType::IQ3_S => QT_IQ3_S,
1709 GgmlType::NVFP4 => QT_NVFP4,
1710 GgmlType::F32 => QT_F32,
1711 GgmlType::BF16 => QT_BF16,
1712 _ => return None,
1713 })
1714}
1715
1716fn staged_expert_row_bytes(ty: GgmlType, in_f: usize) -> Option<usize> {
1717 staged_expert_qtype(ty)?;
1718 let (block, type_size) = ty.block_and_type_size();
1719 assert_eq!(
1720 in_f as u64 % block,
1721 0,
1722 "expert row width {in_f} is not divisible by {ty:?} block {block}"
1723 );
1724 Some((in_f as u64 / block * type_size) as usize)
1725}
1726
1727fn find_expert_disk_strict(
1728 src: &dyn TensorSource,
1729 name: &str,
1730) -> Result<Option<DiskExtent>, Box<dyn std::error::Error>> {
1731 if let Some(extent) = src.find_expert_disk(name) {
1732 return Ok(Some(extent));
1733 }
1734 if src.find_expert_mmap(name).is_some() {
1735 return Err(std::io::Error::new(
1736 std::io::ErrorKind::InvalidData,
1737 format!(
1738 "expert tensor {name} exposes legacy find_expert_mmap without find_expert_disk; \
1739 disk-backed expert loading requires a retained Arc<File>"
1740 ),
1741 )
1742 .into());
1743 }
1744 Ok(None)
1745}
1746
1747pub struct HostExps {
1748 pub bytes: HostBuf, pub tiers: Option<Vec<HostBuf>>,
1754 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>>,
1764 pub macros: Option<Vec<f32>>,
1769 pub fp8_blk: Option<HostExpertFp8BlockScales>,
1772}
1773
1774pub struct HostExpertFp8BlockScales {
1775 pub scales: Vec<f32>,
1776 pub rows: usize,
1777 pub cols: usize,
1778 pub expert_stride: usize,
1779}
1780
1781impl HostExps {
1782 pub fn load(e: &Engine, g: &GgufFile, name: &str) -> Result<Self, Box<dyn std::error::Error>> {
1786 Self::load_stacked_from_source(e, &GgufSource(g), name)
1787 }
1788
1789 pub fn load_stacked_split_from_source(
1796 e: &Engine,
1797 src: &dyn TensorSource,
1798 name: &str,
1799 row0: usize,
1800 row1: usize,
1801 ) -> Result<Self, Box<dyn std::error::Error>> {
1802 let t = src
1803 .find(name)
1804 .unwrap_or_else(|| panic!("missing exps tensor {name}"));
1805 assert_eq!(t.ne.len(), 3, "{name} is not 3D (ne={:?})", t.ne);
1806 let qtype = match t.ggml_type {
1807 GgmlType::Q8_0 => QT_Q8_0,
1808 GgmlType::Q4_K => QT_Q4_K,
1809 GgmlType::Q6_K => QT_Q6_K,
1810 GgmlType::Q5_K => QT_Q5_K,
1811 GgmlType::Q3_K => QT_Q3_K,
1812 GgmlType::IQ4_XS => QT_IQ4_XS,
1813 GgmlType::IQ3_S => QT_IQ3_S,
1814 GgmlType::NVFP4 => QT_NVFP4,
1815 GgmlType::Q4_0 => QT_Q4_0,
1816 other => panic!("exps {name} unsupported quant {other:?}"),
1817 };
1818 let raw: &[u8] = &t.bytes;
1819 let in_f = t.ne[0] as usize;
1820 let out_full = t.ne[1] as usize;
1821 let n_expert = t.ne[2] as usize;
1822 let full_stride = raw.len() / n_expert;
1823 let row_bytes = raw.len() / (out_full * n_expert);
1824 assert_eq!(full_stride, out_full * row_bytes, "{name} stride mismatch");
1825 let out_f = row1 - row0;
1826 let expert_stride = out_f * row_bytes;
1827 let mut buf = vec![0u8; n_expert * expert_stride];
1828 for ex in 0..n_expert {
1829 let s0 = ex * full_stride + row0 * row_bytes;
1830 buf[ex * expert_stride..(ex + 1) * expert_stride]
1831 .copy_from_slice(&raw[s0..s0 + expert_stride]);
1832 }
1833 let pinned = std::env::var("MEMRA_MOE_PINNED").is_ok()
1834 || std::env::var("MEMRA_MOE_CACHE").as_deref() != Ok("0");
1835 let bytes = if pinned {
1836 let mut pn = unsafe { e.ctx().alloc_pinned::<u8>(buf.len())? };
1837 {
1838 let dst = pn.as_mut_slice()?;
1839 dst.copy_from_slice(&buf);
1840 }
1841 let base = pn.as_ptr()?;
1842 let len = buf.len();
1843 HostBuf::Pinned {
1844 slice: std::sync::Arc::new(pn),
1845 base,
1846 len,
1847 }
1848 } else {
1849 HostBuf::Paged(buf)
1850 };
1851 Ok(HostExps {
1852 bytes,
1853 tiers: None,
1854 qtype,
1855 in_f,
1856 out_f,
1857 n_expert,
1858 row_bytes,
1859 expert_stride,
1860 layouts: None,
1861 macros: None,
1862 fp8_blk: None,
1863 })
1864 }
1865
1866 fn stacked_macros(src: &dyn TensorSource, name: &str) -> Option<Vec<f32>> {
1872 let stem = name.strip_suffix(".weight")?;
1873 let sv = src.find(&format!("{stem}.scale"))?;
1874 if sv.ggml_type != GgmlType::F32 {
1875 return None;
1876 }
1877 let macros: Vec<f32> = sv
1878 .bytes
1879 .chunks_exact(4)
1880 .map(|c| f32::from_le_bytes(c.try_into().unwrap()))
1881 .collect();
1882 if macros.iter().all(|&m| m == 1.0) {
1883 None
1884 } else {
1885 Some(macros)
1886 }
1887 }
1888
1889 fn load_nvfp4_stacked_native(
1897 src: &dyn TensorSource,
1898 name: &str,
1899 ) -> Result<Option<Self>, Box<dyn std::error::Error>> {
1900 let Some(bank) = src.find_nvfp4_stacked_native(name) else {
1901 return Ok(None);
1902 };
1903 let (n_expert, out_f, in_f) = (bank.n_expert, bank.out_f, bank.in_f);
1904 if in_f % 64 != 0 {
1905 return Err(
1906 format!("{name} stacked NVFP4 in_features {in_f} is not 64-aligned").into(),
1907 );
1908 }
1909 let row_bytes = in_f / 64 * 36;
1910 let expert_stride = out_f * row_bytes;
1911 let total = n_expert * expert_stride;
1912 let code_stride = out_f * in_f / 2;
1913 let scale_stride = out_f * in_f / 16;
1914 let macros = bank.macros.clone();
1915 let cache_path = if let Some(dir) = src.st_dir() {
1916 let cache_dir = dir.join(".memra-repack");
1917 ensure_repack_cache_dir(&cache_dir)?;
1918 Some(cache_dir.join(format!(
1919 "{}-stacked-{n_expert}x{out_f}x{in_f}{}.nvfp4",
1920 name.replace(['.', '/'], "-"),
1921 src.nvfp4_cache_tag()
1922 )))
1923 } else {
1924 None
1925 };
1926 let bytes = if let Some(cache) = cache_path.as_ref() {
1927 let fresh = repack_cache_is_fresh(cache, total);
1928 if !fresh {
1929 write_repack_cache(cache, |out| {
1930 for expert in 0..n_expert {
1931 use std::io::Write;
1932 out.write_all(&memra_gguf::nvfp4_repack::repack_modelopt_to_gguf(
1933 &bank.codes[expert * code_stride..(expert + 1) * code_stride],
1934 &bank.scales[expert * scale_stride..(expert + 1) * scale_stride],
1935 out_f,
1936 in_f,
1937 ))?;
1938 }
1939 Ok(())
1940 })?;
1941 }
1942 let file = std::sync::Arc::new(open_repack_cache(cache, false)?);
1943 let map = unsafe { memmap2::Mmap::map(file.as_ref())? };
1944 assert_eq!(map.len(), total, "repack cache {cache:?} size mismatch");
1945 let _ = memra_gguf::source::apply_expert_mmap_advice(&map);
1946 memra_gguf::source::populate_expert_slab(&file, total, name);
1947 HostBuf::Mmap {
1948 map: std::sync::Arc::new(map),
1949 file,
1950 off: 0,
1951 len: total,
1952 }
1953 } else {
1954 let mut buf: Vec<u8> = Vec::with_capacity(total);
1955 for expert in 0..n_expert {
1956 buf.extend_from_slice(&memra_gguf::nvfp4_repack::repack_modelopt_to_gguf(
1957 &bank.codes[expert * code_stride..(expert + 1) * code_stride],
1958 &bank.scales[expert * scale_stride..(expert + 1) * scale_stride],
1959 out_f,
1960 in_f,
1961 ));
1962 }
1963 assert_eq!(buf.len(), total);
1964 HostBuf::Paged(buf)
1965 };
1966 let all_one = macros.iter().all(|&value| value == 1.0);
1967 Ok(Some(HostExps {
1968 bytes,
1969 tiers: None,
1970 qtype: QT_NVFP4,
1971 in_f,
1972 out_f,
1973 n_expert,
1974 row_bytes,
1975 expert_stride,
1976 layouts: None,
1977 macros: if all_one { None } else { Some(macros) },
1978 fp8_blk: None,
1979 }))
1980 }
1981
1982 fn load_fp8_stacked_native_with_policy(
1983 src: &dyn TensorSource,
1984 name: &str,
1985 native_enabled: bool,
1986 ) -> Result<Option<Self>, Box<dyn std::error::Error>> {
1987 let Some(f8) = src.find_fp8_stacked_native(name) else {
1988 return Ok(None);
1989 };
1990 if f8.scale_rows != f8.out_f.div_ceil(128) || f8.scale_cols != f8.in_f.div_ceil(128) {
1991 return Err(format!(
1992 "{name} FP8 scale geometry mismatch: got {}x{}, expected {}x{}",
1993 f8.scale_rows,
1994 f8.scale_cols,
1995 f8.out_f.div_ceil(128),
1996 f8.in_f.div_ceil(128)
1997 )
1998 .into());
1999 }
2000 if f8.bytes.iter().any(|code| code & 0x7f == 0x7f) {
2001 return Err(format!("{name} FP8 code slab contains non-finite E4M3 values").into());
2002 }
2003 let scale_stride = f8.scale_rows * f8.scale_cols;
2004 if !native_enabled {
2005 if f8.in_f % 32 != 0 {
2006 return Err(format!(
2007 "{name} FP8 rollback requires an input width divisible by 32, got {}",
2008 f8.in_f
2009 )
2010 .into());
2011 }
2012 let mut q8 = Vec::new();
2013 for expert in 0..f8.n_expert {
2014 let mut data = Vec::with_capacity(f8.out_f * f8.in_f);
2015 for output in 0..f8.out_f {
2016 let row = (expert * f8.out_f + output) * f8.in_f;
2017 for input in 0..f8.in_f {
2018 let scale = f8.scales
2019 [expert * scale_stride + (output / 128) * f8.scale_cols + input / 128];
2020 data.push(
2021 memra_gguf::nvfp4_repack::fp8_e4m3_to_f32(f8.bytes[row + input])
2022 * scale,
2023 );
2024 }
2025 }
2026 q8.extend_from_slice(&memra_gguf::nvfp4_repack::f32_to_q8_0(&data));
2027 }
2028 let row_bytes = f8.in_f / 32 * 34;
2029 let expert_stride = f8.out_f * row_bytes;
2030 assert_eq!(q8.len(), f8.n_expert * expert_stride);
2031 return Ok(Some(HostExps {
2032 bytes: HostBuf::Paged(q8),
2033 tiers: None,
2034 qtype: QT_Q8_0,
2035 in_f: f8.in_f,
2036 out_f: f8.out_f,
2037 n_expert: f8.n_expert,
2038 row_bytes,
2039 expert_stride,
2040 layouts: None,
2041 macros: None,
2042 fp8_blk: None,
2043 }));
2044 }
2045
2046 assert_eq!(
2047 f8.bytes.len(),
2048 f8.n_expert * f8.out_f * f8.in_f,
2049 "{name} FP8 code slab length mismatch"
2050 );
2051 assert_eq!(
2052 f8.scales.len(),
2053 f8.n_expert * scale_stride,
2054 "{name} FP8 scale slab length mismatch"
2055 );
2056 let expert_stride = f8.out_f * f8.in_f;
2057 let bytes = match find_expert_disk_strict(src, name)? {
2058 Some(extent) => {
2059 if extent.len != f8.bytes.len() {
2060 return Err(format!(
2061 "{name} FP8 mmap length mismatch: extent={} tensor={}",
2062 extent.len,
2063 f8.bytes.len()
2064 )
2065 .into());
2066 }
2067 let off = usize::try_from(extent.offset).map_err(|_| {
2068 format!(
2069 "{name} FP8 mmap offset {} does not fit usize",
2070 extent.offset
2071 )
2072 })?;
2073 HostBuf::Mmap {
2074 map: extent.map,
2075 file: extent.file,
2076 off,
2077 len: extent.len,
2078 }
2079 }
2080 None => HostBuf::Paged(f8.bytes.to_vec()),
2081 };
2082 Ok(Some(HostExps {
2083 bytes,
2084 tiers: None,
2085 qtype: crate::QT_F8_E4M3_BLK,
2086 in_f: f8.in_f,
2087 out_f: f8.out_f,
2088 n_expert: f8.n_expert,
2089 row_bytes: f8.in_f,
2090 expert_stride,
2091 layouts: None,
2092 macros: None,
2093 fp8_blk: Some(HostExpertFp8BlockScales {
2094 scales: f8.scales,
2095 rows: f8.scale_rows,
2096 cols: f8.scale_cols,
2097 expert_stride: scale_stride,
2098 }),
2099 }))
2100 }
2101
2102 pub fn load_stacked_from_source(
2103 e: &Engine,
2104 src: &dyn TensorSource,
2105 name: &str,
2106 ) -> Result<Self, Box<dyn std::error::Error>> {
2107 if let Some(exps) = Self::load_fp8_stacked_native_with_policy(
2108 src,
2109 name,
2110 crate::fp8_ffi::st_e4m3_blk_enabled(),
2111 )? {
2112 return Ok(exps);
2113 }
2114 if let Some(exps) = Self::load_nvfp4_stacked_native(src, name)? {
2115 return Ok(exps);
2116 }
2117
2118 let t = src
2119 .find(name)
2120 .unwrap_or_else(|| panic!("missing exps tensor {name}"));
2121 assert_eq!(
2122 t.ne.len(),
2123 3,
2124 "{name} is not a 3D stacked-expert tensor (ne={:?})",
2125 t.ne
2126 );
2127 if let Some(DiskExtent {
2137 map,
2138 file,
2139 offset,
2140 len,
2141 }) = find_expert_disk_strict(src, name)?
2142 {
2143 let off = usize::try_from(offset)
2144 .map_err(|_| format!("{name} disk offset {offset} does not fit usize"))?;
2145 let qtype = match t.ggml_type {
2146 GgmlType::Q8_0 => QT_Q8_0,
2147 GgmlType::Q4_K => QT_Q4_K,
2148 GgmlType::Q6_K => QT_Q6_K,
2149 GgmlType::Q5_K => QT_Q5_K,
2150 GgmlType::Q3_K => QT_Q3_K,
2151 GgmlType::IQ4_XS => QT_IQ4_XS,
2152 GgmlType::IQ3_S => QT_IQ3_S,
2153 GgmlType::NVFP4 => QT_NVFP4,
2154 GgmlType::Q4_0 => QT_Q4_0,
2155 other => panic!("exps {name} unsupported quant {other:?}"),
2156 };
2157 let in_f = t.ne[0] as usize;
2158 let out_f = t.ne[1] as usize;
2159 let n_expert = t.ne[2] as usize;
2160 let expert_stride = len / n_expert;
2161 let row_bytes = len / (out_f * n_expert);
2162 assert_eq!(
2163 expert_stride,
2164 out_f * row_bytes,
2165 "{name} stride mismatch: stride={expert_stride} out_f={out_f} row_bytes={row_bytes}"
2166 );
2167 assert_eq!(
2168 len,
2169 n_expert * expert_stride,
2170 "{name} mmap len != n_expert*stride"
2171 );
2172 return Ok(HostExps {
2173 bytes: HostBuf::Mmap {
2174 map,
2175 file,
2176 off,
2177 len,
2178 },
2179 tiers: None,
2180 qtype,
2181 in_f,
2182 out_f,
2183 n_expert,
2184 row_bytes,
2185 expert_stride,
2186 layouts: None,
2187 macros: Self::stacked_macros(src, name),
2188 fp8_blk: None,
2189 });
2190 }
2191 let raw: &[u8] = &t.bytes;
2192 let qtype = match t.ggml_type {
2194 GgmlType::Q8_0 => QT_Q8_0,
2195 GgmlType::Q4_K => QT_Q4_K,
2196 GgmlType::Q6_K => QT_Q6_K,
2197 GgmlType::Q5_K => QT_Q5_K,
2198 GgmlType::Q3_K => QT_Q3_K,
2199 GgmlType::IQ4_XS => QT_IQ4_XS,
2200 GgmlType::IQ3_S => QT_IQ3_S,
2201 GgmlType::NVFP4 => QT_NVFP4,
2202 GgmlType::Q4_0 => QT_Q4_0,
2203 other => panic!("exps {name} unsupported quant {other:?}"),
2204 };
2205 let in_f = t.ne[0] as usize;
2206 let out_f = t.ne[1] as usize;
2207 let n_expert = t.ne[2] as usize;
2208 let expert_stride = raw.len() / n_expert;
2211 let row_bytes = raw.len() / (out_f * n_expert);
2212 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 pinned = std::env::var("MEMRA_MOE_PINNED").is_ok()
2220 || std::env::var("MEMRA_MOE_CACHE").as_deref() != Ok("0");
2221 let bytes = if pinned {
2222 let mut p = unsafe { e.ctx().alloc_pinned::<u8>(raw.len())? };
2224 {
2225 let dst = p.as_mut_slice()?;
2226 dst.copy_from_slice(raw);
2227 }
2228 let base = p.as_ptr()?; let len = raw.len();
2230 HostBuf::Pinned {
2231 slice: std::sync::Arc::new(p),
2232 base,
2233 len,
2234 }
2235 } else {
2236 HostBuf::Paged(raw.to_vec())
2237 };
2238 Ok(HostExps {
2239 bytes,
2240 tiers: None,
2241 qtype,
2242 in_f,
2243 out_f,
2244 n_expert,
2245 row_bytes,
2246 expert_stride,
2247 layouts: None,
2248 macros: Self::stacked_macros(src, name),
2249 fp8_blk: None,
2250 })
2251 }
2252
2253 pub fn load_tiered(
2262 e: &Engine,
2263 g: &GgufFile,
2264 name: &str,
2265 ctx: &mut crate::spill::SpillCtx,
2266 ) -> Result<Self, Box<dyn std::error::Error>> {
2267 let t = g
2268 .find(name)
2269 .unwrap_or_else(|| panic!("missing exps tensor {name}"));
2270 assert_eq!(
2271 t.ne.len(),
2272 3,
2273 "{name} is not a 3D stacked-expert tensor (ne={:?})",
2274 t.ne
2275 );
2276 let raw = g.tensor_data(t);
2277 let qtype = match t.ggml_type {
2278 GgmlType::Q8_0 => QT_Q8_0,
2279 GgmlType::Q4_K => QT_Q4_K,
2280 GgmlType::Q6_K => QT_Q6_K,
2281 GgmlType::Q5_K => QT_Q5_K,
2282 GgmlType::Q3_K => QT_Q3_K,
2283 GgmlType::IQ4_XS => QT_IQ4_XS,
2284 GgmlType::IQ3_S => QT_IQ3_S,
2285 GgmlType::NVFP4 => QT_NVFP4,
2286 GgmlType::Q4_0 => QT_Q4_0,
2287 other => panic!("exps {name} unsupported quant {other:?}"),
2288 };
2289 let in_f = t.ne[0] as usize;
2290 let out_f = t.ne[1] as usize;
2291 let n_expert = t.ne[2] as usize;
2292 let expert_stride = raw.len() / n_expert;
2293 let row_bytes = raw.len() / (out_f * n_expert);
2294 assert_eq!(
2295 expert_stride,
2296 out_f * row_bytes,
2297 "{name} stride mismatch: stride={expert_stride} out_f={out_f} row_bytes={row_bytes}"
2298 );
2299
2300 let (file_start, _file_end) = g.tensor_file_range(t);
2304
2305 let mut tiers = Vec::with_capacity(n_expert);
2308 for ex in 0..n_expert {
2309 let blk = &raw[ex * expert_stride..(ex + 1) * expert_stride];
2310 let file_off = file_start + ex * expert_stride;
2311 tiers.push(crate::spill::place_expert(ctx, e, blk, file_off, t.shard)?);
2312 }
2313 Ok(HostExps {
2314 bytes: HostBuf::Paged(Vec::new()), tiers: Some(tiers),
2316 qtype,
2317 in_f,
2318 out_f,
2319 n_expert,
2320 row_bytes,
2321 expert_stride,
2322 layouts: None,
2323 macros: Self::stacked_macros(&GgufSource(g), name),
2324 fp8_blk: None,
2325 })
2326 }
2327
2328 pub fn load_from_source(
2343 e: &Engine,
2344 src: &dyn TensorSource,
2345 ggml_exps_name: &str,
2346 n_expert: usize,
2347 ) -> Result<Self, Box<dyn std::error::Error>> {
2348 let rest = ggml_exps_name
2350 .strip_prefix("blk.")
2351 .unwrap_or_else(|| panic!("not a blk.* name: {ggml_exps_name}"));
2352 let (il_s, suffix) = rest.split_once('.').unwrap();
2353 let il: u32 = il_s.parse().unwrap();
2354 let proj = match suffix {
2355 "ffn_gate_exps.weight" => "gate",
2356 "ffn_up_exps.weight" => "up",
2357 "ffn_down_exps.weight" => "down",
2358 other => panic!("not a *_exps suffix: {other}"),
2359 };
2360
2361 let mut signatures = Vec::with_capacity(n_expert);
2365 let active = src.active_experts(il);
2366 for ex in 0..n_expert {
2367 if active.is_some_and(|mask| !mask[ex]) {
2368 signatures.push((i32::MIN, 0));
2369 continue;
2370 }
2371 let name = format!("blk.{il}.ffn_{proj}_exps.{ex}.weight");
2372 if let Some(nv) = src.find_nvfp4_native(&name) {
2373 signatures.push((QT_NVFP4, nv.in_f / 64 * 36));
2374 } else {
2375 let v = src
2376 .find(&name)
2377 .unwrap_or_else(|| panic!("missing expert tensor {name}"));
2378 let in_f = v.ne[0] as usize;
2379 signatures.push(match staged_expert_row_bytes(v.ggml_type, in_f) {
2380 Some(row_bytes) => (staged_expert_qtype(v.ggml_type).unwrap(), row_bytes),
2381 None => (QT_F32, in_f * 4),
2382 });
2383 }
2384 }
2385 let mixed_layout = signatures.windows(2).any(|pair| pair[0] != pair[1]);
2386 if src.preserve_expert_encodings()
2387 && !mixed_layout
2388 && let Some(uniform) = Self::load_uniform_mmap_from_source(src, il, proj, n_expert)?
2389 {
2390 return Ok(uniform);
2391 }
2392 if src.preserve_expert_encodings() || mixed_layout {
2393 return Self::load_mixed_from_source(src, il, proj, n_expert);
2394 }
2395
2396 {
2403 let name0 = format!("blk.{il}.ffn_{proj}_exps.0.weight");
2404 if let Some(nv0) = src.find_nvfp4_native(&name0) {
2405 let (in_f, out_f) = (nv0.in_f, nv0.out_f);
2406 let row_bytes = in_f / 64 * 36;
2407 let expert_stride = out_f * row_bytes;
2408 let disk = std::env::var("MEMRA_ST_REPACK_DISK")
2415 .map(|v| v != "0")
2416 .unwrap_or(true)
2417 && src.st_dir().is_some();
2418 let cache_path = if let Some(dir) = src.st_dir() {
2419 let cache_dir = dir.join(".memra-repack");
2420 ensure_repack_cache_dir(&cache_dir)?;
2421 Some(cache_dir.join(format!(
2422 "blk{il}-{proj}-{n_expert}x{out_f}x{in_f}{}.nvfp4",
2423 src.nvfp4_cache_tag()
2424 )))
2425 } else {
2426 None
2427 };
2428 let total = n_expert * expert_stride;
2429 let mut macros = vec![1.0f32; n_expert];
2430 let read_macros = |macros: &mut Vec<f32>| {
2431 #[allow(clippy::needless_range_loop)]
2432 for ex in 0..n_expert {
2434 let stem = format!("blk.{il}.ffn_{proj}_exps.{ex}");
2435 if let Some(sv) = src.find(&format!("{stem}.scale")) {
2436 macros[ex] = f32::from_le_bytes(sv.bytes[..4].try_into().unwrap());
2437 }
2438 }
2439 };
2440 let bytes = if disk {
2441 let cp = cache_path.as_ref().unwrap();
2442 let fresh = repack_cache_is_fresh(cp, total);
2443 if !fresh {
2444 write_repack_cache(cp, |out| {
2446 for ex in 0..n_expert {
2447 use std::io::Write;
2448 let name = format!("blk.{il}.ffn_{proj}_exps.{ex}.weight");
2449 let nv = src.find_nvfp4_native(&name).unwrap_or_else(|| {
2450 panic!("expert {name} lost NVFP4-native mid-gather")
2451 });
2452 assert_eq!(
2453 (nv.in_f, nv.out_f),
2454 (in_f, out_f),
2455 "expert {ex} dims ({},{}) != expert 0 ({in_f},{out_f})",
2456 nv.in_f,
2457 nv.out_f
2458 );
2459 out.write_all(&memra_gguf::nvfp4_repack::repack_modelopt_to_gguf(
2460 nv.wbytes, &nv.wscale, out_f, in_f,
2461 ))?;
2462 }
2463 Ok(())
2464 })?;
2465 }
2466 read_macros(&mut macros);
2467 let file = std::sync::Arc::new(open_repack_cache(cp, false)?);
2468 let map = unsafe { memmap2::Mmap::map(file.as_ref())? };
2469 assert_eq!(map.len(), total, "repack cache {cp:?} size mismatch");
2470 let _ = memra_gguf::source::apply_expert_mmap_advice(&map);
2473 memra_gguf::source::populate_expert_slab(
2474 &file,
2475 total,
2476 &format!("blk{il}-{proj}"),
2477 );
2478 let map = std::sync::Arc::new(map);
2479 let tiers = if std::env::var("MEMRA_ST_PINNED")
2492 .map(|v| v == "1")
2493 .unwrap_or(false)
2494 {
2495 static PIN_BUDGET: std::sync::OnceLock<std::sync::Mutex<usize>> =
2496 std::sync::OnceLock::new();
2497 let budget = PIN_BUDGET.get_or_init(|| {
2498 let b = crate::spill::MemBudget::probe(e)
2499 .map(|b| b.free_pinnable_ram)
2500 .unwrap_or(0);
2501 eprintln!("[st-spill] free_pinnable_ram={} MiB", b >> 20);
2502 std::sync::Mutex::new(b)
2503 });
2504 let mut rem = budget.lock().unwrap();
2505 let n_pin = (*rem / expert_stride).min(n_expert);
2509 if n_pin == 0 {
2510 None
2511 } else {
2512 let slab_len = n_pin * expert_stride;
2513 let mut pn = unsafe { e.ctx().alloc_pinned::<u8>(slab_len)? };
2514 {
2515 let dst = pn.as_mut_slice()?;
2516 dst.copy_from_slice(&map[..slab_len]);
2517 }
2518 let base = pn.as_ptr()?;
2519 *rem -= slab_len;
2520 let slab = std::sync::Arc::new(HostBuf::Pinned {
2521 slice: std::sync::Arc::new(pn),
2522 base,
2523 len: slab_len,
2524 });
2525 let mut tiers: Vec<HostBuf> = Vec::with_capacity(n_expert);
2526 for ex in 0..n_expert {
2527 let off = ex * expert_stride;
2528 if ex < n_pin {
2529 tiers.push(HostBuf::PinnedAlias {
2530 owner: slab.clone(),
2531 base: unsafe { base.add(off) },
2532 len: expert_stride,
2533 });
2534 } else {
2535 tiers.push(HostBuf::Mmap {
2536 map: map.clone(),
2537 file: file.clone(),
2538 off,
2539 len: expert_stride,
2540 });
2541 }
2542 }
2543 Some(tiers)
2544 }
2545 } else {
2546 None
2547 };
2548 if let Some(tiers) = tiers {
2549 let all_one = macros.iter().all(|&m| m == 1.0);
2550 return Ok(HostExps {
2551 bytes: HostBuf::Mmap {
2552 map,
2553 file,
2554 off: 0,
2555 len: total,
2556 },
2557 tiers: Some(tiers),
2558 qtype: QT_NVFP4,
2559 in_f,
2560 out_f,
2561 n_expert,
2562 row_bytes,
2563 expert_stride,
2564 layouts: None,
2565 macros: if all_one { None } else { Some(macros) },
2566 fp8_blk: None,
2567 });
2568 }
2569 HostBuf::Mmap {
2570 map,
2571 file,
2572 off: 0,
2573 len: total,
2574 }
2575 } else {
2576 let mut buf: Vec<u8> = Vec::with_capacity(total);
2577 for ex in 0..n_expert {
2578 let name = format!("blk.{il}.ffn_{proj}_exps.{ex}.weight");
2579 let nv = src.find_nvfp4_native(&name).unwrap_or_else(|| {
2580 panic!("expert {name} lost NVFP4-native mid-gather")
2581 });
2582 assert_eq!(
2583 (nv.in_f, nv.out_f),
2584 (in_f, out_f),
2585 "expert {ex} dims ({},{}) != expert 0 ({in_f},{out_f})",
2586 nv.in_f,
2587 nv.out_f
2588 );
2589 buf.extend_from_slice(&memra_gguf::nvfp4_repack::repack_modelopt_to_gguf(
2590 nv.wbytes, &nv.wscale, out_f, in_f,
2591 ));
2592 }
2593 assert_eq!(buf.len(), total);
2594 read_macros(&mut macros);
2595 let pinned = std::env::var("MEMRA_MOE_PINNED").is_ok()
2596 || std::env::var("MEMRA_MOE_CACHE").as_deref() != Ok("0");
2597 if pinned {
2598 let mut p = unsafe { e.ctx().alloc_pinned::<u8>(buf.len())? };
2599 {
2600 let dst = p.as_mut_slice()?;
2601 dst.copy_from_slice(&buf);
2602 }
2603 let base = p.as_ptr()?;
2604 let len = buf.len();
2605 HostBuf::Pinned {
2606 slice: std::sync::Arc::new(p),
2607 base,
2608 len,
2609 }
2610 } else {
2611 HostBuf::Paged(buf)
2612 }
2613 };
2614 let all_one = macros.iter().all(|&m| m == 1.0);
2615 return Ok(HostExps {
2616 bytes,
2617 tiers: None,
2618 qtype: QT_NVFP4,
2619 in_f,
2620 out_f,
2621 n_expert,
2622 row_bytes,
2623 expert_stride,
2624 layouts: None,
2625 macros: if all_one { None } else { Some(macros) },
2626 fp8_blk: None,
2627 });
2628 }
2629 }
2630
2631 let mut buf: Vec<u8> = Vec::new();
2633 let mut in_f = 0usize;
2634 let mut out_f = 0usize;
2635 for ex in 0..n_expert {
2636 let name = format!("blk.{il}.ffn_{proj}_exps.{ex}.weight");
2638 let v = src
2639 .find(&name)
2640 .unwrap_or_else(|| panic!("missing expert tensor {name}"));
2641 assert_eq!(v.ne.len(), 2, "expert {name} is not 2D (ne={:?})", v.ne);
2642 let (cur_in, cur_out) = (v.ne[0] as usize, v.ne[1] as usize);
2643 if ex == 0 {
2644 in_f = cur_in;
2645 out_f = cur_out;
2646 } else {
2647 assert_eq!(
2648 (cur_in, cur_out),
2649 (in_f, out_f),
2650 "expert {ex} dims {:?} != expert 0 [{in_f},{out_f}]",
2651 (cur_in, cur_out)
2652 );
2653 }
2654 let n = cur_in * cur_out;
2657 let f32v = dequant::dequantize(v.ggml_type, &v.bytes, n);
2658 buf.reserve(n * 4);
2659 for f in &f32v {
2660 buf.extend_from_slice(&f.to_le_bytes());
2661 }
2662 }
2663 let row_bytes = in_f * 4; let expert_stride = out_f * row_bytes;
2665 assert_eq!(
2666 buf.len(),
2667 n_expert * expert_stride,
2668 "{ggml_exps_name} gather size {} != n_expert*stride {}",
2669 buf.len(),
2670 n_expert * expert_stride
2671 );
2672 assert_eq!(
2674 expert_stride,
2675 out_f * row_bytes,
2676 "{ggml_exps_name} stride mismatch: stride={expert_stride} out_f={out_f} row_bytes={row_bytes}"
2677 );
2678
2679 let pinned = std::env::var("MEMRA_MOE_PINNED").is_ok()
2681 || std::env::var("MEMRA_MOE_CACHE").as_deref() != Ok("0");
2682 let bytes = if pinned {
2683 let mut p = unsafe { e.ctx().alloc_pinned::<u8>(buf.len())? };
2684 {
2685 let dst = p.as_mut_slice()?;
2686 dst.copy_from_slice(&buf);
2687 }
2688 let base = p.as_ptr()?;
2689 let len = buf.len();
2690 HostBuf::Pinned {
2691 slice: std::sync::Arc::new(p),
2692 base,
2693 len,
2694 }
2695 } else {
2696 HostBuf::Paged(buf)
2697 };
2698 Ok(HostExps {
2699 bytes,
2700 tiers: None,
2701 qtype: QT_F32,
2702 in_f,
2703 out_f,
2704 n_expert,
2705 row_bytes,
2706 expert_stride,
2707 layouts: None,
2708 macros: None,
2709 fp8_blk: None,
2710 })
2711 }
2712
2713 fn load_uniform_mmap_from_source(
2718 src: &dyn TensorSource,
2719 il: u32,
2720 proj: &str,
2721 n_expert: usize,
2722 ) -> Result<Option<Self>, Box<dyn std::error::Error>> {
2723 if src
2724 .active_experts(il)
2725 .is_some_and(|mask| mask.iter().any(|&active| !active))
2726 {
2727 return Ok(None);
2728 }
2729 let mut first_map = None;
2730 let mut first_file = None;
2731 let mut base_offset = 0u64;
2732 let mut expert_stride = 0usize;
2733 let mut in_f = 0usize;
2734 let mut out_f = 0usize;
2735 let mut qtype = 0i32;
2736 let mut row_bytes = 0usize;
2737 let mut macros = vec![1.0f32; n_expert];
2738 #[allow(clippy::needless_range_loop)]
2739 for ex in 0..n_expert {
2741 let stem = format!("blk.{il}.ffn_{proj}_exps.{ex}");
2742 let name = format!("{stem}.weight");
2743 let Some(DiskExtent {
2744 map,
2745 file,
2746 offset,
2747 len,
2748 }) = find_expert_disk_strict(src, &name)?
2749 else {
2750 return Ok(None);
2751 };
2752 let Some(v) = src.find(&name) else {
2753 return Ok(None);
2754 };
2755 if v.ne.len() != 2 {
2756 return Ok(None);
2757 }
2758 let (cur_in, cur_out) = (v.ne[0] as usize, v.ne[1] as usize);
2759 let Some(cur_row_bytes) = staged_expert_row_bytes(v.ggml_type, cur_in) else {
2760 return Ok(None);
2761 };
2762 let cur_qtype = staged_expert_qtype(v.ggml_type).unwrap();
2763 if ex == 0 {
2764 base_offset = offset;
2765 expert_stride = len;
2766 in_f = cur_in;
2767 out_f = cur_out;
2768 qtype = cur_qtype;
2769 row_bytes = cur_row_bytes;
2770 first_map = Some(map);
2771 first_file = Some(file);
2772 } else if !std::sync::Arc::ptr_eq(first_map.as_ref().unwrap(), &map)
2773 || !std::sync::Arc::ptr_eq(first_file.as_ref().unwrap(), &file)
2774 || offset != base_offset + (ex * expert_stride) as u64
2775 || len != expert_stride
2776 || (cur_in, cur_out, cur_qtype, cur_row_bytes) != (in_f, out_f, qtype, row_bytes)
2777 {
2778 return Ok(None);
2779 }
2780 if let Some(scale) = src.find(&format!("{stem}.scale")) {
2781 macros[ex] = f32::from_le_bytes(scale.bytes[..4].try_into().unwrap());
2782 }
2783 }
2784 assert_eq!(expert_stride, out_f * row_bytes);
2785 let total = n_expert * expert_stride;
2786 let off = usize::try_from(base_offset)
2787 .map_err(|_| format!("uniform expert disk offset {base_offset} does not fit usize"))?;
2788 let all_one = macros.iter().all(|&scale| scale == 1.0);
2789 Ok(Some(HostExps {
2790 bytes: HostBuf::Mmap {
2791 map: first_map.unwrap(),
2792 file: first_file.unwrap(),
2793 off,
2794 len: total,
2795 },
2796 tiers: None,
2797 qtype,
2798 in_f,
2799 out_f,
2800 n_expert,
2801 row_bytes,
2802 expert_stride,
2803 layouts: None,
2804 macros: if all_one { None } else { Some(macros) },
2805 fp8_blk: None,
2806 }))
2807 }
2808
2809 fn load_mixed_from_source(
2810 src: &dyn TensorSource,
2811 il: u32,
2812 proj: &str,
2813 n_expert: usize,
2814 ) -> Result<Self, Box<dyn std::error::Error>> {
2815 let mut tiers = Vec::with_capacity(n_expert);
2816 let mut layouts = Vec::with_capacity(n_expert);
2817 let mut macros = vec![1.0f32; n_expert];
2818 let mut in_f = 0usize;
2819 let mut out_f = 0usize;
2820 let active = src.active_experts(il);
2821 let mut first_active = None;
2822
2823 for ex in 0..n_expert {
2824 if active.is_some_and(|mask| !mask[ex]) {
2825 layouts.push(ExpertLayout {
2826 offset: 0,
2827 len: 0,
2828 qtype: QT_F32,
2829 row_bytes: 0,
2830 });
2831 tiers.push(HostBuf::Paged(Vec::new()));
2832 continue;
2833 }
2834 let name = format!("blk.{il}.ffn_{proj}_exps.{ex}.weight");
2835 let stem = format!("blk.{il}.ffn_{proj}_exps.{ex}");
2836 if let Some(scale) = src.find(&format!("{stem}.scale")) {
2837 macros[ex] = f32::from_le_bytes(scale.bytes[..4].try_into().unwrap());
2838 }
2839 let (host, byte_len, qtype, row_bytes, cur_in, cur_out) = if let Some(DiskExtent {
2840 map,
2841 file,
2842 offset,
2843 len,
2844 }) =
2845 find_expert_disk_strict(src, &name)?
2846 {
2847 let v = src
2848 .find(&name)
2849 .unwrap_or_else(|| panic!("missing expert tensor {name}"));
2850 assert_eq!(v.ne.len(), 2, "expert {name} is not 2D (ne={:?})", v.ne);
2851 let (cur_in, cur_out) = (v.ne[0] as usize, v.ne[1] as usize);
2852 let row_bytes = staged_expert_row_bytes(v.ggml_type, cur_in).ok_or_else(|| {
2853 format!("mmap expert {name} has unsupported qtype {:?}", v.ggml_type)
2854 })?;
2855 let off = usize::try_from(offset).map_err(|_| {
2856 format!("expert {name} disk offset {offset} does not fit usize")
2857 })?;
2858 (
2859 HostBuf::Mmap {
2860 map,
2861 file,
2862 off,
2863 len,
2864 },
2865 len,
2866 staged_expert_qtype(v.ggml_type).unwrap(),
2867 row_bytes,
2868 cur_in,
2869 cur_out,
2870 )
2871 } else if let Some(nv) = src.find_nvfp4_native(&name) {
2872 let bytes = memra_gguf::nvfp4_repack::repack_modelopt_to_gguf(
2873 nv.wbytes, &nv.wscale, nv.out_f, nv.in_f,
2874 );
2875 let row_bytes = nv.in_f / 64 * 36;
2876 let byte_len = bytes.len();
2877 (
2878 HostBuf::Paged(bytes),
2879 byte_len,
2880 QT_NVFP4,
2881 row_bytes,
2882 nv.in_f,
2883 nv.out_f,
2884 )
2885 } else {
2886 let v = src
2887 .find(&name)
2888 .unwrap_or_else(|| panic!("missing expert tensor {name}"));
2889 assert_eq!(v.ne.len(), 2, "expert {name} is not 2D (ne={:?})", v.ne);
2890 let (cur_in, cur_out) = (v.ne[0] as usize, v.ne[1] as usize);
2891 if let Some(row_bytes) = staged_expert_row_bytes(v.ggml_type, cur_in) {
2892 let bytes = v.bytes.into_owned();
2893 let byte_len = bytes.len();
2894 (
2895 HostBuf::Paged(bytes),
2896 byte_len,
2897 staged_expert_qtype(v.ggml_type).unwrap(),
2898 row_bytes,
2899 cur_in,
2900 cur_out,
2901 )
2902 } else {
2903 let f32v = dequant::dequantize(v.ggml_type, &v.bytes, cur_in * cur_out);
2904 let mut bytes = Vec::with_capacity(f32v.len() * 4);
2905 for f in f32v {
2906 bytes.extend_from_slice(&f.to_le_bytes());
2907 }
2908 let byte_len = bytes.len();
2909 (
2910 HostBuf::Paged(bytes),
2911 byte_len,
2912 QT_F32,
2913 cur_in * 4,
2914 cur_in,
2915 cur_out,
2916 )
2917 }
2918 };
2919
2920 if first_active.is_none() {
2921 in_f = cur_in;
2922 out_f = cur_out;
2923 first_active = Some(ex);
2924 } else {
2925 assert_eq!(
2926 (cur_in, cur_out),
2927 (in_f, out_f),
2928 "expert {ex} dims ({cur_in},{cur_out}) != first active expert ({in_f},{out_f})"
2929 );
2930 }
2931 assert_eq!(
2932 byte_len,
2933 cur_out * row_bytes,
2934 "expert {name} bytes {byte_len} != out_f*row_bytes {}",
2935 cur_out * row_bytes
2936 );
2937 layouts.push(ExpertLayout {
2938 offset: 0,
2939 len: byte_len,
2940 qtype,
2941 row_bytes,
2942 });
2943 tiers.push(host);
2944 }
2945
2946 let first = layouts[*first_active
2947 .as_ref()
2948 .expect("expert mask pruned every expert")];
2949 let expert_stride = layouts.iter().map(|layout| layout.len).max().unwrap_or(0);
2950 let all_one = macros.iter().all(|&scale| scale == 1.0);
2951 Ok(HostExps {
2952 bytes: HostBuf::Paged(Vec::new()),
2953 tiers: Some(tiers),
2954 qtype: first.qtype,
2955 in_f,
2956 out_f,
2957 n_expert,
2958 row_bytes: first.row_bytes,
2959 expert_stride,
2960 layouts: Some(layouts),
2961 macros: if all_one { None } else { Some(macros) },
2962 fp8_blk: None,
2963 })
2964 }
2965
2966 #[inline]
2970 pub fn macro_scale(&self, e: usize) -> f32 {
2971 self.macros.as_ref().map(|m| m[e]).unwrap_or(1.0)
2972 }
2973
2974 #[inline]
2975 pub fn is_uniform_layout(&self) -> bool {
2976 self.layouts.is_none()
2977 }
2978
2979 #[inline]
2980 pub fn expert_layout(&self, e: usize) -> ExpertLayout {
2981 debug_assert!(
2982 e < self.n_expert,
2983 "expert index {e} >= n_expert {}",
2984 self.n_expert
2985 );
2986 self.layouts
2987 .as_ref()
2988 .map(|layouts| layouts[e])
2989 .unwrap_or(ExpertLayout {
2990 offset: e * self.expert_stride,
2991 len: self.expert_stride,
2992 qtype: self.qtype,
2993 row_bytes: self.row_bytes,
2994 })
2995 }
2996
2997 #[inline]
2998 pub fn max_expert_bytes(&self) -> usize {
2999 self.layouts
3000 .as_ref()
3001 .and_then(|layouts| layouts.iter().map(|layout| layout.len).max())
3002 .unwrap_or(self.expert_stride)
3003 }
3004
3005 #[inline]
3007 pub fn expert_bytes(&self, e: usize) -> &[u8] {
3008 let layout = self.expert_layout(e);
3009 match &self.tiers {
3010 Some(tiers) => {
3011 debug_assert_eq!(tiers[e].len(), layout.len);
3012 tiers[e].as_bytes()
3013 }
3014 None => &self.bytes.as_bytes()[layout.offset..layout.offset + layout.len],
3015 }
3016 }
3017
3018 #[inline]
3022 pub(crate) fn expert_source(&self, e: usize) -> ExpertSource<'_> {
3023 let layout = self.expert_layout(e);
3024 match &self.tiers {
3025 Some(tiers) => tiers[e].expert_source(0, layout.len),
3026 None => self.bytes.expert_source(layout.offset, layout.len),
3027 }
3028 }
3029
3030 #[inline]
3034 pub fn prefetch_expert_pages(&self, e: usize) -> bool {
3035 let layout = self.expert_layout(e);
3036 match &self.tiers {
3037 Some(tiers) => tiers[e].advise_willneed(0, layout.len),
3038 None => self.bytes.advise_willneed(layout.offset, layout.len),
3039 }
3040 }
3041}
3042
3043#[cfg(test)]
3044mod tests {
3045 use super::{
3046 ExpertKeepalive, ExpertSource, HostBuf, HostExps, QT_BF16, QT_NVFP4, QT_Q2_K, QT_Q4_K,
3047 ensure_repack_cache_dir, open_repack_cache, repack_cache_is_fresh, repack_nvfp4_split,
3048 unpack_nvfp4_split, write_repack_cache,
3049 };
3050 use memra_gguf::nvfp4_repack::{repack_modelopt_to_gguf, repack_modelopt_to_split};
3051 use memra_gguf::source::{DiskExtent, Fp8StackedNative, TensorSource, TensorView};
3052 use memra_gguf::{GgmlType, config::ModelConfig};
3053 use std::borrow::Cow;
3054
3055 #[cfg(unix)]
3056 #[test]
3057 fn repack_cache_refuses_symlinked_directory_and_file() {
3058 use std::os::unix::fs::symlink;
3059
3060 let root = std::env::temp_dir().join(format!("memra-repack-links-{}", std::process::id()));
3061 std::fs::create_dir_all(&root).unwrap();
3062 let target_dir = root.join("target-dir");
3063 std::fs::create_dir(&target_dir).unwrap();
3064 let cache_dir = root.join(".memra-repack");
3065 symlink(&target_dir, &cache_dir).unwrap();
3066 let error = ensure_repack_cache_dir(&cache_dir).unwrap_err();
3067 assert_eq!(error.kind(), std::io::ErrorKind::InvalidData);
3068
3069 std::fs::remove_file(&cache_dir).unwrap();
3070 std::fs::create_dir(&cache_dir).unwrap();
3071 let target = root.join("outside.bin");
3072 std::fs::write(&target, b"keep").unwrap();
3073 let cache_file = cache_dir.join("artifact.nvfp4");
3074 symlink(&target, &cache_file).unwrap();
3075 assert!(!repack_cache_is_fresh(&cache_file, 4));
3076 let error = open_repack_cache(&cache_file, true).unwrap_err();
3077 assert_ne!(error.kind(), std::io::ErrorKind::NotFound);
3078 assert_eq!(std::fs::read(&target).unwrap(), b"keep");
3079
3080 let hardlink = cache_dir.join("hardlink.nvfp4");
3081 std::fs::hard_link(&target, &hardlink).unwrap();
3082 let error = write_repack_cache(&hardlink, |out| {
3083 use std::io::Write;
3084 out.write_all(b"replacement")
3085 })
3086 .unwrap_err();
3087 assert_eq!(error.kind(), std::io::ErrorKind::InvalidData);
3088 assert_eq!(std::fs::read(&target).unwrap(), b"keep");
3089 std::fs::remove_dir_all(root).ok();
3090 }
3091
3092 struct MixedExpertSource {
3093 bf16: Vec<u8>,
3094 q4k: Vec<u8>,
3095 }
3096
3097 impl TensorSource for MixedExpertSource {
3098 fn config(&self) -> ModelConfig {
3099 panic!("unused by HostExps mixed-loader test")
3100 }
3101
3102 fn find(&self, name: &str) -> Option<TensorView<'_>> {
3103 let (bytes, ggml_type) = if name == "blk.0.ffn_gate_exps.0.weight" {
3104 (&self.bf16, GgmlType::BF16)
3105 } else if name == "blk.0.ffn_gate_exps.1.weight" {
3106 (&self.q4k, GgmlType::Q4_K)
3107 } else {
3108 return None;
3109 };
3110 Some(TensorView {
3111 bytes: Cow::Borrowed(bytes),
3112 ggml_type,
3113 ne: vec![256, 2],
3114 })
3115 }
3116 }
3117
3118 struct PrunedExpertSource {
3119 q2k: Vec<u8>,
3120 nvfp4: Vec<u8>,
3121 active: Vec<bool>,
3122 }
3123
3124 struct MmapExpertSource {
3125 file: std::sync::Arc<std::fs::File>,
3126 map: std::sync::Arc<memmap2::Mmap>,
3127 base_offset: usize,
3128 expert_len: usize,
3129 }
3130
3131 struct LegacyMmapExpertSource {
3132 map: std::sync::Arc<memmap2::Mmap>,
3133 expert_len: usize,
3134 }
3135
3136 struct StackedFp8Source {
3137 file: std::sync::Arc<std::fs::File>,
3138 map: std::sync::Arc<memmap2::Mmap>,
3139 offset: usize,
3140 len: usize,
3141 scales: Vec<f32>,
3142 }
3143
3144 impl TensorSource for StackedFp8Source {
3145 fn config(&self) -> ModelConfig {
3146 panic!("unused by stacked FP8 ownership test")
3147 }
3148
3149 fn find(&self, _name: &str) -> Option<TensorView<'_>> {
3150 None
3151 }
3152
3153 fn find_fp8_stacked_native(&self, name: &str) -> Option<Fp8StackedNative<'_>> {
3154 (name == "blk.0.ffn_gate_exps.weight").then(|| Fp8StackedNative {
3155 bytes: &self.map[self.offset..self.offset + self.len],
3156 scales: self.scales.clone(),
3157 n_expert: 2,
3158 out_f: 2,
3159 in_f: 32,
3160 scale_rows: 1,
3161 scale_cols: 1,
3162 })
3163 }
3164
3165 fn find_expert_disk(&self, name: &str) -> Option<DiskExtent> {
3166 (name == "blk.0.ffn_gate_exps.weight").then(|| DiskExtent {
3167 map: self.map.clone(),
3168 file: self.file.clone(),
3169 offset: self.offset as u64,
3170 len: self.len,
3171 })
3172 }
3173 }
3174
3175 impl TensorSource for MmapExpertSource {
3176 fn config(&self) -> ModelConfig {
3177 panic!("unused by HostExps mmap-loader test")
3178 }
3179 fn preserve_expert_encodings(&self) -> bool {
3180 true
3181 }
3182 fn find(&self, name: &str) -> Option<TensorView<'_>> {
3183 let ex = match name {
3184 "blk.0.ffn_gate_exps.0.weight" => 0,
3185 "blk.0.ffn_gate_exps.1.weight" => 1,
3186 _ => return None,
3187 };
3188 let off = self.base_offset + ex * self.expert_len;
3189 Some(TensorView {
3190 bytes: Cow::Borrowed(&self.map[off..off + self.expert_len]),
3191 ggml_type: GgmlType::Q2_K,
3192 ne: vec![256, 2],
3193 })
3194 }
3195 fn find_expert_disk(&self, name: &str) -> Option<DiskExtent> {
3196 let ex = match name {
3197 "blk.0.ffn_gate_exps.0.weight" => 0,
3198 "blk.0.ffn_gate_exps.1.weight" => 1,
3199 _ => return None,
3200 };
3201 Some(DiskExtent {
3202 map: self.map.clone(),
3203 file: self.file.clone(),
3204 offset: (self.base_offset + ex * self.expert_len) as u64,
3205 len: self.expert_len,
3206 })
3207 }
3208 }
3209
3210 impl TensorSource for LegacyMmapExpertSource {
3211 fn config(&self) -> ModelConfig {
3212 panic!("unused by legacy mmap guard test")
3213 }
3214 fn preserve_expert_encodings(&self) -> bool {
3215 true
3216 }
3217 fn find(&self, name: &str) -> Option<TensorView<'_>> {
3218 let ex = match name {
3219 "blk.0.ffn_gate_exps.0.weight" => 0,
3220 "blk.0.ffn_gate_exps.1.weight" => 1,
3221 _ => return None,
3222 };
3223 let off = ex * self.expert_len;
3224 Some(TensorView {
3225 bytes: Cow::Borrowed(&self.map[off..off + self.expert_len]),
3226 ggml_type: GgmlType::Q2_K,
3227 ne: vec![256, 2],
3228 })
3229 }
3230 fn find_expert_mmap(
3231 &self,
3232 name: &str,
3233 ) -> Option<(std::sync::Arc<memmap2::Mmap>, usize, usize)> {
3234 let ex = match name {
3235 "blk.0.ffn_gate_exps.0.weight" => 0,
3236 "blk.0.ffn_gate_exps.1.weight" => 1,
3237 _ => return None,
3238 };
3239 Some((self.map.clone(), ex * self.expert_len, self.expert_len))
3240 }
3241 }
3242
3243 impl TensorSource for PrunedExpertSource {
3244 fn config(&self) -> ModelConfig {
3245 panic!("unused by HostExps pruned-loader test")
3246 }
3247 fn active_experts(&self, layer: u32) -> Option<&[bool]> {
3248 (layer == 0).then_some(self.active.as_slice())
3249 }
3250 fn find(&self, name: &str) -> Option<TensorView<'_>> {
3251 let (bytes, ggml_type) = match name {
3252 "blk.0.ffn_gate_exps.0.weight" => (&self.q2k, GgmlType::Q2_K),
3253 "blk.0.ffn_gate_exps.2.weight" => (&self.nvfp4, GgmlType::NVFP4),
3254 _ => return None,
3255 };
3256 Some(TensorView {
3257 bytes: Cow::Borrowed(bytes),
3258 ggml_type,
3259 ne: vec![256, 2],
3260 })
3261 }
3262 }
3263
3264 #[test]
3265 fn stacked_fp8_experts_retain_owned_mmap_and_scale_geometry() {
3266 let path = std::env::temp_dir().join(format!("memra-stacked-fp8-{}", std::process::id()));
3267 let offset = 11usize;
3268 let len = 2 * 2 * 32;
3269 let mut file_bytes = vec![0xA5; offset];
3270 file_bytes.extend((0..len).map(|i| (i % 127) as u8));
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,
3278 len,
3279 scales: vec![0.5, 0.25],
3280 };
3281
3282 let exps = HostExps::load_fp8_stacked_native_with_policy(
3283 &source,
3284 "blk.0.ffn_gate_exps.weight",
3285 true,
3286 )
3287 .unwrap()
3288 .unwrap();
3289 assert_eq!(exps.qtype, crate::QT_F8_E4M3_BLK);
3290 assert_eq!((exps.n_expert, exps.out_f, exps.in_f), (2, 2, 32));
3291 assert_eq!(exps.expert_stride, 64);
3292 assert!(matches!(exps.bytes, HostBuf::Mmap { .. }));
3293 assert_eq!(exps.expert_bytes(0), &file_bytes[offset..offset + 64]);
3294 assert_eq!(exps.expert_bytes(1), &file_bytes[offset + 64..offset + len]);
3295 let fp8 = exps.fp8_blk.as_ref().unwrap();
3296 assert_eq!((fp8.rows, fp8.cols, fp8.expert_stride), (1, 1, 1));
3297 assert_eq!(fp8.scales, vec![0.5, 0.25]);
3298
3299 drop(source);
3300 assert_eq!(exps.expert_bytes(1), &file_bytes[offset + 64..offset + len]);
3301 std::fs::remove_file(path).ok();
3302 }
3303
3304 #[test]
3305 fn stacked_fp8_experts_reject_non_finite_codes() {
3306 let path =
3307 std::env::temp_dir().join(format!("memra-stacked-fp8-nan-{}", std::process::id()));
3308 let len = 2 * 2 * 32;
3309 let mut file_bytes = vec![0x12; len];
3310 file_bytes[73] = 0x7f;
3311 std::fs::write(&path, &file_bytes).unwrap();
3312 let file = std::sync::Arc::new(std::fs::File::open(&path).unwrap());
3313 let map = std::sync::Arc::new(unsafe { memmap2::Mmap::map(file.as_ref()).unwrap() });
3314 let source = StackedFp8Source {
3315 file,
3316 map,
3317 offset: 0,
3318 len,
3319 scales: vec![0.5, 0.25],
3320 };
3321
3322 let err = match HostExps::load_fp8_stacked_native_with_policy(
3323 &source,
3324 "blk.0.ffn_gate_exps.weight",
3325 true,
3326 ) {
3327 Ok(_) => panic!("non-finite E4M3 code was accepted"),
3328 Err(err) => err,
3329 };
3330 assert!(err.to_string().contains("non-finite E4M3"));
3331 std::fs::remove_file(path).ok();
3332 }
3333
3334 #[test]
3338 fn direct_split_equals_chained() {
3339 for (out_f, in_f) in [(1usize, 64usize), (3, 128), (5, 320), (8, 1024)] {
3340 let mut w = vec![0u8; out_f * in_f / 2];
3341 let mut s = vec![0u8; out_f * in_f / 16];
3342 for (i, b) in w.iter_mut().enumerate() {
3343 *b = ((i * 41 + 7) & 0xFF) as u8;
3344 }
3345 for (i, b) in s.iter_mut().enumerate() {
3346 *b = (0x20 + ((i * 11 + 5) % 0x50)) as u8;
3347 }
3348 let gguf = repack_modelopt_to_gguf(&w, &s, out_f, in_f);
3349 let chained = repack_nvfp4_split(&gguf, out_f);
3350 let direct = repack_modelopt_to_split(&w, &s, out_f, in_f);
3351 assert_eq!(
3352 direct, chained,
3353 "fused != chained at out_f={out_f} in_f={in_f}"
3354 );
3355 assert_eq!(
3356 unpack_nvfp4_split(&direct, out_f),
3357 gguf,
3358 "split roundtrip broken at out_f={out_f} in_f={in_f}"
3359 );
3360 }
3361 }
3362
3363 #[test]
3364 fn mixed_expert_loader_keeps_each_encoding_and_extent() {
3365 let source = MixedExpertSource {
3366 bf16: vec![0x5a; 256 * 2 * 2],
3367 q4k: vec![0xa5; 2 * 144],
3368 };
3369 let exps = HostExps::load_mixed_from_source(&source, 0, "gate", 2).unwrap();
3370 assert!(!exps.is_uniform_layout());
3371 assert_eq!(exps.max_expert_bytes(), 1024);
3372 assert_eq!(exps.expert_layout(0).qtype, QT_BF16);
3373 assert_eq!(exps.expert_layout(0).row_bytes, 512);
3374 assert_eq!(exps.expert_layout(0).len, 1024);
3375 assert_eq!(exps.expert_layout(1).qtype, QT_Q4_K);
3376 assert_eq!(exps.expert_layout(1).row_bytes, 144);
3377 assert_eq!(exps.expert_layout(1).len, 288);
3378 assert_eq!(exps.expert_bytes(0), source.bf16);
3379 assert_eq!(exps.expert_bytes(1), source.q4k);
3380 match exps.expert_source(1) {
3381 ExpertSource::Memory { bytes, .. } => assert_eq!(bytes, source.q4k),
3382 ExpertSource::Disk { .. } => panic!("paged expert unexpectedly became disk-backed"),
3383 }
3384 }
3385
3386 #[test]
3387 fn mixed_expert_loader_omits_masked_expert_bytes() {
3388 let source = PrunedExpertSource {
3389 q2k: vec![0x22; 2 * 84],
3390 nvfp4: vec![0x44; 2 * 4 * 36],
3391 active: vec![true, false, true],
3392 };
3393 let exps = HostExps::load_mixed_from_source(&source, 0, "gate", 3).unwrap();
3394 assert_eq!(exps.expert_layout(0).qtype, QT_Q2_K);
3395 assert_eq!(exps.expert_layout(0).row_bytes, 84);
3396 assert_eq!(exps.expert_layout(1).len, 0);
3397 assert_eq!(exps.expert_bytes(1), &[]);
3398 assert_eq!(exps.expert_layout(2).qtype, QT_NVFP4);
3399 assert_eq!(exps.expert_layout(2).row_bytes, 4 * 36);
3400 }
3401
3402 #[test]
3403 fn mixed_expert_loader_keeps_mmap_backing_zero_copy() {
3404 let path = std::env::temp_dir().join(format!("memra-mixed-mmap-{}", std::process::id()));
3405 let base_offset = 3usize;
3406 let expert_len = 2 * 84;
3407 let mut bytes = vec![0xE1; base_offset];
3408 bytes.extend(vec![0x31; expert_len]);
3409 bytes.extend(vec![0x72; expert_len]);
3410 std::fs::write(&path, &bytes).unwrap();
3411 let file = std::sync::Arc::new(std::fs::File::open(&path).unwrap());
3412 let map = std::sync::Arc::new(unsafe { memmap2::Mmap::map(file.as_ref()).unwrap() });
3413 let source = MmapExpertSource {
3414 file: file.clone(),
3415 map,
3416 base_offset,
3417 expert_len,
3418 };
3419 let exps = HostExps::load_mixed_from_source(&source, 0, "gate", 2).unwrap();
3420 assert!(matches!(
3421 exps.tiers.as_ref().unwrap()[0],
3422 HostBuf::Mmap { .. }
3423 ));
3424 assert!(matches!(
3425 exps.tiers.as_ref().unwrap()[1],
3426 HostBuf::Mmap { .. }
3427 ));
3428 assert_eq!(
3429 exps.expert_bytes(0),
3430 &bytes[base_offset..base_offset + expert_len]
3431 );
3432 assert_eq!(exps.expert_bytes(1), &bytes[base_offset + expert_len..]);
3433 match exps.expert_source(1) {
3434 ExpertSource::Disk {
3435 file: got_file,
3436 offset,
3437 len,
3438 fallback,
3439 keepalive,
3440 } => {
3441 assert!(std::sync::Arc::ptr_eq(got_file, &file));
3442 assert_eq!(offset, (base_offset + expert_len) as u64);
3443 assert_eq!(len, expert_len);
3444 assert_eq!(fallback, &bytes[base_offset + expert_len..]);
3445 match keepalive {
3446 ExpertKeepalive::Mmap(owner) => {
3447 assert!(std::sync::Arc::ptr_eq(&owner, &source.map));
3448 }
3449 _ => panic!("mmap expert did not retain its mmap owner"),
3450 }
3451 }
3452 ExpertSource::Memory { .. } => panic!("mixed mmap tier lost its disk extent"),
3453 }
3454 #[cfg(unix)]
3455 assert!(exps.prefetch_expert_pages(1));
3456 std::fs::remove_file(path).ok();
3457 }
3458
3459 #[test]
3460 fn tiered_expert_source_does_not_double_apply_layout_offset() {
3461 let path =
3462 std::env::temp_dir().join(format!("memra-tiered-source-offset-{}", std::process::id()));
3463 let base_offset = 7usize;
3464 let expert_len = 2 * 84;
3465 let mut bytes = vec![0xE3; base_offset];
3466 bytes.extend(vec![0x41; expert_len]);
3467 bytes.extend(vec![0x82; expert_len]);
3468 std::fs::write(&path, &bytes).unwrap();
3469 let file = std::sync::Arc::new(std::fs::File::open(&path).unwrap());
3470 let map = std::sync::Arc::new(unsafe { memmap2::Mmap::map(file.as_ref()).unwrap() });
3471 let exps = HostExps {
3472 bytes: HostBuf::Paged(Vec::new()),
3473 tiers: Some(vec![
3474 HostBuf::Mmap {
3475 map: map.clone(),
3476 file: file.clone(),
3477 off: base_offset,
3478 len: expert_len,
3479 },
3480 HostBuf::Mmap {
3481 map,
3482 file: file.clone(),
3483 off: base_offset + expert_len,
3484 len: expert_len,
3485 },
3486 ]),
3487 qtype: QT_Q2_K,
3488 in_f: 256,
3489 out_f: 2,
3490 n_expert: 2,
3491 row_bytes: 84,
3492 expert_stride: expert_len,
3493 layouts: None,
3494 macros: None,
3495 fp8_blk: None,
3496 };
3497
3498 assert_eq!(exps.expert_layout(1).offset, expert_len);
3500 match exps.expert_source(1) {
3501 ExpertSource::Disk {
3502 offset,
3503 len,
3504 fallback,
3505 ..
3506 } => {
3507 assert_eq!(offset, (base_offset + expert_len) as u64);
3508 assert_eq!(len, expert_len);
3509 assert_eq!(fallback, &bytes[base_offset + expert_len..]);
3510 }
3511 ExpertSource::Memory { .. } => panic!("tiered mmap expert lost its disk extent"),
3512 }
3513 std::fs::remove_file(path).ok();
3514 }
3515
3516 #[test]
3517 fn legacy_mmap_source_requires_retained_file_extent() {
3518 let path =
3519 std::env::temp_dir().join(format!("memra-legacy-mmap-source-{}", std::process::id()));
3520 let expert_len = 2 * 84;
3521 std::fs::write(&path, vec![0x64; 2 * expert_len]).unwrap();
3522 let file = std::fs::File::open(&path).unwrap();
3523 let map = std::sync::Arc::new(unsafe { memmap2::Mmap::map(&file).unwrap() });
3524 let source = LegacyMmapExpertSource { map, expert_len };
3525
3526 let err = match HostExps::load_uniform_mmap_from_source(&source, 0, "gate", 2) {
3527 Ok(_) => panic!("legacy mmap-only source silently fell back instead of failing"),
3528 Err(err) => err,
3529 };
3530 let message = err.to_string();
3531 assert!(
3532 message.contains("legacy find_expert_mmap without find_expert_disk"),
3533 "{message}"
3534 );
3535 assert!(message.contains("retained Arc<File>"), "{message}");
3536 std::fs::remove_file(path).ok();
3537 }
3538
3539 #[test]
3540 fn uniform_expert_loader_coalesces_contiguous_mmap() {
3541 let path = std::env::temp_dir().join(format!("memra-uniform-mmap-{}", std::process::id()));
3542 let base_offset = 5usize;
3543 let expert_len = 2 * 84;
3544 let mut bytes = vec![0xE2; base_offset];
3545 bytes.extend(vec![0x19; expert_len]);
3546 bytes.extend(vec![0x91; expert_len]);
3547 std::fs::write(&path, &bytes).unwrap();
3548 let file = std::sync::Arc::new(std::fs::File::open(&path).unwrap());
3549 let map = std::sync::Arc::new(unsafe { memmap2::Mmap::map(file.as_ref()).unwrap() });
3550 let source = MmapExpertSource {
3551 file: file.clone(),
3552 map,
3553 base_offset,
3554 expert_len,
3555 };
3556 let exps = HostExps::load_uniform_mmap_from_source(&source, 0, "gate", 2)
3557 .unwrap()
3558 .expect("contiguous mmap should coalesce");
3559 assert!(exps.is_uniform_layout());
3560 assert!(matches!(&exps.bytes, HostBuf::Mmap { .. }));
3561 assert_eq!(exps.expert_stride, expert_len);
3562 assert_eq!(
3563 exps.expert_bytes(0),
3564 &bytes[base_offset..base_offset + expert_len]
3565 );
3566 assert_eq!(exps.expert_bytes(1), &bytes[base_offset + expert_len..]);
3567 match exps.expert_source(1) {
3568 ExpertSource::Disk {
3569 file: got_file,
3570 offset,
3571 len,
3572 fallback,
3573 ..
3574 } => {
3575 assert!(std::sync::Arc::ptr_eq(got_file, &file));
3576 assert_eq!(offset, (base_offset + expert_len) as u64);
3577 assert_eq!(len, expert_len);
3578 assert_eq!(fallback, &bytes[base_offset + expert_len..]);
3579 }
3580 ExpertSource::Memory { .. } => panic!("uniform mmap slab lost its disk extent"),
3581 }
3582 #[cfg(unix)]
3583 assert!(exps.prefetch_expert_pages(1));
3584 std::fs::remove_file(path).ok();
3585 }
3586}