Skip to content

Added prefill strategy benchmarking script and results#1923

Closed
jijiaz wants to merge 37 commits into
intel:copilot/add-xpu-moe-decode-implementationfrom
jijiaz:prefill-perf-benchmark
Closed

Added prefill strategy benchmarking script and results#1923
jijiaz wants to merge 37 commits into
intel:copilot/add-xpu-moe-decode-implementationfrom
jijiaz:prefill-perf-benchmark

Conversation

@jijiaz

@jijiaz jijiaz commented Jun 15, 2026

Copy link
Copy Markdown

MoE Prefill Optimization Strategy Benchmarking

We refreshed the benchmarking results using the updated optimized kernel and expanded the reported metrics to improve data completeness. In addition to latency and speedup, the updated benchmark now also reports baseline and hybrid TFLOPs.

The benchmark script now covers both threshold tuning and API-path measurement:

Running --mode full evaluates thresholds [64, 128, 256, 512, 1024], exposing the tuning process for the threshold parameter across all tested dtypes/formats.
Running --mode summary reports a compact table at the script's default threshold, which is currently 256.
The script also supports two API modes:
--api wrapper: measures the public Python ARK API, including wrapper-side validation, normalization, and output/workspace allocation overhead.
--api raw: calls ark.xpu_lib directly with preallocated buffers, which does not reimplement the kernel math, but bypasses Python wrapper overhead so the result more closely reflects the underlying kernel plus launch/runtime cost.

This distinction matters for interpretation: wrapper results represent end-to-end public API behavior, while raw results are better suited for strategy studies that want to minimize machine-specific wrapper overhead (for example, scalar-sync cost from num_tokens.sum().item()).

Based on the current full sweep results, 256 is the best-performing threshold across all tested dtypes/formats, while larger thresholds such as 1024 can become counterproductive.

Key Findings:

  • Optimal threshold identification: 256-token threshold consistently delivers the best performance across all tested dtypes/formats
  • Threshold tuning process added: --mode full exposes the full threshold sweep across [64, 128, 256, 512, 1024]
  • Stronger speedups with the updated kernel: up to 2.07x for FP16 and 2.10x for BF16, with quantized/FP8 formats improving by roughly 1.16x-1.43x
  • More complete reporting: benchmark results now include baseline_ms, hybrid_ms, speedup, base_TFLOPs, and hybrid_TFLOPs
  • Format-agnostic benefits: performance gains remain consistent across FP16/BF16, INT8/INT4/INT2 (sym/asym), and FP8 (E4M3/E5M2)
  • Dual measurement semantics: wrapper reflects end-to-end public API cost, while raw isolates kernel/runtime-facing behavior for cleaner baseline-vs-hybrid strategy comparison

Performance Summary (best threshold = 256):

Format Dtype Baseline (ms) Optimized (ms) Speedup Base TFLOPs Hybrid TFLOPs Threshold
float16 float16 26.42 12.75 2.07x 11.23 57.29 256
bfloat16 bfloat16 26.06 12.42 2.10x 11.39 58.81 256
int8_sym bfloat16 51.09 43.68 1.17x 5.81 16.72 256
int8_asym bfloat16 54.11 46.75 1.16x 5.48 15.62 256
int4_sym bfloat16 48.15 39.19 1.23x 6.16 18.64 256
int4_asym bfloat16 51.41 43.23 1.19x 5.77 16.89 256
int2_sym bfloat16 37.28 26.12 1.43x 7.96 27.96 256
int2_asym bfloat16 39.25 28.39 1.38x 7.56 25.72 256
fp8_e4m3 bfloat16 52.57 45.10 1.17x 5.64 16.19 256
fp8_e5m2 bfloat16 52.16 44.42 1.17x 5.69 16.44 256

The results show that with the updated kernel, the hybrid pad-and-clip strategy delivers materially better gains than before, especially for FP16/BF16, while still providing stable improvements across quantized and FP8 formats.

Benchmark Configuration: 256 experts, 31,440 routed tokens, 238 active experts, N=3072, K=1536, group_size=128.

jijiaz and others added 30 commits June 15, 2026 11:53
Signed-off-by: lkk12014402 <kaokao.lv@intel.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Signed-off-by: chensuyue <suyue.chen@intel.com>
…emma4-unified (intel#1879)

Signed-off-by: Wenhua Cheng <wenhua.cheng@intel.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: chensuyue <suyue.chen@intel.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
…nd related tests (intel#1865)

Signed-off-by: Xin He <xin3.he@intel.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Sun, Xuehao <xuehao.sun@intel.com>
Co-authored-by: Yogesh Rao <yogesh-tessl@users.noreply.github.com>
Co-authored-by: Liang Lv <liang1.lv@intel.com>
Signed-off-by: Sun, Xuehao <xuehao.sun@intel.com>
Signed-off-by: Wenhua Cheng <wenhua.cheng@intel.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Signed-off-by: yiliu30 <yi4.liu@intel.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: WeiweiZhang1 <weiwei1.zhang@intel.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Signed-off-by: Xin He <xin3.he@intel.com>
- Use [E, N, K] weight layout for pack helpers (matches their contract
  and the working correctness tests in test_moe.py).
- Drop the erroneous dequant.transpose(1, 2); dequant is already
  [E, N, K], which is what the baseline expects.
- Call ark.moe_gemm_prefill for quantized timing (the dedicated
  quantized prefill kernel) instead of the FP-only ark.moe_gemm.
- Add a per-test skip guard for quantized tests requiring
  moe_gemm_prefill so the FP perf cases still run when only moe_gemm
  is present.
…rness

Print both `base mm(ms)` (matmul-only baseline, prior behavior) and
`base+deq(ms)` (dequant + matmul, the apples-to-apples comparison for
the current Stage-1 `moe_gemm_prefill` which materialises a fp16/bf16
workspace before dispatching to the FP GEMM). Speedup is now reported
against the dequant-inclusive baseline so the numbers reflect real
end-to-end quantized prefill cost.

FP perf test (`test_perf_fp`) is unchanged: it has no dequant pass.
For the quantized paths the Python `moe_gemm_prefill` wrapper previously
allocated a fresh `E*K*N*sizeof(act_dtype)` scratch tensor on every call.
For real MoE prefill workloads the same shape repeats every step, so the
allocator overhead is pure waste — and dominates the small-shape numbers.

Move the workspace to a module-level cache keyed by
`(device, dtype, E, K, N)`. The unquantized fast path is unchanged: it
still uses a per-call transposed copy of `weights`. Added
`clear_moe_prefill_workspace_cache()` for callers that need to drop the
cached buffers.
- Add `ark.moe(...)` dispatcher that auto-selects between `moe_gemm_decode`
  (GEMV-tuned, small tokens/expert) and `moe_gemm_prefill` (GEMM-tuned,
  many tokens/expert). Single call site for model code; `phase="decode"`
  or `phase="prefill"` skips the auto-dispatch host-device sync.
- Add `test_moe_unified.py`: bit-parity tests vs the underlying kernels
  across fp/int8/int4/int2/fp8 + dispatch correctness + error path.
- Add `test_moe_model_perf.py`: model-level forward (1 prefill + N decode
  steps over L MoE layers) comparing always_prefill, always_decode,
  manual_branch, unified_auto, unified_hinted strategies.
- `moe_gemm_decode` / `moe_gemm_prefill` are kept for backward compatibility.
- Add test/test_ark/test_moe_model_perf.py: real MoE LLM perf scan
  (tiny by default, AR_MOE_PERF_FULL=1 for full checkpoints) over
  prefill + per-token decode latency. Compares FP reference vs ARK
  backend (and optional GPTQModel). Asserts ARK decode <= 2x FP to
  guard against silent ark.moe dispatcher regressions.
- Remove obsolete auto_round_extension/ark/test/test_moe_model_perf.py
  (synthetic kernel-trace bench; replaced by the model-level one).
- Register the `perf` pytest marker in pyproject.toml.
@a32543254 a32543254 deleted the branch intel:copilot/add-xpu-moe-decode-implementation July 8, 2026 03:48
@a32543254 a32543254 closed this Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.