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