Skip to main content

zymtrace-anchored-query

Reusable wrapper for the knowledge-base-first SQL pattern, adapted to the zymtrace ClickHouse profiling backend. Operator names the metric / question / time range. Skill anchors the `zymtrace_profiling.events` schema first (DESCRIBE + label-value + cardinality probes), derives the safe narrow SQL, runs it via `kubectl port-forward` + `curl -X POST`, and saves the raw payload to a provenance-bearing bundle per the perf-lake-contract. Workload-agnostic. The ClickHouse cousin of `prometheus-anchored-query`. Triggers on "zymtrace anchored query", "clickhouse anchored query", "zymtrace query", "save zymtrace payload", "anchored zymtrace", "anchored clickhouse", or any combination of "zymtrace / clickhouse / profile" with "anchored / safe / provenance / query / saved-payload".

Quellinformationen

Repository
cfregly/gpu-perf-tune
Letzte Quellaktivität
16. August 2026 um 20:38
Erkannte Sprache von SKILL.md
Englisch
Sterne
3
Forks
0

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
zymtrace-anchored-query
license
MIT
compatibility
Requires a skills-compatible agent and a POSIX shell with the commands named by the workflow.
metadata
{"last-validated":"2026-05-24"}
description
Reusable wrapper for the knowledge-base-first SQL pattern, adapted to the zymtrace ClickHouse profiling backend. Operator names the metric / question / time range. Skill anchors the `zymtrace_profiling.events` schema first (DESCRIBE + label-value + cardinality probes), derives the safe narrow SQL, runs it via `kubectl port-forward` + `curl -X POST`, and saves the raw payload to a provenance-bearing bundle per the perf-lake-contract. Workload-agnostic. The ClickHouse cousin of `prometheus-anchored-query`. Triggers on "zymtrace anchored query", "clickhouse anchored query", "zymtrace query", "save zymtrace payload", "anchored zymtrace", "anchored clickhouse", or any combination of "zymtrace / clickhouse / profile" with "anchored / safe / provenance / query / saved-payload".
allowed-tools
Bash(kubectl:port-forward,*) Bash(kubectl:get,*) Bash(curl:*) Bash(jq:*) Bash(sha256sum:*) Bash(date:*) Read Write
# zymtrace-anchored-query ## Purpose Make ad-hoc ClickHouse queries against the [zymtrace](https://docs.zymtrace.com) profiling backend **safe by default** by wrapping the "anchor labels in the schema FIRST, then run the query" discipline as a reusable skill. Saves the raw payload to a provenance-bearing bundle so future queries can replay the same shape, and so the perf-lake-contract is honored without operator effort. This skill exists because the `zymtrace_profiling.events` table on a busy cluster holds tens of millions of rows per day across every profiler-enabled namespace. An SQL query that forgets to bound `timestamp` or `pod_name LIKE '...'` returns a full-table scan that overloads ClickHouse and starves real-time ingest. The anchor-then-query pattern works for arbitrary profiling questions. This skill makes it agent-routable. [`prometheus-anchored-query`](../prometheus-anchored-query/SKILL.md) is the Prometheus version of the same pattern. Use this when the question targets profiling data (CPU on-cpu samples, GPU cuda kernel samples, stack-traces, function-resolution lookups). Use the Prometheus skill when the question targets time-series cluster metrics. ## When to use - Operator has a profiling question that maps to a ClickHouse query but doesn't know the exact `pod_name` pattern, time-window, or `event_kind` to use yet. - Operator wants to save a zymtrace payload to disk with provenance (for evidence bundles, profile-findings write-ups, share-with-team artifacts, or feeding the optional `kernel_class_gpu_pct` + `cpu_spinpoll_pct` fields into the [`inference-perf-baseline-bridge`](../inference-perf-baseline-bridge/SKILL.md) schema). - Operator wants to confirm a `pod_name` LIKE pattern matches the expected pod set + that the time window has enough samples to be statistically useful before running a full top-N query. Do **not** use this skill for: - Already-vetted profile queries - just run the SQL directly via `curl -X POST 'http://localhost:9123/' --data-binary @<query.sql>`. - Live UI exploration - the zymtrace web UI has its own flamegraph/timeline views. This skill is for headless reproducible queries. - Cross-tenant queries - every example here scopes to a single `pod_name LIKE` pattern. Cross-tenant exploration belongs to the zymtrace UI or the zymtrace MCP's pattern-recognition tools. ## Example prompts - "What are the top 25 hottest CUDA kernels in `basic-inference` pods over the last 5 minutes?" - "Save the on_cpu hot-Python-callers query for `glm-inference` between 16:00 and 16:30 UTC." - "Did `shm_broadcast.py` CPU time in the `glm-inference` pods drop after we set VLLM_USE_SHM_BROADCAST_BLOCKING=1? Compare the last 30 minutes against the window before the change." - "Get me the kernel-class breakdown for the `kimi-inference` pods during the perf-bench window I just ran so I can fill `kernel_class_gpu_pct` in the perf-baseline bundle." - `/zymtrace-anchored-query --question "top-25 cuda kernels for basic-inference pods, last 5 min" --time-range "now-5m..now"` - `/zymtrace-anchored-query --pod 'basic-inference%' --event-kind cuda --window '<start-UTC>..<end-UTC>' --top 25` ## Prerequisites 1. **Cluster context active** - `kubectl config current-context` returns the cluster running zymtrace. 2. **zymtrace backend deployed** - `kubectl -n zymtrace get pods -l app=zymtrace-clickhouse` shows at least one Running pod. 3. **Operator question or pod+kind+window** - one of: - Free-form question (skill derives `pod_name` pattern + `event_kind` + window via schema introspection). - Explicit `--pod <LIKE-pattern> --event-kind <cuda|on_cpu> --window <UTC-range>`. 4. **Time window** - `--time-range "now-Nm..now"` or absolute UTC range. Default `now-5m..now`. Queries with no `timestamp` bound are refused. 5. **`PROFILE_AND_OPTIMIZE_REPO_ROOT`** for the bundle path (falls back to `${PWD}/zymtrace-bundles/<run-id>/`). ## Interaction style Iterative. The whole point of the skill is the "anchor first, then query" discipline. Pause after the schema-anchor call to surface the proposed SQL before running it. ## Workflow ### Phase 0: resolve the question If operator provided a free-form question, restate the question + the proposed `pod_name` LIKE pattern, `event_kind`, and time window in one sentence. Get confirmation. If operator provided explicit pod + kind + window, proceed. ### Phase 1: schema + label anchor Start the port-forward if not already running: ```bash # Idempotent: skip if a port-forward to svc/zymtrace-clickhouse is already up on 9123. if ! curl -fsS -o /dev/null -m 2 'http://localhost:9123/ping'; then nohup kubectl -n zymtrace port-forward svc/zymtrace-clickhouse 9123:8123 \ > /tmp/zt-ch-pf.log 2>&1 & disown sleep 3 fi ``` Probe the schema for the table the query will hit (default `zymtrace_profiling.events`): ```bash curl -fsS -X POST 'http://${CH_USER}:${CH_PASSWORD}@localhost:9123/' \ --data-binary 'DESCRIBE TABLE zymtrace_profiling.events FORMAT JSON' \ > /tmp/zt-schema-anchor.json ``` Then sanity-check cardinality of the proposed selector before running the full top-N query: ```bash curl -fsS -X POST 'http://${CH_USER}:${CH_PASSWORD}@localhost:9123/' \ --data-binary " SELECT count() AS rows, uniqExact(pod_name) AS pods, min(timestamp) AS first_ts, max(timestamp) AS last_ts FROM zymtrace_profiling.events WHERE pod_name LIKE '<pattern>' AND event_kind = '<kind>' AND timestamp >= '<start>' AND timestamp <= '<end>' FORMAT JSON " ``` The cardinality probe response tells us: - Whether the selector matches **any** rows (catches typos in `pod_name` LIKE patterns immediately). - The exact `pod_name` set the query will scan (catches accidental cross-pod scope). - The actual `timestamp` range that has data (catches misaligned windows - e.g. a window anchored on the bench's scheduled start when the run actually began and ended a few minutes later, a common first-pass mistake). - The sample count (so the operator can decide if the window is too short to be statistically meaningful - <1000 samples is typically not enough). If `rows = 0`: do NOT immediately conclude "no signal". Zymtrace data is not instantaneous - rank two causes in this order: 1. **Ingest lag (transient).** If the pod/window are freshly-run (the bench just ended), zymtrace may not have flushed to ClickHouse yet - it flushes **asynchronously** (~seconds-to-minutes). **Wait for the flush and re-run the cardinality probe** for the freshest data before concluding. A simple poll (mirrors [`scripts/zymtrace-ingest-wait.sh`](../../../../scripts/zymtrace-ingest-wait.sh)): ```bash for i in $(seq 1 "${ZYM_INGEST_MAX_ATTEMPTS:-6}"); do rows=$(curl -fsS -X POST 'http://${CH_USER}:${CH_PASSWORD}@localhost:9123/' \ --data-binary "<the cardinality probe SELECT ... FORMAT JSON>" | jq -r '.data[0].rows') [ "${rows:-0}" -gt 0 ] && break sleep "${ZYM_INGEST_WAIT_SEC:-20}" # requery for the freshest data done ``` 2. **Wrong selector / window.** If it STAYS 0 past the flush window, the `pod_name LIKE` pattern or `[start,end]` doesn't match - re-query by `host=<node>`+window (the hash-suffixed pod-name filter often reads empty when the host filter returns frames) and confirm the window. Per the fail-fast rationale in [`server/docs/zymtrace-query-hygiene.md`](../../server/docs/zymtrace-query-hygiene.md), running the top-N on an empty result would look like "no signal" when it is really either ingest lag (requery) or a wrong selector (fix it) - never silently proceed. If `rows > 10_000_000`: refuse. The selector is too broad. Narrow the time window or `pod_name` pattern. ### Phase 2: emit the SQL Construct the narrow SQL using only schema-anchor-confirmed labels and the operator's `--time-range`. The SQL **must** include all three bounds: ```sql WHERE pod_name LIKE '<pattern>' AND event_kind = '<kind>' AND timestamp >= '<start>' AND timestamp <= '<end>' ``` Print the proposed SQL back: ```text Proposed SQL: <full query> Anchor: pod_name LIKE '<pattern>', event_kind = '<kind>' Time range: <start> .. <end> Expected rows scanned: ~<from cardinality probe> LIMIT clause: <N rows> (default 25) ``` Ask: "Run this query?" Do not auto-advance. ### Phase 3: run + save After confirmation, run the query via curl + save the raw response: ```bash RUN_ID="$(date -u +%Y%m%dT%H%M%SZ)" BUNDLE_DIR="${PROFILE_AND_OPTIMIZE_REPO_ROOT:-${PWD}}/experiments/artifacts/zymtrace-bundles/${RUN_ID}" mkdir -p "${BUNDLE_DIR}" cat > "${BUNDLE_DIR}/query.sql" <<'EOF' <the exact SQL from Phase 2> EOF curl -fsS -X POST 'http://${CH_USER}:${CH_PASSWORD}@localhost:9123/' \ --data-binary "@${BUNDLE_DIR}/query.sql" \ -H 'X-ClickHouse-Format: JSON' \ -o "${BUNDLE_DIR}/response.json" sha256sum "${BUNDLE_DIR}/query.sql" "${BUNDLE_DIR}/response.json" \ > "${BUNDLE_DIR}/sha256sums.txt" ``` Save the bundle layout (parallels `prometheus-bundles/<run-id>/` for consistency): ``` ${PROFILE_AND_OPTIMIZE_REPO_ROOT}/experiments/artifacts/zymtrace-bundles/<run-id>/ SOURCE.md # operator + question + cluster + UTC-ts + git SHA query.sql # the exact SQL run query.json # the curl request shape (URL, headers, body-ref) response.json # the raw ClickHouse response (saved verbatim) summary.md # human-readable: row count, top-5 by pct, anchor recap schema-anchor.json # the DESCRIBE + cardinality-probe responses (provenance) sha256sums.txt # query.sql + response.json sha256 ``` ### Phase 4: report Print: - **Row count** + **scanned-rows count** (sanity check: did we get the cardinality the anchor predicted?). - **Top 5 rows** of the response (highest `pct` or `total_samples`). - **Bundle path** for the saved payload. - **Cross-link** to [`inference-perf-baseline-bridge`](../inference-perf-baseline-bridge/SKILL.md) if the operator's question maps to a `kernel_class_gpu_pct` or `cpu_spinpoll_pct` field (it usually does - that's the canonical consumer of this skill's output). ## Kernel-class bucketing (appendix) The [`inference-perf-baseline-bridge`](../inference-perf-baseline-bridge/SKILL.md) schema's `kernel_class_gpu_pct` field is derived by bucketing kernel names from this skill's GPU-side response. The canonical regex set covers the kernel classes that dominate FP8 MoE serving on B200-class hardware: | Bucket key | Regex on `kernel` (func_name) | What it catches | | --- | --- | --- | | `fp8_bmm` | `^bmm_(E4m3|Bfloat16)_E4m3E4m3` OR `sm100_fp8_gemm` OR `deep_gemm::sm100_fp8` | FP8 block-quantized batched matmul (the dominant compute on B200 Kimi/DeepSeek) | | `tp_all_reduce` | `multimem_all_reduce_kernel` OR `trtllm_allreduce` OR `oneshot_lamport` | Tensor-parallel all-reduce kernels (both PyTorch CUDASymmetricMemoryOps + flashinfer paths) | | `cuda_event_sync` | `cudaEventSynchronize` OR `cuda-sync` | Host-side CUDA event sync (sign of cudagraph coverage gaps) | | `mla_attention` | `fmhaSm100fKernel` OR `cute_flash_fwd_sm100` OR `mla_attention` | DeepSeek-V3-style MLA attention (Q576/V512 paged-KV) | | `moe_routing_finalize` | `moe::dev::(routing|finalize|activation)` | DeepSeek MoE routing + finalize kernels | | `per_token_group_quant` | `per_token_group_quant_8bit` | Block-FP8 activation quantization (group_size=128) | Apply the regex against `kernel` in the GPU response, sum the `pct` per bucket, leave classes outside this set under arbitrary `<other-class>` keys (e.g. `nvjet_trt_llm`, `d2d_memcpy`, `elementwise_misc`). ## Full-context reporting (no bare numbers) Per `docs/METHODOLOGY.md` "Full-context reporting": every number this skill emits (throughput, latency, TPOT/ITL, BW, %SoL, speedup, efficiency, goodput, acceptance rate, scaling efficiency, thermal/failure rate - whatever it reports) MUST carry its full measurement-context descriptor, and every comparison MUST be matched on it. A bare number is a defect - it cannot set a default, ship a config, or appear in a report. - **Identity:** model (+HF path), hardware (exact ceiling token `GB300`/`B200`), quant, kv-cache dtype. - **Parallelism:** TP, DP (replicas), PP, EP, parallel_strategy. - **Serving cfg:** max-num-seqs, max-num-batched-tokens, gpu-memory-utilization, max-model-len, cudagraph_mode/enforce_eager, async_scheduling, prefix-caching. - **Workload:** dataset, ISL/OSL (or mean in/out tokens), concurrency, num-prompts. - **Regime:** warm vs cold. Latency vs throughput tier. - **Stack:** image/vllm commit, bench backend, serving engine. - **Grounding:** `%SoL` (+ ceiling key from `configs/sol-ceilings.yaml` - never inline a peak), sol_rigor (L1-L4), trials n (mean±std), same-node, baseline named. (If the metric is not roofline-bound - e.g. accuracy/acceptance - omit `%SoL` but keep the rest of the descriptor.) - **Per-number exact shape (no smoothing):** when reporting more than one number, keep EACH with its own exact shape (ISL/OSL, concurrency, dataset, regime) - never normalize a set to one uniform descriptor that hides per-point variation (e.g. `c=1 @ ISL1024/OSL256` + `c=64 @ ISL4096/OSL512`, NOT one shared "random"). ## Next lever / BREAKTHROUGH (Grind Mandate) If this skill emits a measured result, its output MUST end by naming the **next perf lever**,
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen