Download benchmarks/benchmark.py from flashrt/grouped-moe-gemv: direct link, hf CLI and curl.
- Browser
- Download file 6.03 kB
-
https://huggingface.co/flashrt/grouped-moe-gemv/resolve/main/benchmarks/benchmark.py
- Command line
-
hf download hf://flashrt/grouped-moe-gemv/benchmarks/benchmark.py
-
curl -L -o benchmark.py https://huggingface.co/flashrt/grouped-moe-gemv/resolve/main/benchmarks/benchmark.py
6.03 kB
| #!/usr/bin/env python3 | |
| """RTX benchmark for grouped W4A4 expert projection launch aggregation.""" | |
| from __future__ import annotations | |
| import argparse | |
| import importlib | |
| import sys | |
| from pathlib import Path | |
| import torch | |
| PACKAGE = Path(__file__).resolve().parents[1] | |
| sys.path.insert(0, str(PACKAGE / "tests")) | |
| from test_grouped_moe_gemv import load_source_ops, sfb_bytes # noqa: E402 | |
| def elapsed_us(fn, warmup: int = 20, repeats: int = 100) -> float: | |
| for _ in range(warmup): | |
| fn() | |
| torch.cuda.synchronize() | |
| start = torch.cuda.Event(enable_timing=True) | |
| end = torch.cuda.Event(enable_timing=True) | |
| start.record() | |
| for _ in range(repeats): | |
| fn() | |
| end.record() | |
| end.synchronize() | |
| return start.elapsed_time(end) * 1000.0 / repeats | |
| def load_ops(backend: str, artifact: str | None): | |
| if backend == "source": | |
| return load_source_ops() | |
| if artifact: | |
| sys.path.insert(0, artifact) | |
| return importlib.import_module("grouped_moe_gemv") | |
| def run_case(ops, label: str, m: int, top_k: int, n: int, k: int) -> dict: | |
| experts = 8 | |
| x = torch.randn((m, k), device="cuda", dtype=torch.bfloat16) * 0.2 | |
| packed = torch.empty((m, k // 2), device="cuda", dtype=torch.uint8) | |
| sfa = torch.empty((sfb_bytes(m, k),), device="cuda", dtype=torch.uint8) | |
| weights = torch.full( | |
| (experts, n, k // 2), 0x11, device="cuda", dtype=torch.uint8 | |
| ) | |
| sfb = torch.full( | |
| (experts, sfb_bytes(n, k)), 0x38, device="cuda", dtype=torch.uint8 | |
| ) | |
| alpha = torch.ones((experts,), device="cuda", dtype=torch.float32) | |
| idx = ( | |
| torch.arange(m * top_k, device="cuda", dtype=torch.int32) | |
| .reshape(m, top_k) | |
| .remainder(experts) | |
| .contiguous() | |
| ) | |
| out = torch.empty((m, top_k, n), device="cuda", dtype=torch.bfloat16) | |
| routed_x = x[:, None, :].expand(m, top_k, k).reshape(m * top_k, k).contiguous() | |
| w4a16_out = torch.empty((m * top_k, n), device="cuda", dtype=torch.bfloat16) | |
| def grouped_region(): | |
| ops.quantize_activations_nvfp4_bf16(x, packed=packed, sfa=sfa) | |
| ops.grouped_w4a4_gemv_bf16( | |
| packed, weights, sfa, sfb, alpha, idx, out=out | |
| ) | |
| def grouped_kernel(): | |
| ops.grouped_w4a4_gemv_bf16( | |
| packed, weights, sfa, sfb, alpha, idx, out=out | |
| ) | |
| route_out = torch.empty((m, 1, n), device="cuda", dtype=torch.bfloat16) | |
| route_idx = [idx[:, route : route + 1].contiguous() for route in range(top_k)] | |
| def route_loop(): | |
| ops.quantize_activations_nvfp4_bf16(x, packed=packed, sfa=sfa) | |
| for route in range(top_k): | |
| ops.grouped_w4a4_gemv_bf16( | |
| packed, | |
| weights, | |
| sfa, | |
| sfb, | |
| alpha, | |
| route_idx[route], | |
| out=route_out, | |
| ) | |
| pair_packed = torch.empty((1, k // 2), device="cuda", dtype=torch.uint8) | |
| pair_sfa = torch.empty((sfb_bytes(1, k),), device="cuda", dtype=torch.uint8) | |
| pair_out = torch.empty((1, 1, n), device="cuda", dtype=torch.bfloat16) | |
| pair_idx = [ | |
| idx[token : token + 1, route : route + 1].contiguous() | |
| for token in range(m) | |
| for route in range(top_k) | |
| ] | |
| def pair_loop(): | |
| pair = 0 | |
| for token in range(m): | |
| for _route in range(top_k): | |
| ops.quantize_activations_nvfp4_bf16( | |
| x[token : token + 1], packed=pair_packed, sfa=pair_sfa | |
| ) | |
| ops.grouped_w4a4_gemv_bf16( | |
| pair_packed, | |
| weights, | |
| pair_sfa, | |
| sfb, | |
| alpha, | |
| pair_idx[pair], | |
| out=pair_out, | |
| ) | |
| pair += 1 | |
| grouped_us = elapsed_us(grouped_region) | |
| grouped_kernel_us = elapsed_us(grouped_kernel) | |
| def w4a16_region(): | |
| ops.grouped_w4a16_gemv_bf16( | |
| routed_x, | |
| weights, | |
| sfb, | |
| alpha, | |
| idx.reshape(-1), | |
| w_stride=n * k // 2, | |
| sfb_stride=sfb.shape[1], | |
| n=n, | |
| out=w4a16_out, | |
| ) | |
| w4a16_us = elapsed_us(w4a16_region) | |
| route_us = elapsed_us(route_loop) if top_k > 1 else grouped_us | |
| pair_repeats = 30 if m * top_k >= 32 else 100 | |
| pair_us = elapsed_us(pair_loop, warmup=5, repeats=pair_repeats) | |
| return { | |
| "label": label, | |
| "M": m, | |
| "top_k": top_k, | |
| "pairs": m * top_k, | |
| "N": n, | |
| "K": k, | |
| "grouped_us": grouped_us, | |
| "grouped_kernel_us": grouped_kernel_us, | |
| "route_loop_us": route_us, | |
| "pair_loop_us": pair_us, | |
| "w4a16_us": w4a16_us, | |
| "vs_route_loop": route_us / grouped_us, | |
| "vs_pair_loop": pair_us / grouped_us, | |
| "vs_w4a16": w4a16_us / grouped_us, | |
| } | |
| def main() -> int: | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument("--backend", choices=["source", "installed"], default="source") | |
| parser.add_argument("--artifact") | |
| args = parser.parse_args() | |
| ops = load_ops(args.backend, args.artifact) | |
| cases = [ | |
| ("gate_up_decode", 1, 8, 1024, 2048), | |
| ("gate_up_verify", 7, 8, 1024, 2048), | |
| ("down_decode", 8, 1, 2048, 512), | |
| ("down_verify", 56, 1, 2048, 512), | |
| ] | |
| print("label,M,top_k,pairs,N,K,w4a4_region_us,w4a4_kernel_us,w4a16_us,route_loop_us,pair_loop_us,vs_w4a16,vs_route,vs_pair") | |
| for case in cases: | |
| result = run_case(ops, *case) | |
| print( | |
| f"{result['label']},{result['M']},{result['top_k']},{result['pairs']}," | |
| f"{result['N']},{result['K']},{result['grouped_us']:.3f}," | |
| f"{result['grouped_kernel_us']:.3f},{result['w4a16_us']:.3f}," | |
| f"{result['route_loop_us']:.3f}," | |
| f"{result['pair_loop_us']:.3f},{result['vs_w4a16']:.2f}x," | |
| f"{result['vs_route_loop']:.2f}x,{result['vs_pair_loop']:.2f}x" | |
| ) | |
| return 0 | |
| if __name__ == "__main__": | |
| raise SystemExit(main()) | |