Skip to content

Repository files navigation

Mini Kernel Verifier

cpu-ci

面向 CUDA Custom Operator 的 YAML 驱动自动验证与性能回归平台。输入一张 Task Card 和候选 C++/CUDA 源码,平台完成编译、PyTorch Dispatcher 动态加载、数值与契约验证、 CUDA Event Benchmark、结果归档、排行榜和基线回归判断。

本项目刻意聚焦工程闭环,不负责生成 Kernel。它可以理解为一个更小、更强调可复现构建、 非法输入契约和证据归档的 KernelBench。

快速入口

  1. Quick Start:安装依赖并跑通第一张 Task Card;
  2. 项目架构图:了解输入、Verifier stages 与结果归档之间的关系;
  3. 性能优化证据RMSNorm 优化分析 · 机器可读 Profile 对比

Quick Start

前提:Linux/WSL2、Python 3.12、uv;运行 CUDA 验证还需要可用的 NVIDIA Driver、CUDA Toolkit 和 nvcc

git clone https://github.com/Willowkk/mini-kernel-verifier.git
cd mini-kernel-verifier

uv sync --frozen --extra cu128
source .venv/bin/activate

python -m mini_kv doctor
python -m mini_kv validate-task --task tasks/vector_add.yaml
python -m mini_kv verify --task tasks/vector_add.yaml

无 NVIDIA GPU 时可安装 CPU extra 并运行与 GitHub Actions 相同的静态/单元测试:

uv sync --frozen --extra cpu
pytest -m "not gpu and not profile"

项目架构图

flowchart LR
    subgraph Inputs[Inputs]
        A[YAML Task Card]
        B[Candidate C++ / CUDA]
        C[PyTorch Reference]
    end

    subgraph Verifier[Mini Kernel Verifier]
        D[Strict Loader]
        E[Content-addressed Compiler]
        F[PyTorch Dispatcher Load]
        G[Correctness / Contract / opcheck]
        H[CUDA Event Benchmark]
        I[Baseline Regression Gate]
        P[Nsight Compute Capture]
    end

    subgraph Outputs[Evidence & Derived Views]
        J[Attempt + Logs + Source Snapshot]
        K[Artifact Index]
        L[Environment-scoped Leaderboard]
        M[NCU Report + Profile Comparison]
    end

    A --> D
    B --> D
    C --> D
    D --> E --> F --> G
    G -->|pass| H --> I --> J
    G -->|fail| J
    J --> K --> L
    E --> P --> M
Loading

核心包使用 src layout:

src/mini_kv/
├── task_card.py       # 严格 YAML/路径校验
├── compiler.py        # 内容哈希、项目内 build、dispatcher load
├── correctness.py     # Reference、边界/非法、opcheck、gradcheck
├── benchmark.py       # CUDA Event、P50/P95、稳定性门禁
├── artifacts.py       # 原子 JSON、append-only Attempt、Index
├── regression.py      # pinned baseline、可比性、双批确认
├── leaderboard.py     # latest-valid、环境分组、几何平均 speedup
├── profiler.py        # Nsight Compute 单 case capture
└── profile_analysis.py # NCU 指标解析与 CUDA Event 证据绑定

已实现范围

算子 PyTorch Reference CUDA 候选 主要覆盖
Vector Add torch.add(a, b) v0_naive FP32/FP16、warp 边界、空 Tensor
Fused Bias + ReLU torch.relu(x + bias) v0_naive 1D bias broadcast、非对齐 hidden
RMSNorm FP32 accumulate Reference v0_naivev1_block_reduce reduction、数值稳定性、非对齐 hidden

四个候选均注册 CPU、CUDA 和 Meta backend;CUDA wrapper 使用当前 PyTorch stream、 CUDAGuard 和 launch-error check,且不会在算子内部做破坏异步语义的全设备同步。

平台能力包括:

  • 3 类算子、36 组固定核心 shape × dtype 正确性矩阵;
  • 空 Tensor、zero/tiny/large value、非连续、shape/dtype/device 不匹配和非法参数测试;
  • 独立记录 PyTorch Reference 数值误差、完整 torch.library.opcheck 和 Autograd gradcheck
  • 项目内、内容寻址的 JIT build cache,以及源码、stdout/stderr 和编译元数据归档;
  • 每个实现每个 case 保存 500 个 CUDA Event 原始样本及 P50/P95/均值/标准差/CV;
  • 显式 baseline promotion、环境/套件可比性检查、5% P50 双批确认回归门禁;
  • append-only Attempt、Artifact Index、按 suite/GPU 环境分组的 Leaderboard;
  • 固定 RMSNorm case 的 Nsight Compute 报告采集、强校验与结构化 A/B 对比;
  • CPU GitHub Actions 与本机 GPU gate 分层。

环境与安装

已验收的本机环境:

项目 版本
OS WSL2 Ubuntu 22.04
GPU NVIDIA GeForce RTX 5070 Ti Laptop GPU, compute capability 12.0
PyTorch 2.11.0+cu128
CUDA Toolkit / nvcc 12.9 / 12.9.86
Nsight Compute 2025.2.1.0, build 35987062
Python / C++ 3.12 / C++17

PyTorch wheel 自带的 CUDA runtime 不等于构建 .cu 所需的本地 Toolkit; torch.utils.cpp_extension.load 的构建参数与 plain dynamic-library 模式见 PyTorch 2.11 cpp_extension 文档

uv sync --frozen --extra cu128
source .venv/bin/activate
python -m mini_kv doctor

项目强制把 Extension build 放在 .build/torch_extensions/,不会使用默认的 ~/.cache/torch_extensions。当前 Blackwell 机器建议固定原生目标:

export TORCH_CUDA_ARCH_LIST=12.0

Verifier 默认使用内容寻址 JIT build;也提供经真实验证的 CMake AOT 入口,可一次构建并 加载包含四个唯一 dispatcher op 的共享库:

./scripts/build_cmake.sh

使用

先只验证 Task Card,不触发编译:

python -m mini_kv validate-task --task tasks/vector_add.yaml

执行完整流水线:

python -m mini_kv verify --task tasks/vector_add.yaml
python -m mini_kv verify --task tasks/fused_bias_relu.yaml
python -m mini_kv verify --task tasks/rmsnorm.yaml

覆盖默认候选,例如比较 RMSNorm naive 和 block-reduce:

./scripts/compare_rmsnorm.sh

只跑编译、正确性、opcheckgradcheck

python -m mini_kv verify --task tasks/rmsnorm.yaml --skip-benchmark

完整本机 gate:

./scripts/run_gpu_suite.sh

CLI 使用非零退出码区分配置、编译、正确性、Benchmark、回归和内部错误,适合直接作为 CI gate。

Task Card

Task Card 只描述“测什么”,不嵌入执行代码:

schema_version: "1.0.0"
task_id: vector_add_v1
operator: vector_add
operator_version: "1.0.0"
reference: mini_kv.references.vector_add:reference
input_factory: mini_kv.references.vector_add:make_inputs
candidate: candidates/vector_add/v0_naive
device: cuda

cases:
  - id: core_1025_fp16
    kind: positive
    params: {shape: [1025], dtype: float16}

tolerances:
  float16: {rtol: 1.0e-3, atol: 1.0e-3}

benchmark:
  case_ids: [bench_1m_fp16]
  primary_case_id: bench_1m_fp16
  warmup: 20
  iterations: 100
  repeats: 5

Loader 使用 yaml.safe_load、拒绝未知字段与重复 case ID,并限制 candidate、source 和 baseline 路径留在项目目录内;运行时也强制校验 identifier、import path、dispatcher qualname 和 schema version。Task Card、baseline 与运行结果由 14 份 Draft 2020-12 JSON Schema 约束。

正确性与 PyTorch 兼容性

36 组核心矩阵固定为每个算子 6 个 shape × FP32/FP16。31/32/33127/128/129 用于覆盖 warp/block 边界与非对齐长度;大尺寸性能 case 不混入“36/36” 简历口径。

每个正例都会:

  1. sha256(task_id, case_id) 派生固定 seed;
  2. 给 Candidate 和 Reference 独立 clone 的同一输入;
  3. 同步 CUDA 后比较 shape/dtype/device 和数值;
  4. 记录 max absolute/relative error、mismatch count、异常和输入 metadata;
  5. 检查声明为 functional 的算子没有修改输入。

opcheck 与数值测试分开归档。前者验证 schema、Autograd registration、Meta/FakeTensor 和 AOT dynamic contract,不替代 Reference 数值测试;支持梯度的注册另外执行 gradcheck。这是 PyTorch 官方教程明确区分的两类验证: Custom C++ and CUDA Operators

Benchmark 与回归规则

计时不使用 CPU wall clock。每个 case:

  • Candidate/Reference 各 warm-up 20 次;
  • 5 个 repeat,每个 repeat 100 个独立 CUDA Event 样本;
  • repeat 间交替 Candidate/Reference 先后顺序;
  • 保存 500 个 raw samples、P50/P95/min/mean/std,以及 repeat 级 P50/P95、MAD 和 robust CV;
  • Candidate/Reference P50 robust CV 上限为 3%,Candidate P95 上限为 15%;超限标记 unstable,不进榜、不做 baseline;
  • speedup = reference_p50 / candidate_p50,跨 case 排名使用等权几何平均。

Baseline 永远不会自动更新:

python -m mini_kv promote-baseline \
  --attempt artifacts/rmsnorm_v1/<attempt-id> \
  --output baselines/rmsnorm_v1.json

只有 task/operator semantic version、suite hash 和 environment key 完全相同时才比较; 环境不同返回 INCOMPARABLE,不是伪装成 PASS。当前 P50 阈值为 5%,首次超限会自动跑 独立 confirmation batch,两批都超限才 FAIL;P95 超过 10% 只告警。

仓库已保存三份由真实稳定 Attempt 显式 promotion 的 baseline;2026-07-13 随后的三次完整 运行均得到 regression.status = PASS。Baseline 内嵌原始 Benchmark 数据并通过独立 Schema 校验,在其他 GPU/软件环境会返回 INCOMPARABLE,不会沿用本机数字。

Artifacts 与 Leaderboard

一次运行的最终目录:

artifacts/<task-id>/<attempt-id>/
├── attempt.json
├── task_card.json
├── candidate_manifest.json
├── environment.json
├── compile.json
├── compile_stdout.log
├── compile_stderr.log
├── correctness.json
├── benchmark.json
├── regression.json
└── sources/                 # 本次真正编译的源码快照

写入期间目录以 .partial 结尾;JSON 同目录临时写、fsyncos.replace,最终再原子 rename。attempt.json 保存所有文件的 SHA-256 与大小。artifact_index.json 可幂等重建, 更新时使用文件锁;Leaderboard 只接受完整正确且稳定的 latest-valid attempt,并按 task、 suite、GPU 环境分榜。

python -m mini_kv rebuild-index
python -m mini_kv leaderboard

Nsight Compute 优化闭环

RMSNorm 提供两份独立候选:

  • v0_naive:每个 row 一个线程串行 reduction;
  • v1_block_reduce:每个 row 一个 256-thread block,shared-memory reduction,FP32 accumulate。

固定 [1024, 4096] / FP16 case 收集 Speed of Light、Memory Workload、Occupancy 和 Warp State sections:

./scripts/profile_rmsnorm.sh candidates/rmsnorm/v0_naive
./scripts/profile_rmsnorm.sh candidates/rmsnorm/v1_block_reduce

成功的报告和所有命令日志写入 artifacts/profiles/;失败也会保存结构化原因。Profile 产物绑定原始 Task Card/manifest、源码与 .so SHA-256、build/environment key、固定输入 seed,并使用候选专属 kernel-name filter;只有 .ncu-rep 可重新导入、raw CSV 可解析、 必需指标齐全且唯一数据行完整匹配目标 kernel 才标记成功。compare-profiles 还会要求两份 Profile 与 CUDA Event A/B Comparison 的 task/case/environment/build/source hash 全部一致。 可提交的结构化结果见 RMSNorm Profile 对比摘要。Nsight Compute 支持按 section 选择指标、跳过 launch、导出报告以及 GUI baseline 对比,详见 NVIDIA Nsight Compute CLI报告 Baseline 对比

测试与 CI

ruff check src tests scripts main.py
python scripts/validate_schemas.py
pytest -m "not gpu and not profile"
pytest -m gpu

uv.lockcpucu128 PyTorch 设为互斥 extra;本机使用 uv sync --frozen --extra cu128,Actions 使用 CPU-only wheel,避免在普通 Runner 下载整套 CUDA runtime。CI 还会上传 JUnit 与 coverage XML。

GitHub Actions 只运行 lint、format、Schema/Task Card/baseline 校验和 CPU 单元测试。CUDA 编译、36 组 GPU 正确性、Benchmark、回归和 Nsight 留在本机 GPU gate;项目不会把个人笔记本作为公开 PR 可触发的 self-hosted runner。GitHub 对 self-hosted runner 的部署与权限边界见 官方文档

当前验证快照

2026-07-13 在上表 RTX 5070 Ti Laptop 环境完成真实全量 gate。所有数字均来自保存 500 个原始样本的 Attempt,且质量状态为 valid

主 case 正确性 Candidate P50 / P95 Reference P50 Speedup
Vector Add [1M], FP16 19/19(core 12/12) 7.744 / 58.608 μs 3.680 μs 0.48×
Fused Bias+ReLU [1024,4096], FP16 20/20(core 12/12) 28.224 / 34.147 μs 32.704 μs 1.16×
RMSNorm v1 [1024,4096], FP16 24/24(core 12/12) 20.000 / 32.160 μs 164.368 μs 8.22×

三个算子合计 core 36/36,加边界/非法契约为 63/63;CPU 单测 95 passed,GPU 集成测试 14 passed,合计 109 passed。Vector Add 慢于高度优化的 PyTorch Reference,项目如实记录,未只 挑有利数字。

同进程、同输入、交替顺序的 RMSNorm A/B 对比为:naive P50 1956.096 μs,block-reduce P50 18.016 μs108.58× speedup,延迟下降 99.08%;两边 repeat-P50 robust CV 分别约 0.086%0%,repeat-P95 robust CV 为 1.23%0.70%,质量状态 valid。Comparison 同时保存两边各 500 个样本、完整 24/24 re-gate、源码快照与哈希。 复现命令:

./scripts/compare_rmsnorm.sh

两份 Nsight Compute 2025.2.1 报告已成功采集并重新导入校验,raw CSV 均为唯一目标 Kernel 数据行、587 列。关键变化为:grid 4 → 1024 blocks、waves/SM 0.01 → 3.71、 achieved occupancy 16.66% → 89.44%、DRAM throughput 1.21% → 55.02%、实际 DRAM bandwidth 4.11 → 186.73 GB/s。v0 的 LG Throttle / Long Scoreboard 为 60.56 / 45.05 cycles per issued instruction;v1 降至 0.15 / 6.25,剩余首要 stall 为 Long Scoreboard。NCU 将 v1 的 Speed-of-Light 状态判为 compute/memory balanced。

NCU 多 section replay 下的 6007.808 / 62.880 μs 只用于诊断,不能替代上面的同进程 CUDA Event A/B 延迟。完整指标、两个 report SHA、源码/build/.so/环境绑定关系均保存在 结构化证据,分析见 RMSNorm 优化闭环

参考项目

当前边界

  • 单 GPU、单机、forward-focused;不包含 LLM 生成 Kernel、Web UI 或分布式队列;
  • 每个候选使用唯一 dispatcher op name;未把任意不可信源码接入公开 self-hosted runner;
  • 当前编译、动态加载和候选执行针对可信本地源码,仍在 verifier 进程内;不可信候选的 crash/timeout 子进程隔离属于下一阶段;
  • 采用当前 PyTorch 标准 ATen API,Stable ABI wheel 可作为后续分发增强项;
  • Laptop GPU 的功耗和温度会影响结果,因此环境不同或噪声超限时拒绝做确定性回归结论。

About

YAML-driven CUDA custom operator verification and performance regression platform

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages