PyPTO-Gym 算子布局与结构校验:pypto-op-lint 门禁规则全解与实战
2026/9/19 6:57:52 网站建设 项目流程

PyPTO-Gym 算子布局与结构校验:pypto-op-lint 门禁规则全解与实战

【免费下载链接】pypto-gymPyPTO-Gym 是基于 PyPTO 编程框架构建的算子与模型样例仓库项目地址: https://gitcode.com/cann/pypto-gym

导读

本文围绕 CANN / pypto-gym 仓库中 pypto-op-review 技能族的 CI 设计展开:针对custom/<operator_name>/目录下的算子工程(MEMORY.md、test_<op>.py、分阶段*_module*_impl.py命名、kernel 代码中禁止 Python 循环、view-rank 一致性、cube-tile 合法性、精度比对 helper 等)的布局与结构约束,已全部由 pypto-op-lint hooks 自动强制校验,不再需要单独的 layout 脚本。读完本文,你将掌握 lint 的触发时机(文件写入即时拦截 + 阶段/阶段门禁)、完整规则映射表与rules.json注册表语义、S0/S1 阻塞机制与修复流程,以及如何使用 CLI 手动检查与extract_pypto_calls.py做逐算子调试。


一、背景:从"独立 layout 脚本"到"lint 规则"

在早期版本中,custom/<operator>/的目录布局和文件结构靠一个独立脚本在阶段结束后被动检查;而现在,这些检查被前置并自动化,成为pypto-op-lint hooks的一部分(见 CI.md 开头声明):

Layout and structure rules … are enforcedautomatically by the pypto-op-lint hooks— there is no separate layout script to run.

这意味着:

  • 无需手动运行任何 "layout check" 命令;
  • 约束内嵌于 Agent 的每次文件写入与每个阶段门禁中;
  • 违反规则会当场阻断,而不是留到验收阶段才暴露。

pypto-op-lint 的实际实现位于 pypto-op-lint 插件 下,包含rules.json规则注册表、pypto_op_lint/包(core.py/hooks.py/cli.py/infer.py/checks/等)以及一个向后兼容入口 pypto_op_lint.py。rules.jsonversion字段当前为2.0.0


二、门禁如何触发(How it fires)

根据 CI.md 与 hooks.py 的实现,lint 在两个层面触发:

2.1 每次文件写入:PostToolUse[Write|Edit]

  • 当 Agent 写入或编辑*_impl.pytest_*.py等目标文件时,hook_post_edit会按文件类型运行对应规则集:
    • *_impl.py→ impl 规则(如 OL01–OL08、OL48、OL52、OL57 等);
    • test_*.py→ test 规则(如 OL17–OL22、OL42、OL60)。
  • 若命中S0/S1 级别的 FAIL,hook 返回decision="block"在带内(in-band)拦截本次写入,需要修复后重新 Write/Edit同一个文件
  • 该"产物生成即阻断"模式由环境变量PYPTO_OP_LINT_POST_EDIT_BLOCK(默认"1")控制,见 core.py。
  • 特殊保护:.orchestrator_state.json不允许直接写入(须用state_transition工具);Stage 1 完成后SPEC.md冻结,仅放行"只减少 front mattersupported_dtypes"的收敛性修订。

2.2 阶段 / 阶段门禁:complete_phase / complete_stage / stop

  • complete_phase(Stage 5 内,如M1/M2)触发phase 门禁:仅扫描当前 phase 对应的累积模块 impl(modules/<op>_module1_impl.py等),并额外检查 MEMORY.md 的Phase M_k self-review(OL53/OL54),见 cli.py 的 cmd_check_phase_gate。
  • submit_design(Stage 4,Architect 产出 DESIGN.md 后、Verifier 启动前)触发design 门禁:只跑 OL12 / OL55 / OL56,防止因 DESIGN.md 中的 typo 或不存在 API 导致 Verifier 工作作废。
  • stop(Agent 结束前)触发交付门禁hook_stop:按当前 stage 汇总全部适用规则做跨文件一致性复查,存在 S0/S1 错误级违规即decision="block"并返回非零码。

从源码结构看,checks/目录下按维度组织检查器实现(d1_framework.pyd1_pypto_api.pyd2_artifact.pyd3_separation.pyd4_test_spec.pyd5_consistency.py),并有tests/下的测试(如test_hook_integration.pytest_stage7_impl_gates.pytest_stop_gate_strict_mode.py)验证 hook 行为。


三、规则映射表(原 layout 脚本的替代)

以下是原独立 layout 脚本承担的检查与现 lint 规则 ID 的完整映射(继承自 CI.md,可直接作为审查速查表):

Check(检查项)Lint rule(规则 ID)
test_<op>.py存在(三件套)OL13 / OL44
Test 使用assert_allclosedetailed_tensor_compareOL19
每个 active phase 的 staged module 三件套OL44
Host wrapper 不得用for ... in range(...)驱动 kernelOL45
JIT 图内只允许pypto.loop/pypto.loop_unroll/range(...)OL57
pypto.viewrank 一致性(不是 reshape)OL52
set_cube_tile_shapes的 m/k/n 为[L0, L1]0<L0<=L1L1%L0==0;tile 参数是字面量OL48
动态轴迭代必须存在pypto.loopOL23 / OL43

完整规则注册表见 rules.json。


四、规则注册表 rules.json 详解

rules.json是 lint 的单一事实来源,每条规则包含idseverity(S0–S3)、dimension(D1–D5)、fix_effort(E1–E3)、stages(适用的阶段 1–7)、targetimpl/test/golden/gate)与规则描述。规则按五个维度组织:

D1 框架约束合规(kernel/impl 代码本身)

规则级别语义
OL01S0kernel 函数必须有且仅有一个@pypto.frontend.jit装饰器(禁止一切别名写法,如@pt.frontend.jit@jit
OL02S1输出写回必须用[:]/move()/assemble(),禁止out = expr
OL03S1kernel 函数不能有return语句
OL04S1JIT 入口及其同文件可达的 Layer I/H helper 必须调用set_vec_tile_shapesset_cube_tile_shapes(允许 JIT 入口一行委托)
OL05S1kernel 张量参数必须有pypto.Tensor类型注解
OL06S1kernel 内禁用 Python 原生min()/max()(改用pypto.minimum/maximum
OL07S0impl 文件只能使用正规import pypto,禁止 alias、import pypto.frontend as ...、from-import
OL08S1wrapper 函数必须导出且以_wrapper结尾
OL23S2impl 应显式说明是否需要 loop;未检测到 loop 结构时提醒
OL25S1Tensor 注解禁止空注解:pypto.Tensor()/pypto.Tensor([], dtype)一律 FAIL;只缺 dtype 时 WARN
OL26S1JIT 函数中张量参数必须在非张量参数之前
OL28S2sigmoid/softmax/sin/cos仅支持DT_FP32,非 FP32 时警告
OL29S2Tensor 注解 shape 中应声明pypto.DYNAMIC/pypto.DYN维度
OL37S3design 与 impl 的关键中间变量命名应可追溯(重合较少时提示)
OL45S0Layer K(host wrapper)不得包含for ... in range(...)逐 chunk 驱动 kernel;chunking 属于_kernel_impl内的pypto.loop(N)+pypto.viewoffsets
OL46S2同作用域内仅允许一个pypto.loop(N);冗余的pypto.loop(1)包裹内层pypto.loop(N)被禁止
OL47S3_kernel_impl调用 2+ 个pypto_*子 kernel 时,优先在每个子 kernel 内设置 tile shapes(分阶段局部 tile)
OL48S0tile 参数必须是编译期可知的 Python int 字面量或可解析到字面量的常量 Assign;set_cube_tile_shapes的 m/k/n 每轴必须为 2 元素 list[L0, L1]0<L0<=L1L1%L0==0
OL49S1unroll_list只能出现在最内层pypto.loop/pypto.loop_unroll(避免编译路径爆炸或寄存器拷贝精度异常)
OL52S1pypto.view的 shape / offsets / valid_shape 必须同 rank(view 是同 rank 的 sub-view 抽取,不是 reshape)
OL55S0禁止使用 PyPTO 中不存在的pypto.<attr>(对比 AST 属性访问与dir(pypto),防止 typo 如pypto.empty
OL56S0Stage 6 之前unroll_list只能含单一值(默认[1]);多值展开调优仅允许 Stage 7
OL57S0JIT 图内只允许pypto.loop/pypto.loop_unroll/for ... in range(...),禁止while和非 range 的 Pythonfor(及含 pypto 算子的推导式)
OL58S0Layer K wrapper 内禁止调用pypto.zeros/empty/ones/full(JIT-context creation API 在 host 调用会 runtime crash);output buffer 必须用torch.empty/zeros/empty_like预分配后作为参数传入 JIT 入口
OL61S1Experience Preflight 门禁(MEMORY.md 检查 + AST 扫描 4 类反模式:F4 非法 cast 路径 / F2 Element 双重包装 / F1 scalar 首参 / F8 zeros dtype 位置错误)
OL62S0impl 内 torch 仅限 layout/alloc/cast/reshape;任何 torch 张量算术(torch.matmul/.exp/.sum/@/F.*)即 FAIL,封堵 dummy-JIT(dead JIT + host torch 等作弊模式)

D2 工件完整性与流程合规(文档/交付物与阶段依赖)

规则级别语义
OL09S1Stage 1:SPEC.md 结构化章节校验 + front matter schema 校验(p0_shapes / supported_dtypes / tolerance)
OL10S1Stage 1:API_REPORT.md 结构化章节校验(API 映射、约束、Tiling)
OL11S2Stage 2:{op}_golden.py必须可导入(作为精度基线)
OL12S1Stage 3/4:DESIGN.md 结构化章节校验(计算图、Tiling、验证方案)
OL13S1Stage 5:集成成品三件套完整({op}_impl.pytest_{op}.pyREADME.md
OL14S1进入 Stage 6 需 Stage 5(含 cleanup)已完成
OL24S1.orchestrator_state.json结构合法
OL39S1strict 模式下文档必须包含 front matter
OL40S1strict 模式下 front matter 必填字段必须完整
OL41S1代码工件禁止包含 lint/门禁输出文本污染
OL44S1Stage 5 active Phase M_k 要求modules/<op>_module<suffix_k>_impl.py+_golden.py+test_*三件套
OL53S2MEMORY.md Golden function inventory 所有行须标记 Status ✅(complete_stage 严格判定)
OL54S1complete_phase 时 MEMORY.md 须含## Phase M_k self-review章节,6 个必须项(signature 一致 / output 写出 / view rank / inventory 更新 / 无 for-range / JIT exactly once)全部- [x]
OL59S1Stage 2 完成时 GOLDEN_PERF_REPORT.md 必须存在且含 Op Performance section(由profile_golden.py§15 生成)

D3 三文件分离(golden / impl / test 职责隔离)

规则级别语义
OL15S1golden 文件须为纯 torch 规范化实现:禁止import pypto,禁止.T/.t()(须用torch.transpose
OL16S1impl 文件不应导入 golden 模块
OL17S1test 文件不应包含 kernel 实现代码
OL18S1test 文件必须从 impl 和 golden 分别导入

D4 测试规范

规则级别语义
OL19S1test 必须使用assert_allclosedetailed_tensor_compare做精度比对,禁止手写assert max_diff
OL20S1test 必须处理TILE_FWK_DEVICE_ID环境变量并调用set_device
OL21S2test 必须有 Level 0 与 Level 1 两级测试函数(_l0/level0_l1/level1子串判定)
OL22S2test 应设置torch.manual_seed保证可复现
OL42S1NPU 环境可用时禁止硬编码 sim 模式(default='sim'run_mode='sim'
OL60S0test 实际调用的入口在可达调用链中必须到达至少一个@pypto.frontend.jit函数(防"测试绕过 @jit 走纯 PyTorch 入口")

D5 跨文件一致性(spec / design / impl / test / golden 对齐)

规则级别语义
OL30S2spec 声明支持的 dtype 必须在测试文件中覆盖
OL31S1design 动态轴声明须与 impl Tensor 注解中的 DYNAMIC 一致
OL32S2spec 的 atol/rtol 须与 test 文件一致
OL33S2golden 与 wrapper 的必需参数数量一致
OL34S1spec 的 P0 测试配置 shape 须在 test 中覆盖
OL43S1DESIGN.md 声明动态轴时,相关 impl 的 jit 函数必须包含真实pypto.loop(硬性门禁,不得因 NPU 运行通过而跳过)
OL50S1Layer K wrapper 显式参数必须与eval/module_interfaces.yaml的 primary_inputs 顺序一致;生产 ABI 不暴露 runtime/debug 参数
OL51S1输出数 N 须有 N 个真实写出点(pypto.assemble/out.move/out[:]=),且输出不得是平凡 pass-through
OL62S0见 D1(跨维度封堵 dummy-JIT)

更精简的按维度速查表(含规则语义一句话版)可参考 lint-gate-rules.md,其中还特别说明了 OL21 的测试级别命名坑、supported_dtypes语义(只算 P0 输入/输出 tensor dtype,权重 buffer 与中间计算 dtype 不算)以及{op}_pypto_impl.py桥接文件豁免规则。


五、阻塞行为与修复流程

5.1 S0/S1 FAIL 立即阻断

在 hooks.py 中:

  • _split_findings将 findings 分为 FAIL / error_fails(S0、S1)/ WARN / INFO;
  • post-edit 命中 error_fails 时,_blocking_reason生成包含违规文件:行号、blocking_rules列表与fix_hints的阻断消息,明确要求:

    "read the fix_hints above → fix the violations pointed out by file:line → re-run Write/Edit on the [same file]. Do not use bash to bypass lint, do not move files to another path."

  • stop 门禁命中错误级违规时返回 exit code 2,并要求修复后继续。

5.2 修复提示示例

常用规则的内置修复提示(_rule_fix_hint):

  • OL01:装饰器必须原样写作@pypto.frontend.jit(或@pypto.frontend.jit(...)),每个 impl 恰好一个;别名形式@pt.frontend.jit@F.jit@frontend.jit@jit全部拒绝。
  • OL02:输出写回用y[:] = expr/pypto.move()/pypto.assemble()
  • OL05/OL25:张量参数带完整注解,如pypto.Tensor([N, M], pypto.DT_FP32)
  • OL26:参数必须张量在前、标量在后。
  • OL34:在 SPEC.md front matter 的p0_shapes填写 P0 形状并在 test 覆盖,格式如[[1024,128]][{x: [4,2560]}](value 必须是 list)。

六、手动运行 lint 检查(CLI)

虽然日常流程中 lint 由 hook 自动触发,但 cli.py 也暴露了手动子命令,便于在算子工作区(op-dir)内随时复查:

# 检查 impl 文件(D1 框架约束 + impl 相关规则) python3 -m pypto_op_lint --lint-impl --op-dir custom/<operator_name> --stage 5 # 检查 golden 文件(OL15) python3 -m pypto_op_lint --lint-golden --op-dir custom/<operator_name> --stage 5 # 检查 test 文件(D4 测试规范) python3 -m pypto_op_lint --lint-test --op-dir custom/<operator_name> --stage 5 # 检查跨文件一致性(D5) python3 -m pypto_op_lint --lint-consistency --op-dir custom/<operator_name> --stage 5 # 检查当前 stage 的完整门禁 python3 -m pypto_op_lint --check-gate --op-dir custom/<operator_name> --stage 5 # Stage 5 phase 门禁(只扫描当前 phase 累积模块 impl) python3 -m pypto_op_lint --check-phase-gate --op-dir custom/<operator_name> --phase M1 --stage 5 # Stage 4 design 门禁(Architect 之后、Verifier 之前) python3 -m pypto_op_lint --check-design-gate --op-dir custom/<operator_name> --stage 4

其中--stage默认值为 5,--check-design-gate未显式给 stage 时会自动按 4 处理。任一命令存在 S0/S1 错误级 FAIL 时以 exit code 2 结束;_has_error_fail的判定逻辑见 core.py。规则分组(IMPL_RULE_IDS/GOLDEN_RULE_IDS/TEST_RULE_IDS/CONSISTENCY_RULE_IDS)同样定义在 core.py。


七、配套调试工具:extract_pypto_calls.py

除了自动化布局校验,pypto-op-review 还提供一个逐算子 PyPTO 调用点提取工具extract_pypto_calls.py,用于定位 kernel 中每个pypto.*调用位置,配合 lint 规则做行级调试:

python3 cannbot-skills/ops/pypto-op-review/scripts/extract_pypto_calls.py \ custom/<operator_name>/<kernel_file>.py # JSON lines 输出(每行一个调用点,便于脚本消费) python3 cannbot-skills/ops/pypto-op-review/scripts/extract_pypto_calls.py \ custom/<operator_name>/<kernel_file>.py --json

该工具基于 AST 分析(不执行代码):

  • 先收集import pypto(含import pypto as p别名)与from pypto import matmul等短导入;
  • 再遍历所有ast.Call节点,解析属性链(如pypto.matmul(...)pypto.frontend.jit(...)p.view(...)),记录linecolcall表达式与调用种类(attr/short_import);
  • 默认按行号:列号排序输出L<line>前缀的清单,便于对照源码逐行审查算子实现是否符合 OL02/OL04/OL48/OL52/OL57 等规则。

该脚本也被 pypto-orchestration-manual 的 rules.md 与 pypto-general-debug 参考文档引用为 op-by-op 调试的通用手段。


八、工程实践小结

  1. 把 lint 当编译器:post-edit 的 S0/S1 阻断相当于"写错即报错",修复应在原文件上完成,不要用 bash 绕过或迁移文件路径。
  2. 理解文件类型分流:impl / test / golden / gate 规则集不同,*_pypto_impl.py(纯 torch 桥接)与test_*不要误用 kernel 规则。
  3. 动态轴必须有 loop:OL23 / OL43 / OL57 联动,DESIGN.md 声明 dynamic_axes 后,kernel 内必须有真实的pypto.loop遍历,且图内禁止while与非 range 的for
  4. tile 与 view 是最常见的 S0/S1 雷区set_cube_tile_shapes的 m/k/n 必须是[L0, L1]字面量且满足L1 % L0 == 0pypto.view的 shape/offsets/valid_shape 必须同 rank。
  5. 跨文件一致性靠门禁兜底:dtype、动态轴、容差、P0 shape、golden 与 wrapper 参数数量,全部需要在 spec/design/impl/test/golden 之间对齐,靠--check-gate/ stop 门禁统一收口。

最终规则清单以 rules.json 为准;需要快速查阅某条[OLxx][Sx]的语义时,可先查 lint-gate-rules.md,再回到 rules.json 看完整的stages/target/fix_effort元数据。

【免费下载链接】pypto-gymPyPTO-Gym 是基于 PyPTO 编程框架构建的算子与模型样例仓库项目地址: https://gitcode.com/cann/pypto-gym

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询