blairducrayoppat/npu-specdecode-lunarlake
Speculative decoding draft-device characterization on Intel Lunar Lake (OpenVINO GenAI) Reference performance data for heterogeneous speculative decoding with OpenVINO GenAI: a GPU target model (Qwen3-14B INT4) paired with a small draft model (Qwen3-0.6B INT4) run on the CPU vs the NPU vs the GPU, plus standalone draft-only throughput per device. Measured on a single Intel Core Ultra 7 258V (Lunar Lake) laptop. Headline: putting the draft on the NPU is a net slowdown (0.55–0.74×… See the full description on the dataset page: https://huggingface.co/datasets/blairducrayoppat/npu-specdecode-lunarlake.
Speculative decoding draft-device characterization on Intel Lunar Lake (OpenVINO GenAI)
Reference performance data for heterogeneous speculative decoding with OpenVINO GenAI: a GPU target model (Qwen3-14B INT4) paired with a small draft model (Qwen3-0.6B INT4) run on the CPU vs the NPU vs the GPU, plus standalone draft-only throughput per device. Measured on a single Intel Core Ultra 7 258V (Lunar Lake) laptop.
Headline: putting the draft on the NPU is a net slowdown (0.55–0.74× of GPU-only throughput); the same draft on the CPU is a 1.35× speedup. Root cause: the NPU runs the small draft model ~3.6× slower per token than the CPU, and speculative decoding only pays off when the draft is cheap. This corroborates OpenVINO's documented guidance (CPU draft for a GPU/CPU target, or both models on the NPU) — it is reference characterization, not a bug report.
- Narrative write-up: https://github.com/openvinotoolkit/openvino/discussions/36484
- Related (closed) issue: https://github.com/openvinotoolkit/openvino/issues/34450
Hardware
Models
- Target: Qwen3-14B, INT4 (asymmetric per-group — fine on GPU).
- Draft: Qwen3-0.6B, INT4 symmetric (
--sym --group-size 128 --ratio 1.0). Symmetric is required for the NPU (per-group asymmetric INT4 is unsupported there). Same draft used on every device. - Target and draft share the Qwen3 tokenizer (required for speculative decoding).
Methodology
Greedy, ignore_eos=True, fixed 128-token budget, 1 warm-up + 3 measured reps, each config in a fresh process. num_assistant_tokens (NAT) is the stateful pipeline's adaptive seed, not a fixed per-round proposal count. Metrics from PerfMetrics / SDPerModelsPerfMetrics; acceptance_rate = accepted / draft-proposed. Construct/compile time is excluded from throughput. Single prompt — acceptance numbers are illustrative; the throughput/per-token-latency result is the robust, device-physics finding.
Results
Standalone draft-only (Qwen3-0.6B-sym, no speculative decoding)
Speculative decoding (GPU target + draft)
Files
npu_specdecode_perf.jsonl— one record per config (standalone + spec-decode); programmatic import.npu_specdecode_perf.csv— flattened (env_*/meas_*prefixes).
Not measured (explicit)
Single machine, single prompt, n=3; greedy only; default NPU prompt/response budgets; no co-resident memory cost; no subjective quality beyond a greedy token-identity check. Behavior may differ on OpenVINO 2026.2/master.
License
CC-BY-4.0 (adjust to your preference before publishing). Author: Blair DuCray-Oppat (GitHub @blairducrayoppat).
Citation
NPU vs CPU draft speculative-decoding characterization on Intel Lunar Lake (OpenVINO GenAI 2026.1), 2026. https://github.com/openvinotoolkit/openvino/discussions/36484
