1#[derive(Clone, Copy, Debug, PartialEq, Eq)]
27pub struct GemmDispatch {
28 pub fp8_blockscaled_prefill: bool,
36 pub cublas_gemm: bool,
39 pub cublas_fp8: bool,
41 pub cutlass_gemm: bool,
44 pub cutlass_nvfp4_gemm: bool,
48 pub cutlass_nvfp4_qkvz: bool,
49 pub cutlass_nvfp4_attn_q: bool,
50 pub cutlass_nvfp4_attn_kv: bool,
51 pub cutlass_nvfp4_attn_o: bool,
52 pub cutlass_nvfp4_ssm_out: bool,
53 pub w4a16_variant: u8,
58}
59
60fn from_values(mut value: impl FnMut(&str) -> Option<String>) -> GemmDispatch {
61 fn on(value: &mut impl FnMut(&str) -> Option<String>, var: &str) -> bool {
62 value(var).as_deref() == Some("1")
63 }
64
65 let all_nvfp4 = on(&mut value, "ATLAS_CUTLASS_NVFP4_GEMM");
66 GemmDispatch {
67 w4a16_variant: match value("ATLAS_W4A16_VARIANT").as_deref() {
68 Some("v1") => 1,
69 Some("v2") => 2,
70 Some("v3") => 3,
71 _ => 0,
72 },
73 fp8_blockscaled_prefill: !on(&mut value, "ATLAS_FP8_SINGLE_SCALE"),
74 cublas_gemm: on(&mut value, "ATLAS_CUBLAS_GEMM"),
75 cublas_fp8: on(&mut value, "ATLAS_CUBLAS_FP8"),
76 cutlass_gemm: on(&mut value, "ATLAS_CUTLASS_GEMM"),
77 cutlass_nvfp4_gemm: all_nvfp4,
78 cutlass_nvfp4_qkvz: all_nvfp4 || on(&mut value, "ATLAS_CUTLASS_NVFP4_QKVZ"),
79 cutlass_nvfp4_attn_q: all_nvfp4 || on(&mut value, "ATLAS_CUTLASS_NVFP4_ATTN_Q"),
80 cutlass_nvfp4_attn_kv: all_nvfp4 || on(&mut value, "ATLAS_CUTLASS_NVFP4_ATTN_KV"),
81 cutlass_nvfp4_attn_o: all_nvfp4 || on(&mut value, "ATLAS_CUTLASS_NVFP4_ATTN_O"),
82 cutlass_nvfp4_ssm_out: on(&mut value, "ATLAS_CUTLASS_NVFP4_SSM_OUT"),
84 }
85}
86
87impl GemmDispatch {
88 pub fn from_env() -> Self {
90 from_values(|var| std::env::var(var).ok())
91 }
92
93 pub fn defaults() -> Self {
97 Self {
98 w4a16_variant: 0,
99 fp8_blockscaled_prefill: true,
100 cublas_gemm: false,
101 cublas_fp8: false,
102 cutlass_gemm: false,
103 cutlass_nvfp4_gemm: false,
104 cutlass_nvfp4_qkvz: false,
105 cutlass_nvfp4_attn_q: false,
106 cutlass_nvfp4_attn_kv: false,
107 cutlass_nvfp4_attn_o: false,
108 cutlass_nvfp4_ssm_out: false,
109 }
110 }
111
112 pub fn cutlass_nvfp4_attn_qkv(&self, label: &str) -> bool {
114 match label {
115 "q_proj" => self.cutlass_nvfp4_attn_q,
116 "k_proj" | "v_proj" => self.cutlass_nvfp4_attn_kv,
117 _ => self.cutlass_nvfp4_gemm,
118 }
119 }
120}
121
122impl Default for GemmDispatch {
123 fn default() -> Self {
124 Self::defaults()
125 }
126}
127
128#[cfg(test)]
129mod tests {
130 use super::*;
131 use std::collections::HashMap;
132
133 fn resolve(values: &[(&str, &str)]) -> GemmDispatch {
134 let values: HashMap<_, _> = values.iter().copied().collect();
135 from_values(|name| values.get(name).map(|value| (*value).to_owned()))
136 }
137
138 #[test]
139 fn defaults_have_only_blockscaled_prefill_on() {
140 let d = GemmDispatch::defaults();
141 assert_eq!(
142 resolve(&[]),
143 d,
144 "absent environment uses the public default"
145 );
146 assert_eq!(
147 d,
148 GemmDispatch {
149 fp8_blockscaled_prefill: true,
150 cublas_gemm: false,
151 cublas_fp8: false,
152 cutlass_gemm: false,
153 cutlass_nvfp4_gemm: false,
154 cutlass_nvfp4_qkvz: false,
155 cutlass_nvfp4_attn_q: false,
156 cutlass_nvfp4_attn_kv: false,
157 cutlass_nvfp4_attn_o: false,
158 cutlass_nvfp4_ssm_out: false,
159 w4a16_variant: 0,
160 }
161 );
162 }
163
164 #[test]
165 fn the_umbrella_flag_implies_the_per_projection_ones() {
166 let d = resolve(&[("ATLAS_CUTLASS_NVFP4_GEMM", "1")]);
167 assert!(d.cutlass_nvfp4_gemm);
168 assert!(d.cutlass_nvfp4_qkvz);
169 assert!(d.cutlass_nvfp4_attn_qkv("q_proj"));
170 assert!(d.cutlass_nvfp4_attn_qkv("k_proj"));
171 assert!(d.cutlass_nvfp4_attn_qkv("v_proj"));
172 assert!(d.cutlass_nvfp4_attn_o);
173 assert!(!d.cutlass_nvfp4_ssm_out);
175 }
176
177 #[test]
178 fn per_projection_flags_are_independent() {
179 let cases = [
180 (
181 "ATLAS_CUTLASS_NVFP4_QKVZ",
182 [true, false, false, false, false],
183 ),
184 (
185 "ATLAS_CUTLASS_NVFP4_ATTN_Q",
186 [false, true, false, false, false],
187 ),
188 (
189 "ATLAS_CUTLASS_NVFP4_ATTN_KV",
190 [false, false, true, false, false],
191 ),
192 (
193 "ATLAS_CUTLASS_NVFP4_ATTN_O",
194 [false, false, false, true, false],
195 ),
196 (
197 "ATLAS_CUTLASS_NVFP4_SSM_OUT",
198 [false, false, false, false, true],
199 ),
200 ];
201 for (name, expected) in cases {
202 let d = resolve(&[(name, "1")]);
203 assert_eq!(
204 [
205 d.cutlass_nvfp4_qkvz,
206 d.cutlass_nvfp4_attn_q,
207 d.cutlass_nvfp4_attn_kv,
208 d.cutlass_nvfp4_attn_o,
209 d.cutlass_nvfp4_ssm_out,
210 ],
211 expected,
212 "{name} must not enable a neighboring projection"
213 );
214 }
215 }
216
217 #[test]
218 fn non_nvfp4_flags_map_independently_and_single_scale_is_inverted() {
219 let cases = [
220 ("ATLAS_CUBLAS_GEMM", [true, false, false]),
221 ("ATLAS_CUBLAS_FP8", [false, true, false]),
222 ("ATLAS_CUTLASS_GEMM", [false, false, true]),
223 ];
224 for (name, expected) in cases {
225 let d = resolve(&[(name, "1")]);
226 assert_eq!(
227 [d.cublas_gemm, d.cublas_fp8, d.cutlass_gemm],
228 expected,
229 "{name} must not enable a neighboring GEMM path"
230 );
231 assert!(d.fp8_blockscaled_prefill);
232 }
233 assert!(!resolve(&[("ATLAS_FP8_SINGLE_SCALE", "1")]).fp8_blockscaled_prefill);
234 assert!(
235 !resolve(&[("ATLAS_CUBLAS_GEMM", "true")]).cublas_gemm,
236 "dispatch booleans accept only the documented literal 1"
237 );
238 }
239
240 #[test]
241 fn w4a16_variants_accept_only_documented_spellings() {
242 for (value, expected) in [
243 ("v1", 1),
244 ("v2", 2),
245 ("v3", 3),
246 ("1", 0),
247 ("V1", 0),
248 ("unknown", 0),
249 ] {
250 assert_eq!(
251 resolve(&[("ATLAS_W4A16_VARIANT", value)]).w4a16_variant,
252 expected,
253 "value {value}"
254 );
255 }
256 }
257
258 #[test]
259 fn an_unknown_projection_label_falls_back_to_the_umbrella_flag() {
260 assert!(!GemmDispatch::defaults().cutlass_nvfp4_attn_qkv("mystery"));
261 let d = GemmDispatch {
262 cutlass_nvfp4_gemm: true,
263 ..GemmDispatch::defaults()
264 };
265 assert!(d.cutlass_nvfp4_attn_qkv("mystery"));
266 }
267}