Skip to content
2 changes: 1 addition & 1 deletion agents/triton-ascend-coder.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ Agent 自身维护迭代状态,编排 "生成 → 验证 → Conductor 分析"

```
iteration = 0
max_iterations = 5
max_iterations = 20
history_attempts = []
previous_code = ""
verifier_error = ""
Expand Down
193 changes: 149 additions & 44 deletions skills/triton/kernel-verifier/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,108 @@ argument-hint: >
你是一个内核代码验证专家。你的任务是按照标准验证流程,创建验证项目并运行,检查生成的算子代码是否能正确编译运行且与参考实现的输出一致。验证通过后,执行性能测试并收集性能数据。
</role>

## 精度判定规则

> 本节是 verify.py 精度判定的**唯一权威说明**。所有阈值、决策矩阵、前置检查只在此处定义;下游章节(Step 2/3)只引用、不重复。
> (别名:精度阈值说明 / 验证分类与判定标准)

verify.py 按"`--non-compute` 开关 + 输入 dtype + 输出 dtype"分流到 **5 类判定路径**。

### 1. 输入类型推断(KernelBench / NPUKernelBench 统一)

从实际传入对象推断(不依赖 task 文件结构化 spec):

1. 存在 `torch.Tensor` 输入 → 取所有 tensor 中**最高精度 dtype**
(例:输入为 `[fp16 tensor, fp32 tensor, int64 tensor]` → 取 fp32)
2. 否则存在 `list/tuple of Tensor`(tensor_list)→ 取首个 tensor_list 首元素 dtype
3. 否则视为**无 tensor 输入**(`no_tensor`,最严路径)

**dtype 优先级**:

精度从高到低排列:float64 > float32 > float16 > bfloat16 > float8_e4m3 / float8_e5m2 > int64 > int32 > int16 > int8 / uint8 > bool

**`input_type` 二分类**(用于 §2 决策矩阵分流):

- `input_type = float`:输入最高精度 dtype 属于浮点族(float64/32/16、bfloat16、float8_e4m3/e5m2、复数 complex64/128)
- `input_type = int`:输入最高精度 dtype 属于整型族(int64/32/16/8、uint8、bool)
- `input_type = no_tensor`:无任何 tensor 输入(走最严判定)

> **关于 bool 的两处特殊性**(避免混淆):
> - bool 作**输入**:归入 `int`,与 int 系输入等同;分流时只看输出 dtype(如输出 fp 走浮点判定)
> - bool 作**输出**:不进入 input_type 分流,直接走 §2 "bool 输出"路径(`torch.equal` 严格相等)

### 2. 五类判定决策矩阵

| 类别 | 输入 type | 输出 dtype | `--non-compute` | 误差要求 |
|---|---|---|---|---|
| **非计算类** | 任意 | 任意 | **是** | 二进制完全一致(view-as-int 比对,含 NaN bit pattern) |
| **bool 输出** | 任意 | bool | 否 | `torch.equal` 严格相等 |
| **整数计算类** | int / no_tensor | int | 否 | `\|actual − golden\| == 0` |
| **量化计算类 fp→int** | float | int | 否 | `\|actual − golden\| <= 1` |
| **浮点计算类** | 任意 | float | 否 | 三项 AND(见 §4) |

### 3. 比对前置检查(按顺序,任一失败即判 fail)

1. 形状必须一致
2. NaN 位置必须完全一致(mask 按位相等)
3. Inf 位置和符号必须完全一致
4. `bool` dtype:要求 `torch.equal` 完全相等,不进入精度判定
5. 仅在 `finite_mask`(双方都 finite)上做精度计算;dtype 不一致时 impl 会被 cast 到 golden 的 dtype

### 4. 浮点计算类:三项 AND 整体判定

#### 4.1 元素级 matched 定义(分桶)

对每个 finite 元素 `i`,按 `|golden[i]|` 落入的类别分别判定:

- **小值域** `|golden[i]| < small_value_threshold`:
`matched[i] = (|actual[i] - golden[i]| <= small_value_error)`
- **正常域** `|golden[i]| >= small_value_threshold`:
`matched[i] = (|actual[i] - golden[i]| / (|golden[i]| + 1e-7) <= rel_threshold)`

> 计算前两侧统一升 float32,避免低精度 dtype 自身误差污染。
> 分母 `+1e-7` 仅为保险——正常域里 `|golden| >= sv_thr ≫ 1e-7`。

#### 4.2 三项通过条件(AND,全部满足才算通过)

1. **`max_error_cap`**:所有 finite 元素满足 `|diff| <= atol + rtol * |golden|`(dtype-aware,要求 100% 通过)
2. **`required_matched_ratio`**:`sum(matched) / total_finite >= 0.9`
3. **`MERE`**:对所有 finite 元素计算 `rel_err = |diff| / (|golden| + 1e-7)` 再取均值,要求 `MERE < rel_threshold`。当 `total_finite == 0` 时本项自动通过。

#### 4.3 阈值表

**matched_mask 与 MERE 阈值**(沿用 NPU Benchmark 标准):

| 数据类型 | small_value_threshold | small_value_error | rel_threshold (= MERE 上限) |
|---|---|---|---|
| `float16` | 2⁻¹¹ ≈ 4.88e-4 | 2⁻¹⁶ ≈ 1.53e-5 | 2⁻¹⁰ ≈ 9.77e-4 |
| `bfloat16` | 2⁻⁸ ≈ 3.91e-3 | 2⁻¹⁶ ≈ 1.53e-5 | 2⁻⁷ ≈ 7.81e-3 |
| `float32` | 2⁻¹⁴ ≈ 6.10e-5 | 2⁻³⁰ ≈ 9.31e-10 | 2⁻¹³ ≈ 1.22e-4 |
| `hifloat32` | 2⁻¹² ≈ 2.44e-4 | 2⁻²⁸ ≈ 3.73e-9 | 2⁻¹¹ ≈ 4.88e-4 |
| `float8_e4m3` | 2⁻⁴ = 0.0625 | 2⁻⁶ ≈ 0.015625 | 2⁻³ = 0.125 |
| `float8_e5m2` | 2⁻³ = 0.125 | 2⁻⁵ = 0.03125 | 2⁻² = 0.25 |
| 其他 dtype(fallback) | 2⁻¹⁴ | 2⁻³⁰ | 2⁻¹³ |

**max_error_cap 阈值**(`|diff| <= atol + rtol * |golden|`):

| 数据类型 | atol | rtol |
|---|---|---|
| `float16` | 9e-2 | 2⁻¹⁰ ≈ 9.77e-4 |
| `bfloat16` | 1e-1 | 2⁻⁷ ≈ 7.81e-3 |
| `float32` | 1e-3 | 2⁻¹³ ≈ 1.22e-4 |
| 其他 dtype(fallback) | 1e-3 | 2⁻¹³ |

### 5. 运行时诊断输出

verify.py 在每个 case 会向 stderr 打印:

- `[输入类型判定] 来源=...,候选 dtypes=...,最高精度=...,input_type=...`
- `[评测模式] 模式=...,输入 dtype=...,输出 dtype=...,误差要求=...`

便于上游 agent 立即看到当前 case 落入了哪一类、用了哪些阈值。

---

## 验证流程

```
Expand Down Expand Up @@ -123,14 +225,18 @@ python3 /path/to/kernel-verifier/scripts/verify.py \
| `--op_name` | 是 | 算子名称,与文件名前缀对应 |
| `--verify_dir` | 否 | 验证目录路径,默认当前目录 |
| `--triton_impl_name` | 否 | Triton 实现模块名(不含 `{op_name}_` 前缀),默认 `triton_ascend_impl` |
| `--timeout` | 否 | 超时秒数,默认 900 |
| `--timeout` | 否 | 超时秒数,默认 900(⚠️ 当前已忽略:脚本为同进程串行模式,未实现超时强制中止) |
| `--output` | 否 | 验证结果 JSON 输出路径,默认 `{verify_dir}/verify_result.json` |
| `--non-compute` | 否 | 适用于非计算类算子(不做数值运算、只对张量进行形状变换、维度重排、切分拼接、索引、类型转换等数据重组操作的算子,常见如 Reshape、Transpose、Concat、Split、Gather、Cast、Pad 等),强制走二进制完全一致判定 |

**超时设置**:默认 900 秒,复杂算子可适当增加
**超时设置**:`--timeout` 参数当前已忽略(同进程串行模式),保留仅为兼容旧调用方

**⛔ 禁止事项**:
**注意事项**:
- 禁止自己编写 Python 代码来测试算子(如手动 import 并 forward 比较)
- 禁止使用 `torch.allclose` 或其他自创方法替代 `scripts/verify.py`
- 禁止跳过此步骤直接报告验证结果
- 禁止对计算类算子(含数值运算)传 `--non-compute`;该开关仅适用于不做数值运算、只做形状变换 / 维度重排 / 切分拼接 / 索引 / 类型转换等数据重组操作的算子(如 Reshape、Transpose、Concat、Split、Gather、Cast、Pad)。误用会强制走二进制完全一致判定,把正常的浮点舍入差异判为失败
- 对非计算类算子(例如形状变换、维度重排、切分拼接、索引、类型转换等数据重组操作的算子)**一定要**传 `--non-compute`;漏传会让此类算子按浮点三项判定走,容许超出预期的差异,无法识别真正的位级不一致

---

Expand All @@ -157,13 +263,49 @@ verify.py 会在 `verify_dir` 下生成 `verify_result.json`(或 `--output`
}
```

**精度失败时的 `metrics` 字段**:当 `error_type == "AccuracyError"`(浮点三项判定未通过)时,`failures[*]` 会带上结构化 `metrics`,便于下游分类失败原因(max_error_cap 违例 / 离群点过多 / 平均误差偏大):

```json
{
"case_idx": 1,
"input_desc": [...],
"error_type": "AccuracyError",
"error_msg": "...",
"metrics": {
"matched_ratio": 0.95,
"max_abs_diff": 0.2,
"MERE": 2.0e-4,
"rel_threshold": 1.22e-4,
"small_value_threshold": 6.10e-5,
"small_value_error": 9.31e-10,
"atol": 1.0e-3,
"rtol": 1.22e-4,
"max_error_cap_violation_count": 12,
"required_matched_ratio": 0.9,
"total_finite": 1000,
"matched_count": 950,
"small_count": 0,
"normal_count": 1000,
"checks": {
"max_error_cap": false,
"required_matched_ratio": false,
"MERE": false
}
}
}
```

`checks` 三个布尔位标记每项判定是否独立通过。阈值定义见上文 §精度判定规则 §4。

非浮点类失败(`non_compute` / `bool_output` / `integer_compute` / `quant_fp_to_int`)的 `metrics` 字段较简单,含 `category` / `violation_count` / `total_*` 等基本计数。

**多 shape 行为**:每个 shape 独立 try/except,失败不中止后续 shape;全部跑完才落盘并退出。

**退出码语义(策略 A:严格)**:
- `passed_cases == total_cases` → exit 0,`verifier_result = true`
- `passed_cases < total_cases` → exit 1,`verifier_result = false`,`verifier_error` 应读取 `verify_result.json.failures` 的**全部条目**(不是第一个),汇总后提交给 Conductor。
- `passed_cases == total_cases` 且 `total_cases > 0` → exit 0,`verifier_result = true`
- 否则(`passed_cases < total_cases`,或 `total_cases == 0`)→ exit 1,`verifier_result = false`,`verifier_error` 应读取 `verify_result.json.failures` 的**全部条目**(不是第一个),汇总后提交给 Conductor。

**超时**:脚本输出 `"验证超时"` 且退出码为 1 → `verifier_error = "验证超时({timeout}秒)"`
**超时**:当前 `--timeout` 已被忽略,脚本不会主动中止;不会输出"验证超时"

---

Expand Down Expand Up @@ -325,43 +467,6 @@ benchmark.py 启动时按 `--triton_impl_name` 推导对应的 verify_result 文

---

## 精度阈值说明

验证使用基于数据类型的 **MERE/MARE 双门限相对误差**判定(NPU Benchmark 标准),与 `torch.allclose` 不同。

**判定公式**(必须同时满足):

```
MERE < threshold 且 MARE < 10 × threshold
```

其中:
- `MERE` = mean(|actual - golden| / max(|golden|, threshold)),平均相对误差
- `MARE` = max(|actual - golden| / max(|golden|, threshold)),最大相对误差
- 计算前两侧统一升 float32,避免低精度 dtype 自身误差污染
- 分母用 `clamp(min=threshold)` 而非 `+epsilon`:当 `|golden| < threshold`(参考值已小到 dtype 精度极限)时,rel_err 退化为 `|diff| / threshold`,等价于按绝对误差归一化,避免零值/极小值附近误报

**dtype 阈值表**(2 的幂次方):

| 数据类型 | threshold | MERE 上限 | MARE 上限 (10×t) |
|---------|-----------|-----------|------------------|
| `float16` | 2⁻¹⁰ ≈ 9.77e-4 | 9.77e-4 | 9.77e-3 |
| `bfloat16` | 2⁻⁷ ≈ 7.81e-3 | 7.81e-3 | 7.81e-2 |
| `float32` | 2⁻¹³ ≈ 1.22e-4 | 1.22e-4 | 1.22e-3 |
| `hifloat32` | 2⁻¹¹ ≈ 4.88e-4 | 4.88e-4 | 4.88e-3 |
| `float8_e4m3` | 2⁻³ = 0.125 | 0.125 | 1.25 |
| `float8_e5m2` | 2⁻² = 0.25 | 0.25 | 2.5 |
| 其他 dtype(fallback) | 2⁻¹³ | 1.22e-4 | 1.22e-3 |

**比对前置检查**(按顺序,任一失败即判 fail):
1. 形状必须一致
2. NaN 位置必须完全一致(mask 按位相等)
3. Inf 位置和符号必须完全一致
4. `bool` dtype:要求 `torch.equal` 完全相等,不进入 MERE/MARE 判定
5. 仅在 `finite_mask` 上做 MERE/MARE 计算;当 dtype 不一致时 impl 会被 cast 到 golden 的 dtype

---

## 脚本位置

验证脚本位于本 skill 的 `scripts/` 目录:
Expand All @@ -374,5 +479,5 @@ MERE < threshold 且 MARE < 10 × threshold

**CLI 参数**:
- `validate_triton_impl.py`: `<file_path>`, `[--json]`
- `verify.py`: `--op_name`, `--verify_dir`, `--triton_impl_name`, `--timeout`, `--output`
- `verify.py`: `--op_name`, `--verify_dir`, `--triton_impl_name`, `--timeout`, `--output`, `--non-compute`
- `benchmark.py`: `--op_name`, `--verify_dir`, `--triton_impl_name`, `--warmup`, `--repeats`, `--output`, `--skip_framework`, `--framework_latency_ms`, `--verify_not_required`
Loading