Skip to content

Commit e394fa5

Browse files
davidrhodusclaude
andcommitted
hi-cuda: gemma4 per-layer loader specs; gemma4-12b matrix fixture
The loader's dense-attention matrix specs now use per-layer q/k/v/output dims for gemma4 (mirroring the validation stage), and attn_k/attn_v specs are conditional on tensor presence (global layers ship no attn_v; E-series shared-KV tail layers ship neither). Gemma-4-12B-It Q4_K_M loads, serves, and produces coherent greedy output end to end (decode ~22 tok/s). 15-fixture family matrix green in 203s. E-series (KV sharing + per-layer embeddings) and the 26B-A4B MoE remain follow-up stages. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 050c4c7 commit e394fa5

2 files changed

Lines changed: 64 additions & 6 deletions

File tree

crates/hi-cuda/src/gpu.rs

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23448,6 +23448,41 @@ mod native {
2344823448
}
2344923449
for layer in 0..config.block_count {
2345023450
let prefix = format!("blk.{layer}");
23451+
// Gemma-4 varies attention geometry per layer (sliding: _swa dims
23452+
// with GQA; global: full dims with MQA, no attn_v).
23453+
let (q_dim, k_dim, v_dim, attention_output_dim) = if config.is_gemma4() {
23454+
let idx = layer as usize;
23455+
let layer_hd = config
23456+
.layer_key_head_dim(idx)
23457+
.map(usize::try_from)
23458+
.transpose()
23459+
.context("gemma4 per-layer key head dim does not fit usize")?
23460+
.ok_or_else(|| anyhow!("gemma4 layer {layer} key head dim missing"))?;
23461+
let layer_vd = config
23462+
.layer_value_head_dim(idx)
23463+
.map(usize::try_from)
23464+
.transpose()
23465+
.context("gemma4 per-layer value head dim does not fit usize")?
23466+
.ok_or_else(|| anyhow!("gemma4 layer {layer} value head dim missing"))?;
23467+
let layer_kv = usize::try_from(config.layer_head_count_kv(idx))
23468+
.context("gemma4 per-layer kv head count does not fit usize")?;
23469+
(
23470+
layer_hd
23471+
.checked_mul(heads)
23472+
.context("gemma4 q dimension overflows usize")?,
23473+
layer_hd
23474+
.checked_mul(layer_kv)
23475+
.context("gemma4 k dimension overflows usize")?,
23476+
layer_vd
23477+
.checked_mul(layer_kv)
23478+
.context("gemma4 v dimension overflows usize")?,
23479+
layer_vd
23480+
.checked_mul(heads)
23481+
.context("gemma4 attention output dimension overflows usize")?,
23482+
)
23483+
} else {
23484+
(q_dim, k_dim, v_dim, attention_output_dim)
23485+
};
2345123486
if qwen_ssm_layer_tensors_present(gguf, &prefix) {
2345223487
let ssm = qwen_ssm_dims(config)?
2345323488
.ok_or_else(|| anyhow!("complete SSM tensor layout missing SSM metadata"))?;
@@ -23626,22 +23661,33 @@ mod native {
2362623661
embed,
2362723662
));
2362823663
}
23629-
specs.extend([
23630-
dense_matrix_spec_with_aliases(
23664+
let skip_missing_kv = config.is_gemma4();
23665+
if !skip_missing_kv
23666+
|| qwen_dense_attention_weight_names(&prefix, "k")
23667+
.iter()
23668+
.any(|name| gguf.tensor(name).is_some())
23669+
{
23670+
specs.push(dense_matrix_spec_with_aliases(
2363123671
gguf,
2363223672
format!("{prefix}.attn_k.weight"),
2363323673
qwen_dense_attention_weight_names(&prefix, "k"),
2363423674
k_dim,
2363523675
embed,
23636-
),
23637-
dense_matrix_spec_with_aliases(
23676+
));
23677+
}
23678+
if !skip_missing_kv
23679+
|| qwen_dense_attention_weight_names(&prefix, "v")
23680+
.iter()
23681+
.any(|name| gguf.tensor(name).is_some())
23682+
{
23683+
specs.push(dense_matrix_spec_with_aliases(
2363823684
gguf,
2363923685
format!("{prefix}.attn_v.weight"),
2364023686
qwen_dense_attention_weight_names(&prefix, "v"),
2364123687
v_dim,
2364223688
embed,
23643-
),
23644-
]);
23689+
));
23690+
}
2364523691
}
2364623692
if !qwen_ssm_layer_tensors_present(gguf, &prefix) {
2364723693
specs.push(dense_matrix_spec_with_aliases(

crates/hi-local/tests/cuda_real_smoke.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,18 @@ const FAMILY_FIXTURES: &[FixtureSpec] = &[
146146
"qwen36-27b-gguf/Qwen3.6-27B-Q4_K_M.gguf",
147147
],
148148
},
149+
// Gemma-4: per-layer attention geometry (sliding 256-dim GQA / global
150+
// 512-dim MQA with V=K), proportional rope via freq factors, scale 1.0,
151+
// layer output scales, gemma4 escaped-BPE tokenizer.
152+
FixtureSpec {
153+
label: "gemma4-12b",
154+
env_name: "HI_CUDA_SMOKE_GEMMA4_GGUF",
155+
expected_family: ModelFamily::Gemma,
156+
relative_candidates: &[
157+
"gemma4-12b/model.gguf",
158+
"gemma4-12b-gguf/gemma-4-12b-it-Q4_K_M.gguf",
159+
],
160+
},
149161
];
150162

151163
#[test]

0 commit comments

Comments
 (0)