Gemma-4-12B-CoreAI / v4 /README.md
HiramKHackenbacker's picture
v4: tied-table 12B β€” one bound vocab file, verify at the rungs that load, accepted_count, activations
50a5cd8 verified
|
Raw
History Blame Contribute Delete
5.48 kB

Gemma 4 12B β€” v4: the TIED-TABLE build (one fp16 vocab file, two consumers; verify at the rungs that load)

Supersedes tiered-v3/. Four changes, each measured before it shipped:

1. The head AND the embedding leave the graph as ONE bound file

Gemma 4 ties lm_head.weight to embed_tokens.weight, so v4 binds a single fp16 sidecar (head.f16, [262144 x 3840]) as a graph INPUT serving both the in-graph embedding gather (times the model's own rounded embed_scale = 61.96773353931867) and the head matmul. A bound input's value is unknown at compile time, so the compiler cannot pre-transpose it β€” the mechanism that sank the fp16-head E4B (+1.34 GB of graph constant per entrypoint, measured). Measured on this blob: graph constant -12,907,432 B (~0), resources.bin / main.mlirb ratio 0.9979, and main.mlirb is 5.72 GiB against v3's 7.60 β€” the fp16 head's 1.88 GiB no longer serialized.

This also retires v3's int4 in-graph embedding and its measured 7.43 pp top-1 cost: the gather now reads fp16 rows, bit-exact against the reference ScaledEmbedding (the fp32 round-trip variant measured rel=2.5e-2 on 6-layer logits and was REJECTED by the gate; the shipped op order is fp16 gather x fp16 scalar, max_abs = 0.0).

2. Verify moved to the rungs a 16 GB machine actually loads

v3 pinned verify_c262144 to the top rung on the claim that every rung fits. The demand model falsified it: with the mapped table counted, c262144 demands ~13.8 GiB against a 12.575 GiB budget, while c131072 demands ~11.8. So v4 ships 2 verify entrypoints β€” verify_c131072 and verify_c65536 β€” each S=8, FULL logits [1,8,262144] plus the post-final-norm hidden states as activations [1,8,3840] (the assistant drafter's input; oracle-parity-gated port already in hand).

3. accepted_count β€” speculation that cannot corrupt the cache

Verify takes an int32 [1] accepted_count bounding how many of the block's rows COMMIT to the sliding ring: 0 speculates (ring bit-identical afterwards β€” gated), n commits the accepted prefix, 8 commits all. The blend is a runtime VALUE over the literal ring extent β€” never a shape β€” so every entrypoint stays shape-stable (ZERO symbolic extents, checked at save). Global-cache rows are always written and self-heal: absolute positions mask them and later writes overwrite them. Rows the blend skips keep exactly the keys a future window still admits β€” the wrap arithmetic is in the module comment.

4. Same ladder, same states, same kernels

7 rungs (c4096..c262144) x (main + prefill S=64), the length-bounded Metal flash-decode kernel and its prefill sibling, fp16 KV. function_map = {main: 7, prefill: 7, verify: 2} written by the exporter β€” the role v3 needed a metadata amendment for is now in the artifact from birth.

Loader contract

capacity_tier_notes declares head_table_file / head_table_shape / head_table_dtype AND embed_from_head_table: true. The second declaration matters: it tells the loader this bundle has NO PLE pair, so the family-default static inputs must be cleared before binding the head (a loader that skips this refuses on embed_per_layer.* files that never existed for this model). Absence of both declarations still means an in-graph head β€” every pre-v4 bundle keeps loading.

Bundle β€” v4/gpu-pipelined/gemma4_12b_qat_decode_int4linsym_hsc_msdpa_g8_wkv_stable_pf64_tiered_c4k_c8k_c16k_c32k_c64k_c128k_c256k (6,177,845,160 B)

    gemma4_12b_qat_decode_int4linsym_hsc_msdpa_g8_wkv_stable_pf64_tiered_c4k_c8k_c16k_c32k_c64k_c128k_c256k.aimodel/main.hash            32 B  3ea6c629221724c402f151cd73b0f107981ba3a377c995f25cdcce281e42ca59
    gemma4_12b_qat_decode_int4linsym_hsc_msdpa_g8_wkv_stable_pf64_tiered_c4k_c8k_c16k_c32k_c64k_c128k_c256k.aimodel/main.mlirb 6,145,628,244 B  40e06a7b5f0d71a2138e32722fbff3a940b79b788b8b13561ec1594b324c7fa3
    gemma4_12b_qat_decode_int4linsym_hsc_msdpa_g8_wkv_stable_pf64_tiered_c4k_c8k_c16k_c32k_c64k_c128k_c256k.aimodel/metadata.json           105 B  289d1e4bfcd080febff255b763fb85de7f93ea1767d00e86c04b9276199b6c4b
    metadata.json                                                            5,058 B  d6f7f28732454182a4b29293e80e24bd7e73fd0f293a2c13a3e8f532619d34b6
    tier_report.json                                                        20,322 B  773dea6665588288f4c1a28987fc56e7bdfc7d9b78893ee16e0ae8882eef39ba
    tokenizer/chat_template.jinja                                           18,683 B  ae53464bf3be25802b3a5b37def7fd89667067d7577049b3b2d74c4d8de4c6d4
    tokenizer/tokenizer.json                                            32,169,626 B  cc8d3a0ce36466ccc1278bf987df5f71db1719b9ca6b4118264f45cb627bfe0f
    tokenizer/tokenizer_config.json                                          3,090 B  c3fd34e321798e184e53894aaa1d8c4b37d08daf1fb1826dbceb3dcda0c62d06

Tables β€” v4/ios-frontend/gemma4_12b_tied_vocab (2,013,265,920 B)

    head.f16                                                         2,013,265,920 B  fb21807f7117be132acbb4fcc548d3d0479fb84dce64f9f19e8c4e3af01f1a21

Export: export_gemma4_12b_tiered.py --tiers 4096,8192,16384,32768,65536,131072,262144 --prefill 64 --verify-len 8 --verify-tiers 131072,65536 --head-sidecar --quant-embed none --split-g 8 (2026-08-28). Gates: 6-layer torch parity bit-exact (decode logits, verify logits, hidden, commit semantics all max_abs = 0.0); compiled-blob constant ~0; Mac decode run under the 3-slot loader.