Downloads · 30 days
0
xbill9/gemma-4-E4B-it-inferentia2
gemma-4-E4B-it-inferentia2 is a text generation model from xbill9. Use it when you need the model to write or continue text. It is set up for torch-neuronx. The card lists the license as apache-2.0.
Compiled AWS Neuron artifacts that run google/gemma-4-E4B-it coherently across both NeuronCores of a single Inferentia2 device (inf2.8xlarge), at ~32–34 tokens/sec, with greedy decode token-for-token identical to the…
Downloads · 30 days
0
Access
Public
Updated Jul 12, 2026
Repo size
22.2 GB
Likes
1
Public
Click a slice to open those files.
.pt22.2 GB · 100%
From the Hugging Face model README
Compiled AWS Neuron artifacts that run google/gemma-4-E4B-it
coherently across both NeuronCores of a single Inferentia2 device (inf2.8xlarge), at
~32–34 tokens/sec, with greedy decode token-for-token identical to the CPU reference.
This is a runnable inference port, not a fine-tune — the weights are Google's, unmodified.
What's new is the tensor-parallel compilation recipe: a way to shard Gemma-4-E4B across two
16 GB cores and keep the KV cache device-resident, which the vendor stack
(optimum-neuron / NxD) cannot currently do for this model.
Companion: the smaller
E2Bfits a single core and uses a different (simpler) design. E4B is ~2× larger and does not fit one core — it requires this TP=2 build.
| Base model | google/gemma-4-E4B-it (~8B params, 4B effective via MatFormer + Per-Layer Embeddings), Apache-2.0 |
| Hardware | AWS Inferentia2 — inf2.8xlarge, both NeuronCores (TP = 2, mandatory) |
| Precision | bf16 compute; each rank holds ~half the weights (~7.7 GB/core) |
| Throughput | 33.4 tok/s @ 512-ctx, 31.8 tok/s @ 2048-ctx (~31 ms/token), measured |
| Context | shipped at KV_MAX=512/BUCKET=128 and KV_MAX=2048/BUCKET=512 |
| Output parity | Greedy decode token-for-token identical to the CPU float reference (SEQ_MATCH True) |
The original build seeds the prompt with a host-CPU prefill (~1.4–1.6 s to first token). A newer
build runs prefill on-device via a single weight-sharing ModelBuilder trace — prefill and decode
as two buckets of one resident model, bf16 sharded weights, on-device aliased KV:
host-CPU prefill (tp_alias) | device prefill (tp_mb, bf16) | |
|---|---|---|
| First-token latency | ~1.4–1.6 s | ~0.16 s (≈9× faster) |
| Decode | 31–34 tok/s | ~39 tok/s |
| Correctness | SEQ_MATCH True | SEQ_MATCH True |
Fastest path — prebuilt Docker image (bundles the compiled model + server):
docker run -d --device /dev/neuron0 --ipc=host -p 8080:8080 \
xbill9/gemma4-optb-e4b:tp2-devprefill-512
curl -s localhost:8080/generate -d '{"prompt":"What is AWS Inferentia?","max_tokens":60}'
Serves OpenAI-compatible routes (/v1/chat/completions, /v1/completions) plus /generate,
/health, /metrics. To build it yourself: MB_WDTYPE=bf16 KV_MAX=512 KV_BUCKET=128 MB_SAVE=mb_e4b_512_bf16.pt python tp_mb.py
(compiles + saves the model), then serve with optb_server_mb.py / package with Dockerfile.mb.
Run on a single inf2.xlarge (¼ the price) — slim image. The inf2.xlarge has the same 2
NeuronCores as the inf2.8xlarge, just 16 GB host RAM instead of 128. The slim server
(optb_server_slim.py) fits that by loading the host embedding model in bf16 and dropping the
transformer layers (they run on-device), so the host footprint is a few GB:
docker run -d --device /dev/neuron0 --ipc=host -p 8080:8080 \
xbill9/gemma4-optb-e4b:slim-devprefill
Validated on an inf2.xlarge: coherent output, device prefill ~0.11 s, ~36 tok/s, ~8 GB host RAM.
(Compile still needs an inf2.8xlarge; the slim image reuses the same compiled model.)
The one non-obvious fix that made device prefill correct: Gemma-4's per-layer
layer_scalaris a buffer, and NxD'sModelBuilderweight-sharding loads parameters only — so it must be copied from the checkpoint by hand, else every layer over-scales ~16× into garbage.
A single Option-B neff for E4B materializes ~15.4 GB of fp32 model constants, and a second
neff on the same core tips it past the 16 GB NeuronCore budget → NRT_RESOURCE / status=4 Allocation Failure. bf16 shrinks the on-disk neff but not the on-device constants, so it
doesn't rescue you. The only way to fit E4B is to shard the model across both cores (TP=2),
so each rank holds ~half the weights (~7.7 GB/core).
Tensor-parallel then forces three problems that don't exist single-core. This build (tp_alias)
solves all three:
forward() returns only
rank 0. Fix: KV is kept device-resident via input_output_aliases (never round-tripped
through the host), and the initial seed is sliced head-r → rank r.num_key_value_groups
scrambles which query attends which KV head (the "4-vs-8" repeat_kv mismatch). Fix:
column-shard k/v to 1 head per rank and keep num_key_value_groups unchanged.q_proj/o_proj/k_proj/v_proj/gate/up/down are Column/Row-parallel across TP=2
(NxD ColumnParallelLinear/RowParallelLinear); k/v shard to nkv//TP = 1 head/rank.KV_MAX buffer. The K/V buffers are
device-resident nn.Parameters aliased as graph I/O (input_output_aliases), updated
in place each step via a one-hot masked write (buf*(1-oh)+k*oh, trace-safe arithmetic).DynamicCache at trace time, explicit tanh-GELU + attention
softcap, language model + head as real submodules.| File | What it is |
|---|---|
tpa_dec_512.tar.gz | Decode neff @ KV_MAX=512 — serialized parallel model (tp_0.pt + tp_1.pt, one per core) |
tpa_dec_2048.tar.gz | Decode neff @ KV_MAX=2048 |
tp_alias_trace.py | Compiles the sharded decode neff (parallel_model_trace + aliases → parallel_model_save) |
tp_alias_run.py | CPU-seed prefill + device greedy decode; validates SEQ_MATCH vs the CPU reference and measures tok/s |
mb_e4b_512_bf16.pt | device-prefill model @ 512/128 — one serialized NxDModel (prefill+decode buckets, bf16 sharded weights + aliased KV), load with torch.jit.load |
tp_mb.py | compiles + saves the device-prefill model via NxD ModelBuilder (MB_WDTYPE=bf16 MB_SAVE=... python tp_mb.py) |
optb_server_mb.py | device-prefill HTTP server (OpenAI routes + /generate); loads mb_e4b_512_bf16.pt, host embeddings only |
Dockerfile.mb | packages the device-prefill build → xbill9/gemma4-optb-e4b:tp2-devprefill-512 |
The neffs embed the base weights in bf16, so they are Apache-2.0 derivatives of
google/gemma-4-E4B-it — see License below.
Requirements: an AWS inf2.8xlarge (2 NeuronCores) with the Neuron runtime, plus:
transformers==5.13.0
torch-neuronx==2.8.0 (SDK 2.23, neuronx-cc 2.23.6484.0)
neuronx-distributed>=0.17
# unpack a decode neff
tar xzf tpa_dec_512.tar.gz -C /workspace # -> /workspace/tpa_dec
# validate + measure (CPU-seed prefill + device decode)
export KV_MAX=512 KV_BUCKET=128 MAXNEW=30
python tp_alias_run.py
# -> DEV GEN: 'The capital of France is **Paris**.'
# SEQ_MATCH True
# TP+ALIAS DECODE tok/s: 33.4 | 30 ms/tok
Recompile for a different context window (sizes are baked into the neff):
KV_MAX=2048 KV_BUCKET=512 python tp_alias_trace.py # -> /workspace/tpa_dec
Compilation runs neuronx-cc across both ranks concurrently and peaks past host RAM on a
128 GB box — add swap before compiling (a 55 GB swapfile is enough); the resulting neff runs
fine without swap.
inf2.8xlarge, us-west-2)Context (KV_MAX/BUCKET) | tok/s | ms/token | SEQ_MATCH |
|---|---|---|---|
| 256 / 64 | 33.8 | 30 | ✅ True |
| 512 / 128 | 33.4 | 30 | ✅ True |
| 2048 / 512 | 31.8 | 31 | ✅ True |
Per-token cost is essentially flat across context sizes because the KV cache is device-resident (no host round-trip). Correctness is exact: device greedy argmax matches the CPU float reference token-for-token, e.g. "The capital of France is Paris."
inf2.8xlarge only — needs 2 NeuronCores (TP=2). Does not run on inf2.xlarge.tp_alias build seeds on the host CPU (~1.4–1.6 s first token). The tp_mb
device-prefill build above removes this (~0.16 s first token, prefill on-device via
weight-sharing buckets) and is the recommended path for a low-latency endpoint.google/gemma-4-E4B-it, © Google, Apache-2.0.LICENSE/NOTICE when redistributing.tp_alias recipe (on-device aliased KV, CPU-seed prefill, GQA head-sharding) is
released under Apache-2.0.Not affiliated with or endorsed by Google or AWS. Provided for research/testing.