Problem. Batch-1 decoding is bound by weight bandwidth, but Hugging Face generate() also leaves the GPU idle between kernels. On Qwen3-1.7B with my int8 kernel, the GPU idled about 2 ms per token.
Approach. A weight-only int8 Triton GEMV (a torch.library custom op), plus a sync-free decoder that replays one CUDA graph per token, streaming tokens through pinned memory. Measured steps: 91.3 tok/s with generate() → 96.8 with the sync-free CUDA-graph loop → 105.1 with the int8 kernel configuration chosen by end-to-end timing (the microbenchmark winner was slower inside the model) → 111.9 with a KV cache sized to the request.
Result (Qwen3-1.7B, batch 1, greedy, 256 new tokens, 4 fresh-process rounds, RTX 4060, Windows 11):
- 111.9 tok/s, approximately at parity with the tested llama.cpp Q8_0 configuration (Ollama defaults): 1.02×, 95% CI [1.015, 1.051], below my 5% bar for calling it a win
- 1.33× torchao int8 weight-only, 1.89× HF bf16 with a compiled static cache
Correctness. KernelAgent-Ada, the repo’s Triton kernel search, checks every candidate against fp64 ground truth, mutation-tests its own evaluator (12/12 deliberately wrong kernels rejected) and re-measures winners end to end. That check cut a 1.1–1.6× attention-kernel win to about 1% of the decode step.
Limitations. One GPU, Windows only, no independent reproduction yet. Batch 1 and greedy only. Slower first token than llama.cpp (54 vs 33 ms). llama.cpp ran with Ollama defaults, not a tuned build; vLLM and TensorRT-LLM were not compared.
Could you reproduce it? I’m looking for runs on Linux or on an NVIDIA GPU other than an RTX 4060 (compute capability 8.0+, 8 GB+):
- Set up the environment from
docs/REPRODUCE_ON_ANOTHER_MACHINE.mdin the repo (Python 3.11, torch 2.11 / CUDA 12.8, transformers 5.21). - Run
bash research/release/reproduce.sh(about an hour;--quickcompares int8 vs bf16 only). It packs the logs and raw results into one archive. - Post the archive in the repo’s GitHub Discussions, category “Hardware results” (the pinned post there explains how).
Privacy: before uploading, please open the archive and check the logs, env.json, pip_freeze.txt and nvidia_smi_q.txt for anything personal (user names, paths, host names). The script removes serial numbers, the list of running programs and home-directory paths, but it can’t catch everything.
Failed or contradicting results are as useful as matching ones, and criticism of the method is welcome here or on GitHub.
Repository (MIT): GitHub - BagelsFun/efficientgpt: Weight-only int8 + sync-free CUDA-graph decoder for Qwen3-1.7B in PyTorch/Triton: 111.9 tok/s on an RTX 4060, parity with llama.cpp Q8_0, 1.33x torchao int8, 1.89x HF bf16. Plus KernelAgent-Ada, a verification-first Triton kernel search. All raw evidence included. Fork of nanoGPT. · GitHub
74-second overview video: https://youtu.be/SKWrki4NHn4
Disclosure: built with an AI coding assistant. I checked every number against the raw runs, which are in the repository.