Look up measured GPU kernel performance for LLM serving (GEMM, attention, MoE, normalization, communication) from the ServingStudio Kernel Library API. Not for end-to-end serving latency.
Install
npx skillscat add syfi-servingstudio/servingstudiosim/servingstudio-kernel-performance Install via the SkillsCat registry.
ServingStudio Kernel Performance
The ServingStudio Kernel Library publishes GPU kernel measurements that the
ServingStudio simulator uses to predict LLM serving performance. Each kernel
kind, such as single_gemm or nvfp4_fused_moe, has a table of rows, one per
combination of argument values, GPU and backend. Use this skill to answer
questions such as "how long does a bf16 GEMM with m=64, n=6144, k=4096 take on
H200?"
The API is read-only JSON over HTTPS. Set the base URL once:
API=${SERVINGSTUDIO_API:-https://servingstudio.cs.washington.edu/api/public/v1}
curl -s "$API/health"If /health does not return {"status": "ok", ...}, ask the user for the base
URL; do not guess another host. $API/openapi.json lists every route.
1. Find the kernel kind
The catalog lists every kind with its title, summary, category, backends,
precisions, row count, coverage (rows per GPU, backend and precision) andused_by (the public deployments that call it, by preset id). Match the
user's wording against title and summary; when the question names a model,
match it against used_by instead:
curl -s "$API/kernels" | jq -r '.kernels[] | [.kind, .category, .title] | @tsv'
curl -s "$API/kernels" | jq '.kernels[] | select(.kind == "single_gemm") | .coverage'
curl -s "$API/kernels" | jq -r '.kernels[] | select(any(.used_by[]; startswith("GLM-5.3-Flash/"))) | [.kind, .category] | @tsv'A kind's name does not fix its precision: nvfp4_fused_moe also has fp8
backends. Read the precision from coverage.
Check coverage before asking for rows: a GPU, backend or precision missing
from it has no rows. .gpus[] in the same response names each GPU as rows
spell it (name, such as NVIDIA H200) with its spec-sheet peaks
(peaks.tflops.by_dtype.<dtype>, dense; peaks.memory_bandwidth_gbps.value;peaks.busbw_gbps.value, NVLink one direction), which put a measured number in
context.
2. Read what the kind measures
curl -s "$API/kernels/single_gemm" | jq '{title, description, formula, method, caveats, args, backends}'Read args before filtering rows. Each entry gives the argument's unit and
meaning (doc).
The other fields explain the numbers. formula defines the FLOPs and bytes
behind the throughput metrics, method states how time was measured, andcaveats lists what the measurement leaves out. backends describes each
implementation (for example torch, deepgemm, flashinfer_trtllm_sm100)
with a link to its source. Its supports.gpus names spec-sheet SKUs (such asB200-SXM-180GB), not the GPU names rows carry; filter rows by.gpus[].name.
3. Get the rows
curl -s "$API/kernels/single_gemm/rows?gpu=NVIDIA%20H200&dtype=bf16&n=6144&k=4096"
curl -s "$API/kernels/single_gemm/rows?gpu=NVIDIA%20H200&n=6144&format=csv" > rows.csvEvery query parameter except format filters one column by exact equality:gpu (a .gpus[].name, such as NVIDIA H200), backend, or any argument; an
unknown column returns 400. An unknown value is not an error: gpu=H200 returns
200 with no rows (CSV: the header only), as does a GPU that was never measured,
so confirm the pair in coverage before you report "no data". There are no
range filters, so download a superset and filter ranges yourself. A response
holds every matching row; there are no pages. The JSON is column-oriented:
curl -s "$API/kernels/single_gemm/rows?gpu=NVIDIA%20H200&n=6144&k=4096" | jq -r '
.columns as $c | .rows[] | [$c, .] | transpose | map({(.[0]): .[1]}) | add
| [.backend, .m, .time_ms, .tflops] | @tsv'Rows also carry energy_j, the energy of one call in joules, where measured.
In JSON, each row's last column, provenance, indexes the response'sprovenance list, which records when the row was measured (profiler_run_at)
and with which CUDA, driver and backend versions. CSV repeats those fields on
every row instead.
4. Kernels a deployment calls
A kind's used_by lists the deployments that call it. For the other direction,
which kernels one deployment calls and whether each has rows, read the
deployment's tree (the servingstudio-timing-predict skill explains it). The
tree route takes the preset id from /models, {checkpoint directory}/{arch}
(GLM-5.3-Flash/..., not the Hugging Face name), and one value of each of the
preset's axes as a query parameter:
curl -s "$API/models" | jq -r '.checkpoints[] | .presets[] | [.id, .gpu, (.axes | map(.name) | join(","))] | @tsv'
curl -s "$API/models/GLM-5.3-Flash/glm53_flash_vllm_fp8_kda_dsa_moe/tree?tp_size=4&enable_expert_parallel=true&max_model_len=8192&workload=diverse_100" > tree.json
jq -r '[.sections[].slots[].kernel] | unique[]' tree.json
jq -r '.sections[] | .slots[] | [.kernel, (.backends | join(",")), .config, .name] | @tsv' tree.jsonA deployment runs on its preset's one gpu. Slots repeat per layer kind and
rank, so the slot list is long; the first jq gives the kinds once. The tree'smissing maps a kind to the rows the deployment needs and lacks; empty means
every kernel it calls is measured (/models gives the same missing per
member). configs maps each slot's config id to its kind, identity and
missing rows. /kernels/{kind}/configs/{config} serves one config's cells and
how many each backend measured, so a slot leads to its measurements.
5. Interpret and report
- Read the kind's
methodbefore quotingtime_ms; the timing differs by kind
and sometimes by backend. Most kernels report CUPTI kernel time with the L2
cache flushed before each launch, so the numbers are cold-cache times. Sometorchbackends use CUDA events around back-to-back calls, which includes
the gaps between launches. Collectives time CUDA graph replays or CUDA events
across ranks. When two backends use different methods, say so before
comparing them. - A
methodcan say that nothing is timed and the values come from a stored
table or a formula. Report those rows as modeled, not measured. tflopsandmemory_bandwidth_gbpsare logical rates: the work or bytes in
the kind'sformula, divided by time. A value of 0 means the kind does not
compute that metric.- Quote only rows the API returns. If the exact shape is missing, say so and
give the nearest rows; label any interpolation as your own estimate. - When you answer, name the kind, GPU, backend, argument values, the metric with
its unit, andprofiler_run_at.