Skip to main content

extract-kernel-definitions

Generate Definition JSON files for the flashinfer-trace HuggingFace dataset by harvesting them from a short SGLang inference pass (FlashInfer's @flashinfer_api(trace=...) dumper) — or, as a fallback, by manually transcribing the schema from SGLang sources when FlashInfer doesn't yet have a trace template. Use when adding a new model, extracting GPU kernels (MLA, MoE, GQA, RMSNorm, GEMM, GDN, RoPE, sampling), or filling gaps in the dataset.

Zur Installation springen

Quellinformationen

Repository
flashinfer-ai/flashinfer-bench
Letzte Quellaktivität
1. Mai 2026 um 00:34
Erkannte Sprache von SKILL.md
Englisch
Sterne
281
Forks
49

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
extract-kernel-definitions
description
Generate Definition JSON files for the flashinfer-trace HuggingFace dataset by harvesting them from a short SGLang inference pass (FlashInfer's @flashinfer_api(trace=...) dumper) — or, as a fallback, by manually transcribing the schema from SGLang sources when FlashInfer doesn't yet have a trace template. Use when adding a new model, extracting GPU kernels (MLA, MoE, GQA, RMSNorm, GEMM, GDN, RoPE, sampling), or filling gaps in the dataset.
# Extract Kernel Definitions Produce per-(op, shape) Definition JSONs and stage them in the HuggingFace dataset clone at `tmp/flashinfer-trace/definitions/{op_type}/`. PR submission is **out of scope** here — see [`submit-onboarding-prs`](../submit-onboarding-prs/SKILL.md) (Phase 4 of `/onboard-model`). ## Two paths | Path | When to use | What you do | |------|-------------|-------------| | **A. Trace-dump (primary)** | Kernel is `fi_supported` per `/discover-models` — i.e. the FlashInfer API used by SGLang carries a `@flashinfer_api(trace=...)` template (see [coverage list](#flashinfer-trace-coverage)). | Run a short SGLang inference pass with `FLASHINFER_TRACE_DUMP=1`. The dumper writes one JSON per unique (op, shape) before the kernel runs (crash-safe, deduplicated). | | **B. Manual extraction (fallback)** | Kernel is `fi_missing`, **or** the relevant FlashInfer API is not yet trace-instrumented. | Read the SGLang model source + sgl-cookbook serving config + HF model config; write the Definition JSON by hand using the [schema reference](#schema-reference). | The trace-dump path is the default — it eliminates manual axis derivation and produces JSONs that already carry `axes`, `inputs`, `outputs`, `tags` (`fi_api:*`, `status:verified`), and a `reference` implementation. > Background: the trace dumper was added in > [flashinfer-ai/flashinfer#2931](https://github.com/flashinfer-ai/flashinfer/pull/2931). > Schema and full env-var docs live at > [`docs/fi_trace.rst`](https://github.com/flashinfer-ai/flashinfer/blob/main/docs/fi_trace.rst) > in the FlashInfer repo. SGLang harness reference: > [`tests/trace/example_sglang.py`](https://github.com/flashinfer-ai/flashinfer/blob/main/tests/trace/example_sglang.py). ## Usage ```bash # Path A — auto-dump every fi_supported definition for a model in one inference pass /extract-kernel-definitions --model-name llama-3.2-3b --hf-repo-id meta-llama/Llama-3.2-3B-Instruct # Path A — multi-config: one short run per (TP, EP) listed in sgl-cookbook /extract-kernel-definitions --model-name qwen3-next --tp-list 2,4 # Path B — manual fallback for fi_missing kernels (or names that didn't appear in the dump) /extract-kernel-definitions --model-name kimi-k2 --manual --op-types new_op_type ``` ## Parameters - `--model-name` (required): Model slug (e.g. `llama`, `deepseek-v3`, `qwen3-next`). Used to look up the SGLang model file and the sgl-cookbook YAML. - `--hf-repo-id` (optional): HuggingFace repo override; inferred from `--model-name` if omitted. - `--tp-list` (optional): Comma-separated TP values to run for; default reads sgl-cookbook YAML. - `--ep-list` (optional): Comma-separated EP values for MoE models. - `--manual` (optional): Force Path B (manual extraction) even for fi_supported ops. - `--op-types` (optional): Comma-separated `op_type` filter when using `--manual` or for `--dry-run` reporting. - `--dry-run` (optional): Report what would be dumped/written without running anything. - `--skip-existing` (optional, default `true`): Skip any definition whose name already exists under `tmp/flashinfer-trace/definitions/`. ## Prerequisites - `/clone-repos` has been run, so `tmp/sglang/`, `tmp/flashinfer/`, `tmp/sgl-cookbook/`, and `tmp/flashinfer-trace/` are present and current. The HF dataset clone at `tmp/flashinfer-trace/` is the only home for definitions — the in-repo `flashinfer_trace/` directory was removed in the trace-dataset refactor. - For Path A: a working CUDA-enabled environment, GPU memory sufficient for the chosen model + TP, and `attention_backend="flashinfer"` available in the installed SGLang. - For Path B: HuggingFace `config.json` access for the target model. --- ## Path A: trace-dump from a short SGLang pass The dumper fires inside FlashInfer when both env vars are set **before** the FlashInfer import. SGLang routes through `@flashinfer_api(trace=...)`-decorated APIs whenever `attention_backend="flashinfer"` is selected, so a single short prefill+decode pass exercises most ops at once. ### A1. Pick the serving config(s) Open the sgl-cookbook YAML for the target model and list the unique TP/EP values — one trace-dump pass per unique combination is enough to cover every shape variant. ```bash ls tmp/sgl-cookbook/data/models/generated/v0.5.6/ | grep -i {model_name} cat tmp/sgl-cookbook/data/models/generated/v0.5.6/{model_yaml} ``` If the model has no cookbook entry, default to TP=1 (single-GPU baseline) and skip EP. ### A2. Run the trace-dump pass Use `tools/gpu-lock` so `CUDA_VISIBLE_DEVICES` is set correctly. The script below mirrors [`tests/trace/example_sglang.py`](https://github.com/flashinfer-ai/flashinfer/blob/main/tests/trace/example_sglang.py) in the FlashInfer repo — adapt the `model_path`, `tp_size`, and `attention_backend`: ```bash DUMP_DIR=tmp/dumps/fi_trace_{model_slug}_tp{TP}_ep{EP} tools/gpu-lock --gpus {TP} --exec-timeout 1800 -- python - <<EOF import os, shutil from pathlib import Path # Must be set BEFORE flashinfer / sglang import. os.environ["FLASHINFER_TRACE_DUMP"] = "1" os.environ["FLASHINFER_TRACE_DUMP_DIR"] = "$DUMP_DIR" os.environ.setdefault("SGLANG_SKIP_CUBIN_DOWNLOAD", "1") dump = Path("$DUMP_DIR") if dump.exists(): shutil.rmtree(dump) from sglang.srt.entrypoints.engine import Engine engine = Engine( model_path="{hf_repo_id}", attention_backend="flashinfer", disable_cuda_graph=True, # keep first call on the Python path mem_fraction_static=0.5, tp_size={TP}, disable_radix_cache=True, log_level="warning", ) engine.generate( ["The capital of France is"], {"temperature": 0.0, "max_new_tokens": 4, "top_k": 50, "top_p": 0.9}, ) engine.shutdown() EOF ``` A few non-obvious requirements: - **Set the env vars before import.** `FLASHINFER_TRACE_DUMP` and `FLASHINFER_TRACE_DUMP_DIR` are read at call time, but the `@flashinfer_api` decorator binding happens at import — set them in the shell or at the top of the entry script *before* any `import flashinfer` / `import sglang` runs. - **Use `attention_backend="flashinfer"`.** Other SGLang backends bypass the FlashInfer APIs and produce no dumps. - **Disable CUDA graphs (`disable_cuda_graph=True`)** for the trace pass. Cached graphs skip the Python path and therefore the dumper. - **Page-size variants need separate runs.** SGLang's page size is fixed per server, so to capture both `_ps16` and `_ps64` shapes (for example) you must run twice with different `--page-size`. Enumerate the page sizes used by the target model. - **MoE routing methods.** Each `routing_method_type` (Default, Renormalize, DeepSeekV3, Llama4, RenormalizeNaive, TopK) emits its own template; only the routing actually exercised by the model in your prompts will dump. For DeepSeek-V3 use a real DSv3 model to capture the `ds_routing` variant. - **Quantized variants** (fp8/mxfp8/fp4 GEMM, fp8/fp4 block-scale MoE) require the model to actually use that quant config — load with the matching `--quantization` flag. ### A3. Dedupe and stage into the dataset ```bash # 1. List what was dumped ls "$DUMP_DIR" # 2. For each {name}.json: sort it under the right op_type subdirectory. # The op_type field inside the JSON is the source of truth for the subfolder. python - <<'EOF' import json, shutil from pathlib import Path src = Path("$DUMP_DIR") dst_root = Path("tmp/flashinfer-trace/definitions") for p in src.glob("*.json"): op_type = json.loads(p.read_text())["op_type"] dst = dst_root / op_type / p.name if dst.exists(): print(f"skip (exists): {dst.relative_to(dst_root)}") continue dst.parent.mkdir(parents=True, exist_ok=True) shutil.copy2(p, dst) print(f"added: {dst.relative_to(dst_root)}") EOF ``` ### A3b. Normalize the staged JSONs for `flashinfer-bench validate` The trace dumper's output has three known mismatches with `flashinfer-bench`'s `Definition` schema (all originate in the trace templates shipped with [flashinfer-ai/flashinfer#2931](https://github.com/flashinfer-ai/flashinfer/pull/2931)): 1. `reference` declares the function as `def _<name>_reference(...)`, but `flashinfer-bench` requires a top-level `def run(...)`. 2. Plan-time index tensors (`kv_indptr`, `kv_indices`, `qo_indptr`) come back with `dtype: "unknown"` because the dumper inspects only `run()`'s kwargs, not the wrapper state set during `plan()`. The validator only accepts concrete dtypes from its enum. 3. In-place ops (e.g. `fused_add_rmsnorm`'s residual) declare the same name in both `inputs` and `outputs`. `flashinfer-bench` rejects overlapping I/O names; the dumper's `reference` function only returns the non-overlap outputs anyway, so it's safe to drop the duplicates from `outputs`. Run this once per staging pass to make the JSONs validate: ```bash python - <<'EOF' import json, re from pathlib import Path INDEX_TENSOR_DTYPE = "int32" KNOWN_INDEX_TENSORS = { "kv_indptr", "kv_indices", "qo_indptr", "paged_kv_indptr", "paged_kv_indices", "kv_last_page_len", } REF_RE = re.compile(r"^def\s+_[A-Za-z0-9_]+_reference\b", re.MULTILINE) for p in Path("tmp/flashinfer-trace/definitions").rglob("*.json"): d = json.loads(p.read_text()); changed = False ref = d.get("reference", "") if ref and "def run(" not in ref: new_ref, n = REF_RE.subn("def run", ref, count=1) if n == 1: d["reference"], changed = new_ref, True for name, spec in d.get("inputs", {}).items(): if isinstance(spec, dict) and spec.get("dtype") == "unknown" and name in KNOWN_INDEX_TENSORS: spec["dtype"], changed = INDEX_TENSOR_DTYPE, True overlap = set(d.get("inputs", {})) & set(d.get("outputs", {})) for name in overlap: d["outputs"].pop(name, None) changed = True if changed: p.write_text(json.dumps(d, indent=2) + "\n") print(f"normalized: {p}") EOF ``` These three patches are mechanical — file a follow-up issue against `flashinfer-ai/flashinfer` to emit `def run(...)`, resolve plan-time dtypes, and drop in-place outputs (or rename them) inside the dumper itself, after which A3b becomes a no-op. ### A3c. Validate ```bash flashinfer-bench validate --dataset tmp/flashinfer-trace --disable-gpu ``` Newly staged definitions should report `[WARNING]` (missing descriptions on axes/inputs/outputs are advisory) and not `[ERROR]`. Any `[ERROR]` on a definition you just staged means A3b didn't normalize a new failure mode — inspect the report (`tmp/flashinfer-trace/reports/report-*.txt`) and extend the snippet. That's it for Path A — once normalized, the staged JSONs carry `axes`, `inputs`, `outputs`, `tags` (`fi_api:*`, `status:verified`), and a `reference` implementation, so they're ready for the rest of the onboarding pipeline (workloads → baseline → eval → Phase 4 PRs). ### Trade-off vs. tag enrichment The dumper does **not** auto-emit `tp:N`, `ep:N`, `model:*`, or `quantization:*` tags — those are workflow-level metadata, not kernel-shape metadata. After staging, append the appropriate tags to the JSONs you just produced: ```bash python - <<'EOF' import json from pathlib import Path extra_tags = ["model:{model_slug}", "tp:{TP}"] # add ep:{EP} for MoE for p in Path("tmp/flashinfer-trace/definitions").rglob("*.json"): if p.stat().st_mtime < {dump_run_start_epoch}: continue j = json.loads(p.read_text()) j["tags"] = sorted(set(j.get("tags", []) + extra_tags)) p.write_text(json.dumps(j, indent=2) + "\n") EOF ``` ### FlashInfer trace coverage Per [`docs/fi_trace.rst`](https://github.com/flashinfer-ai/flashinfer/blob/main/docs/fi_trace.rst), the trace registry currently covers: | FlashInfer module | API(s) | `op_type` | |-------------------|--------|-----------|
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen