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 load(e: &Engine, g: &GgufFile, name: &str) -> Result<Self, Box<dyn std::error::Error>> {
642 Self::load_from_source(e, &GgufSource(g), name)
643 }
644
645 pub fn load_from_source(
654 e: &Engine,
655 src: &dyn TensorSource,
656 name: &str,
657 ) -> Result<Self, Box<dyn std::error::Error>> {
658 let t = Self::load_from_source_inner(e, src, name)?;
659 if let GpuTensor::Quant {
660 qtype, bytes, ne, ..
661 } = &t
662 && ne.len() == 2
663 {
664 residency_census_note(*qtype, bytes.len());
665 }
666 Ok(t)
667 }
668
669 #[allow(clippy::manual_is_multiple_of)] fn load_from_source_inner(
671 e: &Engine,
672 src: &dyn TensorSource,
673 name: &str,
674 ) -> Result<Self, Box<dyn std::error::Error>> {
675 let cutlass_wants_raw = cfg!(memra_cutlass) && std::env::var("MEMRA_FP4_CUTLASS").is_ok();
683 let st_direct = std::env::var("MEMRA_ST_DIRECT")
684 .map(|v| v != "0")
685 .unwrap_or(true);
686 if rp_enabled()
687 && st_direct
688 && !cutlass_wants_raw
689 && let Some(nv) = src.find_nvfp4_native(name)
690 && nv.in_f % 64 == 0
691 && nv.out_f > 0
692 {
693 let stem = name.strip_suffix(".weight").unwrap_or(name);
695 let scale = match src.find(&format!("{stem}.scale")) {
696 Some(sv) => f32::from_le_bytes(sv.bytes[..4].try_into().unwrap()),
697 None => 1.0,
698 };
699 let bytes = e.htod_bytes(&memra_gguf::nvfp4_repack::repack_modelopt_to_split(
700 nv.wbytes, nv.wscale, nv.out_f, nv.in_f,
701 ))?;
702 return Ok(GpuTensor::Quant {
703 bytes,
704 qtype: QT_NVFP4,
705 row_bytes: nv.in_f / 64 * 36,
706 ne: vec![nv.in_f as u64, nv.out_f as u64],
707 scale,
708 rp: true,
709 #[cfg(memra_cutlass)]
710 cutlass: None,
711 fp8: None,
712 blk: None,
713 f16: None,
714 rp4: None,
715 });
716 }
717 if crate::fp8_ffi::st_e4m3_enabled()
732 && let Some(f8) = src.find_fp8_native(name)
733 && f8.blk.is_none()
734 && f8.in_f % 32 == 0
735 && f8.out_f > 0
736 {
737 return Ok(GpuTensor::Quant {
738 bytes: e.htod_bytes(&f8.bytes)?,
739 qtype: crate::QT_F8_E4M3,
740 row_bytes: f8.in_f,
741 ne: vec![f8.in_f as u64, f8.out_f as u64],
742 scale: f8.scale,
743 rp: false,
744 #[cfg(memra_cutlass)]
745 cutlass: None,
746 fp8: None,
747 blk: None,
748 f16: None,
749 rp4: None,
750 });
751 }
752 if crate::fp8_ffi::st_e4m3_blk_enabled()
779 && let Some(f8) = src.find_fp8_native(name)
780 && let Some(grid) = f8.blk.as_ref()
781 {
782 let (in_f, out_f) = (f8.in_f, f8.out_f);
783 if in_f % 32 == 0
789 && out_f > 0
790 && f8.bytes.len() == out_f * in_f
791 && grid.rows == out_f.div_ceil(128)
792 && grid.cols == in_f.div_ceil(128)
793 && grid.scales.len() == grid.rows * grid.cols
794 && f8.scale == 1.0
795 {
796 let bytes = e.htod_bytes(&f8.bytes)?;
797 if e.fp8_blk_nan_count(&bytes)? == 0 {
798 let scales = e.htod(&grid.scales)?;
799 return Ok(GpuTensor::Quant {
800 bytes,
801 qtype: crate::QT_F8_E4M3_BLK,
802 row_bytes: in_f,
803 ne: vec![in_f as u64, out_f as u64],
804 scale: 1.0,
805 rp: false,
806 #[cfg(memra_cutlass)]
807 cutlass: None,
808 fp8: None,
809 blk: Some(Fp8BlockScales {
810 scales,
811 rows: grid.rows,
812 cols: grid.cols,
813 }),
814 f16: None,
815 rp4: None,
816 });
817 }
818 crate::fp8_ffi::note_blk_native_nan_refused();
819 }
820 }
821 if crate::fp8_ffi::fp8_blk_gpu_enabled()
847 && let Some(f8) = src.find_fp8_native(name)
848 && let Some(grid) = f8.blk.as_ref()
849 {
850 let (in_f, out_f) = (f8.in_f, f8.out_f);
851 if in_f % 32 == 0 && out_f > 0 && f8.bytes.len() == out_f * in_f {
852 let bytes = e.fp8_blk_dequant_q8_0(&f8.bytes, &grid.scales, out_f, in_f)?;
853 return Ok(GpuTensor::Quant {
854 bytes,
855 qtype: QT_Q8_0,
856 row_bytes: in_f / 32 * 34,
857 ne: vec![in_f as u64, out_f as u64],
858 scale: 1.0,
859 rp: false,
860 #[cfg(memra_cutlass)]
861 cutlass: None,
862 fp8: None,
863 blk: None,
864 f16: None,
865 rp4: None,
866 });
867 }
868 }
869 let mut v = src
870 .find(name)
871 .unwrap_or_else(|| panic!("missing tensor {name}"));
872 let kq = std::env::var("MEMRA_KQ_NVFP4")
887 .ok()
888 .and_then(|x| x.parse::<u8>().ok())
889 .unwrap_or(0);
890 if (kq >= 1 && v.ggml_type == GgmlType::Q4_K || kq >= 2 && v.ggml_type == GgmlType::Q5_K)
891 && v.ne.len() == 2
892 && v.ne[0].is_multiple_of(64)
893 && !name.starts_with("output")
894 {
895 let n: u64 = v.ne.iter().product();
896 let f32v = dequant::dequantize(v.ggml_type, &v.bytes, n as usize);
897 let packed = memra_gguf::nvfp4_repack::f32_to_nvfp4(&f32v);
898 v = memra_gguf::source::TensorView {
899 bytes: std::borrow::Cow::Owned(packed),
900 ggml_type: GgmlType::NVFP4,
901 ne: v.ne.clone(),
902 };
903 }
904 let qtype = match v.ggml_type {
905 GgmlType::Q8_0 => Some(QT_Q8_0),
906 GgmlType::Q4_K => Some(QT_Q4_K),
907 GgmlType::Q6_K => Some(QT_Q6_K),
908 GgmlType::Q5_K => Some(QT_Q5_K),
909 GgmlType::Q3_K => Some(QT_Q3_K),
910 GgmlType::IQ4_XS => Some(QT_IQ4_XS),
911 GgmlType::IQ3_S => Some(QT_IQ3_S),
912 GgmlType::NVFP4 => Some(QT_NVFP4),
913 GgmlType::Q4_0 => Some(QT_Q4_0),
914 _ => None,
916 };
917 match qtype {
918 Some(qt) => {
919 if v.ne.len() != 2 {
932 return Err(format!(
933 "{name}: quantized tensor (qtype {qt}) has {}-D ne {:?}, but every \
934 quantized resident layout in this engine is 2-D — row_bytes is derived \
935 from ne[1] as the out-feature count and would be wrong here. A 3-D \
936 operand must be dequantized at the source (see TensorTransform::\
937 SplitMlaKv) or split per head before it reaches the loader.",
938 v.ne.len(),
939 v.ne
940 )
941 .into());
942 }
943 let out_f = v.ne[1] as usize;
944 let row_bytes = v.bytes.len() / out_f;
945 let scale = if qt == QT_NVFP4 {
950 let stem = name.strip_suffix(".weight").unwrap_or(name);
951 match src.find(&format!("{stem}.scale")) {
952 Some(sv) => f32::from_le_bytes(sv.bytes[..4].try_into().unwrap()),
953 None => 1.0,
954 }
955 } else {
956 1.0
957 };
958 let rp = qt == QT_NVFP4
962 && v.ne.len() == 2
963 && (v.ne[0] as usize).is_multiple_of(64)
964 && v.bytes.len() % out_f == 0
965 && (v.bytes.len() / out_f).is_multiple_of(36)
966 && rp_enabled();
967 let bytes = if rp {
968 e.htod_bytes(&repack_nvfp4_split(&v.bytes, out_f))?
969 } else {
970 e.htod_bytes(&v.bytes)?
971 };
972 #[cfg(memra_cutlass)]
977 let cutlass = {
978 let in_f = v.ne[0] as usize;
979 if qt == QT_NVFP4
982 && in_f % 64 == 0
983 && v.ne.len() == 2
984 && std::env::var("MEMRA_FP4_CUTLASS").is_ok()
985 && std::env::var("MEMRA_FP4_CUTLASS_OTF").is_err()
986 {
987 let raw_dev;
988 let src_dev = if rp {
989 raw_dev = e.htod_bytes(&v.bytes)?;
990 &raw_dev
991 } else {
992 &bytes
993 };
994 let (b_packed, sfb_swizzled) =
995 e.build_cutlass_weight(src_dev, out_f, in_f, row_bytes)?;
996 Some(CutlassWeight {
997 b_packed,
998 sfb_swizzled,
999 })
1000 } else {
1001 None
1002 }
1003 };
1004 let fp8 = if qt == QT_Q8_0
1024 && (crate::fp8_ffi::pp_fp8_enabled() || crate::fp8_ffi::fp8_mmq_enabled())
1025 {
1026 match src.find_fp8_native(name) {
1027 Some(f8)
1028 if v.ne.len() == 2
1029 && f8.in_f as u64 == v.ne[0]
1030 && f8.out_f as u64 == v.ne[1] =>
1031 {
1032 use std::sync::atomic::{AtomicUsize, Ordering};
1033 static FP8_SPENT: AtomicUsize = AtomicUsize::new(0);
1034 static FP8_BUDGET: std::sync::OnceLock<usize> =
1035 std::sync::OnceLock::new();
1036 let budget = *FP8_BUDGET.get_or_init(|| {
1037 std::env::var("MEMRA_PP_FP8_BUDGET_MB")
1038 .ok()
1039 .and_then(|v| v.parse::<usize>().ok())
1040 .unwrap_or(1536)
1041 << 20
1042 });
1043 let sz = f8.bytes.len();
1044 if FP8_SPENT.fetch_add(sz, Ordering::Relaxed) + sz <= budget {
1045 let blk = match f8.blk {
1050 Some(g) => Some(Fp8BlockScales {
1051 scales: e.htod(&g.scales)?,
1052 rows: g.rows,
1053 cols: g.cols,
1054 }),
1055 None => None,
1056 };
1057 Some(Fp8Weight {
1058 bytes: e.htod_bytes(&f8.bytes)?,
1059 scale: f8.scale,
1060 blk,
1061 })
1062 } else {
1063 FP8_SPENT.fetch_sub(sz, Ordering::Relaxed);
1064 None
1065 }
1066 }
1067 _ => None,
1068 }
1069 } else {
1070 None
1071 };
1072 Ok(GpuTensor::Quant {
1073 bytes,
1074 qtype: qt,
1075 row_bytes,
1076 ne: v.ne.clone(),
1077 scale,
1078 rp,
1079 #[cfg(memra_cutlass)]
1080 cutlass,
1081 fp8,
1082 blk: None,
1083 rp4: None,
1084 f16: None,
1085 })
1086 }
1087 None => {
1088 let n: u64 = v.ne.iter().product();
1089 if full_prec_enabled() || crate::Engine::bf16_mmv_on() {
1101 let threshold = if full_prec_enabled() {
1108 1_000_000
1109 } else {
1110 2_000_000
1111 };
1112 if v.ggml_type == GgmlType::BF16 && v.ne.len() == 2 && n >= threshold {
1113 let data = e.htod_bytes(&v.bytes)?; eprintln!(
1124 "[bf16-mmv] RESIDENT {name} ne={:?} n={n} admit={}",
1125 v.ne,
1126 if full_prec_enabled() {
1127 "full_prec"
1128 } else {
1129 "bf16_mmv"
1130 }
1131 );
1132 return Ok(GpuTensor::FloatBf16 {
1133 data,
1134 ne: v.ne.clone(),
1135 });
1136 }
1137 if full_prec_enabled() {
1138 let f32v = dequant::dequantize(v.ggml_type, &v.bytes, n as usize);
1139 return Ok(GpuTensor::Float {
1140 data: e.htod(&f32v)?,
1141 ne: v.ne.clone(),
1142 });
1143 }
1144 }
1145 let f32v = dequant::dequantize(v.ggml_type, &v.bytes, n as usize);
1146 if v.ne.len() == 2
1153 && v.ne[0].is_multiple_of(32)
1154 && (name.ends_with("ssm_beta.weight") || name.ends_with("ssm_alpha.weight")
1155 || name.ends_with("per_layer_model_proj.weight"))
1161 {
1162 let q8 = memra_gguf::nvfp4_repack::f32_to_q8_0(&f32v);
1163 return GpuTensor::from_quant_bytes(
1164 e,
1165 &q8,
1166 GgmlType::Q8_0,
1167 v.ne[0],
1168 v.ne[1],
1169 1.0,
1170 );
1171 }
1172 if v.ne.len() == 2 && v.ne[0] >= 16 && v.ne[1] >= 16 && !float_2d_audited(name) {
1182 warn_float_2d_once(name, &v.ne, v.ggml_type);
1183 }
1184 Ok(GpuTensor::Float {
1186 data: e.htod(&f32v)?,
1187 ne: v.ne.clone(),
1188 })
1189 }
1190 }
1191 }
1192
1193 pub fn from_quant_bytes(
1197 e: &Engine,
1198 bytes: &[u8],
1199 ty: GgmlType,
1200 ne0: u64,
1201 ne1: u64,
1202 scale: f32,
1203 ) -> Result<Self, Box<dyn std::error::Error>> {
1204 let qt = match ty {
1205 GgmlType::Q8_0 => QT_Q8_0,
1206 GgmlType::Q4_K => QT_Q4_K,
1207 GgmlType::Q6_K => QT_Q6_K,
1208 GgmlType::Q5_K => QT_Q5_K,
1209 GgmlType::Q3_K => QT_Q3_K,
1210 GgmlType::IQ4_XS => QT_IQ4_XS,
1211 GgmlType::IQ3_S => QT_IQ3_S,
1212 GgmlType::NVFP4 => QT_NVFP4,
1213 GgmlType::Q4_0 => QT_Q4_0,
1214 other => panic!("from_quant_bytes: unsupported dtype {other:?}"),
1215 };
1216 let row_bytes = bytes.len() / ne1 as usize;
1217 let rp = qt == QT_NVFP4
1220 && ne0.is_multiple_of(64)
1221 && row_bytes.is_multiple_of(36)
1222 && rp_enabled();
1223 let dev = if rp {
1224 e.htod_bytes(&repack_nvfp4_split(bytes, ne1 as usize))?
1225 } else {
1226 e.htod_bytes(bytes)?
1227 };
1228 Ok(GpuTensor::Quant {
1229 bytes: dev,
1230 qtype: qt,
1231 row_bytes,
1232 ne: vec![ne0, ne1],
1233 scale,
1234 rp,
1235 #[cfg(memra_cutlass)]
1236 cutlass: None,
1237 fp8: None,
1238 blk: None,
1239 f16: None,
1240 rp4: None,
1241 })
1242 }
1243
1244 pub fn load_opt(
1245 e: &Engine,
1246 g: &GgufFile,
1247 name: &str,
1248 ) -> Result<Option<Self>, Box<dyn std::error::Error>> {
1249 Self::load_opt_from_source(e, &GgufSource(g), name)
1250 }
1251
1252 pub fn load_opt_from_source(
1253 e: &Engine,
1254 src: &dyn TensorSource,
1255 name: &str,
1256 ) -> Result<Option<Self>, Box<dyn std::error::Error>> {
1257 if src.has(name) {
1258 Ok(Some(Self::load_from_source(e, src, name)?))
1259 } else {
1260 Ok(None)
1261 }
1262 }
1263
1264 pub fn float_data(&self) -> &CudaSlice<f32> {
1266 match self {
1267 GpuTensor::Float { data, .. } => data,
1268 GpuTensor::Quant { .. } => panic!("expected float tensor (norm), got quantized"),
1269 GpuTensor::FloatBf16 { .. } => {
1270 panic!("expected f32 float tensor (norm), got bf16-resident matmul weight")
1271 }
1272 }
1273 }
1274}
1275
1276pub struct Layer {
1277 pub attn_norm: GpuTensor,
1278 pub wq: GpuTensor,
1279 pub wk: GpuTensor,
1280 pub wv: GpuTensor,
1281 pub wo: GpuTensor,
1282 pub q_norm: Option<GpuTensor>,
1283 pub k_norm: Option<GpuTensor>,
1284 pub ffn_norm: GpuTensor,
1285 pub ffn: crate::hybrid::Ffn,
1288}
1289
1290pub struct EmbedHost {
1292 pub raw: Vec<u8>,
1293 pub ggml_type: GgmlType,
1294 pub n_embd: usize,
1295}
1296impl EmbedHost {
1297 pub fn from_gguf(g: &GgufFile, name: &str) -> Self {
1298 Self::from_source(&GgufSource(g), name)
1299 }
1300 pub fn from_source(src: &dyn TensorSource, name: &str) -> Self {
1301 let v = src
1302 .find(name)
1303 .unwrap_or_else(|| panic!("missing embed {name}"));
1304 EmbedHost {
1305 raw: v.bytes.to_vec(),
1306 ggml_type: v.ggml_type,
1307 n_embd: v.ne[0] as usize,
1308 }
1309 }
1310 pub fn qt_and_row_bytes(&self, n_embd: usize) -> (i32, 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 let qt = match self.ggml_type {
1316 GgmlType::Q8_0 => QT_Q8_0,
1317 GgmlType::Q4_K => QT_Q4_K,
1318 GgmlType::Q6_K => QT_Q6_K,
1319 GgmlType::Q5_K => QT_Q5_K,
1320 GgmlType::Q3_K => QT_Q3_K,
1321 GgmlType::IQ4_XS => QT_IQ4_XS,
1322 GgmlType::IQ3_S => QT_IQ3_S,
1323 GgmlType::NVFP4 => QT_NVFP4,
1324 GgmlType::F32 => QT_F32,
1325 GgmlType::BF16 => QT_BF16,
1328 other => panic!("embed_gather: unsupported dtype {other:?}"),
1329 };
1330 (qt, row_bytes)
1331 }
1332
1333 pub fn gather(&self, n_embd: usize, tokens: &[u32]) -> Vec<f32> {
1335 let (blk, tsize) = self.ggml_type.block_and_type_size();
1336 let row_bytes = (n_embd as u64 / blk * tsize) as usize;
1337 let mut x = vec![0f32; tokens.len() * n_embd];
1338 for (ti, &tok) in tokens.iter().enumerate() {
1339 let off = tok as usize * row_bytes;
1340 let row = dequant::dequantize(self.ggml_type, &self.raw[off..off + row_bytes], n_embd);
1341 x[ti * n_embd..ti * n_embd + n_embd].copy_from_slice(&row);
1342 }
1343 x
1344 }
1345}
1346
1347pub struct Model {
1348 pub cfg: ModelConfig,
1349 pub embd: EmbedHost,
1350 pub output_norm: GpuTensor,
1351 pub output: GpuTensor,
1352 pub layers: Vec<Layer>,
1353}
1354
1355impl Model {
1356 pub fn load_dense(e: &Engine, g: &GgufFile) -> Result<Self, Box<dyn std::error::Error>> {
1359 Self::load_dense_from_source(e, &GgufSource(g))
1360 }
1361
1362 pub fn load_dense_from_source(
1366 e: &Engine,
1367 src: &dyn TensorSource,
1368 ) -> Result<Self, Box<dyn std::error::Error>> {
1369 let cfg = src.try_config().map_err(std::io::Error::other)?;
1370 let plan = match memra_gguf::model_packs::for_config(&cfg) {
1371 Some(pack) => pack.compile_plan(&cfg)?,
1372 None => memra_gguf::model_plan::ModelPlan::compile(&cfg)?,
1373 };
1374 if plan.layers.iter().any(|layer| {
1375 !matches!(
1376 layer.attention,
1377 memra_gguf::model_plan::AttentionPlan::Full(_)
1378 )
1379 }) {
1380 return Err("plain executor requires full-attention ModelPlan layers".into());
1381 }
1382 crate::KV_FP8_FORCE.store(0, std::sync::atomic::Ordering::Relaxed);
1389
1390 let embd = EmbedHost::from_source(src, "token_embd.weight");
1391 let output_norm = GpuTensor::load_from_source(e, src, "output_norm.weight")?;
1392 let output = if src.has("output.weight") {
1394 GpuTensor::load_from_source(e, src, "output.weight")?
1395 } else {
1396 GpuTensor::load_from_source(e, src, "token_embd.weight")?
1397 };
1398 let mut resident = crate::hybrid::ResidentPlan::unsharded(e, src, &cfg);
1399 let mut step_runtimes = crate::hybrid::StepParallelRuntimeRegistry::default();
1400
1401 let mut layers = Vec::with_capacity(plan.layers.len());
1402 for (il, layer_plan) in plan.layers.iter().enumerate() {
1403 let il = il as u32;
1404 let p = |s: &str| format!("blk.{il}.{s}");
1405 let ffn = crate::hybrid::load_ffn(
1406 e,
1407 src,
1408 &cfg,
1409 &layer_plan.mlp,
1410 il,
1411 None,
1412 &mut resident,
1413 &mut step_runtimes,
1414 )?;
1415 layers.push(Layer {
1416 attn_norm: GpuTensor::load_from_source(e, src, &p("attn_norm.weight"))?,
1417 wq: GpuTensor::load_from_source(e, src, &p("attn_q.weight"))?,
1418 wk: GpuTensor::load_from_source(e, src, &p("attn_k.weight"))?,
1419 wv: GpuTensor::load_from_source(e, src, &p("attn_v.weight"))?,
1420 wo: GpuTensor::load_from_source(e, src, &p("attn_output.weight"))?,
1421 q_norm: GpuTensor::load_opt_from_source(e, src, &p("attn_q_norm.weight"))?,
1422 k_norm: GpuTensor::load_opt_from_source(e, src, &p("attn_k_norm.weight"))?,
1423 ffn_norm: GpuTensor::load_from_source(e, src, &p("ffn_norm.weight"))?,
1424 ffn,
1425 });
1426 }
1427 Ok(Model {
1428 cfg,
1429 embd,
1430 output_norm,
1431 output,
1432 layers,
1433 })
1434 }
1435
1436 pub(crate) fn max_moe_block(&self) -> usize {
1439 use crate::hybrid::Ffn;
1440 let mut mx = 0usize;
1441 for l in &self.layers {
1442 if let Ffn::Moe(m) = &l.ffn {
1443 mx = mx
1444 .max(m.gate_exps.max_expert_bytes())
1445 .max(m.up_exps.max_expert_bytes())
1446 .max(m.down_exps.max_expert_bytes());
1447 }
1448 }
1449 mx
1450 }
1451
1452 pub fn embed_tokens(
1455 &self,
1456 e: &Engine,
1457 tokens: &[u32],
1458 ) -> Result<CudaSlice<f32>, Box<dyn std::error::Error>> {
1459 let n_embd = self.cfg.n_embd as usize;
1460 let x = self.embd.gather(n_embd, tokens);
1461 e.htod(&x)
1462 }
1463}
1464
1465pub type TensorMap = HashMap<String, GpuTensor>;
1466
1467pub enum HostBuf {
1486 Paged(Vec<u8>),
1487 Pinned {
1490 slice: std::sync::Arc<cudarc::driver::PinnedHostSlice<u8>>,
1491 base: *const u8,
1492 len: usize,
1493 },
1494 PinnedAlias {
1497 owner: std::sync::Arc<HostBuf>,
1498 base: *const u8,
1499 len: usize,
1500 },
1501 Mmap {
1507 map: std::sync::Arc<memmap2::Mmap>,
1508 file: std::sync::Arc<std::fs::File>,
1511 off: usize,
1513 len: usize,
1514 },
1515}
1516unsafe impl Send for HostBuf {}
1521unsafe impl Sync for HostBuf {}
1522impl HostBuf {
1523 #[inline]
1524 pub fn as_bytes(&self) -> &[u8] {
1525 match self {
1526 HostBuf::Paged(v) => v.as_slice(),
1527 HostBuf::Pinned { base, len, .. } => unsafe { std::slice::from_raw_parts(*base, *len) },
1531 HostBuf::PinnedAlias { base, len, .. } => unsafe {
1532 std::slice::from_raw_parts(*base, *len)
1533 },
1534 HostBuf::Mmap { map, off, len, .. } => &map[*off..*off + *len],
1536 }
1537 }
1538 #[inline]
1539 #[allow(clippy::len_without_is_empty)] pub fn len(&self) -> usize {
1541 match self {
1542 HostBuf::Paged(v) => v.len(),
1543 HostBuf::Pinned { len, .. } => *len,
1544 HostBuf::PinnedAlias { len, .. } => *len,
1545 HostBuf::Mmap { len, .. } => *len,
1546 }
1547 }
1548
1549 #[inline]
1554 pub fn advise_willneed(&self, rel_off: usize, len: usize) -> bool {
1555 let HostBuf::Mmap {
1556 map,
1557 off,
1558 len: extent,
1559 ..
1560 } = self
1561 else {
1562 return false;
1563 };
1564 if len == 0 || rel_off > *extent || len > *extent - rel_off {
1565 return false;
1566 }
1567 #[cfg(unix)]
1568 {
1569 map.advise_range(memmap2::Advice::WillNeed, *off + rel_off, len)
1570 .is_ok()
1571 }
1572 #[cfg(not(unix))]
1573 {
1574 let _ = (map, off);
1575 false
1576 }
1577 }
1578
1579 #[inline]
1580 fn expert_source(&self, rel_off: usize, len: usize) -> ExpertSource<'_> {
1581 debug_assert!(rel_off <= self.len() && len <= self.len() - rel_off);
1582 match self {
1583 HostBuf::Mmap { map, file, off, .. } => {
1584 let offset = *off + rel_off;
1585 ExpertSource::Disk {
1586 file,
1587 offset: offset as u64,
1588 len,
1589 fallback: &map[offset..offset + len],
1590 keepalive: ExpertKeepalive::Mmap(map.clone()),
1591 }
1592 }
1593 HostBuf::Pinned { slice, .. } => ExpertSource::Memory {
1594 bytes: &self.as_bytes()[rel_off..rel_off + len],
1595 keepalive: Some(ExpertKeepalive::Pinned(slice.clone())),
1596 },
1597 HostBuf::PinnedAlias { owner, .. } => ExpertSource::Memory {
1598 bytes: &self.as_bytes()[rel_off..rel_off + len],
1599 keepalive: Some(ExpertKeepalive::Buffer(owner.clone())),
1600 },
1601 HostBuf::Paged(_) => ExpertSource::Memory {
1602 bytes: &self.as_bytes()[rel_off..rel_off + len],
1603 keepalive: None,
1606 },
1607 }
1608 }
1609}
1610
1611#[allow(dead_code)]
1614pub(crate) enum ExpertKeepalive {
1615 Pinned(std::sync::Arc<cudarc::driver::PinnedHostSlice<u8>>),
1616 Buffer(std::sync::Arc<HostBuf>),
1617 Mmap(std::sync::Arc<memmap2::Mmap>),
1618}
1619
1620pub(crate) enum ExpertSource<'a> {
1623 Memory {
1624 bytes: &'a [u8],
1625 keepalive: Option<ExpertKeepalive>,
1626 },
1627 Disk {
1628 file: &'a std::sync::Arc<std::fs::File>,
1629 offset: u64,
1630 len: usize,
1631 fallback: &'a [u8],
1632 keepalive: ExpertKeepalive,
1633 },
1634}
1635
1636#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1648pub struct ExpertLayout {
1649 pub offset: usize,
1650 pub len: usize,
1651 pub qtype: i32,
1652 pub row_bytes: usize,
1653}
1654
1655fn staged_expert_qtype(ty: GgmlType) -> Option<i32> {
1656 Some(match ty {
1657 GgmlType::Q8_0 => QT_Q8_0,
1658 GgmlType::Q2_K => QT_Q2_K,
1659 GgmlType::Q4_K => QT_Q4_K,
1660 GgmlType::Q6_K => QT_Q6_K,
1661 GgmlType::Q5_K => QT_Q5_K,
1662 GgmlType::Q3_K => QT_Q3_K,
1663 GgmlType::IQ4_XS => QT_IQ4_XS,
1664 GgmlType::IQ3_S => QT_IQ3_S,
1665 GgmlType::NVFP4 => QT_NVFP4,
1666 GgmlType::F32 => QT_F32,
1667 GgmlType::BF16 => QT_BF16,
1668 _ => return None,
1669 })
1670}
1671
1672fn staged_expert_row_bytes(ty: GgmlType, in_f: usize) -> Option<usize> {
1673 staged_expert_qtype(ty)?;
1674 let (block, type_size) = ty.block_and_type_size();
1675 assert_eq!(
1676 in_f as u64 % block,
1677 0,
1678 "expert row width {in_f} is not divisible by {ty:?} block {block}"
1679 );
1680 Some((in_f as u64 / block * type_size) as usize)
1681}
1682
1683fn find_expert_disk_strict(
1684 src: &dyn TensorSource,
1685 name: &str,
1686) -> Result<Option<DiskExtent>, Box<dyn std::error::Error>> {
1687 if let Some(extent) = src.find_expert_disk(name) {
1688 return Ok(Some(extent));
1689 }
1690 if src.find_expert_mmap(name).is_some() {
1691 return Err(std::io::Error::new(
1692 std::io::ErrorKind::InvalidData,
1693 format!(
1694 "expert tensor {name} exposes legacy find_expert_mmap without find_expert_disk; \
1695 disk-backed expert loading requires a retained Arc<File>"
1696 ),
1697 )
1698 .into());
1699 }
1700 Ok(None)
1701}
1702
1703pub struct HostExps {
1704 pub bytes: HostBuf, pub tiers: Option<Vec<HostBuf>>,
1710 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>>,
1720 pub macros: Option<Vec<f32>>,
1725 pub fp8_blk: Option<HostExpertFp8BlockScales>,
1728}
1729
1730pub struct HostExpertFp8BlockScales {
1731 pub scales: Vec<f32>,
1732 pub rows: usize,
1733 pub cols: usize,
1734 pub expert_stride: usize,
1735}
1736
1737impl HostExps {
1738 pub fn load(e: &Engine, g: &GgufFile, name: &str) -> Result<Self, Box<dyn std::error::Error>> {
1742 Self::load_stacked_from_source(e, &GgufSource(g), name)
1743 }
1744
1745 pub fn load_stacked_split_from_source(
1752 e: &Engine,
1753 src: &dyn TensorSource,
1754 name: &str,
1755 row0: usize,
1756 row1: usize,
1757 ) -> Result<Self, Box<dyn std::error::Error>> {
1758 let t = src
1759 .find(name)
1760 .unwrap_or_else(|| panic!("missing exps tensor {name}"));
1761 assert_eq!(t.ne.len(), 3, "{name} is not 3D (ne={:?})", t.ne);
1762 let qtype = match t.ggml_type {
1763 GgmlType::Q8_0 => QT_Q8_0,
1764 GgmlType::Q4_K => QT_Q4_K,
1765 GgmlType::Q6_K => QT_Q6_K,
1766 GgmlType::Q5_K => QT_Q5_K,
1767 GgmlType::Q3_K => QT_Q3_K,
1768 GgmlType::IQ4_XS => QT_IQ4_XS,
1769 GgmlType::IQ3_S => QT_IQ3_S,
1770 GgmlType::NVFP4 => QT_NVFP4,
1771 GgmlType::Q4_0 => QT_Q4_0,
1772 other => panic!("exps {name} unsupported quant {other:?}"),
1773 };
1774 let raw: &[u8] = &t.bytes;
1775 let in_f = t.ne[0] as usize;
1776 let out_full = t.ne[1] as usize;
1777 let n_expert = t.ne[2] as usize;
1778 let full_stride = raw.len() / n_expert;
1779 let row_bytes = raw.len() / (out_full * n_expert);
1780 assert_eq!(full_stride, out_full * row_bytes, "{name} stride mismatch");
1781 let out_f = row1 - row0;
1782 let expert_stride = out_f * row_bytes;
1783 let mut buf = vec![0u8; n_expert * expert_stride];
1784 for ex in 0..n_expert {
1785 let s0 = ex * full_stride + row0 * row_bytes;
1786 buf[ex * expert_stride..(ex + 1) * expert_stride]
1787 .copy_from_slice(&raw[s0..s0 + expert_stride]);
1788 }
1789 let pinned = std::env::var("MEMRA_MOE_PINNED").is_ok()
1790 || std::env::var("MEMRA_MOE_CACHE").as_deref() != Ok("0");
1791 let bytes = if pinned {
1792 let mut pn = unsafe { e.ctx().alloc_pinned::<u8>(buf.len())? };
1793 {
1794 let dst = pn.as_mut_slice()?;
1795 dst.copy_from_slice(&buf);
1796 }
1797 let base = pn.as_ptr()?;
1798 let len = buf.len();
1799 HostBuf::Pinned {
1800 slice: std::sync::Arc::new(pn),
1801 base,
1802 len,
1803 }
1804 } else {
1805 HostBuf::Paged(buf)
1806 };
1807 Ok(HostExps {
1808 bytes,
1809 tiers: None,
1810 qtype,
1811 in_f,
1812 out_f,
1813 n_expert,
1814 row_bytes,
1815 expert_stride,
1816 layouts: None,
1817 macros: None,
1818 fp8_blk: None,
1819 })
1820 }
1821
1822 fn stacked_macros(src: &dyn TensorSource, name: &str) -> Option<Vec<f32>> {
1828 let stem = name.strip_suffix(".weight")?;
1829 let sv = src.find(&format!("{stem}.scale"))?;
1830 if sv.ggml_type != GgmlType::F32 {
1831 return None;
1832 }
1833 let macros: Vec<f32> = sv
1834 .bytes
1835 .chunks_exact(4)
1836 .map(|c| f32::from_le_bytes(c.try_into().unwrap()))
1837 .collect();
1838 if macros.iter().all(|&m| m == 1.0) {
1839 None
1840 } else {
1841 Some(macros)
1842 }
1843 }
1844
1845 fn load_nvfp4_stacked_native(
1853 src: &dyn TensorSource,
1854 name: &str,
1855 ) -> Result<Option<Self>, Box<dyn std::error::Error>> {
1856 let Some(bank) = src.find_nvfp4_stacked_native(name) else {
1857 return Ok(None);
1858 };
1859 let (n_expert, out_f, in_f) = (bank.n_expert, bank.out_f, bank.in_f);
1860 if in_f % 64 != 0 {
1861 return Err(
1862 format!("{name} stacked NVFP4 in_features {in_f} is not 64-aligned").into(),
1863 );
1864 }
1865 let row_bytes = in_f / 64 * 36;
1866 let expert_stride = out_f * row_bytes;
1867 let total = n_expert * expert_stride;
1868 let code_stride = out_f * in_f / 2;
1869 let scale_stride = out_f * in_f / 16;
1870 let macros = bank.macros.clone();
1871 let cache_path = if let Some(dir) = src.st_dir() {
1872 let cache_dir = dir.join(".memra-repack");
1873 ensure_repack_cache_dir(&cache_dir)?;
1874 Some(cache_dir.join(format!(
1875 "{}-stacked-{n_expert}x{out_f}x{in_f}.nvfp4",
1876 name.replace(['.', '/'], "-")
1877 )))
1878 } else {
1879 None
1880 };
1881 let bytes = if let Some(cache) = cache_path.as_ref() {
1882 let fresh = repack_cache_is_fresh(cache, total);
1883 if !fresh {
1884 write_repack_cache(cache, |out| {
1885 for expert in 0..n_expert {
1886 use std::io::Write;
1887 out.write_all(&memra_gguf::nvfp4_repack::repack_modelopt_to_gguf(
1888 &bank.codes[expert * code_stride..(expert + 1) * code_stride],
1889 &bank.scales[expert * scale_stride..(expert + 1) * scale_stride],
1890 out_f,
1891 in_f,
1892 ))?;
1893 }
1894 Ok(())
1895 })?;
1896 }
1897 let file = std::sync::Arc::new(open_repack_cache(cache, false)?);
1898 let map = unsafe { memmap2::Mmap::map(file.as_ref())? };
1899 assert_eq!(map.len(), total, "repack cache {cache:?} size mismatch");
1900 let _ = memra_gguf::source::apply_expert_mmap_advice(&map);
1901 memra_gguf::source::populate_expert_slab(&file, total, name);
1902 HostBuf::Mmap {
1903 map: std::sync::Arc::new(map),
1904 file,
1905 off: 0,
1906 len: total,
1907 }
1908 } else {
1909 let mut buf: Vec<u8> = Vec::with_capacity(total);
1910 for expert in 0..n_expert {
1911 buf.extend_from_slice(&memra_gguf::nvfp4_repack::repack_modelopt_to_gguf(
1912 &bank.codes[expert * code_stride..(expert + 1) * code_stride],
1913 &bank.scales[expert * scale_stride..(expert + 1) * scale_stride],
1914 out_f,
1915 in_f,
1916 ));
1917 }
1918 assert_eq!(buf.len(), total);
1919 HostBuf::Paged(buf)
1920 };
1921 let all_one = macros.iter().all(|&value| value == 1.0);
1922 Ok(Some(HostExps {
1923 bytes,
1924 tiers: None,
1925 qtype: QT_NVFP4,
1926 in_f,
1927 out_f,
1928 n_expert,
1929 row_bytes,
1930 expert_stride,
1931 layouts: None,
1932 macros: if all_one { None } else { Some(macros) },
1933 fp8_blk: None,
1934 }))
1935 }
1936
1937 fn load_fp8_stacked_native_with_policy(
1938 src: &dyn TensorSource,
1939 name: &str,
1940 native_enabled: bool,
1941 ) -> Result<Option<Self>, Box<dyn std::error::Error>> {
1942 let Some(f8) = src.find_fp8_stacked_native(name) else {
1943 return Ok(None);
1944 };
1945 if f8.scale_rows != f8.out_f.div_ceil(128) || f8.scale_cols != f8.in_f.div_ceil(128) {
1946 return Err(format!(
1947 "{name} FP8 scale geometry mismatch: got {}x{}, expected {}x{}",
1948 f8.scale_rows,
1949 f8.scale_cols,
1950 f8.out_f.div_ceil(128),
1951 f8.in_f.div_ceil(128)
1952 )
1953 .into());
1954 }
1955 if f8.bytes.iter().any(|code| code & 0x7f == 0x7f) {
1956 return Err(format!("{name} FP8 code slab contains non-finite E4M3 values").into());
1957 }
1958 let scale_stride = f8.scale_rows * f8.scale_cols;
1959 if !native_enabled {
1960 if f8.in_f % 32 != 0 {
1961 return Err(format!(
1962 "{name} FP8 rollback requires an input width divisible by 32, got {}",
1963 f8.in_f
1964 )
1965 .into());
1966 }
1967 let mut q8 = Vec::new();
1968 for expert in 0..f8.n_expert {
1969 let mut data = Vec::with_capacity(f8.out_f * f8.in_f);
1970 for output in 0..f8.out_f {
1971 let row = (expert * f8.out_f + output) * f8.in_f;
1972 for input in 0..f8.in_f {
1973 let scale = f8.scales
1974 [expert * scale_stride + (output / 128) * f8.scale_cols + input / 128];
1975 data.push(
1976 memra_gguf::nvfp4_repack::fp8_e4m3_to_f32(f8.bytes[row + input])
1977 * scale,
1978 );
1979 }
1980 }
1981 q8.extend_from_slice(&memra_gguf::nvfp4_repack::f32_to_q8_0(&data));
1982 }
1983 let row_bytes = f8.in_f / 32 * 34;
1984 let expert_stride = f8.out_f * row_bytes;
1985 assert_eq!(q8.len(), f8.n_expert * expert_stride);
1986 return Ok(Some(HostExps {
1987 bytes: HostBuf::Paged(q8),
1988 tiers: None,
1989 qtype: QT_Q8_0,
1990 in_f: f8.in_f,
1991 out_f: f8.out_f,
1992 n_expert: f8.n_expert,
1993 row_bytes,
1994 expert_stride,
1995 layouts: None,
1996 macros: None,
1997 fp8_blk: None,
1998 }));
1999 }
2000
2001 assert_eq!(
2002 f8.bytes.len(),
2003 f8.n_expert * f8.out_f * f8.in_f,
2004 "{name} FP8 code slab length mismatch"
2005 );
2006 assert_eq!(
2007 f8.scales.len(),
2008 f8.n_expert * scale_stride,
2009 "{name} FP8 scale slab length mismatch"
2010 );
2011 let expert_stride = f8.out_f * f8.in_f;
2012 let bytes = match find_expert_disk_strict(src, name)? {
2013 Some(extent) => {
2014 if extent.len != f8.bytes.len() {
2015 return Err(format!(
2016 "{name} FP8 mmap length mismatch: extent={} tensor={}",
2017 extent.len,
2018 f8.bytes.len()
2019 )
2020 .into());
2021 }
2022 let off = usize::try_from(extent.offset).map_err(|_| {
2023 format!(
2024 "{name} FP8 mmap offset {} does not fit usize",
2025 extent.offset
2026 )
2027 })?;
2028 HostBuf::Mmap {
2029 map: extent.map,
2030 file: extent.file,
2031 off,
2032 len: extent.len,
2033 }
2034 }
2035 None => HostBuf::Paged(f8.bytes.to_vec()),
2036 };
2037 Ok(Some(HostExps {
2038 bytes,
2039 tiers: None,
2040 qtype: crate::QT_F8_E4M3_BLK,
2041 in_f: f8.in_f,
2042 out_f: f8.out_f,
2043 n_expert: f8.n_expert,
2044 row_bytes: f8.in_f,
2045 expert_stride,
2046 layouts: None,
2047 macros: None,
2048 fp8_blk: Some(HostExpertFp8BlockScales {
2049 scales: f8.scales,
2050 rows: f8.scale_rows,
2051 cols: f8.scale_cols,
2052 expert_stride: scale_stride,
2053 }),
2054 }))
2055 }
2056
2057 pub fn load_stacked_from_source(
2058 e: &Engine,
2059 src: &dyn TensorSource,
2060 name: &str,
2061 ) -> Result<Self, Box<dyn std::error::Error>> {
2062 if let Some(exps) = Self::load_fp8_stacked_native_with_policy(
2063 src,
2064 name,
2065 crate::fp8_ffi::st_e4m3_blk_enabled(),
2066 )? {
2067 return Ok(exps);
2068 }
2069 if let Some(exps) = Self::load_nvfp4_stacked_native(src, name)? {
2070 return Ok(exps);
2071 }
2072
2073 let t = src
2074 .find(name)
2075 .unwrap_or_else(|| panic!("missing exps tensor {name}"));
2076 assert_eq!(
2077 t.ne.len(),
2078 3,
2079 "{name} is not a 3D stacked-expert tensor (ne={:?})",
2080 t.ne
2081 );
2082 if let Some(DiskExtent {
2092 map,
2093 file,
2094 offset,
2095 len,
2096 }) = find_expert_disk_strict(src, name)?
2097 {
2098 let off = usize::try_from(offset)
2099 .map_err(|_| format!("{name} disk offset {offset} does not fit usize"))?;
2100 let qtype = match t.ggml_type {
2101 GgmlType::Q8_0 => QT_Q8_0,
2102 GgmlType::Q4_K => QT_Q4_K,
2103 GgmlType::Q6_K => QT_Q6_K,
2104 GgmlType::Q5_K => QT_Q5_K,
2105 GgmlType::Q3_K => QT_Q3_K,
2106 GgmlType::IQ4_XS => QT_IQ4_XS,
2107 GgmlType::IQ3_S => QT_IQ3_S,
2108 GgmlType::NVFP4 => QT_NVFP4,
2109 GgmlType::Q4_0 => QT_Q4_0,
2110 other => panic!("exps {name} unsupported quant {other:?}"),
2111 };
2112 let in_f = t.ne[0] as usize;
2113 let out_f = t.ne[1] as usize;
2114 let n_expert = t.ne[2] as usize;
2115 let expert_stride = len / n_expert;
2116 let row_bytes = len / (out_f * n_expert);
2117 assert_eq!(
2118 expert_stride,
2119 out_f * row_bytes,
2120 "{name} stride mismatch: stride={expert_stride} out_f={out_f} row_bytes={row_bytes}"
2121 );
2122 assert_eq!(
2123 len,
2124 n_expert * expert_stride,
2125 "{name} mmap len != n_expert*stride"
2126 );
2127 return Ok(HostExps {
2128 bytes: HostBuf::Mmap {
2129 map,
2130 file,
2131 off,
2132 len,
2133 },
2134 tiers: None,
2135 qtype,
2136 in_f,
2137 out_f,
2138 n_expert,
2139 row_bytes,
2140 expert_stride,
2141 layouts: None,
2142 macros: Self::stacked_macros(src, name),
2143 fp8_blk: None,
2144 });
2145 }
2146 let raw: &[u8] = &t.bytes;
2147 let qtype = match t.ggml_type {
2149 GgmlType::Q8_0 => QT_Q8_0,
2150 GgmlType::Q4_K => QT_Q4_K,
2151 GgmlType::Q6_K => QT_Q6_K,
2152 GgmlType::Q5_K => QT_Q5_K,
2153 GgmlType::Q3_K => QT_Q3_K,
2154 GgmlType::IQ4_XS => QT_IQ4_XS,
2155 GgmlType::IQ3_S => QT_IQ3_S,
2156 GgmlType::NVFP4 => QT_NVFP4,
2157 GgmlType::Q4_0 => QT_Q4_0,
2158 other => panic!("exps {name} unsupported quant {other:?}"),
2159 };
2160 let in_f = t.ne[0] as usize;
2161 let out_f = t.ne[1] as usize;
2162 let n_expert = t.ne[2] as usize;
2163 let expert_stride = raw.len() / n_expert;
2166 let row_bytes = raw.len() / (out_f * n_expert);
2167 assert_eq!(
2169 expert_stride,
2170 out_f * row_bytes,
2171 "{name} stride mismatch: stride={expert_stride} out_f={out_f} row_bytes={row_bytes}"
2172 );
2173
2174 let pinned = std::env::var("MEMRA_MOE_PINNED").is_ok()
2175 || std::env::var("MEMRA_MOE_CACHE").as_deref() != Ok("0");
2176 let bytes = if pinned {
2177 let mut p = unsafe { e.ctx().alloc_pinned::<u8>(raw.len())? };
2179 {
2180 let dst = p.as_mut_slice()?;
2181 dst.copy_from_slice(raw);
2182 }
2183 let base = p.as_ptr()?; let len = raw.len();
2185 HostBuf::Pinned {
2186 slice: std::sync::Arc::new(p),
2187 base,
2188 len,
2189 }
2190 } else {
2191 HostBuf::Paged(raw.to_vec())
2192 };
2193 Ok(HostExps {
2194 bytes,
2195 tiers: None,
2196 qtype,
2197 in_f,
2198 out_f,
2199 n_expert,
2200 row_bytes,
2201 expert_stride,
2202 layouts: None,
2203 macros: Self::stacked_macros(src, name),
2204 fp8_blk: None,
2205 })
2206 }
2207
2208 pub fn load_tiered(
2217 e: &Engine,
2218 g: &GgufFile,
2219 name: &str,
2220 ctx: &mut crate::spill::SpillCtx,
2221 ) -> Result<Self, Box<dyn std::error::Error>> {
2222 let t = g
2223 .find(name)
2224 .unwrap_or_else(|| panic!("missing exps tensor {name}"));
2225 assert_eq!(
2226 t.ne.len(),
2227 3,
2228 "{name} is not a 3D stacked-expert tensor (ne={:?})",
2229 t.ne
2230 );
2231 let raw = g.tensor_data(t);
2232 let qtype = match t.ggml_type {
2233 GgmlType::Q8_0 => QT_Q8_0,
2234 GgmlType::Q4_K => QT_Q4_K,
2235 GgmlType::Q6_K => QT_Q6_K,
2236 GgmlType::Q5_K => QT_Q5_K,
2237 GgmlType::Q3_K => QT_Q3_K,
2238 GgmlType::IQ4_XS => QT_IQ4_XS,
2239 GgmlType::IQ3_S => QT_IQ3_S,
2240 GgmlType::NVFP4 => QT_NVFP4,
2241 GgmlType::Q4_0 => QT_Q4_0,
2242 other => panic!("exps {name} unsupported quant {other:?}"),
2243 };
2244 let in_f = t.ne[0] as usize;
2245 let out_f = t.ne[1] as usize;
2246 let n_expert = t.ne[2] as usize;
2247 let expert_stride = raw.len() / n_expert;
2248 let row_bytes = raw.len() / (out_f * n_expert);
2249 assert_eq!(
2250 expert_stride,
2251 out_f * row_bytes,
2252 "{name} stride mismatch: stride={expert_stride} out_f={out_f} row_bytes={row_bytes}"
2253 );
2254
2255 let (file_start, _file_end) = g.tensor_file_range(t);
2259
2260 let mut tiers = Vec::with_capacity(n_expert);
2263 for ex in 0..n_expert {
2264 let blk = &raw[ex * expert_stride..(ex + 1) * expert_stride];
2265 let file_off = file_start + ex * expert_stride;
2266 tiers.push(crate::spill::place_expert(ctx, e, blk, file_off, t.shard)?);
2267 }
2268 Ok(HostExps {
2269 bytes: HostBuf::Paged(Vec::new()), tiers: Some(tiers),
2271 qtype,
2272 in_f,
2273 out_f,
2274 n_expert,
2275 row_bytes,
2276 expert_stride,
2277 layouts: None,
2278 macros: Self::stacked_macros(&GgufSource(g), name),
2279 fp8_blk: None,
2280 })
2281 }
2282
2283 pub fn load_from_source(
2298 e: &Engine,
2299 src: &dyn TensorSource,
2300 ggml_exps_name: &str,
2301 n_expert: usize,
2302 ) -> Result<Self, Box<dyn std::error::Error>> {
2303 let rest = ggml_exps_name
2305 .strip_prefix("blk.")
2306 .unwrap_or_else(|| panic!("not a blk.* name: {ggml_exps_name}"));
2307 let (il_s, suffix) = rest.split_once('.').unwrap();
2308 let il: u32 = il_s.parse().unwrap();
2309 let proj = match suffix {
2310 "ffn_gate_exps.weight" => "gate",
2311 "ffn_up_exps.weight" => "up",
2312 "ffn_down_exps.weight" => "down",
2313 other => panic!("not a *_exps suffix: {other}"),
2314 };
2315
2316 let mut signatures = Vec::with_capacity(n_expert);
2320 let active = src.active_experts(il);
2321 for ex in 0..n_expert {
2322 if active.is_some_and(|mask| !mask[ex]) {
2323 signatures.push((i32::MIN, 0));
2324 continue;
2325 }
2326 let name = format!("blk.{il}.ffn_{proj}_exps.{ex}.weight");
2327 if let Some(nv) = src.find_nvfp4_native(&name) {
2328 signatures.push((QT_NVFP4, nv.in_f / 64 * 36));
2329 } else {
2330 let v = src
2331 .find(&name)
2332 .unwrap_or_else(|| panic!("missing expert tensor {name}"));
2333 let in_f = v.ne[0] as usize;
2334 signatures.push(match staged_expert_row_bytes(v.ggml_type, in_f) {
2335 Some(row_bytes) => (staged_expert_qtype(v.ggml_type).unwrap(), row_bytes),
2336 None => (QT_F32, in_f * 4),
2337 });
2338 }
2339 }
2340 let mixed_layout = signatures.windows(2).any(|pair| pair[0] != pair[1]);
2341 if src.preserve_expert_encodings()
2342 && !mixed_layout
2343 && let Some(uniform) = Self::load_uniform_mmap_from_source(src, il, proj, n_expert)?
2344 {
2345 return Ok(uniform);
2346 }
2347 if src.preserve_expert_encodings() || mixed_layout {
2348 return Self::load_mixed_from_source(src, il, proj, n_expert);
2349 }
2350
2351 {
2358 let name0 = format!("blk.{il}.ffn_{proj}_exps.0.weight");
2359 if let Some(nv0) = src.find_nvfp4_native(&name0) {
2360 let (in_f, out_f) = (nv0.in_f, nv0.out_f);
2361 let row_bytes = in_f / 64 * 36;
2362 let expert_stride = out_f * row_bytes;
2363 let disk = std::env::var("MEMRA_ST_REPACK_DISK")
2370 .map(|v| v != "0")
2371 .unwrap_or(true)
2372 && src.st_dir().is_some();
2373 let cache_path = if let Some(dir) = src.st_dir() {
2374 let cache_dir = dir.join(".memra-repack");
2375 ensure_repack_cache_dir(&cache_dir)?;
2376 Some(cache_dir.join(format!("blk{il}-{proj}-{n_expert}x{out_f}x{in_f}.nvfp4")))
2377 } else {
2378 None
2379 };
2380 let total = n_expert * expert_stride;
2381 let mut macros = vec![1.0f32; n_expert];
2382 let read_macros = |macros: &mut Vec<f32>| {
2383 #[allow(clippy::needless_range_loop)]
2384 for ex in 0..n_expert {
2386 let stem = format!("blk.{il}.ffn_{proj}_exps.{ex}");
2387 if let Some(sv) = src.find(&format!("{stem}.scale")) {
2388 macros[ex] = f32::from_le_bytes(sv.bytes[..4].try_into().unwrap());
2389 }
2390 }
2391 };
2392 let bytes = if disk {
2393 let cp = cache_path.as_ref().unwrap();
2394 let fresh = repack_cache_is_fresh(cp, total);
2395 if !fresh {
2396 write_repack_cache(cp, |out| {
2398 for ex in 0..n_expert {
2399 use std::io::Write;
2400 let name = format!("blk.{il}.ffn_{proj}_exps.{ex}.weight");
2401 let nv = src.find_nvfp4_native(&name).unwrap_or_else(|| {
2402 panic!("expert {name} lost NVFP4-native mid-gather")
2403 });
2404 assert_eq!(
2405 (nv.in_f, nv.out_f),
2406 (in_f, out_f),
2407 "expert {ex} dims ({},{}) != expert 0 ({in_f},{out_f})",
2408 nv.in_f,
2409 nv.out_f
2410 );
2411 out.write_all(&memra_gguf::nvfp4_repack::repack_modelopt_to_gguf(
2412 nv.wbytes, nv.wscale, out_f, in_f,
2413 ))?;
2414 }
2415 Ok(())
2416 })?;
2417 }
2418 read_macros(&mut macros);
2419 let file = std::sync::Arc::new(open_repack_cache(cp, false)?);
2420 let map = unsafe { memmap2::Mmap::map(file.as_ref())? };
2421 assert_eq!(map.len(), total, "repack cache {cp:?} size mismatch");
2422 let _ = memra_gguf::source::apply_expert_mmap_advice(&map);
2425 memra_gguf::source::populate_expert_slab(
2426 &file,
2427 total,
2428 &format!("blk{il}-{proj}"),
2429 );
2430 let map = std::sync::Arc::new(map);
2431 let tiers = if std::env::var("MEMRA_ST_PINNED")
2444 .map(|v| v == "1")
2445 .unwrap_or(false)
2446 {
2447 static PIN_BUDGET: std::sync::OnceLock<std::sync::Mutex<usize>> =
2448 std::sync::OnceLock::new();
2449 let budget = PIN_BUDGET.get_or_init(|| {
2450 let b = crate::spill::MemBudget::probe(e)
2451 .map(|b| b.free_pinnable_ram)
2452 .unwrap_or(0);
2453 eprintln!("[st-spill] free_pinnable_ram={} MiB", b >> 20);
2454 std::sync::Mutex::new(b)
2455 });
2456 let mut rem = budget.lock().unwrap();
2457 let n_pin = (*rem / expert_stride).min(n_expert);
2461 if n_pin == 0 {
2462 None
2463 } else {
2464 let slab_len = n_pin * expert_stride;
2465 let mut pn = unsafe { e.ctx().alloc_pinned::<u8>(slab_len)? };
2466 {
2467 let dst = pn.as_mut_slice()?;
2468 dst.copy_from_slice(&map[..slab_len]);
2469 }
2470 let base = pn.as_ptr()?;
2471 *rem -= slab_len;
2472 let slab = std::sync::Arc::new(HostBuf::Pinned {
2473 slice: std::sync::Arc::new(pn),
2474 base,
2475 len: slab_len,
2476 });
2477 let mut tiers: Vec<HostBuf> = Vec::with_capacity(n_expert);
2478 for ex in 0..n_expert {
2479 let off = ex * expert_stride;
2480 if ex < n_pin {
2481 tiers.push(HostBuf::PinnedAlias {
2482 owner: slab.clone(),
2483 base: unsafe { base.add(off) },
2484 len: expert_stride,
2485 });
2486 } else {
2487 tiers.push(HostBuf::Mmap {
2488 map: map.clone(),
2489 file: file.clone(),
2490 off,
2491 len: expert_stride,
2492 });
2493 }
2494 }
2495 Some(tiers)
2496 }
2497 } else {
2498 None
2499 };
2500 if let Some(tiers) = tiers {
2501 let all_one = macros.iter().all(|&m| m == 1.0);
2502 return Ok(HostExps {
2503 bytes: HostBuf::Mmap {
2504 map,
2505 file,
2506 off: 0,
2507 len: total,
2508 },
2509 tiers: Some(tiers),
2510 qtype: QT_NVFP4,
2511 in_f,
2512 out_f,
2513 n_expert,
2514 row_bytes,
2515 expert_stride,
2516 layouts: None,
2517 macros: if all_one { None } else { Some(macros) },
2518 fp8_blk: None,
2519 });
2520 }
2521 HostBuf::Mmap {
2522 map,
2523 file,
2524 off: 0,
2525 len: total,
2526 }
2527 } else {
2528 let mut buf: Vec<u8> = Vec::with_capacity(total);
2529 for ex in 0..n_expert {
2530 let name = format!("blk.{il}.ffn_{proj}_exps.{ex}.weight");
2531 let nv = src.find_nvfp4_native(&name).unwrap_or_else(|| {
2532 panic!("expert {name} lost NVFP4-native mid-gather")
2533 });
2534 assert_eq!(
2535 (nv.in_f, nv.out_f),
2536 (in_f, out_f),
2537 "expert {ex} dims ({},{}) != expert 0 ({in_f},{out_f})",
2538 nv.in_f,
2539 nv.out_f
2540 );
2541 buf.extend_from_slice(&memra_gguf::nvfp4_repack::repack_modelopt_to_gguf(
2542 nv.wbytes, nv.wscale, out_f, in_f,
2543 ));
2544 }
2545 assert_eq!(buf.len(), total);
2546 read_macros(&mut macros);
2547 let pinned = std::env::var("MEMRA_MOE_PINNED").is_ok()
2548 || std::env::var("MEMRA_MOE_CACHE").as_deref() != Ok("0");
2549 if pinned {
2550 let mut p = unsafe { e.ctx().alloc_pinned::<u8>(buf.len())? };
2551 {
2552 let dst = p.as_mut_slice()?;
2553 dst.copy_from_slice(&buf);
2554 }
2555 let base = p.as_ptr()?;
2556 let len = buf.len();
2557 HostBuf::Pinned {
2558 slice: std::sync::Arc::new(p),
2559 base,
2560 len,
2561 }
2562 } else {
2563 HostBuf::Paged(buf)
2564 }
2565 };
2566 let all_one = macros.iter().all(|&m| m == 1.0);
2567 return Ok(HostExps {
2568 bytes,
2569 tiers: None,
2570 qtype: QT_NVFP4,
2571 in_f,
2572 out_f,
2573 n_expert,
2574 row_bytes,
2575 expert_stride,
2576 layouts: None,
2577 macros: if all_one { None } else { Some(macros) },
2578 fp8_blk: None,
2579 });
2580 }
2581 }
2582
2583 let mut buf: Vec<u8> = Vec::new();
2585 let mut in_f = 0usize;
2586 let mut out_f = 0usize;
2587 for ex in 0..n_expert {
2588 let name = format!("blk.{il}.ffn_{proj}_exps.{ex}.weight");
2590 let v = src
2591 .find(&name)
2592 .unwrap_or_else(|| panic!("missing expert tensor {name}"));
2593 assert_eq!(v.ne.len(), 2, "expert {name} is not 2D (ne={:?})", v.ne);
2594 let (cur_in, cur_out) = (v.ne[0] as usize, v.ne[1] as usize);
2595 if ex == 0 {
2596 in_f = cur_in;
2597 out_f = cur_out;
2598 } else {
2599 assert_eq!(
2600 (cur_in, cur_out),
2601 (in_f, out_f),
2602 "expert {ex} dims {:?} != expert 0 [{in_f},{out_f}]",
2603 (cur_in, cur_out)
2604 );
2605 }
2606 let n = cur_in * cur_out;
2609 let f32v = dequant::dequantize(v.ggml_type, &v.bytes, n);
2610 buf.reserve(n * 4);
2611 for f in &f32v {
2612 buf.extend_from_slice(&f.to_le_bytes());
2613 }
2614 }
2615 let row_bytes = in_f * 4; let expert_stride = out_f * row_bytes;
2617 assert_eq!(
2618 buf.len(),
2619 n_expert * expert_stride,
2620 "{ggml_exps_name} gather size {} != n_expert*stride {}",
2621 buf.len(),
2622 n_expert * expert_stride
2623 );
2624 assert_eq!(
2626 expert_stride,
2627 out_f * row_bytes,
2628 "{ggml_exps_name} stride mismatch: stride={expert_stride} out_f={out_f} row_bytes={row_bytes}"
2629 );
2630
2631 let pinned = std::env::var("MEMRA_MOE_PINNED").is_ok()
2633 || std::env::var("MEMRA_MOE_CACHE").as_deref() != Ok("0");
2634 let bytes = if pinned {
2635 let mut p = unsafe { e.ctx().alloc_pinned::<u8>(buf.len())? };
2636 {
2637 let dst = p.as_mut_slice()?;
2638 dst.copy_from_slice(&buf);
2639 }
2640 let base = p.as_ptr()?;
2641 let len = buf.len();
2642 HostBuf::Pinned {
2643 slice: std::sync::Arc::new(p),
2644 base,
2645 len,
2646 }
2647 } else {
2648 HostBuf::Paged(buf)
2649 };
2650 Ok(HostExps {
2651 bytes,
2652 tiers: None,
2653 qtype: QT_F32,
2654 in_f,
2655 out_f,
2656 n_expert,
2657 row_bytes,
2658 expert_stride,
2659 layouts: None,
2660 macros: None,
2661 fp8_blk: None,
2662 })
2663 }
2664
2665 fn load_uniform_mmap_from_source(
2670 src: &dyn TensorSource,
2671 il: u32,
2672 proj: &str,
2673 n_expert: usize,
2674 ) -> Result<Option<Self>, Box<dyn std::error::Error>> {
2675 if src
2676 .active_experts(il)
2677 .is_some_and(|mask| mask.iter().any(|&active| !active))
2678 {
2679 return Ok(None);
2680 }
2681 let mut first_map = None;
2682 let mut first_file = None;
2683 let mut base_offset = 0u64;
2684 let mut expert_stride = 0usize;
2685 let mut in_f = 0usize;
2686 let mut out_f = 0usize;
2687 let mut qtype = 0i32;
2688 let mut row_bytes = 0usize;
2689 let mut macros = vec![1.0f32; n_expert];
2690 #[allow(clippy::needless_range_loop)]
2691 for ex in 0..n_expert {
2693 let stem = format!("blk.{il}.ffn_{proj}_exps.{ex}");
2694 let name = format!("{stem}.weight");
2695 let Some(DiskExtent {
2696 map,
2697 file,
2698 offset,
2699 len,
2700 }) = find_expert_disk_strict(src, &name)?
2701 else {
2702 return Ok(None);
2703 };
2704 let Some(v) = src.find(&name) else {
2705 return Ok(None);
2706 };
2707 if v.ne.len() != 2 {
2708 return Ok(None);
2709 }
2710 let (cur_in, cur_out) = (v.ne[0] as usize, v.ne[1] as usize);
2711 let Some(cur_row_bytes) = staged_expert_row_bytes(v.ggml_type, cur_in) else {
2712 return Ok(None);
2713 };
2714 let cur_qtype = staged_expert_qtype(v.ggml_type).unwrap();
2715 if ex == 0 {
2716 base_offset = offset;
2717 expert_stride = len;
2718 in_f = cur_in;
2719 out_f = cur_out;
2720 qtype = cur_qtype;
2721 row_bytes = cur_row_bytes;
2722 first_map = Some(map);
2723 first_file = Some(file);
2724 } else if !std::sync::Arc::ptr_eq(first_map.as_ref().unwrap(), &map)
2725 || !std::sync::Arc::ptr_eq(first_file.as_ref().unwrap(), &file)
2726 || offset != base_offset + (ex * expert_stride) as u64
2727 || len != expert_stride
2728 || (cur_in, cur_out, cur_qtype, cur_row_bytes) != (in_f, out_f, qtype, row_bytes)
2729 {
2730 return Ok(None);
2731 }
2732 if let Some(scale) = src.find(&format!("{stem}.scale")) {
2733 macros[ex] = f32::from_le_bytes(scale.bytes[..4].try_into().unwrap());
2734 }
2735 }
2736 assert_eq!(expert_stride, out_f * row_bytes);
2737 let total = n_expert * expert_stride;
2738 let off = usize::try_from(base_offset)
2739 .map_err(|_| format!("uniform expert disk offset {base_offset} does not fit usize"))?;
2740 let all_one = macros.iter().all(|&scale| scale == 1.0);
2741 Ok(Some(HostExps {
2742 bytes: HostBuf::Mmap {
2743 map: first_map.unwrap(),
2744 file: first_file.unwrap(),
2745 off,
2746 len: total,
2747 },
2748 tiers: None,
2749 qtype,
2750 in_f,
2751 out_f,
2752 n_expert,
2753 row_bytes,
2754 expert_stride,
2755 layouts: None,
2756 macros: if all_one { None } else { Some(macros) },
2757 fp8_blk: None,
2758 }))
2759 }
2760
2761 fn load_mixed_from_source(
2762 src: &dyn TensorSource,
2763 il: u32,
2764 proj: &str,
2765 n_expert: usize,
2766 ) -> Result<Self, Box<dyn std::error::Error>> {
2767 let mut tiers = Vec::with_capacity(n_expert);
2768 let mut layouts = Vec::with_capacity(n_expert);
2769 let mut macros = vec![1.0f32; n_expert];
2770 let mut in_f = 0usize;
2771 let mut out_f = 0usize;
2772 let active = src.active_experts(il);
2773 let mut first_active = None;
2774
2775 for ex in 0..n_expert {
2776 if active.is_some_and(|mask| !mask[ex]) {
2777 layouts.push(ExpertLayout {
2778 offset: 0,
2779 len: 0,
2780 qtype: QT_F32,
2781 row_bytes: 0,
2782 });
2783 tiers.push(HostBuf::Paged(Vec::new()));
2784 continue;
2785 }
2786 let name = format!("blk.{il}.ffn_{proj}_exps.{ex}.weight");
2787 let stem = format!("blk.{il}.ffn_{proj}_exps.{ex}");
2788 if let Some(scale) = src.find(&format!("{stem}.scale")) {
2789 macros[ex] = f32::from_le_bytes(scale.bytes[..4].try_into().unwrap());
2790 }
2791 let (host, byte_len, qtype, row_bytes, cur_in, cur_out) = if let Some(DiskExtent {
2792 map,
2793 file,
2794 offset,
2795 len,
2796 }) =
2797 find_expert_disk_strict(src, &name)?
2798 {
2799 let v = src
2800 .find(&name)
2801 .unwrap_or_else(|| panic!("missing expert tensor {name}"));
2802 assert_eq!(v.ne.len(), 2, "expert {name} is not 2D (ne={:?})", v.ne);
2803 let (cur_in, cur_out) = (v.ne[0] as usize, v.ne[1] as usize);
2804 let row_bytes = staged_expert_row_bytes(v.ggml_type, cur_in).ok_or_else(|| {
2805 format!("mmap expert {name} has unsupported qtype {:?}", v.ggml_type)
2806 })?;
2807 let off = usize::try_from(offset).map_err(|_| {
2808 format!("expert {name} disk offset {offset} does not fit usize")
2809 })?;
2810 (
2811 HostBuf::Mmap {
2812 map,
2813 file,
2814 off,
2815 len,
2816 },
2817 len,
2818 staged_expert_qtype(v.ggml_type).unwrap(),
2819 row_bytes,
2820 cur_in,
2821 cur_out,
2822 )
2823 } else if let Some(nv) = src.find_nvfp4_native(&name) {
2824 let bytes = memra_gguf::nvfp4_repack::repack_modelopt_to_gguf(
2825 nv.wbytes, nv.wscale, nv.out_f, nv.in_f,
2826 );
2827 let row_bytes = nv.in_f / 64 * 36;
2828 let byte_len = bytes.len();
2829 (
2830 HostBuf::Paged(bytes),
2831 byte_len,
2832 QT_NVFP4,
2833 row_bytes,
2834 nv.in_f,
2835 nv.out_f,
2836 )
2837 } else {
2838 let v = src
2839 .find(&name)
2840 .unwrap_or_else(|| panic!("missing expert tensor {name}"));
2841 assert_eq!(v.ne.len(), 2, "expert {name} is not 2D (ne={:?})", v.ne);
2842 let (cur_in, cur_out) = (v.ne[0] as usize, v.ne[1] as usize);
2843 if let Some(row_bytes) = staged_expert_row_bytes(v.ggml_type, cur_in) {
2844 let bytes = v.bytes.into_owned();
2845 let byte_len = bytes.len();
2846 (
2847 HostBuf::Paged(bytes),
2848 byte_len,
2849 staged_expert_qtype(v.ggml_type).unwrap(),
2850 row_bytes,
2851 cur_in,
2852 cur_out,
2853 )
2854 } else {
2855 let f32v = dequant::dequantize(v.ggml_type, &v.bytes, cur_in * cur_out);
2856 let mut bytes = Vec::with_capacity(f32v.len() * 4);
2857 for f in f32v {
2858 bytes.extend_from_slice(&f.to_le_bytes());
2859 }
2860 let byte_len = bytes.len();
2861 (
2862 HostBuf::Paged(bytes),
2863 byte_len,
2864 QT_F32,
2865 cur_in * 4,
2866 cur_in,
2867 cur_out,
2868 )
2869 }
2870 };
2871
2872 if first_active.is_none() {
2873 in_f = cur_in;
2874 out_f = cur_out;
2875 first_active = Some(ex);
2876 } else {
2877 assert_eq!(
2878 (cur_in, cur_out),
2879 (in_f, out_f),
2880 "expert {ex} dims ({cur_in},{cur_out}) != first active expert ({in_f},{out_f})"
2881 );
2882 }
2883 assert_eq!(
2884 byte_len,
2885 cur_out * row_bytes,
2886 "expert {name} bytes {byte_len} != out_f*row_bytes {}",
2887 cur_out * row_bytes
2888 );
2889 layouts.push(ExpertLayout {
2890 offset: 0,
2891 len: byte_len,
2892 qtype,
2893 row_bytes,
2894 });
2895 tiers.push(host);
2896 }
2897
2898 let first = layouts[*first_active
2899 .as_ref()
2900 .expect("expert mask pruned every expert")];
2901 let expert_stride = layouts.iter().map(|layout| layout.len).max().unwrap_or(0);
2902 let all_one = macros.iter().all(|&scale| scale == 1.0);
2903 Ok(HostExps {
2904 bytes: HostBuf::Paged(Vec::new()),
2905 tiers: Some(tiers),
2906 qtype: first.qtype,
2907 in_f,
2908 out_f,
2909 n_expert,
2910 row_bytes: first.row_bytes,
2911 expert_stride,
2912 layouts: Some(layouts),
2913 macros: if all_one { None } else { Some(macros) },
2914 fp8_blk: None,
2915 })
2916 }
2917
2918 #[inline]
2922 pub fn macro_scale(&self, e: usize) -> f32 {
2923 self.macros.as_ref().map(|m| m[e]).unwrap_or(1.0)
2924 }
2925
2926 #[inline]
2927 pub fn is_uniform_layout(&self) -> bool {
2928 self.layouts.is_none()
2929 }
2930
2931 #[inline]
2932 pub fn expert_layout(&self, e: usize) -> ExpertLayout {
2933 debug_assert!(
2934 e < self.n_expert,
2935 "expert index {e} >= n_expert {}",
2936 self.n_expert
2937 );
2938 self.layouts
2939 .as_ref()
2940 .map(|layouts| layouts[e])
2941 .unwrap_or(ExpertLayout {
2942 offset: e * self.expert_stride,
2943 len: self.expert_stride,
2944 qtype: self.qtype,
2945 row_bytes: self.row_bytes,
2946 })
2947 }
2948
2949 #[inline]
2950 pub fn max_expert_bytes(&self) -> usize {
2951 self.layouts
2952 .as_ref()
2953 .and_then(|layouts| layouts.iter().map(|layout| layout.len).max())
2954 .unwrap_or(self.expert_stride)
2955 }
2956
2957 #[inline]
2959 pub fn expert_bytes(&self, e: usize) -> &[u8] {
2960 let layout = self.expert_layout(e);
2961 match &self.tiers {
2962 Some(tiers) => {
2963 debug_assert_eq!(tiers[e].len(), layout.len);
2964 tiers[e].as_bytes()
2965 }
2966 None => &self.bytes.as_bytes()[layout.offset..layout.offset + layout.len],
2967 }
2968 }
2969
2970 #[inline]
2974 pub(crate) fn expert_source(&self, e: usize) -> ExpertSource<'_> {
2975 let layout = self.expert_layout(e);
2976 match &self.tiers {
2977 Some(tiers) => tiers[e].expert_source(0, layout.len),
2978 None => self.bytes.expert_source(layout.offset, layout.len),
2979 }
2980 }
2981
2982 #[inline]
2986 pub fn prefetch_expert_pages(&self, e: usize) -> bool {
2987 let layout = self.expert_layout(e);
2988 match &self.tiers {
2989 Some(tiers) => tiers[e].advise_willneed(0, layout.len),
2990 None => self.bytes.advise_willneed(layout.offset, layout.len),
2991 }
2992 }
2993}
2994
2995#[cfg(test)]
2996mod tests {
2997 use super::{
2998 ExpertKeepalive, ExpertSource, HostBuf, HostExps, QT_BF16, QT_NVFP4, QT_Q2_K, QT_Q4_K,
2999 ensure_repack_cache_dir, open_repack_cache, repack_cache_is_fresh, repack_nvfp4_split,
3000 unpack_nvfp4_split, write_repack_cache,
3001 };
3002 use memra_gguf::nvfp4_repack::{repack_modelopt_to_gguf, repack_modelopt_to_split};
3003 use memra_gguf::source::{DiskExtent, Fp8StackedNative, TensorSource, TensorView};
3004 use memra_gguf::{GgmlType, config::ModelConfig};
3005 use std::borrow::Cow;
3006
3007 #[cfg(unix)]
3008 #[test]
3009 fn repack_cache_refuses_symlinked_directory_and_file() {
3010 use std::os::unix::fs::symlink;
3011
3012 let root = std::env::temp_dir().join(format!("memra-repack-links-{}", std::process::id()));
3013 std::fs::create_dir_all(&root).unwrap();
3014 let target_dir = root.join("target-dir");
3015 std::fs::create_dir(&target_dir).unwrap();
3016 let cache_dir = root.join(".memra-repack");
3017 symlink(&target_dir, &cache_dir).unwrap();
3018 let error = ensure_repack_cache_dir(&cache_dir).unwrap_err();
3019 assert_eq!(error.kind(), std::io::ErrorKind::InvalidData);
3020
3021 std::fs::remove_file(&cache_dir).unwrap();
3022 std::fs::create_dir(&cache_dir).unwrap();
3023 let target = root.join("outside.bin");
3024 std::fs::write(&target, b"keep").unwrap();
3025 let cache_file = cache_dir.join("artifact.nvfp4");
3026 symlink(&target, &cache_file).unwrap();
3027 assert!(!repack_cache_is_fresh(&cache_file, 4));
3028 let error = open_repack_cache(&cache_file, true).unwrap_err();
3029 assert_ne!(error.kind(), std::io::ErrorKind::NotFound);
3030 assert_eq!(std::fs::read(&target).unwrap(), b"keep");
3031
3032 let hardlink = cache_dir.join("hardlink.nvfp4");
3033 std::fs::hard_link(&target, &hardlink).unwrap();
3034 let error = write_repack_cache(&hardlink, |out| {
3035 use std::io::Write;
3036 out.write_all(b"replacement")
3037 })
3038 .unwrap_err();
3039 assert_eq!(error.kind(), std::io::ErrorKind::InvalidData);
3040 assert_eq!(std::fs::read(&target).unwrap(), b"keep");
3041 std::fs::remove_dir_all(root).ok();
3042 }
3043
3044 struct MixedExpertSource {
3045 bf16: Vec<u8>,
3046 q4k: Vec<u8>,
3047 }
3048
3049 impl TensorSource for MixedExpertSource {
3050 fn config(&self) -> ModelConfig {
3051 panic!("unused by HostExps mixed-loader test")
3052 }
3053
3054 fn find(&self, name: &str) -> Option<TensorView<'_>> {
3055 let (bytes, ggml_type) = if name == "blk.0.ffn_gate_exps.0.weight" {
3056 (&self.bf16, GgmlType::BF16)
3057 } else if name == "blk.0.ffn_gate_exps.1.weight" {
3058 (&self.q4k, GgmlType::Q4_K)
3059 } else {
3060 return None;
3061 };
3062 Some(TensorView {
3063 bytes: Cow::Borrowed(bytes),
3064 ggml_type,
3065 ne: vec![256, 2],
3066 })
3067 }
3068 }
3069
3070 struct PrunedExpertSource {
3071 q2k: Vec<u8>,
3072 nvfp4: Vec<u8>,
3073 active: Vec<bool>,
3074 }
3075
3076 struct MmapExpertSource {
3077 file: std::sync::Arc<std::fs::File>,
3078 map: std::sync::Arc<memmap2::Mmap>,
3079 base_offset: usize,
3080 expert_len: usize,
3081 }
3082
3083 struct LegacyMmapExpertSource {
3084 map: std::sync::Arc<memmap2::Mmap>,
3085 expert_len: usize,
3086 }
3087
3088 struct StackedFp8Source {
3089 file: std::sync::Arc<std::fs::File>,
3090 map: std::sync::Arc<memmap2::Mmap>,
3091 offset: usize,
3092 len: usize,
3093 scales: Vec<f32>,
3094 }
3095
3096 impl TensorSource for StackedFp8Source {
3097 fn config(&self) -> ModelConfig {
3098 panic!("unused by stacked FP8 ownership test")
3099 }
3100
3101 fn find(&self, _name: &str) -> Option<TensorView<'_>> {
3102 None
3103 }
3104
3105 fn find_fp8_stacked_native(&self, name: &str) -> Option<Fp8StackedNative<'_>> {
3106 (name == "blk.0.ffn_gate_exps.weight").then(|| Fp8StackedNative {
3107 bytes: &self.map[self.offset..self.offset + self.len],
3108 scales: self.scales.clone(),
3109 n_expert: 2,
3110 out_f: 2,
3111 in_f: 32,
3112 scale_rows: 1,
3113 scale_cols: 1,
3114 })
3115 }
3116
3117 fn find_expert_disk(&self, name: &str) -> Option<DiskExtent> {
3118 (name == "blk.0.ffn_gate_exps.weight").then(|| DiskExtent {
3119 map: self.map.clone(),
3120 file: self.file.clone(),
3121 offset: self.offset as u64,
3122 len: self.len,
3123 })
3124 }
3125 }
3126
3127 impl TensorSource for MmapExpertSource {
3128 fn config(&self) -> ModelConfig {
3129 panic!("unused by HostExps mmap-loader test")
3130 }
3131 fn preserve_expert_encodings(&self) -> bool {
3132 true
3133 }
3134 fn find(&self, name: &str) -> Option<TensorView<'_>> {
3135 let ex = match name {
3136 "blk.0.ffn_gate_exps.0.weight" => 0,
3137 "blk.0.ffn_gate_exps.1.weight" => 1,
3138 _ => return None,
3139 };
3140 let off = self.base_offset + ex * self.expert_len;
3141 Some(TensorView {
3142 bytes: Cow::Borrowed(&self.map[off..off + self.expert_len]),
3143 ggml_type: GgmlType::Q2_K,
3144 ne: vec![256, 2],
3145 })
3146 }
3147 fn find_expert_disk(&self, name: &str) -> Option<DiskExtent> {
3148 let ex = match name {
3149 "blk.0.ffn_gate_exps.0.weight" => 0,
3150 "blk.0.ffn_gate_exps.1.weight" => 1,
3151 _ => return None,
3152 };
3153 Some(DiskExtent {
3154 map: self.map.clone(),
3155 file: self.file.clone(),
3156 offset: (self.base_offset + ex * self.expert_len) as u64,
3157 len: self.expert_len,
3158 })
3159 }
3160 }
3161
3162 impl TensorSource for LegacyMmapExpertSource {
3163 fn config(&self) -> ModelConfig {
3164 panic!("unused by legacy mmap guard test")
3165 }
3166 fn preserve_expert_encodings(&self) -> bool {
3167 true
3168 }
3169 fn find(&self, name: &str) -> Option<TensorView<'_>> {
3170 let ex = match name {
3171 "blk.0.ffn_gate_exps.0.weight" => 0,
3172 "blk.0.ffn_gate_exps.1.weight" => 1,
3173 _ => return None,
3174 };
3175 let off = ex * self.expert_len;
3176 Some(TensorView {
3177 bytes: Cow::Borrowed(&self.map[off..off + self.expert_len]),
3178 ggml_type: GgmlType::Q2_K,
3179 ne: vec![256, 2],
3180 })
3181 }
3182 fn find_expert_mmap(
3183 &self,
3184 name: &str,
3185 ) -> Option<(std::sync::Arc<memmap2::Mmap>, usize, usize)> {
3186 let ex = match name {
3187 "blk.0.ffn_gate_exps.0.weight" => 0,
3188 "blk.0.ffn_gate_exps.1.weight" => 1,
3189 _ => return None,
3190 };
3191 Some((self.map.clone(), ex * self.expert_len, self.expert_len))
3192 }
3193 }
3194
3195 impl TensorSource for PrunedExpertSource {
3196 fn config(&self) -> ModelConfig {
3197 panic!("unused by HostExps pruned-loader test")
3198 }
3199 fn active_experts(&self, layer: u32) -> Option<&[bool]> {
3200 (layer == 0).then_some(self.active.as_slice())
3201 }
3202 fn find(&self, name: &str) -> Option<TensorView<'_>> {
3203 let (bytes, ggml_type) = match name {
3204 "blk.0.ffn_gate_exps.0.weight" => (&self.q2k, GgmlType::Q2_K),
3205 "blk.0.ffn_gate_exps.2.weight" => (&self.nvfp4, GgmlType::NVFP4),
3206 _ => return None,
3207 };
3208 Some(TensorView {
3209 bytes: Cow::Borrowed(bytes),
3210 ggml_type,
3211 ne: vec![256, 2],
3212 })
3213 }
3214 }
3215
3216 #[test]
3217 fn stacked_fp8_experts_retain_owned_mmap_and_scale_geometry() {
3218 let path = std::env::temp_dir().join(format!("memra-stacked-fp8-{}", std::process::id()));
3219 let offset = 11usize;
3220 let len = 2 * 2 * 32;
3221 let mut file_bytes = vec![0xA5; offset];
3222 file_bytes.extend((0..len).map(|i| (i % 127) as u8));
3223 std::fs::write(&path, &file_bytes).unwrap();
3224 let file = std::sync::Arc::new(std::fs::File::open(&path).unwrap());
3225 let map = std::sync::Arc::new(unsafe { memmap2::Mmap::map(file.as_ref()).unwrap() });
3226 let source = StackedFp8Source {
3227 file,
3228 map,
3229 offset,
3230 len,
3231 scales: vec![0.5, 0.25],
3232 };
3233
3234 let exps = HostExps::load_fp8_stacked_native_with_policy(
3235 &source,
3236 "blk.0.ffn_gate_exps.weight",
3237 true,
3238 )
3239 .unwrap()
3240 .unwrap();
3241 assert_eq!(exps.qtype, crate::QT_F8_E4M3_BLK);
3242 assert_eq!((exps.n_expert, exps.out_f, exps.in_f), (2, 2, 32));
3243 assert_eq!(exps.expert_stride, 64);
3244 assert!(matches!(exps.bytes, HostBuf::Mmap { .. }));
3245 assert_eq!(exps.expert_bytes(0), &file_bytes[offset..offset + 64]);
3246 assert_eq!(exps.expert_bytes(1), &file_bytes[offset + 64..offset + len]);
3247 let fp8 = exps.fp8_blk.as_ref().unwrap();
3248 assert_eq!((fp8.rows, fp8.cols, fp8.expert_stride), (1, 1, 1));
3249 assert_eq!(fp8.scales, vec![0.5, 0.25]);
3250
3251 drop(source);
3252 assert_eq!(exps.expert_bytes(1), &file_bytes[offset + 64..offset + len]);
3253 std::fs::remove_file(path).ok();
3254 }
3255
3256 #[test]
3257 fn stacked_fp8_experts_reject_non_finite_codes() {
3258 let path =
3259 std::env::temp_dir().join(format!("memra-stacked-fp8-nan-{}", std::process::id()));
3260 let len = 2 * 2 * 32;
3261 let mut file_bytes = vec![0x12; len];
3262 file_bytes[73] = 0x7f;
3263 std::fs::write(&path, &file_bytes).unwrap();
3264 let file = std::sync::Arc::new(std::fs::File::open(&path).unwrap());
3265 let map = std::sync::Arc::new(unsafe { memmap2::Mmap::map(file.as_ref()).unwrap() });
3266 let source = StackedFp8Source {
3267 file,
3268 map,
3269 offset: 0,
3270 len,
3271 scales: vec![0.5, 0.25],
3272 };
3273
3274 let err = match HostExps::load_fp8_stacked_native_with_policy(
3275 &source,
3276 "blk.0.ffn_gate_exps.weight",
3277 true,
3278 ) {
3279 Ok(_) => panic!("non-finite E4M3 code was accepted"),
3280 Err(err) => err,
3281 };
3282 assert!(err.to_string().contains("non-finite E4M3"));
3283 std::fs::remove_file(path).ok();
3284 }
3285
3286 #[test]
3290 fn direct_split_equals_chained() {
3291 for (out_f, in_f) in [(1usize, 64usize), (3, 128), (5, 320), (8, 1024)] {
3292 let mut w = vec![0u8; out_f * in_f / 2];
3293 let mut s = vec![0u8; out_f * in_f / 16];
3294 for (i, b) in w.iter_mut().enumerate() {
3295 *b = ((i * 41 + 7) & 0xFF) as u8;
3296 }
3297 for (i, b) in s.iter_mut().enumerate() {
3298 *b = (0x20 + ((i * 11 + 5) % 0x50)) as u8;
3299 }
3300 let gguf = repack_modelopt_to_gguf(&w, &s, out_f, in_f);
3301 let chained = repack_nvfp4_split(&gguf, out_f);
3302 let direct = repack_modelopt_to_split(&w, &s, out_f, in_f);
3303 assert_eq!(
3304 direct, chained,
3305 "fused != chained at out_f={out_f} in_f={in_f}"
3306 );
3307 assert_eq!(
3308 unpack_nvfp4_split(&direct, out_f),
3309 gguf,
3310 "split roundtrip broken at out_f={out_f} in_f={in_f}"
3311 );
3312 }
3313 }
3314
3315 #[test]
3316 fn mixed_expert_loader_keeps_each_encoding_and_extent() {
3317 let source = MixedExpertSource {
3318 bf16: vec![0x5a; 256 * 2 * 2],
3319 q4k: vec![0xa5; 2 * 144],
3320 };
3321 let exps = HostExps::load_mixed_from_source(&source, 0, "gate", 2).unwrap();
3322 assert!(!exps.is_uniform_layout());
3323 assert_eq!(exps.max_expert_bytes(), 1024);
3324 assert_eq!(exps.expert_layout(0).qtype, QT_BF16);
3325 assert_eq!(exps.expert_layout(0).row_bytes, 512);
3326 assert_eq!(exps.expert_layout(0).len, 1024);
3327 assert_eq!(exps.expert_layout(1).qtype, QT_Q4_K);
3328 assert_eq!(exps.expert_layout(1).row_bytes, 144);
3329 assert_eq!(exps.expert_layout(1).len, 288);
3330 assert_eq!(exps.expert_bytes(0), source.bf16);
3331 assert_eq!(exps.expert_bytes(1), source.q4k);
3332 match exps.expert_source(1) {
3333 ExpertSource::Memory { bytes, .. } => assert_eq!(bytes, source.q4k),
3334 ExpertSource::Disk { .. } => panic!("paged expert unexpectedly became disk-backed"),
3335 }
3336 }
3337
3338 #[test]
3339 fn mixed_expert_loader_omits_masked_expert_bytes() {
3340 let source = PrunedExpertSource {
3341 q2k: vec![0x22; 2 * 84],
3342 nvfp4: vec![0x44; 2 * 4 * 36],
3343 active: vec![true, false, true],
3344 };
3345 let exps = HostExps::load_mixed_from_source(&source, 0, "gate", 3).unwrap();
3346 assert_eq!(exps.expert_layout(0).qtype, QT_Q2_K);
3347 assert_eq!(exps.expert_layout(0).row_bytes, 84);
3348 assert_eq!(exps.expert_layout(1).len, 0);
3349 assert_eq!(exps.expert_bytes(1), &[]);
3350 assert_eq!(exps.expert_layout(2).qtype, QT_NVFP4);
3351 assert_eq!(exps.expert_layout(2).row_bytes, 4 * 36);
3352 }
3353
3354 #[test]
3355 fn mixed_expert_loader_keeps_mmap_backing_zero_copy() {
3356 let path = std::env::temp_dir().join(format!("memra-mixed-mmap-{}", std::process::id()));
3357 let base_offset = 3usize;
3358 let expert_len = 2 * 84;
3359 let mut bytes = vec![0xE1; base_offset];
3360 bytes.extend(vec![0x31; expert_len]);
3361 bytes.extend(vec![0x72; expert_len]);
3362 std::fs::write(&path, &bytes).unwrap();
3363 let file = std::sync::Arc::new(std::fs::File::open(&path).unwrap());
3364 let map = std::sync::Arc::new(unsafe { memmap2::Mmap::map(file.as_ref()).unwrap() });
3365 let source = MmapExpertSource {
3366 file: file.clone(),
3367 map,
3368 base_offset,
3369 expert_len,
3370 };
3371 let exps = HostExps::load_mixed_from_source(&source, 0, "gate", 2).unwrap();
3372 assert!(matches!(
3373 exps.tiers.as_ref().unwrap()[0],
3374 HostBuf::Mmap { .. }
3375 ));
3376 assert!(matches!(
3377 exps.tiers.as_ref().unwrap()[1],
3378 HostBuf::Mmap { .. }
3379 ));
3380 assert_eq!(
3381 exps.expert_bytes(0),
3382 &bytes[base_offset..base_offset + expert_len]
3383 );
3384 assert_eq!(exps.expert_bytes(1), &bytes[base_offset + expert_len..]);
3385 match exps.expert_source(1) {
3386 ExpertSource::Disk {
3387 file: got_file,
3388 offset,
3389 len,
3390 fallback,
3391 keepalive,
3392 } => {
3393 assert!(std::sync::Arc::ptr_eq(got_file, &file));
3394 assert_eq!(offset, (base_offset + expert_len) as u64);
3395 assert_eq!(len, expert_len);
3396 assert_eq!(fallback, &bytes[base_offset + expert_len..]);
3397 match keepalive {
3398 ExpertKeepalive::Mmap(owner) => {
3399 assert!(std::sync::Arc::ptr_eq(&owner, &source.map));
3400 }
3401 _ => panic!("mmap expert did not retain its mmap owner"),
3402 }
3403 }
3404 ExpertSource::Memory { .. } => panic!("mixed mmap tier lost its disk extent"),
3405 }
3406 #[cfg(unix)]
3407 assert!(exps.prefetch_expert_pages(1));
3408 std::fs::remove_file(path).ok();
3409 }
3410
3411 #[test]
3412 fn tiered_expert_source_does_not_double_apply_layout_offset() {
3413 let path =
3414 std::env::temp_dir().join(format!("memra-tiered-source-offset-{}", std::process::id()));
3415 let base_offset = 7usize;
3416 let expert_len = 2 * 84;
3417 let mut bytes = vec![0xE3; base_offset];
3418 bytes.extend(vec![0x41; expert_len]);
3419 bytes.extend(vec![0x82; expert_len]);
3420 std::fs::write(&path, &bytes).unwrap();
3421 let file = std::sync::Arc::new(std::fs::File::open(&path).unwrap());
3422 let map = std::sync::Arc::new(unsafe { memmap2::Mmap::map(file.as_ref()).unwrap() });
3423 let exps = HostExps {
3424 bytes: HostBuf::Paged(Vec::new()),
3425 tiers: Some(vec![
3426 HostBuf::Mmap {
3427 map: map.clone(),
3428 file: file.clone(),
3429 off: base_offset,
3430 len: expert_len,
3431 },
3432 HostBuf::Mmap {
3433 map,
3434 file: file.clone(),
3435 off: base_offset + expert_len,
3436 len: expert_len,
3437 },
3438 ]),
3439 qtype: QT_Q2_K,
3440 in_f: 256,
3441 out_f: 2,
3442 n_expert: 2,
3443 row_bytes: 84,
3444 expert_stride: expert_len,
3445 layouts: None,
3446 macros: None,
3447 fp8_blk: None,
3448 };
3449
3450 assert_eq!(exps.expert_layout(1).offset, expert_len);
3452 match exps.expert_source(1) {
3453 ExpertSource::Disk {
3454 offset,
3455 len,
3456 fallback,
3457 ..
3458 } => {
3459 assert_eq!(offset, (base_offset + expert_len) as u64);
3460 assert_eq!(len, expert_len);
3461 assert_eq!(fallback, &bytes[base_offset + expert_len..]);
3462 }
3463 ExpertSource::Memory { .. } => panic!("tiered mmap expert lost its disk extent"),
3464 }
3465 std::fs::remove_file(path).ok();
3466 }
3467
3468 #[test]
3469 fn legacy_mmap_source_requires_retained_file_extent() {
3470 let path =
3471 std::env::temp_dir().join(format!("memra-legacy-mmap-source-{}", std::process::id()));
3472 let expert_len = 2 * 84;
3473 std::fs::write(&path, vec![0x64; 2 * expert_len]).unwrap();
3474 let file = std::fs::File::open(&path).unwrap();
3475 let map = std::sync::Arc::new(unsafe { memmap2::Mmap::map(&file).unwrap() });
3476 let source = LegacyMmapExpertSource { map, expert_len };
3477
3478 let err = match HostExps::load_uniform_mmap_from_source(&source, 0, "gate", 2) {
3479 Ok(_) => panic!("legacy mmap-only source silently fell back instead of failing"),
3480 Err(err) => err,
3481 };
3482 let message = err.to_string();
3483 assert!(
3484 message.contains("legacy find_expert_mmap without find_expert_disk"),
3485 "{message}"
3486 );
3487 assert!(message.contains("retained Arc<File>"), "{message}");
3488 std::fs::remove_file(path).ok();
3489 }
3490
3491 #[test]
3492 fn uniform_expert_loader_coalesces_contiguous_mmap() {
3493 let path = std::env::temp_dir().join(format!("memra-uniform-mmap-{}", std::process::id()));
3494 let base_offset = 5usize;
3495 let expert_len = 2 * 84;
3496 let mut bytes = vec![0xE2; base_offset];
3497 bytes.extend(vec![0x19; expert_len]);
3498 bytes.extend(vec![0x91; expert_len]);
3499 std::fs::write(&path, &bytes).unwrap();
3500 let file = std::sync::Arc::new(std::fs::File::open(&path).unwrap());
3501 let map = std::sync::Arc::new(unsafe { memmap2::Mmap::map(file.as_ref()).unwrap() });
3502 let source = MmapExpertSource {
3503 file: file.clone(),
3504 map,
3505 base_offset,
3506 expert_len,
3507 };
3508 let exps = HostExps::load_uniform_mmap_from_source(&source, 0, "gate", 2)
3509 .unwrap()
3510 .expect("contiguous mmap should coalesce");
3511 assert!(exps.is_uniform_layout());
3512 assert!(matches!(&exps.bytes, HostBuf::Mmap { .. }));
3513 assert_eq!(exps.expert_stride, expert_len);
3514 assert_eq!(
3515 exps.expert_bytes(0),
3516 &bytes[base_offset..base_offset + expert_len]
3517 );
3518 assert_eq!(exps.expert_bytes(1), &bytes[base_offset + expert_len..]);
3519 match exps.expert_source(1) {
3520 ExpertSource::Disk {
3521 file: got_file,
3522 offset,
3523 len,
3524 fallback,
3525 ..
3526 } => {
3527 assert!(std::sync::Arc::ptr_eq(got_file, &file));
3528 assert_eq!(offset, (base_offset + expert_len) as u64);
3529 assert_eq!(len, expert_len);
3530 assert_eq!(fallback, &bytes[base_offset + expert_len..]);
3531 }
3532 ExpertSource::Memory { .. } => panic!("uniform mmap slab lost its disk extent"),
3533 }
3534 #[cfg(unix)]
3535 assert!(exps.prefetch_expert_pages(1));
3536 std::fs::remove_file(path).ok();
3537 }
3538}