Summary
Benchmark of Gemma4 inference through onnxruntime-genai on ONNX models exported with mobius, comparing full-precision vs INT4-quantized decoders across CUDA and CPU. Quantization is done with Olive (OnnxKQuantQuantization / OnnxBnb4Quantization).
TL;DR: Q4_K_M is the recommended format — it is the fastest on CPU (+80% tok/s) and slightly faster than f16 on CUDA (+4% tok/s), at ~3.1x smaller decoder. NF4 should be avoided — it is slower than f16 on both EPs.
Environment
|
|
| GPU |
NVIDIA H200 (143 GB) |
| onnxruntime |
1.27.0 |
| onnxruntime-genai |
0.14.0-dev (commit 9b875c3, + per-layer-KV patch) |
| mobius |
44fdbd0 |
| Model |
google/gemma-4-E2B-it (text-only decode path) |
| Quantizer |
Olive — Q4_K_M (OnnxKQuantQuantization, bits=4, block_size=32), NF4 (OnnxBnb4Quantization) |
Methodology: 92-token prompt, forced 64-token decode (min_length==max_length, greedy), 2 warmup runs + best of 3. TTFT = prefill + first token. Decode tok/s = steady-state after first token.
Results — gemma-4-E2B-it
CUDA EP (H200)
| Dtype |
Decode tok/s |
TTFT (ms) |
Decoder size |
vs f16 (decode) |
| f16 |
148.0 |
7.5 |
4.73 GB |
baseline |
| Q4_K_M |
153.5 |
10.4 |
1.51 GB |
+3.7% |
| NF4 |
127.8 |
11.6 |
1.41 GB |
−13.6% |
CPU EP
| Dtype |
Decode tok/s |
TTFT (ms) |
vs f16 (decode) |
| f16 |
15.8 |
327 |
baseline |
| Q4_K_M |
28.5 |
494 |
+80.4% |
| NF4 |
8.3 |
443 |
−47.5% |
Key findings
- Q4_K_M wins overall. Fastest decode on CPU (+80%) and slightly faster than f16 on CUDA (+4%), with a ~3.1x smaller decoder (4.73 GB → 1.51 GB). No quality regression observed in spot checks (consistent with the L4/L5 golden tests).
- NF4 is not worth it for inference. Slower than f16 on both CUDA (−14%) and CPU (−47%) despite similar size to Q4_K_M.
- Quantization raises TTFT but lowers decode latency. Prefill is compute-bound and pays a dequant cost (TTFT f16 7.5 ms → Q4_K_M 10.4 ms on CUDA), while decode is memory-bandwidth-bound and benefits from the smaller weights. For typical chat workloads (decode-dominated) the net effect is a win.
- Single-token batch=1 decode underutilizes the H200 — throughput is memory-bound, so the absolute CUDA tok/s would not improve much on a larger GPU. Batching would.
gemma-4-12B (unified multimodal) — status
12B was exported (bf16 + Q4_K_M, decoder 23 GB → 6.8 GB) and the files load, but end-to-end genai generation is not yet runnable here: the global-attention layers (head_dim=512) emit the standard Attention op, which has no CUDA kernel and falls back to the CPU EP, where it fails on the mixed-KV-cache total_sequence_length check. Tracking separately; not included in the throughput numbers above. (A bf16 loadability fix for the unified vision/audio Compress op landed in 44fdbd0.)
Reproduction
# Export
mobius build --model google/gemma-4-E2B-it --dtype f16 --ep cuda \
--runtime ort-genai /tmp/g4e2b/f16/cuda/
# Quantize (Olive, decoder only) — see examples/gemma4_unified_ort_genai.py:quantize_decoder
# Benchmark: 92-tok prompt, 64-tok forced greedy decode, 2 warmup + best-of-3
Summary
Benchmark of Gemma4 inference through onnxruntime-genai on ONNX models exported with mobius, comparing full-precision vs INT4-quantized decoders across CUDA and CPU. Quantization is done with Olive (
OnnxKQuantQuantization/OnnxBnb4Quantization).TL;DR: Q4_K_M is the recommended format — it is the fastest on CPU (+80% tok/s) and slightly faster than f16 on CUDA (+4% tok/s), at ~3.1x smaller decoder. NF4 should be avoided — it is slower than f16 on both EPs.
Environment
9b875c3, + per-layer-KV patch)44fdbd0google/gemma-4-E2B-it(text-only decode path)OnnxKQuantQuantization, bits=4, block_size=32), NF4 (OnnxBnb4Quantization)Methodology: 92-token prompt, forced 64-token decode (
min_length==max_length, greedy), 2 warmup runs + best of 3. TTFT = prefill + first token. Decode tok/s = steady-state after first token.Results — gemma-4-E2B-it
CUDA EP (H200)
CPU EP
Key findings
gemma-4-12B (unified multimodal) — status
12B was exported (bf16 + Q4_K_M, decoder 23 GB → 6.8 GB) and the files load, but end-to-end genai generation is not yet runnable here: the global-attention layers (
head_dim=512) emit the standardAttentionop, which has no CUDA kernel and falls back to the CPU EP, where it fails on the mixed-KV-cachetotal_sequence_lengthcheck. Tracking separately; not included in the throughput numbers above. (A bf16 loadability fix for the unified vision/audioCompressop landed in44fdbd0.)Reproduction