spark_runtime/fast_weights/
skip.rs

1// SPDX-License-Identifier: AGPL-3.0-only
2
3//! Which tensors the fast loader does NOT upload.
4//!
5//! Three independent rules, worth reading together because each one withholds
6//! bytes a downstream loader might expect:
7//!
8//!   1. **EP sharding** — remote experts belong to another rank.
9//!   2. **`skip_activation_scales`** — W4A4 `*.input_scale`, opt-in.
10//!   3. **`skip_mtp`** — `mtp.*` for a loader that builds no MTP head, opt-in.
11//!   4. **`skip_vision`** — the vision tower, for a text-only port that binds
12//!      no vision encoder. Derived from the loader, not opt-in per model.
13//!
14//! Rules 2 and 3 default OFF and are allow-listed per model, because
15//! withholding a tensor a loader DOES read is invisible until the output is
16//! subtly wrong. Rule 1 is structural and always active under EP.
17//!
18//! **DEFER is a fifth rule and a different kind.** A skipped tensor is gone; a
19//! deferred one is recorded with its on-disk location because the model's own
20//! loader will read it from the host. [`FastSafetensorsLoader::is_deferred`]
21//! lives here so the two questions are answered side by side, but it is asked
22//! AFTER `should_skip_tensor` — see [`crate::weights::deferred`].
23
24use super::FastSafetensorsLoader;
25use crate::weights::{WeightDtype, parse_expert_index};
26
27impl FastSafetensorsLoader {
28    /// Does the model's loader claim this tensor? `false` when no hook is set,
29    /// which is every model but the ones that opt in.
30    ///
31    /// 🪤 Keyed on the STORE dtype — the width the tensor would have had in the
32    /// store, which for an F16 export is BF16. A predicate that says "BF16
33    /// routed expert" therefore also catches the F16 spelling of the same
34    /// export, which is the honest answer.
35    pub fn is_deferred(&self, name: &str, dtype: WeightDtype) -> bool {
36        self.defer.as_ref().is_some_and(|f| f(name, dtype))
37    }
38}
39
40impl FastSafetensorsLoader {
41    pub(super) fn should_skip_tensor(&self, name: &str) -> bool {
42        // Checked before the EP short-circuit: a text-only port skips the
43        // vision tower at tp/ep 1 too.
44        if self.skip_vision && super::is_vision_tensor(name) {
45            return true;
46        }
47        // MTP head weights for a model whose loader does not build one.
48        if self.skip_mtp && name.starts_with("mtp.") {
49            return true;
50        }
51        // W4A4 activation scales: never read on the w4a16 path (the NVFP4
52        // loader falls back to `DevicePtr::NULL`), and 4-byte allocations are
53        // almost pure granule padding at expert scale.
54        if self.skip_activation_scales && name.ends_with(".input_scale") {
55            return true;
56        }
57        if self.ep_world_size <= 1 {
58            return false;
59        }
60        if name.starts_with("mtp.") {
61            return false;
62        }
63        if let Some(idx) = parse_expert_index(name) {
64            let per_rank = self.num_experts / self.ep_world_size;
65            let local_start = self.ep_rank * per_rank;
66            let local_end = if self.ep_rank == self.ep_world_size - 1 {
67                self.num_experts
68            } else {
69                local_start + per_rank
70            };
71            idx < local_start || idx >= local_end
72        } else {
73            false
74        }
75    }
76}
77
78#[cfg(test)]
79mod activation_scale_tests {
80    use super::FastSafetensorsLoader;
81
82    fn loader() -> FastSafetensorsLoader {
83        let mut l = FastSafetensorsLoader::new();
84        l.skip_activation_scales = true;
85        l
86    }
87
88    /// 🔴 The BLAST RADIUS of the opt-in, pinned. The rule is a `.input_scale`
89    /// suffix and nothing else; every model added to the server's allow-list
90    /// depends on it never reaching `weight_scale` / `weight_scale_2`, which
91    /// ARE the w4a16 operands. A predicate widened to `contains("scale")` or
92    /// to `.starts_with` would pass every other test in this crate and quietly
93    /// unbind every quantised projection in the checkpoint.
94    #[test]
95    fn the_rule_reaches_only_activation_scales() {
96        let l = loader();
97        assert!(l.should_skip_tensor("model.layers.0.mlp.gate_proj.input_scale"));
98        assert!(l.should_skip_tensor("model.layers.0.mlp.experts.7.up_proj.input_scale"));
99
100        for keep in [
101            "model.layers.0.mlp.gate_proj.weight",
102            "model.layers.0.mlp.gate_proj.weight_scale",
103            "model.layers.0.mlp.gate_proj.weight_scale_2",
104            "model.layers.0.self_attn.k_proj.k_scale",
105            "model.layers.0.mlp.gate_proj.input_scale_inv",
106            "input_scale",
107        ] {
108            assert!(!l.should_skip_tensor(keep), "{keep} must still load");
109        }
110    }
111
112    /// OPT-IN: off by default, so a model that never asks keeps every scalar.
113    #[test]
114    fn nothing_is_skipped_unless_the_model_opted_in() {
115        let l = FastSafetensorsLoader::new();
116        assert!(!l.skip_activation_scales);
117        assert!(!l.should_skip_tensor("model.layers.0.mlp.gate_proj.input_scale"));
118    }
119}
120
121#[cfg(test)]
122#[path = "defer_tests.rs"]
123mod defer_tests;