Find the hot kernel, cool it down: an Nsight/SASS MCP server with a verify-and-record contract and a…
hotkernel
以下摘录自该仓库的 README(片段) · 在 GitHub 读完整 README →
**Find the hot kernel, cool it down.**
An MCP server that gives your coding agent hands on Nsight and SASS, a verify-and-record contract it cannot fudge, and a kernel-speedrun loop it runs on its own on the GPU on your desk.
English | 中文
Ask Claude to "make this kernel faster" today and it guesses: it cannot see the Nsight report, does not know which kernel eats 60% of the step, has never read the SASS the compiler produced, and cannot benchmark its own rewrite on your card. hotkernel is the missing pair of hands. Ten tools wrap nsys, ncu, cuobjdump, torch.profiler and a strict verify-and-record contract; one skill turns them into a loop: profile, pick the hot kernel, read its SASS, check it against the roofline, rewrite it in Triton, verify against the baseline, record the verdict, keep or revert, repeat.
**Five targets, five autonomous agent runs, one RTX 5090: rmsnorm 3.2× faster than eager PyTorch, softmax 1.2× faster than torch.softmax, gemv level with cuBLAS. Every kernel the agent kept runs at 95–105% of the card's measured streaming bandwidth. Where the library already sat near that ceiling (cuDNN decode attention, tinygemm int4 GEMV), the agent found nothing, stopped on its own, and the board says so.**¹
> ¹ Each range comes from three independent verify() calls of the agent's final kernel against the baseline, n=7 interleaved runs each, on one RTX 5090 at 575 W under WSL2. Speedups are relative to the baseline scripts in examples/: eager PyTorch for rmsnorm, torch.softmax for softmax, torch.mv (cuBLAS) for gemv. "Measured streaming bandwidth" is device memcpy on the same card under the same timer, 1501 GB/s (84% of the 1792 GB/s spec), see the calibration. Raw logs for every number are in results/.
Replay of a real run, rendered from its log: results/softmax/agent-run-20261014-200625. The 1.22× on screen was measured under timing protocol 2; the same kernel re-measured under protocol 3 is 1.17–1.21×.
Install
Claude Code, one command (Claude Code 2.1.275 or later): it adds this repository as a plugin marketplace and installs the plugin, which is the MCP server plus the kernel-speedrun skill.
Inside a session the same is /plugin marketplace add xinhuagu/hotkernel followed by /plugin install hotkernel@hotkernel. The plugin has one option, the Python that has your PyTorch and Triton: set it with /plugin configure hotkernel@hotkernel, or at install time with claude plugin install hotkernel@hotkernel --config hotkernel_python=$HOME/venvs/mytorch/bin/python. Left empty, hotkernel uses the first python on PATH that can import torch, and says so if there is none. The server itself stays torch-free and runs as uvx hotkernel.
Codex and other MCP clients (Cursor, DSH) keep the plain MCP setup:
or {"command": "uvx", "args": ["hotkernel"], "env": {"HOTKERNEL_PYTHON": "..."}} in the client's MCP config, plus a copy of skills/kernel-speedrun/ in the agent's skills directory. Claude Code without the plugin works the same way: claude mcp add -e HOTKERNEL_PYTHON=... hotkernel -- uvx hotkernel.
Point it at your own kernel
hotkernel new turns any PyTorch function into a target with the same contract as the examples: the function becomes the baseline, its fp32 result the reference, tolerances default by dtype, and the protocol-3 timer is vendored next to the scripts, so they run in your torch interpreter whether or not hotkernel is installed there.
writes targets/gelu_baseline.py, targets/gelu_candidate.py (starts as the baseline; this is the file the loop edits) and targets/_hotkernel_contract.py. A function of your own works the same way, with extra inputs in call order: --from ./mykernels.py:fused --extra w:8192. Then bench the baseline for the number to beat, and verify the untouched candidate against it, which must come back inconclusive before anything changed. Agents get the same through the new_target tool. On the reference card the untouched gelu candidate benched at 0.0952 ms and verified inconclusive; a deliberately wrong one came back incorrect.