feat(rocm): add shape-based AITER FMoE tuning - #1345
Conversation
LLLLKKKK
left a comment
There was a problem hiding this comment.
AI Code Review - PR #1345
Status: BLOCKING
Summary: P0/0 · P1/2 · P2/14 · P3/5
Reviewed: commit 7e74c6aab4b0 · 2026-08-28 17:24 UTC+8
Blocking Issues
P1
_moe_activation_type未覆盖ActivationType.Swiglu,新增 fail-closed 守卫在所有生产 MoE 模型上恒不触发 @rtp_llm/models_py/modules/factory/fused_moe/impl/rocm/executors/rocm_moe.py:41- 建议:改为显式映射表并补入
"swiglu"/"gated-silu"→Silu,未知取值raise ValueError而非静默落到Gelu(该 fallback 会同时污染 signature 与真实 kernel 选择);键建议取getActivationTypeStr之类的规范名,不依赖 pybind enum 的.name/__str__。更根本地让守卫与 dispatch 共用同一来源:把act_type下移到execute()用实参补齐后再校验,或在__init__断言config.activation_type与execute()收到的activation归一化结果一致。同时给require_aiter_fmoe_tuning的 fail-open 分支加一条 debug 日志(打印实际 signature),本条问题若有此日志本可在自测阶段暴露。注意:本条修复后下一条的启动崩溃风险将从潜伏转为现实,两者需一并处理。
- 建议:改为显式映射表并补入
- 未证明 provision 就绪的 ROCm MTP smoke suite 被并入主 CI 聚合 suite,阻塞说明被同时删除且与本 PR 主题无关 @
rtp_llm/test/smoke/BUILD:78- 建议:拆分为独立变更:本 PR 只保留 kernel tuning 相关内容。若确认 checkpoint 已在共享 ROCm worker 就位,请在 PR 描述或注释中给出可核验依据(provision 记录或一次包含该 suite 的绿色 CI run),再单独提交
maga_model_smoke的成员变更并单跑一次 ROCm CI;否则回退第 78 行的 suite 成员变更并还原原注释中记录的阻塞原因,不要以「改注释」代替「解除阻塞」。
- 建议:拆分为独立变更:本 PR 只保留 kernel tuning 相关内容。若确认 checkpoint 已在共享 ROCm worker 就位,请在 PR 描述或注释中给出可核验依据(provision 记录或一次包含该 suite 的绿色 CI run),再单独提交
Non-blocking Suggestions
P2
- aiter 版本精确全等匹配叠加加载期硬 raise,无降级与运维逃生通道,且与仓内既有约定相反 @
rtp_llm/models_py/kernel_tuning/aiter/fmoe.py:192- 建议:改用与
fp8_ptpc_linear.py一致的版本 prefix 匹配(去掉.dYYYYMMDD段),并抽出共用的 aiter 版本/arch 判定工具消除两份实现;内容兼容性已由 sha256 与 dispatch key 冲突检测覆盖,版本号可放宽为最小兼容区间。同时提供显式运维开关(如require|warn|off三态,默认require),warn/off退化为 ERROR/WARNING + 继续启动,把「强制复核」诉求放在 CI 断言而非线上启动路径。注意两点耦合:一是修复上一条后本路径才会被生产流量真正命中(当前受 signature 判定门控,生产恒不可达,故本条按 P2 处理);二是放宽版本匹配会同时移除下一条 glob 重建的唯一门控,必须同步加固。若确实保留硬失败,请在 PR description 与错误信息中写明这是有意的部署闸门及其回滚手段。
- 建议:改用与
- 启动期用 glob 重建的列表整体覆写
AITER_CONFIG_FMOE,波及进程内所有 gfx942 MoE 负载且最终清单无日志 @rtp_llm/models_py/kernel_tuning/aiter/fmoe.py:259- 建议:优先读取 aiter 自身暴露的默认配置集合再追加 overlay,而不是重建;若确实只能重建,补一条在 pinned 版本下断言「重建集合 ⊇ aiter 默认解析结果」的 ROCm 门控测试,让上游改名/移动由测试而非线上行为暴露。同时把
_LOGGER.info升级为打印最终生效的完整AITER_CONFIG_FMOE清单(含 stock 文件数量),便于线上核对实际生效的 dispatch 表;并考虑把 env 写入从「启动期按 arch 无条件执行」收敛为命中受影响 signature 后再配置(该时机仍早于首次前向)。若采纳上一条放宽版本匹配的建议,本条必须同批落地,否则将失去唯一保护。
- 建议:优先读取 aiter 自身暴露的默认配置集合再追加 overlay,而不是重建;若确实只能重建,补一条在 pinned 版本下断言「重建集合 ⊇ aiter 默认解析结果」的 ROCm 门控测试,让上游改名/移动由测试而非线上行为暴露。同时把
- stock 与 overlay 两条 CSV 解析路径重复实现,且
_tag过滤语义不对称可致误判 dispatch 冲突 @rtp_llm/models_py/kernel_tuning/aiter/fmoe.py:114- 建议:抽出单一的
_read_dispatch_keys(config, *, exclude_tagged: bool)供两处复用,并让 stock 侧与 overlay 侧对_tag采用同一语义(按代码注释所述,两侧都应排除 tagged 行);补一个「stock 含 tagged 同 key 行不应判为冲突」的用例固化该语义。若刻意保留 stock 侧的保守策略,请在代码注释中写明「宁可误判也不放过」的取舍及其对启动失败的影响。
- 建议:抽出单一的
- 启动期可选性能 overlay 未做 fail-open 保护,其 IO 异常会击穿全部 rank 启动,与 registry 的 warn-only 契约矛盾 @
rtp_llm/start_backend_server.py:92- 建议:二选一:(1)在调用点按同文件 JIT 缓存的既有范式包一层
try/except Exception+logging.exception(...)后继续启动,注意不要捕获BaseException以免吞掉启动窗口内的KeyboardInterrupt;(2)把_sha256、locate_file、_stock_fmoe_configs与 metadata 异常纳入已有的except (OSError, ValueError),使configure_kernel_tuning在契约上保证不抛异常。同时建议在第 92 行补一行注释,说明该位置承载的两个隐式时序不变量(必须在设备设置之后、任何 aiter 导入与BackendManager构造之前)及其失效后果,并指向jit_cache_manager_test.py:1085已锁定的顺序断言。
- 建议:二选一:(1)在调用点按同文件 JIT 缓存的既有范式包一层
- 新增数值测试重复施加 gate/up 重排相互抵消,且
moe_s2旁路 shuffle,未复现注释声称的生产权重 layout @rtp_llm/models_py/modules/factory/fused_moe/impl/rocm/test/rocm_fp8_fused_moe_test.py:278- 建议:去掉第 278-291 行的手工交换,直接把 checkpoint 顺序的张量交给
shuffle_moe_weight完成唯一一次交换(与生产_postprocess一致),并把参考值改为按交换后的[gate, up]语义构造,使半区顺序不一致时断言能够失败;同时让W.moe_s2也走一遍shuffle_moe_weight,与ffn_weight.py的四路一致处理对齐(当前对 float32 scale 是 no-op,但可避免后续语义漂移);修正或删除那句已不成立的注释。
- 建议:去掉第 278-291 行的手工交换,直接把 checkpoint 顺序的张量交给
- 新增数值用例把宿主 gfx/CU 指纹硬编码为断言,非目标机型硬失败而非跳过 @
rtp_llm/models_py/modules/factory/fused_moe/impl/rocm/test/rocm_fp8_fused_moe_test.py:322- 建议:在该用例开头按
gcnArchName与multi_processor_count做前置SkipTest(附「该 overlay 仅针对 gfx942/80CU」的说明),使非目标卡上是明确跳过而非失败;目标卡上保留该硬断言并补上包含实际算出 signature 的 assert message,使机型不匹配与逻辑回归两种失败可区分。同目录rocm_mxfp4_fused_moe_test已有tags=["rocm_gfx950","manual"]+ 注释的成熟约定可参考。
- 建议:在该用例开头按
aiter_fmoe_test漏掉 sha256 漂移、aiter 未安装、配置缺失等关键 fail-closed 分支 @rtp_llm/models_py/kernel_tuning/test/aiter_fmoe_test.py:72- 建议:为各分支各补一个用例:构造 sha 不一致的 default config 并断言
applied is False且 reason 含预期关键字;令 distribution 抛PackageNotFoundError;分别删除 default config 与 overlay;放入一个untuned_fmoe.csv验证被过滤;再补一条AITER_CONFIG_FMOE已含 overlay 的成功用例,断言applied is True且环境变量保持原值不被覆写。
- 建议:为各分支各补一个用例:构造 sha 不一致的 default config 并断言
- bundled overlay 断言退化为「不抛异常」,CSV 真正决定选核的调优列无任何校验 @
rtp_llm/models_py/kernel_tuning/test/aiter_fmoe_test.py:190- 建议:把该用例改为直接读取
_OVERLAY_CONFIG:断言 header 逐字符等于期望的 26 列 schema,并逐行断言block_m、ksplit、run_1stage、kernelName2与常量化的kernelName1;行数/键集一致性可继续依赖_validated_overlay_dispatch_keys的异常路径。另建议在 aiter 可 import 时把 overlay header 与 stocktuned_fmoe.csv的 header 做集合比对并纳入校验,让上游列漂移走既有 fail-closed 路径而非被DictReader静默吞掉。
- 建议:把该用例改为直接读取
registry_test未覆盖所有 CUDA/CPU 部署必经的非 ROCm no-op 路径,也未断言真实 provider 表 @rtp_llm/models_py/kernel_tuning/test/registry_test.py:12- 建议:补四条用例:
torch.cuda.is_available()为 False、torch.version.hip is None、get_device_properties抛异常时_current_rocm_arch()均返回 None 且不向上抛;非 ROCm 环境下不传参调用configure_kernel_tuning()返回空 tuple、不调用任何 provider 且不产生环境变量副作用。再补一条不带clear=True的断言,验证真实_PROVIDERS_BY_ARCH含gfx942且指向configure_aiter_fmoe_overlays。
- 建议:补四条用例:
- 测试用
RocmImpl.__new__构造半初始化 device 对象绕过生产构造路径 @rtp_llm/models_py/modules/factory/fused_moe/impl/rocm/test/rocm_fp8_fused_moe_test.py:252- 建议:改为通过仓内既有 device 获取入口拿到真实
RocmImpl实例;若构造代价过高,则改用注入最小py_env_configs的 fixture 显式补齐被依赖属性并注明该约束,避免留下一个随内部实现调整即崩的半初始化对象。
- 建议:改为通过仓内既有 device 获取入口拿到真实
- 新增测试 fixture 用非生产取值
activation_type="silu",掩盖生产 SiGLU 分歧使断言恒为通过 @rtp_llm/models_py/modules/factory/fused_moe/impl/rocm/test/rocm_fp8_fused_moe_test.py:126- 建议:把
_make_config_adapter的activation_type提升为参数,用subTest/参数化同时覆盖"silu"与"SiGLU",并要求assertTrue(is_affected_aiter_fmoe_signature(...))至少在"SiGLU"这一生产取值下通过;另补一条_moe_activation_type的纯函数用例,参数化覆盖"SiGLU"/ActivationType.Swiglu/"silu"/ActivationType.Silu/"gelu"。这样修复映射后即获得回归保护,且未来 fixture 与生产取值再次漂移会被立即发现。
- 建议:把
- 调优表全部性能与误差列为 0 占位值,调优结论不可追溯且
err1=0.0%是未经测量的正确性声明 @rtp_llm/models_py/kernel_tuning/aiter/configs/gfx942_cu80_fmoe_m1_16_h2048_i128_e256_topk8_bf16_fp8pt.csv:2- 建议:二选一:(1)回填 AITER 调优脚本产出的真实
us1/us/tflops/bw/err1;(2)保留 0 占位,但把无法在 CSV 格式内表达的 provenance 落到configs/下的 README 或AITER_FMOE_GFX942_OVERLAY常量旁的注释,至少记录调优机型与 CU 数、复现命令与版本、baseline 与 overlay 的 us/tflops 对比、误差判定口径与重新生成步骤。无论哪种方式,都建议把err1从0.0%改为真实值或留空,避免在数据文件里留下伪造的精度结论。
- 建议:二选一:(1)回填 AITER 调优脚本产出的真实
- token 覆盖仅到 16 且只有 2 的幂桶,桶间与桶外 token 的选核语义未记录也未覆盖 @
rtp_llm/models_py/kernel_tuning/aiter/configs/gfx942_cu80_fmoe_m1_16_h2048_i128_e256_topk8_bf16_fp8pt.csv:2- 建议:明确并在
_AFFECTED_TOKEN_BUCKETS处注释 AITER 对token列的解析语义(精确匹配/向上取整/向下取整)及适用上界与截断理由:若为精确匹配,补齐连续 token 行或写明非桶 token 会回落到 stock 选核;若为向下取整,建议补一行 token=32(沿用 AITER 原表在该点的选择)作为显式上边界,避免 overlay 影响范围超出实际调优区间。同时在rocm_fp8_fused_moe_test.py:329的 token 参数中补一个非桶取值(如 3 或 12)作为边界用例。
- 建议:明确并在
- signature 构造 helper 名称通用但写死量化语义,且
q_dtype_a用权重 dtype 代理激活量化 dtype @rtp_llm/models_py/modules/factory/fused_moe/impl/rocm/executors/rocm_moe.py:46- 建议:把
quant_type、doweight_stage1与激活量化 dtype 提升为显式入参由调用方传入,或将函数重命名为_per_token_fp8_workload_signature并加断言明确适用范围;q_dtype_a建议取真实的激活量化 dtype(如self.quant_config.quant_dtype,rocm_moe.py:223 已设置)而非复用w1.dtype,避免二者未来分叉时静默失配。
- 建议:把
P3
configure_aiter_fmoe_overlays自身无 arch 自检,作为公共 API 可在非 gfx942 上装入 gfx942 调优行 @rtp_llm/models_py/kernel_tuning/aiter/fmoe.py:178- 建议:在
configure_aiter_fmoe_overlays入口增加一次 arch 自检(与_AFFECTED_WORKLOAD_SIGNATURES中的gfx取值比对,不匹配则返回 not-applied 而非写 env),使该函数脱离 registry 单独调用时同样安全;或收窄导出面,仅由 registry 内部调用。
- 建议:在
- dispatch key 依赖第三方枚举的
__str__表示,且该假设未被任何断言固化 @rtp_llm/models_py/modules/factory/fused_moe/impl/rocm/executors/rocm_moe.py:62- 建议:在
aiter_fmoe_test.py中补一条断言(aiter 不可用时跳过),固化str(aiter.ActivationType.Silu) == "ActivationType.Silu"、str(aiter.QuantType.per_Token) == "QuantType.per_Token",使 Python 或 aiter 升级导致的表示变化在测试而非线上暴露。
- 建议:在
- 测试手工复刻生产 fp8 e4m3fn→fnuz 转换并遗漏 gfx950 分支 @
rtp_llm/models_py/modules/factory/fused_moe/impl/rocm/test/rocm_fp8_fused_moe_test.py:59- 建议:直接调用
runtime_device.convert_fp8_weight_params(wq, scale)复用生产实现,删除测试内的手写位级转换,使 gfx950 分支与后续改动自动被覆盖。
- 建议:直接调用
- gcnArchName 解析惯用法再次复制,仓内已有多份不一致实现 @
rtp_llm/models_py/kernel_tuning/registry.py:21- 建议:抽出统一的
current_rocm_arch()工具函数(放在rtp_llm/device或 ROCm 侧公共 utils)供各处复用;本 PR 至少让新增的两处共用同一实现,并可与上文 aiter 版本判定工具的抽取一并处理。
- 建议:抽出统一的
tp_size外层循环使重型 GPU 子用例翻倍但不增加鉴别力 @rtp_llm/models_py/modules/factory/fused_moe/impl/rocm/test/rocm_fp8_fused_moe_test.py:307- 建议:把第 329-357 行的数值子用例提到
tp_size循环之外只跑一遍;tp_size循环内只保留第 308-322 行的 config/signature 构造与断言,用于表达「signature 与 TP 无关」这一设计意图,从而在保留意图的同时把重型子用例减半。
- 建议:把第 329-357 行的数值子用例提到
Checklist Findings (18 fail / 55 total)
General Principles Checklist
- [6.1] Architecture — 兼容性:外部 HTTP/RPC API、持久数据、配置、环境迁移安全 → issue
dispatch key 依赖第三方枚举的str表示,且该假设未被任何断言固化
signature 的act_type/q_type由str(_moe_activation_type(...))、str(aiter.QuantType.per_Token)生成(rocm_moe.py:62、66),并与 CSV 及_AFFECTED_WORKLOAD_SIGNATURES中的字面量"ActivationType.Silu"、"QuantType.per_Token"做字符串相等比较。这一相等关系完全依赖第三方枚举的__str__行为:若其为IntEnum,在 Python 3.11+ 上str()会退化为纯数字,届时匹配将静默失效(守卫恒不触发、CSV 行永不命中)。当前运行时为 Python 3.10 故可用,但该跨版本假设未被任何测试固化。 - [6.1] Architecture — 分层边界:新概念在正确层级,不泄漏内部 → issue ``configure_aiter_fmoe_overlays
自身无 arch 自检,作为公共 API 可在非 gfx942 上装入 gfx942 调优行
_arch 维度只体现在两处函数体外的信息中:`registry.PROVIDERS_BY_ARCH` 的 key(registry.py:12)与 overlay 文件名前缀 `gfx942_cu80`。函数本身不做任何 arch/CU 校验,而它已通过 `aiter/init.py` 的 `all` 导出为公共 API,任何直接调用者(含未来其他 provider)在 gfx950 上都会把 gfx942 的行写进 `AITER_CONFIG_FMOE`。`validated_overlay_dispatch_keys` 的 `expected_keys` 也不覆盖 `gfx` 字段(CSV 无该列),未来若受影响签名集合扩展到多 arch,key 会退化重合。 - [6.1] Architecture — 可观测性:日志/指标/超时可操作、非噪声 → issue
signature 构造 helper 名称通用但写死量化语义,且q_dtype_a用权重 dtype 代理激活量化 dtype
_aiter_fmoe_workload_signature的名字不含任何量化语义,但函数体写死q_type=str(aiter.QuantType.per_Token)(第 66 行)与doweight_stage1=0(第 68 行),并用权重 dtypestr(w1.dtype)代理 CSV 中语义为「量化后激活 dtype」的q_dtype_a(第 64 行),本 workload 下两者恰好同为float8_e4m3fnuz才自洽。同文件RocmExpertsFp8PerBlock实际用per_128x128(第 424 行),RocmExpertsFp4PerGroup/RocmExpertsMXFp4用per_1x32且doweight_stage1=apply_router_weight_on_input(第 568/573、700/705 行)。若后续有人复用该 helper 到这些 executor,算出的 signature 会与真实 dispatch key 不符;而 signatur - [6.1] Architecture — 回滚路径:风险行为存在运维回滚手段 → issue
启动期可选性能 overlay 未做 fail-open 保护,其 IO 异常会击穿全部 rank 启动,与 registry 的 warn-only 契约矛盾
第 92 行configure_kernel_tuning()裸调用在local_rank_start的 try 块内,异常会被第 116 行except BaseException捕获、经 pipe 上报 failed 并 re-raise,进而终止全部 rank。但被调方设计意图是 fail-open:registry.py:36-42 对未生效 overlay 只打 warning,真正的 fail-closed 被刻意下沉到执行期require_aiter_fmoe_tuning。而configure_aiter_fmoe_overlays的兜底并不完备——_sha256(fmoe.py:209)、locate_file(fmoe.py:200-202)、_stock_fmoe_configs(fmoe.py:226)以及importlib.metadata的非PackageNotFoundError异常,均在 fmoe.py:239 的except (OSError, ValueError)保护范围之外 - [6.1] Architecture — 状态不变量:创建/更新/失败/重试/回滚路径有效 → issue ``configure_aiter_fmoe_overlays
自身无 arch 自检,作为公共 API 可在非 gfx942 上装入 gfx942 调优行
_arch 维度只体现在两处函数体外的信息中:`registry.PROVIDERS_BY_ARCH` 的 key(registry.py:12)与 overlay 文件名前缀 `gfx942_cu80`。函数本身不做任何 arch/CU 校验,而它已通过 `aiter/init.py` 的 `all` 导出为公共 API,任何直接调用者(含未来其他 provider)在 gfx950 上都会把 gfx942 的行写进 `AITER_CONFIG_FMOE`。`validated_overlay_dispatch_keys` 的 `expected_keys` 也不覆盖 `gfx` 字段(CSV 无该列),未来若受影响签名集合扩展到多 arch,key 会退化重合。 - [6.1] Architecture — 错误语义:fail-fast/retry/fallback/silent 行为显式 → issue
signature 构造 helper 名称通用但写死量化语义,且q_dtype_a用权重 dtype 代理激活量化 dtype
_aiter_fmoe_workload_signature的名字不含任何量化语义,但函数体写死q_type=str(aiter.QuantType.per_Token)(第 66 行)与doweight_stage1=0(第 68 行),并用权重 dtypestr(w1.dtype)代理 CSV 中语义为「量化后激活 dtype」的q_dtype_a(第 64 行),本 workload 下两者恰好同为float8_e4m3fnuz才自洽。同文件RocmExpertsFp8PerBlock实际用per_128x128(第 424 行),RocmExpertsFp4PerGroup/RocmExpertsMXFp4用per_1x32且doweight_stage1=apply_router_weight_on_input(第 568/573、700/705 行)。若后续有人复用该 helper 到这些 executor,算出的 signature 会与真实 dispatch key 不符;而 signatur - [6.1] Quality — Commit 原子、message 与行为匹配 → issue
未证明 provision 就绪的 ROCm MTP smoke suite 被并入主 CI 聚合 suite,阻塞说明被同时删除且与本 PR 主题无关
diff 显示本 PR 一边在rtp_llm/test/smoke/BUILD:78把:smoke_rocm_qwen35_mtp加入顶层 CI suitemaga_model_smoke,一边把suites_rocm_oss.bzl原注释「Keep this suite standalone until Qwen3.6-27B is provisioned on the shared ROCm CI workers; run it directly on an MI308X host with that checkpoint」替换为「Keep this as a dedicated suite so CI and local runs can select it directly」——在删除阻塞说明的同时执行了该说明明确禁止的动作。该 suite 唯一用例依赖共享存储上的 Qwen3.6-27B 草稿 checkpoint(--sp_checkpoint_path)并 pin MI308X、PD 双角色,而本 PR 全部 17 个变更文件无任何 pr - [6.1] Quality — Mega-PR 已拆分为独立变更 → issue
未证明 provision 就绪的 ROCm MTP smoke suite 被并入主 CI 聚合 suite,阻塞说明被同时删除且与本 PR 主题无关
diff 显示本 PR 一边在rtp_llm/test/smoke/BUILD:78把:smoke_rocm_qwen35_mtp加入顶层 CI suitemaga_model_smoke,一边把suites_rocm_oss.bzl原注释「Keep this suite standalone until Qwen3.6-27B is provisioned on the shared ROCm CI workers; run it directly on an MI308X host with that checkpoint」替换为「Keep this as a dedicated suite so CI and local runs can select it directly」——在删除阻塞说明的同时执行了该说明明确禁止的动作。该 suite 唯一用例依赖共享存储上的 Qwen3.6-27B 草稿 checkpoint(--sp_checkpoint_path)并 pin MI308X、PD 双角色,而本 PR 全部 17 个变更文件无任何 pr - [6.1] Quality — PR description 说明动机与设计 → issue
调优表全部性能与误差列为 0 占位值,调优结论不可追溯且err1=0.0%是未经测量的正确性声明
5 行数据的测量列全为占位值:us1=0.0、err1=0.0%、us2=0.0、err2=0.0%、us=0.0、tflops=0.0、bw=0.0。后果有两点:一是无法复核「one-stage 32x128 优于 stock 选核」这一结论,fmoe.py:17 的版本 pin 上抬时维护者没有任何基线可对比,只能重新盲调;二是err1=0.0%在无实测依据下声明了零数值误差。文件形式上是 AITER tuning 输出、实质是手工撰写的 dispatch 覆盖,仓内未留下实测延迟、tuning 命令行或采集环境记录。同仓同类离线调优数据linear/impl/rocm/data/fp8_ptpc_hipb_solutions.json带有format_version、target(arch/hip/aiter 版本 prefix)与selection_policy(GPU 集合、提速门槛、回退规则),本文件没有任何等价 provenance。 - [6.1] Software Engineering — DRY:重复非平凡逻辑被抽取或显式复用 → issue
gcnArchName 解析惯用法再次复制,仓内已有多份不一致实现
str(getattr(properties, "gcnArchName", "")).split(":", 1)[0]这一惯用法在本 PR 中被新增两份(registry.py:21 与 rocm_moe.py:54),而仓内已有device/device_impl.py:28(用in子串包含)、utils/jit_cache_manager.py:31、linear/impl/rocm/fp8_ptpc_linear.py:226(不做 split,用 startswith)、triton_kernels/fla/utils.py:262等多处各写一遍,对:sramecc+:xnack-后缀的处理并不一致。后果是 ROCm arch 判定语义分散在六处以上,未来新增 gfx 代号或 arch 串格式变化时需要逐处修改且容易漏改。 - [6.1] Software Engineering — KISS/YAGNI:无投机性抽象 → issue ``tp_size
外层循环使重型 GPU 子用例翻倍但不增加鉴别力
_第 307 行 `for tp_size in (2, 4)` 之下,第 329 行又嵌套 5 个 token 档位的重型子用例(256 experts、hidden 2048),共 10 个子用例。但 `aiter_fmoe_workload_signature` 的入参只有 `w1`/`w2`/`topk`/`activation`/`output_dtype`,`RocmExpertsFp8PerChannel.init`(rocm_moe.py:213-249)只用到 `expert_num`/`ep_rank`/`ep_size`/`moe_k`/`activation_type`/`compute_dtype` 与权重字典,`tp_size` 与 `inter_size` 均不进入被测代码路径。两轮循环使用同一份 `weights`、得到同一个 signature、跑同一份参考权重,第二轮不引入任何新覆盖维度。 - [6.1] Software Engineering — SRP:模块/类职责单一 → issue
signature 构造 helper 名称通用但写死量化语义,且q_dtype_a用权重 dtype 代理激活量化 dtype
_aiter_fmoe_workload_signature的名字不含任何量化语义,但函数体写死q_type=str(aiter.QuantType.per_Token)(第 66 行)与doweight_stage1=0(第 68 行),并用权重 dtypestr(w1.dtype)代理 CSV 中语义为「量化后激活 dtype」的q_dtype_a(第 64 行),本 workload 下两者恰好同为float8_e4m3fnuz才自洽。同文件RocmExpertsFp8PerBlock实际用per_128x128(第 424 行),RocmExpertsFp4PerGroup/RocmExpertsMXFp4用per_1x32且doweight_stage1=apply_router_weight_on_input(第 568/573、700/705 行)。若后续有人复用该 helper 到这些 executor,算出的 signature 会与真实 dispatch key 不符;而 signatur - [6.1] Tests — 分布式/跨平台变更有对应覆盖 → issue ``registry_test
未覆盖所有 CUDA/CPU 部署必经的非 ROCm no-op 路径,也未断言真实 provider 表
_`configure_kernel_tuning()` 现被无条件插入所有平台的 backend 启动路径,「在 CUDA/CPU/PPU 上必须是 no-op」是本次改动最关键的跨平台安全属性。但两个用例都显式传入 `arch`("gfx942"/"gfx950"),registry.py:32 的默认参数路径从未执行;`current_rocm_arch` 只覆盖 gfx942 成功分支,`torch.cuda.is_available()` 为 False、`torch.version.hip is None`(registry.py:17)、`get_device_properties` 抛异常走 warning 返回 None(registry.py:22-24)三条分支都无用例。而 `start_backend_server.py:92` 是无参调用,`jit_cache_manager_test.py:1071` 又把该函数整体 mock 掉,导致默认路径在全仓无任何执行覆盖。第 12-13 行 `mock.patch.dict(..., clear=True)` 还整 - [6.1] Tests — 新逻辑有聚焦单测 + 相关集成/smoke 测试 → issue
新增测试 fixture 用非生产取值activation_type="silu",掩盖生产 SiGLU 分歧使断言恒为通过
_make_config_adapter固定写入model_config.activation_type = "silu"(第 126 行),而仓内全部 gated-silu 生产模型写的都是"SiGLU"。"silu"经 pybind setter 落成ActivationType::Silu、.name == "Silu",恰好命中_moe_activation_type的 silu 分支;生产的"SiGLU"落成Swiglu则不会。第 315-322 行正是用这个非生产取值构造 signature 并assertTrue(is_affected_aiter_fmoe_signature(signature)),因此该断言在 CI 里恒为通过,无法暴露上文 P1 的 Gelu 误判。这条「声称覆盖 signature 匹配」的断言因 fixture 与生产配置边界取值不一致而失去保护作用。 - [6.1] Tests — 边界 case 覆盖(空、单元素、最大值) → issue ``tp_size
外层循环使重型 GPU 子用例翻倍但不增加鉴别力
_第 307 行 `for tp_size in (2, 4)` 之下,第 329 行又嵌套 5 个 token 档位的重型子用例(256 experts、hidden 2048),共 10 个子用例。但 `aiter_fmoe_workload_signature` 的入参只有 `w1`/`w2`/`topk`/`activation`/`output_dtype`,`RocmExpertsFp8PerChannel.init`(rocm_moe.py:213-249)只用到 `expert_num`/`ep_rank`/`ep_size`/`moe_k`/`activation_type`/`compute_dtype` 与权重字典,`tp_size` 与 `inter_size` 均不进入被测代码路径。两轮循环使用同一份 `weights`、得到同一个 signature、跑同一份参考权重,第二轮不引入任何新覆盖维度。
RTP-LLM Checklist
- [I] 代码质量 — 同一功能用统一工具函数 → issue
gcnArchName 解析惯用法再次复制,仓内已有多份不一致实现
str(getattr(properties, "gcnArchName", "")).split(":", 1)[0]这一惯用法在本 PR 中被新增两份(registry.py:21 与 rocm_moe.py:54),而仓内已有device/device_impl.py:28(用in子串包含)、utils/jit_cache_manager.py:31、linear/impl/rocm/fp8_ptpc_linear.py:226(不做 split,用 startswith)、triton_kernels/fla/utils.py:262等多处各写一遍,对:sramecc+:xnack-后缀的处理并不一致。后果是 ROCm arch 判定语义分散在六处以上,未来新增 gfx 代号或 arch 串格式变化时需要逐处修改且容易漏改。
Python Static-First Checklist
- [P.A] 静态结构与类型纪律 — 字符串分发用 Enum/Literal → issue ``_moe_activation_type
未覆盖ActivationType.Swiglu`,新增 fail-closed 守卫在所有生产 MoE 模型上恒不触发`
`activation_types.h:48` 把 `"SiGLU"`/`"gated-silu"` 映射为 `Swiglu`,`pybind/ConfigInit.cc:1966-1976` 的 getter 返回 pybind 枚举。仓内全部 gated-silu 生产模型写的都是 `"SiGLU"`(deepseek_v2.py:555、qwen3_next.py:93、glm4_moe.py:410 等)。故 `init` 侧 `config.activation_type`(rocm_moe.py:242)→ `.name="Swiglu"` → `"swiglu"` → 不在 `("silu","siglu")` → 返回 `Gelu` → `act_type="ActivationType.Gelu"` ≠ fmoe.py:76 声明的 `"ActivationType.Silu"` → `require_aiter_fmoe_tuning` 在 fmoe.py:274-275 直接 return(fail-open 且无日志)。同一契约字段由两处不同来源推导:守 - [P.G] 测试规范 — mock/fake/stub 不得替代本次声称覆盖的生产边界 → issue
测试手工复刻生产 fp8 e4m3fn→fnuz 转换并遗漏 gfx950 分支
_online_loader_quant_fp8(第 59-67 行)手写bits[bits == -128] = 0与scale * 2.0,与生产实现RocmImpl.convert_fp8_weight_params(device_impl.py:1007-1025)逐行等价,包括「-128 位模式在 e4m3fnuz 中是 NaN」与「同位模式下 fnuz 值为 fn 一半故 scale 需加倍」两个关键点。但生产实现在self._is_gfx950()时直接原样返回(第 1011-1012 行,保留 e4m3fn、不加倍 scale),测试副本没有该短路分支并硬编码torch.float8_e4m3fnuz,也没有生产侧那两段解释魔数的注释。因此注释所称「复现真实 checkpoint 加载」并不成立,生产转换调整后该测试不会同步失败。
Strengths
- overlay 的「加性」语义有真实防护而非口头承诺:
_validated_overlay_dispatch_keys(fmoe.py:129-164)强校验列完整性、要求行集合与「声明 signature × token 桶」精确相等、_tag必须为空,并逐个 stock CSV 做 dispatch key 交集检测(fmoe.py:229-238),一旦上游补齐同 key 行即主动失效并要求人工复核。 - signature 抽象取舍讲得清楚且被测试固化:
AiterFmoeWorkloadSignature的 docstring 明确说明 tp/ep/模型标识被刻意排除,aiter_fmoe_test.py:160-182用dataclasses.fields断言签名不含 model/tp_size/ep_size 并逐字段验证不匹配即落空,避免了「按模型名打补丁」这一常见反模式。 - 对第三方 pin 的漂移有显式感知:同时校验 aiter 版本与其自带
tuned_fmoe.csv的 sha256,任一变化都在 reason 中写明「需重新评审 overlay」;fmoe.py:17的 pin 与deps/requirements_lock_rocm.txt:114、deps/http.bzl:86、arch_config/arch_select.bzl:97的 wheel 完全一致。 - 跨平台隔离干净:
registry.py:17以torch.cuda.is_available()与torch.version.hip is None短路,_PROVIDERS_BY_ARCH只注册 gfx942,且kernel_tuning全链路不 import 第三方aiter,因此start_backend_server.py:25的顶层引入在 CUDA/CPU/PPU 上零成本、无 ImportError 风险。 - 启动顺序契约被机械锁定:
configure_kernel_tuning()(start_backend_server.py:92)位于setup_cuda_device_and_accl_env(内部执行torch.cuda.set_device,server_config_setup.py:527)之后、BackendManager延迟导入(第 97-99 行)之前,而rocm_moe.py:4是模块级import aiter;jit_cache_manager_test.py:1085以events == ["device","tuning","backend"]把该时序变成可回归断言,且mock.patch.object打在使用处而非定义处。 - 尊重运维显式设置:
AITER_CONFIG_FMOE已被外部指定时不覆写,而是校验其是否包含 overlay 路径(fmoe.py:245-257)。 - 数据文件自描述且与代码常量双向强绑定:文件名的 gfx942/cu80/m1_16/h2048/i128/e256/topk8/bf16_fp8pt 与行内取值逐项对应,
block_m=32与 kernel 名中的32x128、run_1stage=1与kernelName2=Null自洽,q_dtype_*正确使用 gfx942 专有的torch.float8_e4m3fnuz而非e4m3fn,规避了跨平台 FP8 变体写错这一常见坑。 - 构建接线完整无环:
kernel_tuning同时接入//rtp_llm:sdk与//rtp_llm/models_py:modules,只依赖 pip alias//rtp_llm:torch,CSV 以dataglob 进入 runfiles,两个新 py_test 仅需 CPU。
| ":smoke_rocm_dense", | ||
| ":smoke_rocm_moe", | ||
| ":smoke_rocm_qwen35_mrope_cg", | ||
| ":smoke_rocm_qwen35_mtp", |
There was a problem hiding this comment.
[P1] 未证明 provision 就绪的 ROCm MTP smoke suite 被并入主 CI 聚合 suite,阻塞说明被同时删除且与本 PR 主题无关
diff 显示本 PR 一边在 rtp_llm/test/smoke/BUILD:78 把 :smoke_rocm_qwen35_mtp 加入顶层 CI suite maga_model_smoke,一边把 suites_rocm_oss.bzl 原注释「Keep this suite standalone until Qwen3.6-27B is provisioned on the shared ROCm CI workers; run it directly on an MI308X host with that checkpoint」替换为「Keep this as a dedicated suite so CI and local runs can select it directly」——在删除阻塞说明的同时执行了该说明明确禁止的动作。该 suite 唯一用例依赖共享存储上的 Qwen3.6-27B 草稿 checkpoint(--sp_checkpoint_path)并 pin MI308X、PD 双角色,而本 PR 全部 17 个变更文件无任何...
建议: 拆分为独立变更:本 PR 只保留 kernel tuning 相关内容。若确认 checkpoint 已在共享 ROCm worker 就位,请在 PR 描述或注释中给出可核验依据(provision 记录或一次包含该 suite 的绿色 CI run),再单独提交 maga_model_smoke 的成员变更并单跑一次 ROCm CI;否则回退第 78 行的 suite 成员变更并还原原注释中记录的阻塞原因,不要以「改注释」代替「解除阻塞」。
Checklist: [6.1] Commit 原子、message 与行为匹配;[6.1] Mega-PR 已拆分为独立变更
| return _CONFIG_STATUS | ||
|
|
||
| version = distribution.version | ||
| if version != _SUPPORTED_AITER_VERSION: |
There was a problem hiding this comment.
[P2] aiter 版本精确全等匹配叠加加载期硬 raise,无降级与运维逃生通道,且与仓内既有约定相反
_SUPPORTED_AITER_VERSION(fmoe.py:17)含 .d20260623 构建日期段,fmoe.py:192 用 != 全等比较,同一 commit 换日期重新构建 aiter 即失配;随后 require_aiter_fmoe_tuning(fmoe.py:279)在 RocmExpertsFp8PerChannel.__init__(rocm_moe.py:237)抛 RuntimeError,即权重加载期失败,经 start_backend_server.py:116 的 except BaseException 上报后终止全部 rank。回滚通道不存在:版本判定位于 env 分支(fmoe.py:245)之前,预设不含 overlay 的 AITER_CONFIG_FMOE 会走 fmoe.py:251 的 applied=False 同样抛异常。仓内解决同类问题的 fp8_ptpc_linear.py:235-241 恰好相反:prefix 匹配(其 prefix 刻意不含日期段)、失配仅返回 False 静默降级...
建议: 改用与 fp8_ptpc_linear.py 一致的版本 prefix 匹配(去掉 .dYYYYMMDD 段),并抽出共用的 aiter 版本/arch 判定工具消除两份实现;内容兼容性已由 sha256 与 dispatch key 冲突检测覆盖,版本号可放宽为最小兼容区间。同时提供显式运维开关(如 require|warn|off 三态,默认 require),warn/off 退化为 ERROR/WARNING + 继续启动,把「强制复核」诉求放在 CI 断言而非线上启动路径。注意两点耦合:一是修复上一条后本路径才会被生产流量真正命中(当前受 signature 判定门控,生产恒不可达,故本条按 P2 处理);二是放宽版本匹配会同时移除下一条 glob 重建的唯一门控,必须同步加固。若确实保留硬失败,请在 PR description 与错误信息中写明这是有意的部署闸门及其回滚手段。
| ) | ||
| return _CONFIG_STATUS | ||
| else: | ||
| config_paths = [*stock_configs, overlay_config] |
There was a problem hiding this comment.
[P2] 启动期用 glob 重建的列表整体覆写 AITER_CONFIG_FMOE,波及进程内所有 gfx942 MoE 负载且最终清单无日志
_PROVIDERS_BY_ARCH(registry.py:11-13)在 configure_kernel_tuning()(registry.py:32-35)按 arch 无条件执行,此时进程还不知道要加载哪个模型。fmoe.py:259-260 执行 config_paths = [*stock_configs, overlay_config] 后整体覆写 env,而非在 aiter 已解析的默认集合上追加。stock_configs(fmoe.py:104-111)用 tuned_fmoe.csv + model_configs/*tuned_fmoe*.csv(排除 untuned)这一 glob 启发式复刻 aiter 内部规则,仓内无任何断言证明其等于 aiter 默认集合——aiter_fmoe_test.py:93-96 断言的是 RTP 自己写出的 env 字符串;Path.glob 在目录不存在时静默返回空。若 aiter 实际解析范围更广,未复刻的已调优行被静默丢弃(性能回退、无报错),而 _LOGGER.info(...
建议: 优先读取 aiter 自身暴露的默认配置集合再追加 overlay,而不是重建;若确实只能重建,补一条在 pinned 版本下断言「重建集合 ⊇ aiter 默认解析结果」的 ROCm 门控测试,让上游改名/移动由测试而非线上行为暴露。同时把 _LOGGER.info 升级为打印最终生效的完整 AITER_CONFIG_FMOE 清单(含 stock 文件数量),便于线上核对实际生效的 dispatch 表;并考虑把 env 写入从「启动期按 arch 无条件执行」收敛为命中受影响 signature 后再配置(该时机仍早于首次前向)。若采纳上一条放宽版本匹配的建议,本条必须同批落地,否则将失去唯一保护。
| return [default_config, *model_configs] | ||
|
|
||
|
|
||
| def _dispatch_keys(config: Path) -> set[tuple[str, ...]]: |
There was a problem hiding this comment.
[P2] stock 与 overlay 两条 CSV 解析路径重复实现,且 _tag 过滤语义不对称可致误判 dispatch 冲突
_dispatch_keys(fmoe.py:114-126)与 _validated_overlay_dispatch_keys(fmoe.py:129-164)逐字重复「打开 CSV → 校验 _DISPATCH_KEY_FIELDS 齐全 → 拼 key tuple」。更关键的是语义不一致:overlay 侧显式认定「AITER 会把 _tag 非空的行排除在正常 FMoE dispatch 之外」并据此拒绝(fmoe.py:140-145),但用于 stock 配置的 _dispatch_keys 完全不看 _tag。因此若 stock tuned_fmoe.csv 或任一 model_configs/*tuned_fmoe*.csv 存在 _tag 非空、key 与 overlay 相同的行,按 overlay 侧自己的规则它并不参与常规 dispatch、不构成真冲突,却会在 fmoe.py:230-238 被判为 overlap → overlay 静默失效;修复上文 act_type 问题后这将直接升级为权重加载期的 Runti...
建议: 抽出单一的 _read_dispatch_keys(config, *, exclude_tagged: bool) 供两处复用,并让 stock 侧与 overlay 侧对 _tag 采用同一语义(按代码注释所述,两侧都应排除 tagged 行);补一个「stock 含 tagged 同 key 行不应判为冲突」的用例固化该语义。若刻意保留 stock 侧的保守策略,请在代码注释中写明「宁可误判也不放过」的取舍及其对启动失败的影响。
| py_env_configs.server_config.set_local_rank(local_rank) | ||
| py_env_configs.distribute_config.set_local_rank(local_rank) | ||
| setup_cuda_device_and_accl_env(local_rank) | ||
| configure_kernel_tuning() |
There was a problem hiding this comment.
[P2] 启动期可选性能 overlay 未做 fail-open 保护,其 IO 异常会击穿全部 rank 启动,与 registry 的 warn-only 契约矛盾
第 92 行 configure_kernel_tuning() 裸调用在 local_rank_start 的 try 块内,异常会被第 116 行 except BaseException 捕获、经 pipe 上报 failed 并 re-raise,进而终止全部 rank。但被调方设计意图是 fail-open:registry.py:36-42 对未生效 overlay 只打 warning,真正的 fail-closed 被刻意下沉到执行期 require_aiter_fmoe_tuning。而 configure_aiter_fmoe_overlays 的兜底并不完备——_sha256(fmoe.py:209)、locate_file(fmoe.py:200-202)、_stock_fmoe_configs(fmoe.py:226)以及 importlib.metadata 的非 PackageNotFoundError 异常,均在 fmoe.py:239 的 except (OSError, ValueError) 保护范...
建议: 二选一:(1)在调用点按同文件 JIT 缓存的既有范式包一层 try / except Exception + logging.exception(...) 后继续启动,注意不要捕获 BaseException 以免吞掉启动窗口内的 KeyboardInterrupt;(2)把 _sha256、locate_file、_stock_fmoe_configs 与 metadata 异常纳入已有的 except (OSError, ValueError),使 configure_kernel_tuning 在契约上保证不抛异常。同时建议在第 92 行补一行注释,说明该位置承载的两个隐式时序不变量(必须在设备设置之后、任何 aiter 导入与 BackendManager 构造之前)及其失效后果,并指向 jit_cache_manager_test.py:1085 已锁定的顺序断言。
Checklist: [6.1] 回滚路径:风险行为存在运维回滚手段
| ) | ||
| w1q_checkpoint, s1_checkpoint = _online_loader_quant_fp8(w1_checkpoint) | ||
| w2q, s2 = _online_loader_quant_fp8(w2_checkpoint) | ||
| w1q_loader = runtime_device.cat_0( |
There was a problem hiding this comment.
[P2] 新增数值测试重复施加 gate/up 重排相互抵消,且 moe_s2 旁路 shuffle,未复现注释声称的生产权重 layout
测试第 254-255 行注释声称复现真实 checkpoint 加载的 [gate, up] 重排,随后第 278-291 行手工交换 w1q/s1 两个半区,再调用 shuffle_moe_weight(第 293-299 行)。而 RocmImpl.shuffle_moe_weight 对 W.moe_w1/W.moe_s1 已内置同一次交换(device_impl.py:894、901-905,注释即 "swap from [up, gate] to [gate, up]"),生产链路 ffn_weight.py:395-398 只对原始 checkpoint 张量调用一次。两次交换互为逆操作、净效果为恒等;参考值 w1_dequant(第 302 行)也按未交换的 checkpoint 顺序构造,故整链自洽、cosine 恒 ≈1,即使 reorder 方向写反该用例仍通过。另第 300 行 W.moe_s2: s2 旁路了 shuffle_moe_weight,而生产对 moe_w1/w2/s1/s2 四者一律调用。
建议: 去掉第 278-291 行的手工交换,直接把 checkpoint 顺序的张量交给 shuffle_moe_weight 完成唯一一次交换(与生产 _postprocess 一致),并把参考值改为按交换后的 [gate, up] 语义构造,使半区顺序不一致时断言能够失败;同时让 W.moe_s2 也走一遍 shuffle_moe_weight,与 ffn_weight.py 的四路一致处理对齐(当前对 float32 scale 是 no-op,但可避免后续语义漂移);修正或删除那句已不成立的注释。
| ) | ||
|
|
||
|
|
||
| def configure_aiter_fmoe_overlays() -> KernelTuningStatus: |
There was a problem hiding this comment.
[P3] configure_aiter_fmoe_overlays 自身无 arch 自检,作为公共 API 可在非 gfx942 上装入 gfx942 调优行
arch 维度只体现在两处函数体外的信息中:registry._PROVIDERS_BY_ARCH 的 key(registry.py:12)与 overlay 文件名前缀 gfx942_cu80_。函数本身不做任何 arch/CU 校验,而它已通过 aiter/__init__.py 的 __all__ 导出为公共 API,任何直接调用者(含未来其他 provider)在 gfx950 上都会把 gfx942 的行写进 AITER_CONFIG_FMOE。_validated_overlay_dispatch_keys 的 expected_keys 也不覆盖 gfx 字段(CSV 无该列),未来若受影响签名集合扩展到多 arch,key 会退化重合。
建议: 在 configure_aiter_fmoe_overlays 入口增加一次 arch 自检(与 _AFFECTED_WORKLOAD_SIGNATURES 中的 gfx 取值比对,不匹配则返回 not-applied 而非写 env),使该函数脱离 registry 单独调用时同样安全;或收窄导出面,仅由 registry 内部调用。
Checklist: [6.1] 分层边界:新概念在正确层级,不泄漏内部;[6.1] 状态不变量:创建/更新/失败/重试/回滚路径有效
| inter_dim=w2.shape[2], | ||
| expert=w1.shape[0], | ||
| topk=topk, | ||
| act_type=str(_moe_activation_type(activation)), |
There was a problem hiding this comment.
[P3] dispatch key 依赖第三方枚举的 __str__ 表示,且该假设未被任何断言固化
signature 的 act_type/q_type 由 str(_moe_activation_type(...))、str(aiter.QuantType.per_Token) 生成(rocm_moe.py:62、66),并与 CSV 及 _AFFECTED_WORKLOAD_SIGNATURES 中的字面量 "ActivationType.Silu"、"QuantType.per_Token" 做字符串相等比较。这一相等关系完全依赖第三方枚举的 __str__ 行为:若其为 IntEnum,在 Python 3.11+ 上 str() 会退化为纯数字,届时匹配将静默失效(守卫恒不触发、CSV 行永不命中)。当前运行时为 Python 3.10 故可用,但该跨版本假设未被任何测试固化。
建议: 在 aiter_fmoe_test.py 中补一条断言(aiter 不可用时跳过),固化 str(aiter.ActivationType.Silu) == "ActivationType.Silu"、str(aiter.QuantType.per_Token) == "QuantType.per_Token",使 Python 或 aiter 升级导致的表示变化在测试而非线上暴露。
Checklist: [6.1] 兼容性:外部 HTTP/RPC API、持久数据、配置、环境迁移安全
| return wq, scale.squeeze(-1) | ||
|
|
||
|
|
||
| def _online_loader_quant_fp8(w: torch.Tensor): |
There was a problem hiding this comment.
[P3] 测试手工复刻生产 fp8 e4m3fn→fnuz 转换并遗漏 gfx950 分支
_online_loader_quant_fp8(第 59-67 行)手写 bits[bits == -128] = 0 与 scale * 2.0,与生产实现 RocmImpl.convert_fp8_weight_params(device_impl.py:1007-1025)逐行等价,包括「-128 位模式在 e4m3fnuz 中是 NaN」与「同位模式下 fnuz 值为 fn 一半故 scale 需加倍」两个关键点。但生产实现在 self._is_gfx950() 时直接原样返回(第 1011-1012 行,保留 e4m3fn、不加倍 scale),测试副本没有该短路分支并硬编码 torch.float8_e4m3fnuz,也没有生产侧那两段解释魔数的注释。因此注释所称「复现真实 checkpoint 加载」并不成立,生产转换调整后该测试不会同步失败。
建议: 直接调用 runtime_device.convert_fp8_weight_params(wq, scale) 复用生产实现,删除测试内的手写位级转换,使 gfx950 分支与后续改动自动被覆盖。
Checklist: [P.G] mock/fake/stub 不得替代本次声称覆盖的生产边界
| return None | ||
| try: | ||
| properties = torch.cuda.get_device_properties(torch.cuda.current_device()) | ||
| return str(getattr(properties, "gcnArchName", "")).split(":", 1)[0] or None |
There was a problem hiding this comment.
[P3] gcnArchName 解析惯用法再次复制,仓内已有多份不一致实现
str(getattr(properties, "gcnArchName", "")).split(":", 1)[0] 这一惯用法在本 PR 中被新增两份(registry.py:21 与 rocm_moe.py:54),而仓内已有 device/device_impl.py:28(用 in 子串包含)、utils/jit_cache_manager.py:31、linear/impl/rocm/fp8_ptpc_linear.py:226(不做 split,用 startswith)、triton_kernels/fla/utils.py:262 等多处各写一遍,对 :sramecc+:xnack- 后缀的处理并不一致。后果是 ROCm arch 判定语义分散在六处以上,未来新增 gfx 代号或 arch 串格式变化时需要逐处修改且容易漏改。
建议: 抽出统一的 current_rocm_arch() 工具函数(放在 rtp_llm/device 或 ROCm 侧公共 utils)供各处复用;本 PR 至少让新增的两处共用同一实现,并可与上文 aiter 版本判定工具的抽取一并处理。
Checklist: [6.1] DRY:重复非平凡逻辑被抽取或显式复用;[I] 同一功能用统一工具函数
|
|
||
| # TP is deliberately varied while the local AITER dispatch shape stays | ||
| # fixed. The tuning decision must therefore be identical for both. | ||
| for tp_size in (2, 4): |
There was a problem hiding this comment.
[P3] tp_size 外层循环使重型 GPU 子用例翻倍但不增加鉴别力
第 307 行 for tp_size in (2, 4) 之下,第 329 行又嵌套 5 个 token 档位的重型子用例(256 experts、hidden 2048),共 10 个子用例。但 _aiter_fmoe_workload_signature 的入参只有 w1/w2/topk/activation/output_dtype,RocmExpertsFp8PerChannel.__init__(rocm_moe.py:213-249)只用到 expert_num/ep_rank/ep_size/moe_k/activation_type/compute_dtype 与权重字典,tp_size 与 inter_size 均不进入被测代码路径。两轮循环使用同一份 weights、得到同一个 signature、跑同一份参考权重,第二轮不引入任何新覆盖维度。
建议: 把第 329-357 行的数值子用例提到 tp_size 循环之外只跑一遍;tp_size 循环内只保留第 308-322 行的 config/signature 构造与断言,用于表达「signature 与 TP 无关」这一设计意图,从而在保留意图的同时把重型子用例减半。
Checklist: [6.1] KISS/YAGNI:无投机性抽象;[6.1] 边界 case 覆盖(空、单元素、最大值)
7e74c6a to
c71d2b6
Compare
LLLLKKKK
left a comment
There was a problem hiding this comment.
AI Code Review - PR #1345
Status: BLOCKING
Summary: P0/1 · P1/1 · P2/17 · P3/3
Reviewed: commit c71d2b68fff4 · 2026-08-29 09:15 UTC+8
Blocking Issues
P0
_SUPPORTED_AITER_VERSION与仓库锁定的 aiter wheel 不一致,overlay 恒失效且受影响形状在模型加载期直接抛错 @rtp_llm/models_py/kernel_tuning/aiter/fmoe.py:17- 建议:用锁定的 wheel 重新采集
_SUPPORTED_AITER_VERSION与_SUPPORTED_DEFAULT_CONFIG_SHA256,并确认在 0.1.21 下 overlay 仍然必要。更关键的是把常量来源固定住:补一条无需 GPU 的真实环境断言(比对importlib.metadata.version("aiter")与_SUPPORTED_AITER_VERSION、_sha256(locate_file("aiter/configs/tuned_fmoe.csv"))与常量),让漂移在 CI 阶段红而不是线上加载模型时红。仓内linear/impl/rocm/data/fp8_ptpc_hipb_solutions.json的validated_aiter_versions列表机制已解决同类问题(见fp8_ptpc_solution_cache_test.py),建议直接复用而非新造一套精确单值全等比较。
- 建议:用锁定的 wheel 重新采集
P1
- 未证明 provision 就绪的 ROCm MTP smoke suite 被并入顶层 CI 聚合 suite,且阻塞说明被同时删除 @
rtp_llm/test/smoke/BUILD:78- 建议:拆成独立变更:本 PR 只保留 kernel tuning 内容。若确认检查点已在共享 ROCm worker 就位,请在 PR 描述中给出可核验依据(provision 记录或一次包含该 suite 的绿色 ROCm CI run),再单独提交聚合 suite 的成员变更;否则回退第 78 行并还原注释中记录的阻塞原因,不要用「改注释」代替「解除阻塞」。拆分后 kernel tuning 改动也可独立 bisect。
Non-blocking Suggestions
P2
- fail-closed 缺少运维逃生开关与 overlay 复核流程,版本门位于 env 分支之前使显式配置也无法兜底 @
rtp_llm/models_py/kernel_tuning/aiter/fmoe.py:192- 建议:增加显式逃生开关(如
RTP_AITER_FMOE_OVERLAY取auto/off/force),使运维可在不改代码的前提下降级为 warning;或把精确相等改为「已知不安全版本区间」语义,并把版本门移到 env 检查之后,使显式设置AITER_CONFIG_FMOE能作为有效兜底。在kernel_tuning包内补一份 overlay 生成与退役说明(tuning 命令、采集机型、如何刷新 version 与 sha256、失效后处理路径)。把 inactive warning 收敛为仅在命中受影响形状时输出。
- 建议:增加显式逃生开关(如
- 启动期用 glob 重建的列表整体覆写
AITER_CONFIG_FMOE,波及进程内所有 gfx942 MoE 负载 @rtp_llm/models_py/kernel_tuning/aiter/fmoe.py:259- 建议:优先只做追加而不接管:若 AITER 提供配置查询或追加入口,改用该接口而非路径 glob。若必须覆写,请在 configure 阶段把
_stock_fmoe_configs()结果与 AITER 内部默认解析出的列表显式比对,不一致时返回applied=False并在 reason 中列出差集,并为该比对补一条基于真实 AITER 安装目录的用例(现有test_configures_additive_overlay_and_keeps_model_configs使用自写 fixture,属自证)。同时把写 env 的生效范围收窄到「确实命中受影响签名」时,并把最终生效清单写入日志便于线上排障。
- 建议:优先只做追加而不接管:若 AITER 提供配置查询或追加入口,改用该接口而非路径 glob。若必须覆写,请在 configure 阶段把
applied=True只代表环境变量已写入,无法证明 AITER 真正消费了 overlay,兜底调用还发生在 import aiter 之后 @rtp_llm/models_py/kernel_tuning/aiter/fmoe.py:262- 建议:在成功分支加后置校验:回读 AITER 解析出的 FMoE 配置来源列表并断言包含 overlay 路径,或对受影响探针 shape 断言最终命中的 kernel 名等于 CSV 中声明的
1tg_ps_32x128变体,校验失败则applied=False。补一条「在import aiter之后调用configure_aiter_fmoe_overlays仍然生效」的回归用例。若确实无法断言,请把状态字段语义改为「env 已配置(未验证生效)」并在日志中显式声明,不要以它作为 fail-closed 的唯一依据。
- 建议:在成功分支加后置校验:回读 AITER 解析出的 FMoE 配置来源列表并断言包含 overlay 路径,或对受影响探针 shape 断言最终命中的 kernel 名等于 CSV 中声明的
- 两条 CSV 解析路径整段重复,且
_tag过滤语义不对称可致误判 dispatch 冲突 @rtp_llm/models_py/kernel_tuning/aiter/fmoe.py:114- 建议:抽出
_read_dispatch_rows(config) -> list[dict]统一负责打开与缺列校验,两个调用方各自在其上做 key 构造与额外校验;并在 stock 侧同样按_tag非空过滤掉不参与常规 dispatch 的行,使两条路径的 tag 语义与 AITER 的实际 dispatch 集合一致。补一条「stock 存在同 key 但带 tag 的行时 overlay 仍应生效」的用例。
- 建议:抽出
- 激活映射收窄后 GELU 家族由静默回退变为构造期硬失败,且被 5 个 ROCm executor 共用 @
rtp_llm/models_py/modules/factory/fused_moe/impl/rocm/executors/rocm_moe.py:34- 建议:把 geglu、gated-gelu、gelu-none-approximate、geglu-none-approximate 一并映射到
aiter.ActivationType.Gelu(gating 交由use_g1u1表达)以保持既有行为,仅对 Identity/Sigmoid/Relu 这类确实不支持的值显式报错,并在错误信息中写明「ROCm FMoE 暂不支持」。补一条参数化用例枚举ActivationType全部成员,使新增 enum 成员在测试而非线上暴露。同时把入参类型收敛为Union[str, ActivationType]并用isinstance分支,替代 rocm_moe.py:48 的str(getattr(activation, "name", activation))字面量探测。
- 建议:把 geglu、gated-gelu、gelu-none-approximate、geglu-none-approximate 一并映射到
execute()激活一致性校验只加在 1 个 executor 上,未修 activation 未从 config 接线的根因 @rtp_llm/models_py/modules/factory/fused_moe/impl/rocm/executors/rocm_moe.py:291- 建议:修根因:让
forward的activation由调用方显式传入config.activation_type,或删除该参数、统一从 config 读取,使五个 executor 行为一致。若本 PR 不打算扩大范围,请把该校验提取为共享 helper 并在所有 ROCm executor 上启用,同时在注释中记录「forward 默认值与 config 未接线」这一已知缺口。
- 建议:修根因:让
- 签名的
q_dtype_a取权重 dtype 代理激活量化 dtype,dtype 分叉时 fail-closed 守卫静默变为 fail-open @rtp_llm/models_py/modules/factory/fused_moe/impl/rocm/executors/rocm_moe.py:77- 建议:
q_dtype_a改用同一构造路径中已确定的激活量化 dtype(self.quant_config.quant_dtype/get_rocm_fp8_dtype()),q_dtype_w保留w1.dtype并对w1.dtype != w2.dtype显式断言,让 dtype 分叉在构造期暴露而不是让签名静默 miss;同时把函数名或参数收敛以反映其写死 per-token 量化的事实,避免通用名称掩盖专用语义。
- 建议:
- 新增 GPU 用例把宿主机型指纹硬编码为断言,非 gfx942/80CU 机型硬失败而非跳过 @
rtp_llm/models_py/modules/factory/fused_moe/impl/rocm/test/rocm_fp8_fused_moe_test.py:352- 建议:参照 mxfp4 用例,在该用例开头按
gcnArchName与multi_processor_count(或直接用is_affected_aiter_fmoe_signature的结果)做前置SkipTest,附「该 overlay 仅针对 gfx942/80CU」说明;目标卡上保留硬断言并补上包含实算 signature 的 assert message。对 aiter 版本 pin 不匹配也给出明确 skip 或带指引的失败信息,让环境漂移与代码回归两类失败可区分。同时评估是否需要为该重型用例单独声明 Bazeltags与更大timeout。
- 建议:参照 mxfp4 用例,在该用例开头按
- 新增用例数值判据过弱,均值 cosine 掩盖单 token 偏差且对幅度误差不敏感 @
rtp_llm/models_py/modules/factory/fused_moe/impl/rocm/test/rocm_fp8_fused_moe_test.py:387- 建议:改为逐 token 断言(per-token 最小 cosine),或直接与
assert_close组合以覆盖幅度误差;至少对 token=1/2 这类最小 bucket 使用与同文件既有用例一致的容差。
- 建议:改为逐 token 断言(per-token 最小 cosine),或直接与
- gate/up 交换施加两次相互抵消,注释声称复现的 loader reorder 实际未进入断言链 @
rtp_llm/models_py/modules/factory/fused_moe/impl/rocm/test/rocm_fp8_fused_moe_test.py:307- 建议:删除 :307-320 的手工交换,直接把 checkpoint 顺序张量交给
shuffle_moe_weight完成唯一一次交换,并按交换后的[gate, up]语义构造参考值(可参考同目录 mxfp4 用例只在参考侧交换一次的做法),使半区顺序不一致时断言能够失败;同时修正或删除已不成立的注释。
- 建议:删除 :307-320 的手工交换,直接把 checkpoint 顺序张量交给
- 测试自行复刻生产 fp8 fn→fnuz 转换并遗漏 gfx950 分支,且用
__new__绕过 device 构造 @rtp_llm/models_py/modules/factory/fused_moe/impl/rocm/test/rocm_fp8_fused_moe_test.py:61- 建议:改为直接调用
runtime_device.convert_fp8_weight_params(...)(或 loader 侧同一入口)完成 fn→fnuz 转换与 scale 调整,删除测试内的复制实现,使这条「复现真实 checkpoint 加载」的用例真正跨越生产边界;同时避免__new__绕过初始化,改为构造真实设备对象或把所需转换提取为不依赖实例状态的纯函数。
- 建议:改为直接调用
- aiter_fmoe_test 缺少 sha256 漂移、aiter 未安装、配置缺失等 fail-closed 分支覆盖 @
rtp_llm/models_py/kernel_tuning/test/aiter_fmoe_test.py:71- 建议:逐分支各补一个用例:构造 sha 不一致的 default config 并断言
applied is False且 reason 含预期关键字;令 distribution 抛PackageNotFoundError;分别删除 default config 与 overlay 并断言各自 reason 文案;放入一个untuned_fmoe.csv验证被过滤;再补一条 env 已含 overlay 的成功用例,断言applied is True且 env 保持原值不被覆写。同时补一条断言真实安装 aiter 版本与_SUPPORTED_AITER_VERSION一致的用例,避免常量自引用导致漂移无守卫。
- 建议:逐分支各补一个用例:构造 sha 不一致的 default config 并断言
- bundled overlay 断言退化为「行数正确且不抛异常」,真正决定选核的调优列零校验且 fixture schema 与真实文件不一致 @
rtp_llm/models_py/kernel_tuning/test/aiter_fmoe_test.py:190- 建议:把该用例改为直接读取
_OVERLAY_CONFIG:断言 header 与真实 26 列 schema 逐项相等,并逐行断言block_m=32、ksplit=0、run_1stage=1、kernelName2=Null与常量化的kernelName1(可附_ZN5aiter前缀与 mangling 长度前缀自检);_write_config按真实 schema 补齐全部列(调优列填占位),使「fixture 能通过校验」与「AITER 能真正解析」不再脱钩。若能查询已安装 AITER 的可用 kernel 集合,可在 configure 阶段直接校验符号存在性。
- 建议:把该用例改为直接读取
- registry_test 未覆盖所有 CUDA/CPU/PPU 部署必经的非 ROCm no-op 路径,也未断言真实 provider 表 @
rtp_llm/models_py/kernel_tuning/test/registry_test.py:12- 建议:补四条用例:
torch.cuda.is_available()为 False、torch.version.hip is None、get_device_properties抛异常时_current_rocm_arch()均返回 None 且不向上抛;非 ROCm 环境下不传参调用configure_kernel_tuning()返回空 tuple、不调用任何 provider、不产生环境变量副作用。再补一条不带clear=True的断言,验证真实_PROVIDERS_BY_ARCH含gfx942且指向configure_aiter_fmoe_overlays。
- 建议:补四条用例:
- 启动期可选性能 overlay 未做 fail-open 保护,其 I/O 异常会击穿全部 rank 启动 @
rtp_llm/start_backend_server.py:92- 建议:把第 92 行包成与
_install_hot_hook_runtime同构的 fail-open 调用:try/except Exception后logging.exception("KERNEL_TUNING_FAIL_OPEN: ...")并继续启动,与本文件JIT_CACHE_FAIL_OPEN的失败语义对齐——真正需要 fail-closed 的受影响 workload 已由 rocm_moe.py:253 在模型加载路径兜底。同时把 fmoe.py 中 :200-226 的 I/O 一并纳入 try 覆盖,使 provider 对调用方的「不抛」契约成立。若确认 fail-fast 是有意设计,请在 PR 描述中说明并补一条对应用例。
- 建议:把第 92 行包成与
- 调优产物的性能与精度列全为 0.0 占位,且无生成来源记录,收益与精度不可复核 @
rtp_llm/models_py/kernel_tuning/aiter/configs/gfx942_cu80_fmoe_m1_16_h2048_i128_e256_topk8_bf16_fp8pt.csv:2- 建议:回填真实 tuning 输出的
us/tflops/bw/err;若上游 tuning 脚本不产出这些列,请在configs/下补一份说明文件,记录生成命令、AITER 版本、设备 SKU(gfx942 80 CU)、日期,以及 stock 行与 overlay 的实测耗时与精度对比,并写明 overlay 的退役步骤。同时在 PR 描述中明确 stock dispatch 行究竟是数值错误还是仅性能退化——若仅是性能问题,fail-closed 的可用性代价不成立。
- 建议:回填真实 tuning 输出的
- overlay 只覆盖 token 精确值 1/2/4/8/16,中间 token 的命中语义无文档也无测试固化 @
rtp_llm/models_py/kernel_tuning/aiter/configs/gfx942_cu80_fmoe_m1_16_h2048_i128_e256_topk8_bf16_fp8pt.csv:2- 建议:二选一并落到可验证形态:若为向上取桶,请在
_AFFECTED_TOKEN_BUCKETS处或同目录说明中写明该语义及其在 pin 定版本中的出处;若为精确匹配,请补齐 token 1~16 全部行,或把命名与文案从m1_16改为明确的离散桶表述。同时在 ROCm 用例的 token 循环里加入 3、7、15 等非桶边界值,使「小 token 已覆盖」有测试支撑。
- 建议:二选一并落到可验证形态:若为向上取桶,请在
P3
- arch 与 dispatch key 依赖 getattr 字面量探测与第三方枚举的
__str__,跨版本易静默漂移 @rtp_llm/models_py/kernel_tuning/registry.py:21- 建议:抽出统一的
current_gfx_arch()工具函数供 registry 与 rocm_moe 复用(并与device_impl的 arch 解析对齐),在已确认 HIP 的分支内直接属性访问properties.gcnArchName,让缺失以 AttributeError 暴露(registry.py:22 已有except Exception兜底并 warning)。同时补一条无需 GPU 的断言固化str(aiter.ActivationType.Silu) == "ActivationType.Silu"、str(aiter.QuantType.per_Token) == "QuantType.per_Token",让上游表示变化在 CI 暴露。
- 建议:抽出统一的
- kernel_tuning BUILD 的 srcs/data glob 只覆盖一层目录,新增 provider 会静默漏出 runfiles @
rtp_llm/models_py/kernel_tuning/BUILD:3- 建议:改为递归 glob(
"**/*.py"、"**/*.csv",必要时排除test/),使新增 provider 目录默认被打包,避免扩展时出现只能在特定 arch 上复现的运行期缺文件问题。
- 建议:改为递归 glob(
- 单测直接读写模块私有全局状态,并跨模块引用私有符号 @
rtp_llm/models_py/kernel_tuning/test/aiter_fmoe_test.py:32- 建议:为
_CONFIG_STATUS提供一个显式的reset_kernel_tuning_status()测试钩子(或让configure_aiter_fmoe_overlays接受force_refresh参数,替代直接赋值),并把被跨模块稳定依赖的_aiter_fmoe_workload_signature、_moe_activation_type提升为不带下划线的模块级公开函数,使测试依赖显式契约而非私有实现细节。
- 建议:为
Checklist Findings (24 fail / 55 total)
General Principles Checklist
- [6.1] Architecture — 兼容性:外部 HTTP/RPC API、持久数据、配置、环境迁移安全 → issue
arch 与 dispatch key 依赖 getattr 字面量探测与第三方枚举的str,跨版本易静默漂移
registry._current_rocm_arch(registry.py:21)与_aiter_fmoe_workload_signature(rocm_moe.py:67)均用str(getattr(properties, "gcnArchName", "")).split(":", 1)[0];registry.py:17 已确认torch.version.hip is not None,该分支内属性必然存在,用 getattr 兜空串会让属性缺失静默退化为「非 gfx942」,掩盖真实环境问题,且device_impl.py另有一套基于设备名的 arch 解析,仓内实现不一致。同时 dispatch key 的act_type/q_type直接依赖str(aiter.ActivationType.Silu)、str(aiter.QuantType.per_Token)恰好渲染为"ActivationType.Silu"/"QuantType.per_Token"(rocm_moe.py:75,79),该第三方约 - [6.1] Architecture — 分层边界:新概念在正确层级,不泄漏内部 → issue
启动期用 glob 重建的列表整体覆写AITER_CONFIG_FMOE,波及进程内所有 gfx942 MoE 负载
registry.py:11 仅以gfx942为键注册 provider,start_backend_server.py:92 对任意 gfx942 rank 无条件调用,因此与 overlay 形状完全无关的 dense/embedding 服务也会在 fmoe.py:260 把该变量从「未设置(由 AITER 自决)」覆写为 RTP 拼出的列表。该列表由_stock_fmoe_configs(fmoe.py:104-111)用glob("*tuned_fmoe*.csv")排除 untuned 自行重建 AITER 的默认发现集合;sha256 只锁单文件内容,不覆盖文件集合的新增/改名。全仓除新代码与其单测外无一处引用AITER_CONFIG_FMOE,其 pathsep 多路径与「替换默认集合」语义在仓内无文档无断言。一旦重建结果与上游默认集合或优先级不一致,同进程内所有 FMoE 形状(含不做任何校验的RocmExpertsBf16)的 dispatch 都会随之变化。 - [6.1] Architecture — 可观测性:日志/指标/超时可操作、非噪声 → issue
调优产物的性能与精度列全为 0.0 占位,且无生成来源记录,收益与精度不可复核
5 行数据的us1、us2、us、tflops、bw全为0.0,err1、err2全为0.0%。目录名kernel_tuning与 fmoe.py:286 的 "reviewed one-stage tuning overlay" 均声称这是调优产物,但零值与「基准未跑」无法区分:既不能证明所选 kernel 快于 stock 行,也不能证明精度误差曾被校验,err1=0.0%更是一条未经测量的正确性声明。仓内也检索不到生成命令、机型或 AITER commit 记录,fmoe.py:287 却要求维护者「Revalidate the small-token FMoE kernels」。AITER 升级迫使版本常量上调时没有基线可比,只能盲测重做。 - [6.1] Architecture — 回滚路径:风险行为存在运维回滚手段 → issue
调优产物的性能与精度列全为 0.0 占位,且无生成来源记录,收益与精度不可复核
5 行数据的us1、us2、us、tflops、bw全为0.0,err1、err2全为0.0%。目录名kernel_tuning与 fmoe.py:286 的 "reviewed one-stage tuning overlay" 均声称这是调优产物,但零值与「基准未跑」无法区分:既不能证明所选 kernel 快于 stock 行,也不能证明精度误差曾被校验,err1=0.0%更是一条未经测量的正确性声明。仓内也检索不到生成命令、机型或 AITER commit 记录,fmoe.py:287 却要求维护者「Revalidate the small-token FMoE kernels」。AITER 升级迫使版本常量上调时没有基线可比,只能盲测重做。 - [6.1] Architecture — 状态不变量:创建/更新/失败/重试/回滚路径有效 → issue ``applied=True
只代表环境变量已写入,无法证明 AITER 真正消费了 overlay,兜底调用还发生在 import aiter 之后
fmoe.py:260-262 写完 env 即返回 `applied=True`,`require_aiter_fmoe_tuning` 以此放行。整套机制依赖三个仓内无文档、无断言的上游假设:AITER 按 `os.pathsep` 解析多路径、该变量完全替换默认列表、且在首次 FMoE 查表时才读取。`configure_kernel_tuning` 只挂在 start_backend_server.py:92;不经该入口时只能依赖 rocm_moe.py:253 的兜底,而 rocm_moe.py:4,6 在模块导入期已执行 `import aiter`。唯一跑真实 aiter 的 rocm_fp8_fused_moe_test 亦在顶层导入 aiter 且从不调用 `configure_kernel_tuning()`,判据只有 cosine——若 AITER 在导入期快照 env,overlay 静默失效而用例照样通过,恰是 fail-closed 想拦住的场景。 - [6.1] Architecture — 错误语义:fail-fast/retry/fallback/silent 行为显式 → issue
启动期可选性能 overlay 未做 fail-open 保护,其 I/O 异常会击穿全部 rank 启动
第 92 行configure_kernel_tuning()为裸调用,位于local_rank_start的 try 块内,异常会落到 :116-122 的except BaseException,经_send_pipe_status(failed)让该 rank 与整个后端启动失败。但本文件对可选启动特性一律 fail-open:_install_hot_hook_runtime(:37-44 try/except 仅 log)、JIT cache(JIT_CACHE_FAIL_OPEN继续冷启)。而 provider 内部并非全程 fail-open:registry.py:34 的provider()无保护,fmoe.py:200-202 的locate_file(...).resolve()、:209 的_sha256(内部path.open("rb"))、:226 的_stock_fmoe_configsglob 均位于 :227 的 try 之外,仅is_file()之后的 I/O 竞态即可 - [6.1] Quality — Commit 原子、message 与行为匹配 → issue
未证明 provision 就绪的 ROCm MTP smoke suite 被并入顶层 CI 聚合 suite,且阻塞说明被同时删除
BUILD:78 把:smoke_rocm_qwen35_mtp加入顶层聚合 suitemaga_model_smoke;同一 PR 在 suites_rocm_oss.bzl:117 把原注释「Keep this suite standalone until Qwen3.6-27B is provisioned on the shared ROCm CI workers; run it directly on an MI308X host with that checkpoint」替换为「Keep this as a dedicated suite so CI and local runs can select it directly」——在删除阻塞说明的同时执行了该说明禁止的动作。该 suite 唯一用例(suites_rocm_oss.bzl:121-134)pin MI308X、PD 双角色,依赖共享存储上的主模型与草稿检查点,全部变更文件无 provision 就绪证据。该用例是 dense MTP + PD,与本 PR 的 AITER FMoE 调优主题无关, - [6.1] Quality — Mega-PR 已拆分为独立变更 → issue
未证明 provision 就绪的 ROCm MTP smoke suite 被并入顶层 CI 聚合 suite,且阻塞说明被同时删除
BUILD:78 把:smoke_rocm_qwen35_mtp加入顶层聚合 suitemaga_model_smoke;同一 PR 在 suites_rocm_oss.bzl:117 把原注释「Keep this suite standalone until Qwen3.6-27B is provisioned on the shared ROCm CI workers; run it directly on an MI308X host with that checkpoint」替换为「Keep this as a dedicated suite so CI and local runs can select it directly」——在删除阻塞说明的同时执行了该说明禁止的动作。该 suite 唯一用例(suites_rocm_oss.bzl:121-134)pin MI308X、PD 双角色,依赖共享存储上的主模型与草稿检查点,全部变更文件无 provision 就绪证据。该用例是 dense MTP + PD,与本 PR 的 AITER FMoE 调优主题无关, - [6.1] Quality — PR description 说明动机与设计 → issue
调优产物的性能与精度列全为 0.0 占位,且无生成来源记录,收益与精度不可复核
5 行数据的us1、us2、us、tflops、bw全为0.0,err1、err2全为0.0%。目录名kernel_tuning与 fmoe.py:286 的 "reviewed one-stage tuning overlay" 均声称这是调优产物,但零值与「基准未跑」无法区分:既不能证明所选 kernel 快于 stock 行,也不能证明精度误差曾被校验,err1=0.0%更是一条未经测量的正确性声明。仓内也检索不到生成命令、机型或 AITER commit 记录,fmoe.py:287 却要求维护者「Revalidate the small-token FMoE kernels」。AITER 升级迫使版本常量上调时没有基线可比,只能盲测重做。 - [6.1] Quality — 逻辑变更未混入无关格式化 → issue
未证明 provision 就绪的 ROCm MTP smoke suite 被并入顶层 CI 聚合 suite,且阻塞说明被同时删除
BUILD:78 把:smoke_rocm_qwen35_mtp加入顶层聚合 suitemaga_model_smoke;同一 PR 在 suites_rocm_oss.bzl:117 把原注释「Keep this suite standalone until Qwen3.6-27B is provisioned on the shared ROCm CI workers; run it directly on an MI308X host with that checkpoint」替换为「Keep this as a dedicated suite so CI and local runs can select it directly」——在删除阻塞说明的同时执行了该说明禁止的动作。该 suite 唯一用例(suites_rocm_oss.bzl:121-134)pin MI308X、PD 双角色,依赖共享存储上的主模型与草稿检查点,全部变更文件无 provision 就绪证据。该用例是 dense MTP + PD,与本 PR 的 AITER FMoE 调优主题无关, - [6.1] Software Engineering — DRY:重复非平凡逻辑被抽取或显式复用 → issue
测试自行复刻生产 fp8 fn→fnuz 转换并遗漏 gfx950 分支,且用new绕过 device 构造
_online_loader_quant_fp8(:61-69)在量化后自行做bits[bits == -128] = 0+view(torch.float8_e4m3fnuz)+scale * 2.0,与device/device_impl.py:1007-1025的RocmImpl.convert_fp8_weight_params完全同义,但丢掉了其中的_is_gfx950()直通分支(:1011),在 gfx950 上与生产语义相反。注释仍称 "Reproduce the FP8 loader conversion",实为测试侧复制品:生产转换变更不会被这条用例发现,且参考权重由同一份被放大的 scale 构造,测试对自身修正完全自洽。此外 :281 用RocmImpl.__new__(RocmImpl)绕过__init__调用cat_0/shuffle_moe_weight,被调方法将来若依赖实例状态会以未初始化状态运行。 - [6.1] Software Engineering — KISS/YAGNI:无投机性抽象 → issue
单测直接读写模块私有全局状态,并跨模块引用私有符号
测试在 setUp/tearDown 直接赋值fmoe._CONFIG_STATUS(:25、:32),并依赖_DISPATCH_KEY_FIELDS、_AFFECTED_TOKEN_BUCKETS、_SUPPORTED_AITER_VERSION、_SUPPORTED_DEFAULT_CONFIG_SHA256、_OVERLAY_CONFIG、_status、_AFFECTED_WORKLOAD_SIGNATURES等多个私有符号;rocm_fp8_fused_moe_test.py 还跨模块导入_aiter_fmoe_workload_signature、_moe_activation_type。私有实现一旦重命名,测试会以 AttributeError 而非有意义的断言失败告终,且缓存状态靠手工赋值复位,遗漏即产生用例间串扰。 - [6.1] Software Engineering — LSP:子类/重写保持基类契约 → issue ``execute()
激活一致性校验只加在 1 个 executor 上,未修 activation 未从 config 接线的根因
`FusedMoeModularKernel.forward` 的 `activation` 参数在仓内唯一生产调用方 `models_py/model_desc/generic_moe.py:223` 被硬编码为 `"SiGLU"`,没有任何调用方传入 `config.activation_type`。本 PR 只为 `RocmExpertsFp8PerChannel` 在 rocm_moe.py:291-296 增加「与 `init` 解析结果不一致即抛 ValueError」的校验:对 activation_type 非 silu 家族的 MoE 模型,只要通过 `init` 白名单,每次 forward 都会抛错;而 `RocmExpertsBf16`(:197)与 Fp8PerBlock / Fp4PerGroup / MXFp4 仍继续静默使用调用方硬编码值,五个 executor 的失败语义不一致。 - [6.1] Software Engineering — OCP:本地扩展点优先于修改中心逻辑 → issue
kernel_tuning BUILD 的 srcs/data glob 只覆盖一层目录,新增 provider 会静默漏出 runfiles
srcs = glob(["*.py", "aiter/*.py"])(BUILD:3-6)与data = glob(["aiter/configs/*.csv"])(:7-9)都只匹配单层。而 registry.py:11 的_PROVIDERS_BY_ARCH正是本模块声明的扩展点:后续新增 provider 子目录或把 CSV 放进子目录时,文件不会进入 srcs/data,构建仍然成功,只在目标 arch 的运行时以 ImportError 或「RTP AITER FMoE overlay is missing」形式暴露——而后者对受影响签名等价于硬失败。同仓//rtp_llm/models_py:modules等 py_library 已使用modules/**/*.py这类递归 glob。 - [6.1] Software Engineering — SRP:模块/类职责单一 → issue
签名的q_dtype_a取权重 dtype 代理激活量化 dtype,dtype 分叉时 fail-closed 守卫静默变为 fail-open
_aiter_fmoe_workload_signature用q_dtype_a=str(w1.dtype)、q_dtype_w=str(w2.dtype)构造 dispatch key,并把q_type硬写为aiter.QuantType.per_Token。AITER 的q_dtype_a语义是激活量化 dtype、q_dtype_w是权重量化 dtype,这里两者都取自权重张量,仅因当前路径 w1/w2 与激活都是float8_e4m3fnuz才碰巧相等;而_utils.get_rocm_fp8_dtype()在 gfx950 上返回float8_e4m3fn。一旦激活量化 dtype 与权重 dtype 分叉,或 w1/w2 dtype 不同,构造出的签名就不等于 AITER 真实 dispatch key,is_affected_aiter_fmoe_signature返回 False,fmoe.py:274 直接 return,守卫静默失效。 - [6.1] Tests — 分布式/跨平台变更有对应覆盖 → issue
registry_test 未覆盖所有 CUDA/CPU/PPU 部署必经的非 ROCm no-op 路径,也未断言真实 provider 表
configure_kernel_tuning()已被无条件插入所有平台的 backend 启动路径(start_backend_server.py:92),「在 CUDA/CPU/PPU 上必须零副作用 no-op」是本次改动最关键的跨平台安全属性。但两个用例都显式传入 arch(:15-16 的 "gfx942"/"gfx950"),registry.py:32 的默认参数路径从未执行;_current_rocm_arch只覆盖 gfx942 成功分支,torch.cuda.is_available()为 False、torch.version.hip is None(:17)、get_device_properties抛异常(:22)三条返回 None 的分支都无用例。唯一执行local_rank_start的 jit_cache_manager_test 又把该函数整体 mock 掉。:13 的clear=True还整表替换,真实_PROVIDERS_BY_ARCH是否仍注册 gfx942 也无断言。 - [6.1] Tests — 新逻辑有聚焦单测 + 相关集成/smoke 测试 → issue
overlay 只覆盖 token 精确值 1/2/4/8/16,中间 token 的命中语义无文档也无测试固化
CSV 仅有 token=1、2、4、8、16 五行,fmoe.py:41 的_AFFECTED_TOKEN_BUCKETS要求行集合与之精确相等,require_aiter_fmoe_tuning一旦配置成功即视为该 workload 小 token 路径已覆盖。但文件名m1_16与 fmoe.py:285 的 "for token buckets" 都暗示意图覆盖 1..16 区间,而仓内没有任何地方固化 AITER 把任意 token 映射到这些行的规则(精确匹配还是向上取桶);rocm_fp8_fused_moe_test.py:359 的 token 循环同样只取 (1,2,4,8,16)。若为精确匹配,token=3、57、915 仍走本 PR 认定不佳的 stock 行,覆盖率不足一半,而状态与错误文案都显示 overlay 已生效,形成覆盖假象。 - [6.1] Tests — 边界 case 覆盖(空、单元素、最大值) → issue
overlay 只覆盖 token 精确值 1/2/4/8/16,中间 token 的命中语义无文档也无测试固化
CSV 仅有 token=1、2、4、8、16 五行,fmoe.py:41 的_AFFECTED_TOKEN_BUCKETS要求行集合与之精确相等,require_aiter_fmoe_tuning一旦配置成功即视为该 workload 小 token 路径已覆盖。但文件名m1_16与 fmoe.py:285 的 "for token buckets" 都暗示意图覆盖 1..16 区间,而仓内没有任何地方固化 AITER 把任意 token 映射到这些行的规则(精确匹配还是向上取桶);rocm_fp8_fused_moe_test.py:359 的 token 循环同样只取 (1,2,4,8,16)。若为精确匹配,token=3、57、915 仍走本 PR 认定不佳的 stock 行,覆盖率不足一半,而状态与错误文案都显示 overlay 已生效,形成覆盖假象。
RTP-LLM Checklist
- [I] 代码质量 — 删除或重命名内部 file、registry entry、model name、metric enum、op binding、plugin symbol 时,必须全仓搜索消费者,并提供替代实现、迁移说明或 smoke 覆盖;只有暴露到 HTTP/RPC/config/persisted format 时才按外部兼容性处理 → issue
registry_test 未覆盖所有 CUDA/CPU/PPU 部署必经的非 ROCm no-op 路径,也未断言真实 provider 表
configure_kernel_tuning()已被无条件插入所有平台的 backend 启动路径(start_backend_server.py:92),「在 CUDA/CPU/PPU 上必须零副作用 no-op」是本次改动最关键的跨平台安全属性。但两个用例都显式传入 arch(:15-16 的 "gfx942"/"gfx950"),registry.py:32 的默认参数路径从未执行;_current_rocm_arch只覆盖 gfx942 成功分支,torch.cuda.is_available()为 False、torch.version.hip is None(:17)、get_device_properties抛异常(:22)三条返回 None 的分支都无用例。唯一执行local_rank_start的 jit_cache_manager_test 又把该函数整体 mock 掉。:13 的clear=True还整表替换,真实_PROVIDERS_BY_ARCH是否仍注册 gfx942 也无断言。 - [I] 代码质量 — 同一功能用统一工具函数 → issue
arch 与 dispatch key 依赖 getattr 字面量探测与第三方枚举的str,跨版本易静默漂移
registry._current_rocm_arch(registry.py:21)与_aiter_fmoe_workload_signature(rocm_moe.py:67)均用str(getattr(properties, "gcnArchName", "")).split(":", 1)[0];registry.py:17 已确认torch.version.hip is not None,该分支内属性必然存在,用 getattr 兜空串会让属性缺失静默退化为「非 gfx942」,掩盖真实环境问题,且device_impl.py另有一套基于设备名的 arch 解析,仓内实现不一致。同时 dispatch key 的act_type/q_type直接依赖str(aiter.ActivationType.Silu)、str(aiter.QuantType.per_Token)恰好渲染为"ActivationType.Silu"/"QuantType.per_Token"(rocm_moe.py:75,79),该第三方约
Python Static-First Checklist
- [P.A] 静态结构与类型纪律 — 字符串分发用 Enum/Literal → issue
arch 与 dispatch key 依赖 getattr 字面量探测与第三方枚举的str,跨版本易静默漂移
registry._current_rocm_arch(registry.py:21)与_aiter_fmoe_workload_signature(rocm_moe.py:67)均用str(getattr(properties, "gcnArchName", "")).split(":", 1)[0];registry.py:17 已确认torch.version.hip is not None,该分支内属性必然存在,用 getattr 兜空串会让属性缺失静默退化为「非 gfx942」,掩盖真实环境问题,且device_impl.py另有一套基于设备名的 arch 解析,仓内实现不一致。同时 dispatch key 的act_type/q_type直接依赖str(aiter.ActivationType.Silu)、str(aiter.QuantType.per_Token)恰好渲染为"ActivationType.Silu"/"QuantType.per_Token"(rocm_moe.py:75,79),该第三方约 - [P.A] 静态结构与类型纪律 — 禁止 getattr/setattr literal 访问 → issue
arch 与 dispatch key 依赖 getattr 字面量探测与第三方枚举的str,跨版本易静默漂移
registry._current_rocm_arch(registry.py:21)与_aiter_fmoe_workload_signature(rocm_moe.py:67)均用str(getattr(properties, "gcnArchName", "")).split(":", 1)[0];registry.py:17 已确认torch.version.hip is not None,该分支内属性必然存在,用 getattr 兜空串会让属性缺失静默退化为「非 gfx942」,掩盖真实环境问题,且device_impl.py另有一套基于设备名的 arch 解析,仓内实现不一致。同时 dispatch key 的act_type/q_type直接依赖str(aiter.ActivationType.Silu)、str(aiter.QuantType.per_Token)恰好渲染为"ActivationType.Silu"/"QuantType.per_Token"(rocm_moe.py:75,79),该第三方约 - [P.B] 错误处理 — 禁止 bare except 或静默吞异常 → issue
启动期可选性能 overlay 未做 fail-open 保护,其 I/O 异常会击穿全部 rank 启动
第 92 行configure_kernel_tuning()为裸调用,位于local_rank_start的 try 块内,异常会落到 :116-122 的except BaseException,经_send_pipe_status(failed)让该 rank 与整个后端启动失败。但本文件对可选启动特性一律 fail-open:_install_hot_hook_runtime(:37-44 try/except 仅 log)、JIT cache(JIT_CACHE_FAIL_OPEN继续冷启)。而 provider 内部并非全程 fail-open:registry.py:34 的provider()无保护,fmoe.py:200-202 的locate_file(...).resolve()、:209 的_sha256(内部path.open("rb"))、:226 的_stock_fmoe_configsglob 均位于 :227 的 try 之外,仅is_file()之后的 I/O 竞态即可 - [P.G] 测试规范 — mock/fake/stub 不得替代本次声称覆盖的生产边界 → issue
单测直接读写模块私有全局状态,并跨模块引用私有符号
测试在 setUp/tearDown 直接赋值fmoe._CONFIG_STATUS(:25、:32),并依赖_DISPATCH_KEY_FIELDS、_AFFECTED_TOKEN_BUCKETS、_SUPPORTED_AITER_VERSION、_SUPPORTED_DEFAULT_CONFIG_SHA256、_OVERLAY_CONFIG、_status、_AFFECTED_WORKLOAD_SIGNATURES等多个私有符号;rocm_fp8_fused_moe_test.py 还跨模块导入_aiter_fmoe_workload_signature、_moe_activation_type。私有实现一旦重命名,测试会以 AttributeError 而非有意义的断言失败告终,且缓存状态靠手工赋值复位,遗漏即产生用例间串扰。
Strengths
AiterFmoeWorkloadSignature(fmoe.py:44)用 frozen dataclass 显式建模 dispatch key,明确排除 model 名与 tp_size/ep_size;aiter_fmoe_test.py:160以dataclasses.fields+replace逐字段反证,rocm_fp8_fused_moe_test.py:336用 tp_size=2/4 两组配置验证「TP 不同但本地 dispatch 形状相同」,有效防住「按模型名打补丁」这一常见反模式。- overlay 采取「只追加、不覆盖」策略,
_validated_overlay_dispatch_keys(fmoe.py:129)同时校验缺列、_tag为空(AITER 排除带 tag 行)、key 集合与_AFFECTED_WORKLOAD_SIGNATURES × _AFFECTED_TOKEN_BUCKETS精确相等及行数一致,并与 stock 表做 key 交集检测,上游一旦补上同 key 行即自动停用并给出可操作 reason,三条都有对应单测。 - 启动时序契约选点准确且被锁定:
configure_kernel_tuning()位于setup_cuda_device_and_accl_env(内部torch.cuda.set_device)之后、BackendManager导入与构造之前(start_backend_server.py:91-99);jit_cache_manager_test.py:1085以events == ["device", "tuning", "backend"]把该隐式不变量固化为机械断言,且mock.patch.object打在使用处而非定义处,符合 P.P.G.1。 - 跨平台自动退化为真 no-op:
registry.py:17以torch.cuda.is_available()与torch.version.hip is None短路,CUDA/ARM/CPU 走_PROVIDERS_BY_ARCH.get(None, ());kernel_tuning只依赖标准库、torch 与本地types,对 aiter 用importlib.metadata.distribution探测而非顶层导入,未把 ROCm 依赖泄漏进通用 bootstrap。 - 构建接线干净无环:
kernel_tuning仅依赖 pip alias//rtp_llm:torch,rtp_llm/BUILD:493与rtp_llm/models_py/BUILD:62分别满足start_backend_server.py与rocm_moe.py的新 import,CSV 经dataglob 进入 runfiles 并被无需 GPU 的aiter_fmoe_test.py:190真实读取。 - CSV 制品本身自洽无错位:表头 26 列与 5 行字段数对齐;13 个 key 列与
_AFFECTED_WORKLOAD_SIGNATURES逐字段一致;run_1stage=1与kernelName2=Null、us2=0.0自洽;block_m=32与符号尾部ps_32x128及inter_dim=128自洽;mangling 长度前缀48与标识符实际长度精确吻合;e4m3fnuz符合 gfx942 约定;cu_num=80使作用域天然收窄。 KernelTuningStatus用 frozen dataclass 承载overlay/applied/reason/dependency_version,inactive 时registry.py:38输出结构化 warning 而非静默 return,比返回 bool 或字符串更可观测。rocm_moe.py:291新增「execute 收到的 activation 必须与 ModelConfig 解析结果一致」校验,主动暴露了forward(activation=...)硬编码值与config.activation_type未接线的历史隐患。
| ":smoke_rocm_dense", | ||
| ":smoke_rocm_moe", | ||
| ":smoke_rocm_qwen35_mrope_cg", | ||
| ":smoke_rocm_qwen35_mtp", |
There was a problem hiding this comment.
[P1] 未证明 provision 就绪的 ROCm MTP smoke suite 被并入顶层 CI 聚合 suite,且阻塞说明被同时删除
BUILD:78 把 :smoke_rocm_qwen35_mtp 加入顶层聚合 suite maga_model_smoke;同一 PR 在 suites_rocm_oss.bzl:117 把原注释「Keep this suite standalone until Qwen3.6-27B is provisioned on the shared ROCm CI workers; run it directly on an MI308X host with that checkpoint」替换为「Keep this as a dedicated suite so CI and local runs can select it directly」——在删除阻塞说明的同时执行了该说明禁止的动作。该 suite 唯一用例(suites_rocm_oss.bzl:121-134)pin MI308X、PD 双角色,依赖共享存储上的主模型与草稿检查点,全部变更文件无 provision 就绪证据。该用例是 dense MTP + PD,与本 PR 的 AITER FMoE 调优主题...
建议: 拆成独立变更:本 PR 只保留 kernel tuning 内容。若确认检查点已在共享 ROCm worker 就位,请在 PR 描述中给出可核验依据(provision 记录或一次包含该 suite 的绿色 ROCm CI run),再单独提交聚合 suite 的成员变更;否则回退第 78 行并还原注释中记录的阻塞原因,不要用「改注释」代替「解除阻塞」。拆分后 kernel tuning 改动也可独立 bisect。
Checklist: [6.1] Commit 原子、message 与行为匹配;[6.1] Mega-PR 已拆分为独立变更;[6.1] 逻辑变更未混入无关格式化
| return _CONFIG_STATUS | ||
|
|
||
| version = distribution.version | ||
| if version != _SUPPORTED_AITER_VERSION: |
There was a problem hiding this comment.
[P2] fail-closed 缺少运维逃生开关与 overlay 复核流程,版本门位于 env 分支之前使显式配置也无法兜底
版本不等(fmoe.py:192)、stock CSV sha256 变化(:210)、任一 stock CSV 缺 13 个 dispatch 列或 key 冲突(:229)中任意一条成立即 applied=False,随后 fmoe.py:283 在 executor __init__ 抛 RuntimeError,即模型加载期硬失败。版本门早于 fmoe.py:245 的 env 分支,因此运维手工设置 AITER_CONFIG_FMOE 也绕不过;aiter_fmoe_test.py:129 还把该行为固化为断言。全链路无降级开关,唯一恢复手段是改代码发版。错误信息要求「Revalidate the small-token FMoE kernels」,但仓内没有生成/复核该 CSV 的脚本或说明。此外 inactive 时 registry.py:38 会在每个 gfx942 rank 打 warning,与该形状无关的部署也会看到噪声。
建议: 增加显式逃生开关(如 RTP_AITER_FMOE_OVERLAY 取 auto/off/force),使运维可在不改代码的前提下降级为 warning;或把精确相等改为「已知不安全版本区间」语义,并把版本门移到 env 检查之后,使显式设置 AITER_CONFIG_FMOE 能作为有效兜底。在 kernel_tuning 包内补一份 overlay 生成与退役说明(tuning 命令、采集机型、如何刷新 version 与 sha256、失效后处理路径)。把 inactive warning 收敛为仅在命中受影响形状时输出。
| ) | ||
| return _CONFIG_STATUS | ||
| else: | ||
| config_paths = [*stock_configs, overlay_config] |
There was a problem hiding this comment.
[P2] 启动期用 glob 重建的列表整体覆写 AITER_CONFIG_FMOE,波及进程内所有 gfx942 MoE 负载
registry.py:11 仅以 gfx942 为键注册 provider,start_backend_server.py:92 对任意 gfx942 rank 无条件调用,因此与 overlay 形状完全无关的 dense/embedding 服务也会在 fmoe.py:260 把该变量从「未设置(由 AITER 自决)」覆写为 RTP 拼出的列表。该列表由 _stock_fmoe_configs(fmoe.py:104-111)用 glob("*tuned_fmoe*.csv") 排除 untuned 自行重建 AITER 的默认发现集合;sha256 只锁单文件内容,不覆盖文件集合的新增/改名。全仓除新代码与其单测外无一处引用 AITER_CONFIG_FMOE,其 pathsep 多路径与「替换默认集合」语义在仓内无文档无断言。一旦重建结果与上游默认集合或优先级不一致,同进程内所有 FMoE 形状(含不做任何校验的 RocmExpertsBf16)的 dispatch 都会随之变化。
建议: 优先只做追加而不接管:若 AITER 提供配置查询或追加入口,改用该接口而非路径 glob。若必须覆写,请在 configure 阶段把 _stock_fmoe_configs() 结果与 AITER 内部默认解析出的列表显式比对,不一致时返回 applied=False 并在 reason 中列出差集,并为该比对补一条基于真实 AITER 安装目录的用例(现有 test_configures_additive_overlay_and_keeps_model_configs 使用自写 fixture,属自证)。同时把写 env 的生效范围收窄到「确实命中受影响签名」时,并把最终生效清单写入日志便于线上排障。
Checklist: [6.1] 分层边界:新概念在正确层级,不泄漏内部
| config_paths = [*stock_configs, overlay_config] | ||
| os.environ["AITER_CONFIG_FMOE"] = os.pathsep.join(map(str, config_paths)) | ||
|
|
||
| _CONFIG_STATUS = _status(True, "RTP AITER FMoE overlay configured", version) |
There was a problem hiding this comment.
[P2] applied=True 只代表环境变量已写入,无法证明 AITER 真正消费了 overlay,兜底调用还发生在 import aiter 之后
fmoe.py:260-262 写完 env 即返回 applied=True,require_aiter_fmoe_tuning 以此放行。整套机制依赖三个仓内无文档、无断言的上游假设:AITER 按 os.pathsep 解析多路径、该变量完全替换默认列表、且在首次 FMoE 查表时才读取。configure_kernel_tuning 只挂在 start_backend_server.py:92;不经该入口时只能依赖 rocm_moe.py:253 的兜底,而 rocm_moe.py:4,6 在模块导入期已执行 import aiter。唯一跑真实 aiter 的 rocm_fp8_fused_moe_test 亦在顶层导入 aiter 且从不调用 configure_kernel_tuning(),判据只有 cosine——若 AITER 在导入期快照 env,overlay 静默失效而用例照样通过,恰是 fail-closed 想拦住的场景。
建议: 在成功分支加后置校验:回读 AITER 解析出的 FMoE 配置来源列表并断言包含 overlay 路径,或对受影响探针 shape 断言最终命中的 kernel 名等于 CSV 中声明的 1tg_ps_32x128 变体,校验失败则 applied=False。补一条「在 import aiter 之后调用 configure_aiter_fmoe_overlays 仍然生效」的回归用例。若确实无法断言,请把状态字段语义改为「env 已配置(未验证生效)」并在日志中显式声明,不要以它作为 fail-closed 的唯一依据。
Checklist: [6.1] 状态不变量:创建/更新/失败/重试/回滚路径有效
| return [default_config, *model_configs] | ||
|
|
||
|
|
||
| def _dispatch_keys(config: Path) -> set[tuple[str, ...]]: |
There was a problem hiding this comment.
[P2] 两条 CSV 解析路径整段重复,且 _tag 过滤语义不对称可致误判 dispatch 冲突
_dispatch_keys(fmoe.py:114-126)与 _validated_overlay_dispatch_keys(fmoe.py:129-150)逐字重复了「打开 CSV、DictReader、检查 _DISPATCH_KEY_FIELDS 缺列、抛同一条 ValueError、按字段 strip 构造 key 元组」这段非平凡逻辑,后续调整 dispatch 列必须双改。更关键的是语义不对称:overlay 侧因「AITER 排除带 tag 行」而要求 _tag 为空(fmoe.py:140-145),但 stock 侧 _dispatch_keys 不做任何 tag 过滤,于是上游一条带 tag、本就不参与常规 dispatch 的 stock 行只要 key 相同,就会在 fmoe.py:230 被判为冲突,令 overlay 无谓停用并使受影响形状硬失败。
建议: 抽出 _read_dispatch_rows(config) -> list[dict] 统一负责打开与缺列校验,两个调用方各自在其上做 key 构造与额外校验;并在 stock 侧同样按 _tag 非空过滤掉不参与常规 dispatch 的行,使两条路径的 tag 语义与 AITER 的实际 dispatch 集合一致。补一条「stock 存在同 key 但带 tag 的行时 overlay 仍应生效」的用例。
| if activation in ("silu", "SiGLU"): | ||
| return aiter.ActivationType.Silu | ||
| return aiter.ActivationType.Gelu | ||
| _MOE_ACTIVATION_TYPES = { |
There was a problem hiding this comment.
[P2] 激活映射收窄后 GELU 家族由静默回退变为构造期硬失败,且被 5 个 ROCm executor 共用
旧实现为「非 silu 一律回退 Gelu」;新 _MOE_ACTIVATION_TYPES(rocm_moe.py:34-40)只列 gelu/gated-silu/siglu/silu/swiglu 五键,未命中即抛 ValueError(:52-56)。而 ActivationType(ops/libth_transformer_config.pyi:21-45)仍含 Geglu、GeluNoneApproximate、GeGluNoneApproximate、Relu、Identity、Sigmoid,仓内确有配置 gated-gelu 与 gelu-none-approximate 的模型。本 PR 新增 rocm_moe.py:249 把已归一化的 config.activation_type 喂进白名单,此类 MoE checkpoint 会在 executor __init__ 直接抛错;_moe_activation_type 被 :197/:249/:290 等 5 个 ROCm executor 共用。新测试只覆盖 silu 别名...
建议: 把 geglu、gated-gelu、gelu-none-approximate、geglu-none-approximate 一并映射到 aiter.ActivationType.Gelu(gating 交由 use_g1u1 表达)以保持既有行为,仅对 Identity/Sigmoid/Relu 这类确实不支持的值显式报错,并在错误信息中写明「ROCm FMoE 暂不支持」。补一条参数化用例枚举 ActivationType 全部成员,使新增 enum 成员在测试而非线上暴露。同时把入参类型收敛为 Union[str, ActivationType] 并用 isinstance 分支,替代 rocm_moe.py:48 的 str(getattr(activation, "name", activation)) 字面量探测。
| @@ -0,0 +1,6 @@ | |||
| cu_num,token,model_dim,inter_dim,expert,topk,act_type,dtype,q_dtype_a,q_dtype_w,q_type,use_g1u1,doweight_stage1,block_m,ksplit,us1,kernelName1,err1,us2,kernelName2,err2,us,run_1stage,tflops,bw,_tag | |||
| 80,1,2048,128,256,8,ActivationType.Silu,torch.bfloat16,torch.float8_e4m3fnuz,torch.float8_e4m3fnuz,QuantType.per_Token,1,0,32,0,0.0,_ZN5aiter48fmoe_bf16_pertokenFp8_g1u1_vs_silu_1tg_ps_32x128E,0.0%,0.0,Null,0.0%,0.0,1,0.0,0.0, | |||
There was a problem hiding this comment.
[P2] 调优产物的性能与精度列全为 0.0 占位,且无生成来源记录,收益与精度不可复核
5 行数据的 us1、us2、us、tflops、bw 全为 0.0,err1、err2 全为 0.0%。目录名 kernel_tuning 与 fmoe.py:286 的 "reviewed one-stage tuning overlay" 均声称这是调优产物,但零值与「基准未跑」无法区分:既不能证明所选 kernel 快于 stock 行,也不能证明精度误差曾被校验,err1=0.0% 更是一条未经测量的正确性声明。仓内也检索不到生成命令、机型或 AITER commit 记录,fmoe.py:287 却要求维护者「Revalidate the small-token FMoE kernels」。AITER 升级迫使版本常量上调时没有基线可比,只能盲测重做。
建议: 回填真实 tuning 输出的 us/tflops/bw/err;若上游 tuning 脚本不产出这些列,请在 configs/ 下补一份说明文件,记录生成命令、AITER 版本、设备 SKU(gfx942 80 CU)、日期,以及 stock 行与 overlay 的实测耗时与精度对比,并写明 overlay 的退役步骤。同时在 PR 描述中明确 stock dispatch 行究竟是数值错误还是仅性能退化——若仅是性能问题,fail-closed 的可用性代价不成立。
Checklist: [6.1] 可观测性:日志/指标/超时可操作、非噪声;[6.1] 回滚路径:风险行为存在运维回滚手段;[6.1] PR description 说明动机与设计
| @@ -0,0 +1,6 @@ | |||
| cu_num,token,model_dim,inter_dim,expert,topk,act_type,dtype,q_dtype_a,q_dtype_w,q_type,use_g1u1,doweight_stage1,block_m,ksplit,us1,kernelName1,err1,us2,kernelName2,err2,us,run_1stage,tflops,bw,_tag | |||
| 80,1,2048,128,256,8,ActivationType.Silu,torch.bfloat16,torch.float8_e4m3fnuz,torch.float8_e4m3fnuz,QuantType.per_Token,1,0,32,0,0.0,_ZN5aiter48fmoe_bf16_pertokenFp8_g1u1_vs_silu_1tg_ps_32x128E,0.0%,0.0,Null,0.0%,0.0,1,0.0,0.0, | |||
There was a problem hiding this comment.
[P2] overlay 只覆盖 token 精确值 1/2/4/8/16,中间 token 的命中语义无文档也无测试固化
CSV 仅有 token=1、2、4、8、16 五行,fmoe.py:41 的 _AFFECTED_TOKEN_BUCKETS 要求行集合与之精确相等,require_aiter_fmoe_tuning 一旦配置成功即视为该 workload 小 token 路径已覆盖。但文件名 m1_16 与 fmoe.py:285 的 "for token buckets" 都暗示意图覆盖 1..16 区间,而仓内没有任何地方固化 AITER 把任意 token 映射到这些行的规则(精确匹配还是向上取桶);rocm_fp8_fused_moe_test.py:359 的 token 循环同样只取 (1,2,4,8,16)。若为精确匹配,token=3、57、915 仍走本 PR 认定不佳的 stock 行,覆盖率不足一半,而状态与错误文案都显示 overlay 已生效,形成覆盖假象。
建议: 二选一并落到可验证形态:若为向上取桶,请在 _AFFECTED_TOKEN_BUCKETS 处或同目录说明中写明该语义及其在 pin 定版本中的出处;若为精确匹配,请补齐 token 1~16 全部行,或把命名与文案从 m1_16 改为明确的离散桶表述。同时在 ROCm 用例的 token 循环里加入 3、7、15 等非桶边界值,使「小 token 已覆盖」有测试支撑。
Checklist: [6.1] 新逻辑有聚焦单测 + 相关集成/smoke 测试;[6.1] 边界 case 覆盖(空、单元素、最大值)
| return None | ||
| try: | ||
| properties = torch.cuda.get_device_properties(torch.cuda.current_device()) | ||
| return str(getattr(properties, "gcnArchName", "")).split(":", 1)[0] or None |
There was a problem hiding this comment.
[P3] arch 与 dispatch key 依赖 getattr 字面量探测与第三方枚举的 __str__,跨版本易静默漂移
registry._current_rocm_arch(registry.py:21)与 _aiter_fmoe_workload_signature(rocm_moe.py:67)均用 str(getattr(properties, "gcnArchName", "")).split(":", 1)[0];registry.py:17 已确认 torch.version.hip is not None,该分支内属性必然存在,用 getattr 兜空串会让属性缺失静默退化为「非 gfx942」,掩盖真实环境问题,且 device_impl.py 另有一套基于设备名的 arch 解析,仓内实现不一致。同时 dispatch key 的 act_type/q_type 直接依赖 str(aiter.ActivationType.Silu)、str(aiter.QuantType.per_Token) 恰好渲染为 "ActivationType.Silu"/"QuantType.per_Token"(rocm_moe.py:75,79),该第...
建议: 抽出统一的 current_gfx_arch() 工具函数供 registry 与 rocm_moe 复用(并与 device_impl 的 arch 解析对齐),在已确认 HIP 的分支内直接属性访问 properties.gcnArchName,让缺失以 AttributeError 暴露(registry.py:22 已有 except Exception 兜底并 warning)。同时补一条无需 GPU 的断言固化 str(aiter.ActivationType.Silu) == "ActivationType.Silu"、str(aiter.QuantType.per_Token) == "QuantType.per_Token",让上游表示变化在 CI 暴露。
Checklist: [6.1] 兼容性:外部 HTTP/RPC API、持久数据、配置、环境迁移安全;[P.A] 字符串分发用 Enum/Literal;[P.A] 禁止 getattr/setattr literal 访问;[I] 同一功能用统一工具函数
| @@ -0,0 +1,26 @@ | |||
| py_library( | |||
| name = "kernel_tuning", | |||
| srcs = glob([ | |||
There was a problem hiding this comment.
[P3] kernel_tuning BUILD 的 srcs/data glob 只覆盖一层目录,新增 provider 会静默漏出 runfiles
srcs = glob(["*.py", "aiter/*.py"])(BUILD:3-6)与 data = glob(["aiter/configs/*.csv"])(:7-9)都只匹配单层。而 registry.py:11 的 _PROVIDERS_BY_ARCH 正是本模块声明的扩展点:后续新增 provider 子目录或把 CSV 放进子目录时,文件不会进入 srcs/data,构建仍然成功,只在目标 arch 的运行时以 ImportError 或「RTP AITER FMoE overlay is missing」形式暴露——而后者对受影响签名等价于硬失败。同仓 //rtp_llm/models_py:modules 等 py_library 已使用 modules/**/*.py 这类递归 glob。
建议: 改为递归 glob("**/*.py"、"**/*.csv",必要时排除 test/),使新增 provider 目录默认被打包,避免扩展时出现只能在特定 arch 上复现的运行期缺文件问题。
Checklist: [6.1] OCP:本地扩展点优先于修改中心逻辑
| os.environ["AITER_CONFIG_FMOE"] = self._old_env | ||
| else: | ||
| os.environ.pop("AITER_CONFIG_FMOE", None) | ||
| fmoe._CONFIG_STATUS = None |
There was a problem hiding this comment.
[P3] 单测直接读写模块私有全局状态,并跨模块引用私有符号
测试在 setUp/tearDown 直接赋值 fmoe._CONFIG_STATUS(:25、:32),并依赖 _DISPATCH_KEY_FIELDS、_AFFECTED_TOKEN_BUCKETS、_SUPPORTED_AITER_VERSION、_SUPPORTED_DEFAULT_CONFIG_SHA256、_OVERLAY_CONFIG、_status、_AFFECTED_WORKLOAD_SIGNATURES 等多个私有符号;rocm_fp8_fused_moe_test.py 还跨模块导入 _aiter_fmoe_workload_signature、_moe_activation_type。私有实现一旦重命名,测试会以 AttributeError 而非有意义的断言失败告终,且缓存状态靠手工赋值复位,遗漏即产生用例间串扰。
建议: 为 _CONFIG_STATUS 提供一个显式的 reset_kernel_tuning_status() 测试钩子(或让 configure_aiter_fmoe_overlays 接受 force_refresh 参数,替代直接赋值),并把被跨模块稳定依赖的 _aiter_fmoe_workload_signature、_moe_activation_type 提升为不带下划线的模块级公开函数,使测试依赖显式契约而非私有实现细节。
Checklist: [6.1] KISS/YAGNI:无投机性抽象;[P.G] mock/fake/stub 不得替代本次声称覆盖的生产边界
c71d2b6 to
ed7dcad
Compare
LLLLKKKK
left a comment
There was a problem hiding this comment.
AI Code Review - PR #1345
Status: LGTM
Summary: P0/0 · P1/0 · P2/18 · P3/4
Reviewed: commit ed7dcad62a4c · 2026-08-31 18:55 UTC+8
lgtm ready to ci
Non-blocking Suggestions
P2
- 未证明 provision 就绪的 ROCm MTP smoke 套件被并入顶层共享聚合套件,且阻塞说明被同时删除 @
rtp_llm/test/smoke/BUILD:86- 建议:请二选一:(1) 在 PR 描述中给出该 checkpoint 已在共享 ROCm CI worker 就绪的证据(例如一次绿色的
smoke_rocm_qwen35_mtp记录),并说明它与本 PR 的关系;(2) 从maga_model_smoke撤回该条目、恢复原注释与 standalone 状态,把 CI 纳管拆到独立提交——可参照仓内smoke_rocm_mxfp4/suites_sm100.bzl一类「不并入聚合、由独立 job 触发」的既有做法。鉴于该 fixture 对本 PR 的 overlay 无覆盖价值,建议按 (2) 拆分,避免 CI 拓扑变更与 FMoE tuning 功能在同一提交里相互掩盖失败原因,也便于 CI 二分定位。
- 建议:请二选一:(1) 在 PR 描述中给出该 checkpoint 已在共享 ROCm CI worker 就绪的证据(例如一次绿色的
- applied=True 只代表环境变量已写入,无法证明 AITER 真正消费了 overlay,兜底调用还发生在 import aiter 之后 @
rtp_llm/models_py/kernel_tuning/aiter/fmoe.py:262- 建议:补一道后置校验使「overlay 未真正生效」无法通过守卫,二选一或并用:(1)配置完成后回读 AITER 已加载的 FMoE dispatch 表,确认 overlay 的 5 条 key 在其中才置
applied=True;(2)在configure_aiter_fmoe_overlays开头检测"aiter" in sys.modules,已导入则返回applied=False并在 reason 中说明「配置时机过晚」。同时把最终生效的AITER_CONFIG_FMOE取值写入 reason 便于线上定位,并在 ROCm 用例中断言目标形状实际命中的 kernel 名为 overlay 声明的..._1tg_ps_32x128变体,使 fail-open 可被测试发现。
- 建议:补一道后置校验使「overlay 未真正生效」无法通过守卫,二选一或并用:(1)配置完成后回读 AITER 已加载的 FMoE dispatch 表,确认 overlay 的 5 条 key 在其中才置
- 启动期用 glob 重建的列表整体覆写 AITER_CONFIG_FMOE,波及进程内所有 gfx942 MoE 负载 @
rtp_llm/models_py/kernel_tuning/aiter/fmoe.py:259- 建议:把 env 改写收敛到确实需要的场景:让 provider 注册 key 带上 cu_num,或改为在
require_aiter_fmoe_tuning命中受影响签名时惰性配置,把影响面从「全部 gfx942 进程」压回目标形状。若必须在启动期注入,则写入前调用 AITER 自身的配置解析入口取回默认清单并断言与重建结果一致,不一致时返回applied=False而非继续覆写。同时在_stock_fmoe_configs与写入点补注释,写明「该变量为替换语义」以及 glob 复刻的是哪个 AITER 版本的目录约定,使后续升级有明确复核依据。
- 建议:把 env 改写收敛到确实需要的场景:让 provider 注册 key 带上 cu_num,或改为在
- fail-closed 缺少运维逃生开关,版本与哈希门位于 env 分支之前使显式配置也无法兜底 @
rtp_llm/models_py/kernel_tuning/aiter/fmoe.py:283- 建议:增加一个显式逃生开关(例如
RTP_ALLOW_UNTUNED_AITER_FMOE=1,默认保持现有 fail-closed 语义):置位时把 RuntimeError 降级为高等级错误日志(打印完整 reason 与命中签名,并提示「小 token 延迟可能显著上升」)并放行 stock 分发,同时把开关状态写入KernelTuningStatus.reason以便可观测;RuntimeError 文案中直接给出该开关名与「需重新 tuning 并更新 overlay」的操作指引。这样 aiter wheel 临时升级或打包漏文件时,线上表现为小 token 延迟回退而非整体不可用,运维具备不发版即可回滚的手段。
- 建议:增加一个显式逃生开关(例如
- 两条 CSV 解析路径整段重复,且 _tag 过滤语义不对称可致误判 dispatch 冲突 @
rtp_llm/models_py/kernel_tuning/aiter/fmoe.py:114- 建议:抽出一个共用的 CSV reader 统一两处对
_tag的语义:读取 stock 配置时同样跳过_tag非空的行(它们不参与普通 dispatch),overlay 侧继续保留「不允许带 tag」的强校验。这样 overlap 判定与 AITER 实际的 dispatch 集合一致,同时消除当前两段 CSV 解析代码的重复,后续新增 dispatch key 列时也只需改一处。建议补一条用例:stockmodel_configs中存在与 overlay 同 key 但带 tag 的行时,overlay 仍应正常生效。
- 建议:抽出一个共用的 CSV reader 统一两处对
- 激活映射收窄后 GELU 家族由静默回退变为构造期硬失败,且被 5 个 ROCm executor 共用 @
rtp_llm/models_py/modules/factory/fused_moe/impl/rocm/executors/rocm_moe.py:34- 建议:把 gated-GELU 一族显式登记回映射表(
geglu/gated-gelu/geglunoneapproximate/gelunoneapproximate→aiter.ActivationType.Gelu,与改动前行为一致,gated 语义由use_g1u1承载),ValueError 只保留给真正不支持的取值(如relu/sigmoid);若本意是「仅调优签名路径收紧」,则把严格校验限制在_aiter_fmoe_workload_signature内部,另 4 个与调优无关的 executor 保留原语义。同时在test_activation_type_normalization中补齐这批枚举取值,把「哪些 activation 在 ROCm MoE 上受支持」固化为契约,并在 PR 描述中显式声明这次收窄的兼容性影响。
- 建议:把 gated-GELU 一族显式登记回映射表(
- execute() 激活一致性校验与硬编码 SiGLU 的唯一调用方矛盾,且 5 个同族 executor 契约分裂 @
rtp_llm/models_py/modules/factory/fused_moe/impl/rocm/executors/rocm_moe.py:291- 建议:根因是调用方硬编码激活而非透传配置:建议让
generic_moe传入config.activation_type,然后把一致性检查从execute()上移到构造期一次性完成(或直接删除),避免把「调用方硬编码"SiGLU"、config 另有取值」这一既有不一致升级为 per-forward 异常,也省掉热路径上每次的字符串归一化。若短期无法改动调用方,请把该前置条件提取到FusedMoeExpertExecutor层由 5 个 executor 共享,让同族行为一致,并补一条「config 为 gelu 而 execute 传 SiGLU」的用例明确期望行为。
- 建议:根因是调用方硬编码激活而非透传配置:建议让
- 签名的 q_dtype_a 取权重 dtype 代理激活量化 dtype,dtype 分叉时 fail-closed 守卫静默变为 no-op @
rtp_llm/models_py/modules/factory/fused_moe/impl/rocm/executors/rocm_moe.py:77- 建议:按语义取值:
q_dtype_a用激活量化 dtype(该文件已 importget_rocm_fp8_dtype,或直接用self.quant_config.quant_dtype),q_dtype_w用w1.dtype,并在_aiter_fmoe_workload_signature中对w1.dtype != w2.dtype显式断言,避免「签名推导错误」与「workload 确实不受影响」在守卫处不可区分。输出 dtype 若构造期无法确定,可把该字段推导移到首次execute(),或显式断言compute_dtype与后续激活 dtype 一致。另请把「未命中」分支的日志从 debug 提到一次性 info,使推导错误与「gfx942 + FP8 per-token MoE 未命中任何 overlay 行」的部署组合在线上可观测。
- 建议:按语义取值:
- bundled overlay 断言退化为「行数正确且不抛异常」,真正决定选核的调优列零校验且 fixture schema 与真实文件不一致 @
rtp_llm/models_py/kernel_tuning/test/aiter_fmoe_test.py:232- 建议:在
_validated_overlay_dispatch_keys中补 payload 校验:要求block_m/ksplit/kernelName1/run_1stage列存在,run_1stage ∈ {0,1}、block_m为正整数、kernelName1非空且不等于Null、run_1stage=1时kernelName2 == "Null";并用正则^_ZN5aiter(\d+)(.+)E$解析kernelName1,断言长度前缀与捕获标识符长度一致(本行应为 48)。同时把 fixture 的 fieldnames 扩展为与真实 overlay 同构的列集合,避免 stub 掩盖 schema 漂移,并新增一条直接针对入库 CSV 逐行断言 payload 取值的用例。
- 建议:在
- 调优产物的性能与精度列全为 0.0 占位,且无生成来源记录,收益与精度不可复核 @
rtp_llm/models_py/kernel_tuning/aiter/configs/gfx942_cu80_fmoe_m1_16_h2048_i128_e256_topk8_bf16_fp8pt.csv:2- 建议:按 stock
tuned_fmoe.csv的格式回填目标机型上 token 1/2/4/8/16 的真实 tune 输出(至少us与err1;run_1stage=1时us2/kernelName2保持 AITER 自身的空值约定)。若工具链确实不产出这些列,则在aiter/configs/下新增一份 README 记录生成命令、tuning 机型与 gfx/CU 数、日期、AITER 版本,以及 overlay 行与 stock fallback 的 us/精度对照,并在_OVERLAY_CONFIG定义处注释指向它,使版本 bump 后的复核有明确基线;PR 描述中也应给出 token=1..16 的 before/after 数据。注意不要在 CSV 内插注释行——csv.DictReader会把它解析成数据行并触发严格行数校验失败。
- 建议:按 stock
- overlay 命中面比 fail-closed 声明更窄,中间 token 与 EP>1 的回落语义无文档也无测试 @
rtp_llm/models_py/kernel_tuning/aiter/configs/gfx942_cu80_fmoe_m1_16_h2048_i128_e256_topk8_bf16_fp8pt.csv:2- 建议:在
_AFFECTED_TOKEN_BUCKETS旁用一行注释写明 AITER 对token列的查表/取整语义与 bucket 选取依据,并明确 token > 16 时的预期行为;若为精确匹配则补齐 token 1..16 的全部行。同时注明expert/inter_dim为 EP/TP 分片后的本地值、本 overlay 仅覆盖 ep_size=1。覆盖上建议补一个在 aiter 可用时才运行的 gated 用例(或匹配该 signature 的 MI308X smoke case),断言若干非 2 的幂 token(如 5)确实命中 overlay 行而非 stock 回落,把当前只存在于作者头脑中的查表假设变成可回归的断言。
- 建议:在
- gate/up 交换施加两次相互抵消,注释声称复现的 loader reorder 实际未进入断言链 @
rtp_llm/models_py/modules/factory/fused_moe/impl/rocm/test/rocm_fp8_fused_moe_test.py:307- 建议:删掉 307-320 行的手工
cat,让shuffle_moe_weight成为唯一一次 reorder,与ffn_weight.py的生产顺序完全一致;并把参考权重改为交换后的张量(按同序cat后再 dequant),使测试与生产的 gate/up 语义对齐、真正具备发现朝向回归的能力。同时修正 283-284 行注释,明确它复现的是哪几步 loader 后处理(当前未覆盖maybe_rewrite_weight_by_key)。
- 建议:删掉 307-320 行的手工
- 测试自行复刻生产 fp8 fn→fnuz 转换并遗漏 gfx950 分支,且用 new 绕过 device 构造 @
rtp_llm/models_py/modules/factory/fused_moe/impl/rocm/test/rocm_fp8_fused_moe_test.py:61- 建议:按同目录既有约定(
rocm_mxfp4_fused_moe_test.py使用get_current_device())获取已初始化的设备实现,直接调用convert_fp8_weight_params(...)与shuffle_moe_weight(...),删除测试内的手写副本,使 gfx950 分支与后续转换改动都被同一条测试覆盖;或把[gate, up]重排与 shuffle 这段纯张量布局变换抽成不依赖实例状态的模块级函数供生产与测试共用。若确实要保留__new__写法,至少补一行注释说明所依赖的前提(仅走非 MXFP4 分支、不触碰实例状态)。
- 建议:按同目录既有约定(
- 新增 GPU 用例把宿主机型指纹硬编码为断言,非 gfx942/80CU 机型硬失败而非跳过 @
rtp_llm/models_py/modules/factory/fused_moe/impl/rocm/test/rocm_fp8_fused_moe_test.py:352- 建议:增加
skipUnless守卫:读取torch.cuda.get_device_properties(0)的gcnArchName与multi_processor_count,仅在 gfx942 且 CU 数为 80 时执行,其余机型在分配权重之前明确 skip 并给出原因;或按同目录rocm_mxfp4_fused_moe_test的既有约定拆成带专用 tag 的目标。另外 336 行的tp_size in (2, 4)循环使用同一份权重与同一签名,并未改变喂给 AITER 的本地 shape,却把重型 GPU 用例耗时翻倍,建议只保留一次执行 + 一条「签名与 tp_size 无关」的纯计算断言。
- 建议:增加
- 新增用例数值判据过弱,均值 cosine 掩盖单 token 偏差且对幅度误差不敏感 @
rtp_llm/models_py/modules/factory/fused_moe/impl/rocm/test/rocm_fp8_fused_moe_test.py:387- 建议:改用逐 token 判据(对 cosine 取
min()而非mean()),并补一条相对误差断言(如torch.testing.assert_close或最大相对误差上限)以覆盖幅度错误;同时按前述建议断言目标形状实际命中的 kernel 名称,使「overlay 生效」与「数值正确」两件事各有独立、可回归的判据。
- 建议:改用逐 token 判据(对 cosine 取
- aiter_fmoe_test 未按 ROCm 硬件调度,sha256 与已安装 wheel 校验恒为 skip,且缺少多条 fail-closed 分支覆盖 @
rtp_llm/models_py/kernel_tuning/BUILD:16- 建议:拆分目标:纯 Python 逻辑用例(fake distribution、临时 CSV、requirements 版本比对)保持无 tag 在通用 runner 上跑;把依赖真实 aiter 的断言拆到一个带
tags = ["rocm"]与exec_properties = {'gpu':'MI308X-ROCM7'}的 target(可复用同一 srcs + 显式main),并加注释说明它是该 sha256 常量的唯一直接校验点。同时给 CPU 目标补timeout,并用 fixture 构造 sha256 漂移、PackageNotFoundError、overlay 缺失三种情形补齐 fail-closed 分支断言。
- 建议:拆分目标:纯 Python 逻辑用例(fake distribution、临时 CSV、requirements 版本比对)保持无 tag 在通用 runner 上跑;把依赖真实 aiter 的断言拆到一个带
- registry_test 未覆盖所有 CUDA/CPU/PPU 部署必经的非 ROCm no-op 路径,也未断言真实 provider 表 @
rtp_llm/models_py/kernel_tuning/test/registry_test.py:12- 建议:补三条用例:(1)
torch.version.hip is None与torch.cuda.is_available()为 False 时_current_rocm_arch()返回 None 且configure_kernel_tuning()返回()并不修改os.environ;(2)get_device_properties抛异常时返回 None 且记录 warning;(3) 不打桩地断言set(registry._PROVIDERS_BY_ARCH) == {"gfx942"},使「新增 arch 必须同步更新测试」成为契约。这样 CUDA/CPU 平台的零影响结论有确定性守护,而不只靠人工推理。
- 建议:补三条用例:(1)
- 启动期可选性能 overlay 未做 fail-open 保护,其 I/O 异常会击穿全部 rank 启动 @
rtp_llm/start_backend_server.py:92- 建议:把第 92 行包成与本文件一致的 fail-open 形式(
try/except Exception+ 明确前缀的 error 日志),或在registry.configure_kernel_tuning内对每个 provider 调用做兜底并视作applied=False,让 overlay 自检异常只降级为「未加速」,由require_aiter_fmoe_tuning在真正命中受影响签名时再 fail-closed。同时在第 92 行补一行注释,说明该调用必须早于任何传递性import aiter的模块导入,把当前仅由行序隐式维持的排序不变量显式化。
- 建议:把第 92 行包成与本文件一致的 fail-open 形式(
P3
- arch 与 dispatch key 依赖 getattr 字面量探测与第三方枚举的 str,跨版本易静默漂移 @
rtp_llm/models_py/kernel_tuning/registry.py:21- 建议:把
gcnArchName缺失从静默降级改为一次性 warning,异常捕获收窄到具体类型;并在configure_aiter_fmoe_overlays成功分支中加一条一次性自检,把本进程推导出的枚举字符串与 overlay CSV 对应列比对,不一致时返回applied=False并说明「AITER 枚举文本已变更,overlay 可能失效」,使跨版本漂移在启动期显式暴露而非退化为静默 no-op。
- 建议:把
- kernel_tuning BUILD 的 srcs/data glob 只覆盖一层目录,新增 provider 会静默漏出 runfiles @
rtp_llm/models_py/kernel_tuning/BUILD:3- 建议:改为
glob(["**/*.py"], exclude = ["test/**"])与glob(["**/configs/*.csv"]),让目录结构演进自动被打包覆盖(同时确认test/不会被 srcs 意外吸入而与 py_test 的 srcs 重复);并在 overlay 缺失的 reason 中显式提示「检查 BUILD 的 data glob 与 wheel 打包」,缩短从现象到根因的距离。
- 建议:改为
- AITER 版本护栏漏掉第三处 pin,且非 Bazel fallback 路径可能读到与 CI 不同的文件 @
rtp_llm/models_py/kernel_tuning/test/aiter_fmoe_test.py:160- 建议:把
deps/http.bzl(deps/BUILD:5-10已exports_files)一并加入该 py_test 的data并纳入_AITER_WHEEL_VERSION_PATTERN的扫描集合(现有正则可直接复用),让三处 pin 必须同时一致;_runfile的 fallback 建议在缺少TEST_SRCDIR时直接 skip,避免读到与 CI 不同的文件而给出假绿。
- 建议:把
- 单测直接读写模块私有全局状态,并断言未 resolve 的临时路径 @
rtp_llm/models_py/kernel_tuning/test/aiter_fmoe_test.py:39- 建议:为
_CONFIG_STATUS提供一个显式的公开重置入口(如reset_kernel_tuning_status())供测试与多进程场景使用,避免直接写私有全局;断言前对期望路径统一Path(...).resolve(),或改为断言集合/顺序关系(stock 在前、overlay 在末)而非逐字符串相等,降低对宿主文件系统布局的耦合。
- 建议:为
Checklist Findings (19 fail / 55 total)
General Principles Checklist
- [6.1] Architecture — 兼容性:外部 HTTP/RPC API、持久数据、配置、环境迁移安全 → issue
arch 与 dispatch key 依赖 getattr 字面量探测与第三方枚举的 __str__,跨版本易静默漂移
registry.py:21用str(getattr(properties, "gcnArchName", ""))字面量探测架构(违反 P.P.A.0),rocm_moe.py:67同样写法;该属性一旦更名或缺失会静默回落空串 →_current_rocm_arch()返回 None → provider 不执行,而registry.py:22的宽泛except Exception只 warning。更关键的是签名的act_type/q_type直接取str(aiter.ActivationType.Silu)、str(aiter.QuantType.per_Token)并与 CSV 中的ActivationType.Silu/QuantType.per_Token文本逐字符比对;AITER 若调整枚举的__repr__/__str__,签名会不再命中白名单,require_aiter_fmoe_tuning随即变为 no-op(fmoe.py:274-279只有 debug 日志) - [6.1] Architecture — 分层边界:新概念在正确层级,不泄漏内部 → issue
启动期用 glob 重建的列表整体覆写 AITER_CONFIG_FMOE,波及进程内所有 gfx942 MoE 负载
fmoe.py:259-260在 env 未设置时写入os.pathsep.join([default_config, *model_configs, overlay])。主动重列 stock 文件说明作者认定该变量是替换语义,因此需同时成立三个假设:AITER 按os.pathsep拆分多路径、在首次 FMoE lookup 时才读取、_stock_fmoe_configs(fmoe.py:104-111,globmodel_configs/*tuned_fmoe*.csv并排除untuned)重建的清单与 AITER 自身发现结果等价。全仓检索AITER_CONFIG_FMOE仅命中本 PR 两个文件,三点均无断言或注释支撑。一旦不成立,gfx942 上全部 MoE 形状都会丢失 stock tuned 行。且registry.py:11-13只按 arch 注册,非 80 CU 的 gfx942 与纯 dense 模型也被改写。 - [6.1] Architecture — 可观测性:日志/指标/超时可操作、非噪声 → issue
overlay 命中面比 fail-closed 声明更窄,中间 token 与 EP>1 的回落语义无文档也无测试
两个维度都比 fail-closed 声明更窄。其一,fmoe.py:271-288只依据 signature、不依据 token:命中 signature 即声称「该 workload 需要本 overlay」,但 CSV 只提供 token ∈ {1,2,4,8,16};token=3/5-7/9-15 或 >16 是否被覆盖完全取决于 AITER 对token列的查表语义(精确匹配则未覆盖),仓内既无注释也无测试说明依赖哪一种,而suites_rocm_oss.bzl中decode_capture_config '1,2,3,4'表明 token=3 是真实 decode batch。其二,expert=256/inter_dim=128取自w1.shape[0]/w2.shape[2],都是分片后本地值,故该行只匹配 ep_size=1;EP>1 时签名不命中而仅打 debug 日志,运维侧无感。 - [6.1] Architecture — 回滚路径:风险行为存在运维回滚手段 → issue
启动期可选性能 overlay 未做 fail-open 保护,其 I/O 异常会击穿全部 rank 启动
本文件对辅助子系统一律 fail-open:_install_hot_hook_runtime(37-44 行)try/except 后仅 log;JIT cache 初始化异常时打日志后冷启动。而第 92 行的裸调用落在local_rank_start的except BaseException内(116-122 行),异常会经第 122 行 re-raise 拖垮该 rank 并连带 terminate 全部 rank。被调方设计意图本是 fail-open(返回applied=False+ warning),但fmoe.py:209的_sha256(default_config)与 226 行的_stock_fmoe_configs都在 227 行 try 之外,兜底也只捕(OSError, ValueError);读第三方 wheel 内 csv 出现权限或 I/O 异常时,纯性能 overlay 会变成 gfx942 全量 rank 的启动阻断项。真正的 fail-closed 保障已由 `rocm_moe.py:253 - [6.1] Architecture — 状态不变量:创建/更新/失败/重试/回滚路径有效 → issue
签名的 q_dtype_a 取权重 dtype 代理激活量化 dtype,dtype 分叉时 fail-closed 守卫静默变为 no-op
AITER dispatch key 中q_dtype_a是激活量化 dtype、q_dtype_w是权重量化 dtype,但代码取q_dtype_a=str(w1.dtype)、q_dtype_w=str(w2.dtype)(77-78 行),仅因二者当前恰好都等于get_rocm_fp8_dtype()才与 CSV 对上;同一__init__中 13 行之前已存在权威值self.quant_config.quant_dtype(236 行)。同理dtype取自构造期config.model_config.compute_dtype(259 行),而 AITER 实际输出 dtype 由运行时激活 dtype 决定。此外expert/inter_dim取自 TP/EP 分片后的本地 shape。任一偏差都会让签名不命中_AFFECTED_WORKLOAD_SIGNATURES,require_aiter_fmoe_tuning随即在fmoe.py:274-279静默 return:不抛 - [6.1] Architecture — 错误语义:fail-fast/retry/fallback/silent 行为显式 → issue
kernel_tuning BUILD 的 srcs/data glob 只覆盖一层目录,新增 provider 会静默漏出 runfiles
srcs = glob(["*.py", "aiter/*.py"])、data = glob(["aiter/configs/*.csv"])都只匹配单层。按当前目录结构功能正确,但后续新增 provider(如放在xxx/yyy/*.py)或把配置分子目录存放时,Bazel 不会报错,只会在运行期表现为RTP AITER FMoE overlay is missing(fmoe.py:220-224返回applied=False)→ 受影响 workload 在 executor 构造期抛 RuntimeError,失败点距根因很远。同仓models_py/BUILD:40-44的tile_kernels_mhc已使用**/*.py递归 glob。 - [6.1] Quality — Commit 原子、message 与行为匹配 → issue
未证明 provision 就绪的 ROCm MTP smoke 套件被并入顶层共享聚合套件,且阻塞说明被同时删除
diff 有两处配对改动:smoke/BUILD在顶层聚合套件maga_model_smoke(72-93 行)中新增:smoke_rocm_qwen35_mtp;suites_rocm_oss.bzl:117把原注释「Keep this suite standalone until Qwen3.6-27B is provisioned on the shared ROCm CI workers」改为「Keep this as a dedicated suite so CI and local runs can select it directly」。PR 内无任何 provisioning 变更作为依据,fixture 的--sp_checkpoint_path仍指向共享存储上的 27B 权重。该用例是 27B、PD 双角色、MTP step3 的重型 dense case,不经过本 PR 修改的RocmExpertsFp8PerChannel。maga_model_smoke同时聚合 h20/sm100 等 CUDA 套件,单点失败会让整 - [6.1] Quality — Mega-PR 已拆分为独立变更 → issue
未证明 provision 就绪的 ROCm MTP smoke 套件被并入顶层共享聚合套件,且阻塞说明被同时删除
diff 有两处配对改动:smoke/BUILD在顶层聚合套件maga_model_smoke(72-93 行)中新增:smoke_rocm_qwen35_mtp;suites_rocm_oss.bzl:117把原注释「Keep this suite standalone until Qwen3.6-27B is provisioned on the shared ROCm CI workers」改为「Keep this as a dedicated suite so CI and local runs can select it directly」。PR 内无任何 provisioning 变更作为依据,fixture 的--sp_checkpoint_path仍指向共享存储上的 27B 权重。该用例是 27B、PD 双角色、MTP step3 的重型 dense case,不经过本 PR 修改的RocmExpertsFp8PerChannel。maga_model_smoke同时聚合 h20/sm100 等 CUDA 套件,单点失败会让整 - [6.1] Quality — PR description 说明动机与设计 → issue
调优产物的性能与精度列全为 0.0 占位,且无生成来源记录,收益与精度不可复核
5 行数据的us1/us2/us/tflops/bw全为0.0,err1/err2全为0.0%——这些正是 AITER tune 脚本写回实测结果的列,说明文件不是 tuner 的原始产物。这与fmoe.py:283-288的 fail-closed 强约束矛盾:错误文案明确要求维护者「Revalidate the small-token FMoE kernels and update or remove the overlay」,但仓库内既无 overlay 行的实测 us,也无 stock fallback 对照值,该指令无法执行。仓内也未记录生成命令、tuning 机型、日期与对应 AITER commit,全部上下文只编码在文件名中。若 AITER 在同 key 多候选间按us择优,0.0还会让该行无条件胜出,这层隐式依赖亦未文档化。 - [6.1] Quality — 无 per-forward 调试日志 / 噪声热路径输出 → issue
execute() 激活一致性校验与硬编码 SiGLU 的唯一调用方矛盾,且 5 个同族 executor 契约分裂
__init__从config.activation_type推导_configured_activation_type(249-251 行),execute()在 291-296 行要求它与入参归一化结果一致。但唯一的生产调用方models_py/model_desc/generic_moe.py:223硬编码activation="SiGLU",与模型配置无关。因此config.activation_type归一化为 Gelu 的 MoE 会在每次 forward 抛 ValueError;同时该检查在热路径上对一个常量反复做str/getattr/rsplit/lower+ 字典查找。RocmExpertsBf16/Fp8PerBlock/Fp4PerGroup/MXFp4四个同族 executor 仍走旧的单点归一化、没有该前置条件,同一基类下行为分裂;新用例(test:343/375)两侧都传SiGLU,未覆盖不一致组合。 - [6.1] Quality — 逻辑变更未混入无关格式化 → issue
未证明 provision 就绪的 ROCm MTP smoke 套件被并入顶层共享聚合套件,且阻塞说明被同时删除
diff 有两处配对改动:smoke/BUILD在顶层聚合套件maga_model_smoke(72-93 行)中新增:smoke_rocm_qwen35_mtp;suites_rocm_oss.bzl:117把原注释「Keep this suite standalone until Qwen3.6-27B is provisioned on the shared ROCm CI workers」改为「Keep this as a dedicated suite so CI and local runs can select it directly」。PR 内无任何 provisioning 变更作为依据,fixture 的--sp_checkpoint_path仍指向共享存储上的 27B 权重。该用例是 27B、PD 双角色、MTP step3 的重型 dense case,不经过本 PR 修改的RocmExpertsFp8PerChannel。maga_model_smoke同时聚合 h20/sm100 等 CUDA 套件,单点失败会让整 - [6.1] Software Engineering — DRY:重复非平凡逻辑被抽取或显式复用 → issue
启动期可选性能 overlay 未做 fail-open 保护,其 I/O 异常会击穿全部 rank 启动
本文件对辅助子系统一律 fail-open:_install_hot_hook_runtime(37-44 行)try/except 后仅 log;JIT cache 初始化异常时打日志后冷启动。而第 92 行的裸调用落在local_rank_start的except BaseException内(116-122 行),异常会经第 122 行 re-raise 拖垮该 rank 并连带 terminate 全部 rank。被调方设计意图本是 fail-open(返回applied=False+ warning),但fmoe.py:209的_sha256(default_config)与 226 行的_stock_fmoe_configs都在 227 行 try 之外,兜底也只捕(OSError, ValueError);读第三方 wheel 内 csv 出现权限或 I/O 异常时,纯性能 overlay 会变成 gfx942 全量 rank 的启动阻断项。真正的 fail-closed 保障已由 `rocm_moe.py:253 - [6.1] Software Engineering — LSP:子类/重写保持基类契约 → issue
execute() 激活一致性校验与硬编码 SiGLU 的唯一调用方矛盾,且 5 个同族 executor 契约分裂
__init__从config.activation_type推导_configured_activation_type(249-251 行),execute()在 291-296 行要求它与入参归一化结果一致。但唯一的生产调用方models_py/model_desc/generic_moe.py:223硬编码activation="SiGLU",与模型配置无关。因此config.activation_type归一化为 Gelu 的 MoE 会在每次 forward 抛 ValueError;同时该检查在热路径上对一个常量反复做str/getattr/rsplit/lower+ 字典查找。RocmExpertsBf16/Fp8PerBlock/Fp4PerGroup/MXFp4四个同族 executor 仍走旧的单点归一化、没有该前置条件,同一基类下行为分裂;新用例(test:343/375)两侧都传SiGLU,未覆盖不一致组合。 - [6.1] Tests — 分布式/跨平台变更有对应覆盖 → issue
registry_test 未覆盖所有 CUDA/CPU/PPU 部署必经的非 ROCm no-op 路径,也未断言真实 provider 表
configure_kernel_tuning()已挂在全部 backend rank 的启动路径上(start_backend_server.py:92),因此 CUDA/CPU/PPU 部署每次启动都会执行_current_rocm_arch()。但 registry_test 只有两条用例:test_provider_is_selected_by_compute_architecture用mock.patch.dict(..., clear=True)整表替换_PROVIDERS_BY_ARCH,真实注册表(registry.py:11-13只有 gfx942)从未被断言;test_current_arch_uses_rocm_device_properties只覆盖 hip 可用的正向路径。缺失的是torch.cuda.is_available()为 False 或torch.version.hip is None时返回 None、configure_kernel_tuning()返回空元组且不触碰环境变量这 - [6.1] Tests — 新逻辑有聚焦单测 + 相关集成/smoke 测试 → issue
kernel_tuning BUILD 的 srcs/data glob 只覆盖一层目录,新增 provider 会静默漏出 runfiles
srcs = glob(["*.py", "aiter/*.py"])、data = glob(["aiter/configs/*.csv"])都只匹配单层。按当前目录结构功能正确,但后续新增 provider(如放在xxx/yyy/*.py)或把配置分子目录存放时,Bazel 不会报错,只会在运行期表现为RTP AITER FMoE overlay is missing(fmoe.py:220-224返回applied=False)→ 受影响 workload 在 executor 构造期抛 RuntimeError,失败点距根因很远。同仓models_py/BUILD:40-44的tile_kernels_mhc已使用**/*.py递归 glob。 - [6.1] Tests — 边界 case 覆盖(空、单元素、最大值) → issue
单测直接读写模块私有全局状态,并断言未 resolve 的临时路径
测试在 setUp/tearDown 直接赋值fmoe._CONFIG_STATUS = None(39、46 行),并在多处引用fmoe._DISPATCH_KEY_FIELDS、fmoe._AFFECTED_TOKEN_BUCKETS、fmoe._status、fmoe._sha256等私有符号,缓存语义变更时测试与实现会一起漂移而不报错。另外生产写入 env 的路径均经.resolve()(fmoe.py:200-202、219 行),而test_configures_additive_overlay_and_keeps_model_configs(107-110 行)断言的是未 resolve 的str(default_config)等;在 TMPDIR 含符号链接分量的环境下两边字符串不等,会产生与被测逻辑无关的假失败。
RTP-LLM Checklist
- [I] 代码质量 — 同一功能用统一工具函数 → issue
AITER 版本护栏漏掉第三处 pin,且非 Bazel fallback 路径可能读到与 CI 不同的文件
同一 aiter wheel 在三处被 pin:deps/http.bzl:83-89的http_archive(name = "aiter")(带独立 sha256)、deps/requirements_rocm.txt:8、deps/requirements_lock_rocm.txt:114。test_supported_version_matches_pinned_rocm_wheel只遍历后两者,单独升级http.bzl不会被发现,而_SUPPORTED_DEFAULT_CONFIG_SHA256校验的正是 wheel 内的 stock CSV。此外_runfile(20-24 行)在无TEST_SRCDIR时把rtp_deps/替换为deps/,读的是开源 deps 目录;而内部构建用--override_repository把@rtp_deps指向内部 deps,本地直跑通过不代表 Bazel 下校验的是同一份文件。
Python Static-First Checklist
- [P.A] 静态结构与类型纪律 — 禁止 getattr/setattr literal 访问 → issue
arch 与 dispatch key 依赖 getattr 字面量探测与第三方枚举的 __str__,跨版本易静默漂移
registry.py:21用str(getattr(properties, "gcnArchName", ""))字面量探测架构(违反 P.P.A.0),rocm_moe.py:67同样写法;该属性一旦更名或缺失会静默回落空串 →_current_rocm_arch()返回 None → provider 不执行,而registry.py:22的宽泛except Exception只 warning。更关键的是签名的act_type/q_type直接取str(aiter.ActivationType.Silu)、str(aiter.QuantType.per_Token)并与 CSV 中的ActivationType.Silu/QuantType.per_Token文本逐字符比对;AITER 若调整枚举的__repr__/__str__,签名会不再命中白名单,require_aiter_fmoe_tuning随即变为 no-op(fmoe.py:274-279只有 debug 日志) - [P.G] 测试规范 — mock/fake/stub 不得替代本次声称覆盖的生产边界 → issue
单测直接读写模块私有全局状态,并断言未 resolve 的临时路径
测试在 setUp/tearDown 直接赋值fmoe._CONFIG_STATUS = None(39、46 行),并在多处引用fmoe._DISPATCH_KEY_FIELDS、fmoe._AFFECTED_TOKEN_BUCKETS、fmoe._status、fmoe._sha256等私有符号,缓存语义变更时测试与实现会一起漂移而不报错。另外生产写入 env 的路径均经.resolve()(fmoe.py:200-202、219 行),而test_configures_additive_overlay_and_keeps_model_configs(107-110 行)断言的是未 resolve 的str(default_config)等;在 TMPDIR 含符号链接分量的环境下两边字符串不等,会产生与被测逻辑无关的假失败。
Strengths
- 「上游变更即失效」的防漂移链条完整且相互独立:AITER 版本精确 pin(
fmoe.py:192)、stocktuned_fmoe.csv的 sha256 校验(fmoe.py:210)、overlay 与 stock/model_configs的 dispatch key 交集检测(fmoe.py:229-238)、_tag非空拒绝(fmoe.py:140-145)。其中交集检测保证 overlay 只「新增行」而非覆盖上游调优结果,使配置链顺序不影响正确性,是该方案最关键的安全设计。 _validated_overlay_dispatch_keys(fmoe.py:147-163)把 overlay 行集合与_AFFECTED_WORKLOAD_SIGNATURES × _AFFECTED_TOKEN_BUCKETS做双向严格比对并校验行数,杜绝「CSV 悄悄多加/少加行」;test_bundled_overlay_matches_declared_dispatch_rows直接作用于入库文件。test_supported_version_matches_pinned_rocm_wheel(aiter_fmoe_test.py:160)从 requirements 的 wheel URL 反解版本并与常量比对,把「依赖升级必须回看 overlay」从注释提醒升级为无需 GPU 即可失败的确定性守卫。AiterFmoeWorkloadSignature只描述 AITER 实际看到的本地 shape,显式把 TP/EP/模型名排除在外并注释说明理由(fmoe.py:46-50),再由test_signature_is_shape_based_not_model_or_parallelism_based用dataclasses.fields反向断言字段集合,抽象边界选得准确且被测试锁定。- 启动挂载点选择精确:
configure_kernel_tuning()(start_backend_server.py:92)位于setup_cuda_device_and_accl_env之后(保证 arch 探测读到本 rank 真实设备)、BackendManager导入(第 97 行)之前;三条 rank 启动路径全部汇聚到local_rank_start,单点插桩即全覆盖。 - 该时序被
jit_cache_manager_test.py的events == ["device", "tuning", "backend"]固化为顺序断言(而非仅断言被调用过),且mock.patch.object打在使用处模块,符合 P.P.G.1。 kernel_tuningpy_library 只依赖//rtp_llm:torch且自身不import aiter,因此服务入口顶层导入不会提前拉起 AITER,也不影响 CUDA/CPU 构建冷启动;data = glob(["aiter/configs/*.csv"])与运行期Path(__file__).parent/"configs"解析一致,runfiles 与 wheel 两条路径都能取到 overlay。- overlay CSV 逐列自洽:13 个 dispatch key 列与
fmoe.py:67-85、rocm_moe.py:68-82的签名构造逐字段一致;kernelName1的 Itanium mangling 长度前缀 48 与标识符长度相符;_32x128与block_m=32、inter_dim=128一致;run_1stage=1与kernelName2=Null一致。 - 新增端到端用例使用真实 2048/128/256/topk8 形状、经
shuffle_moe_weight的物理布局与 BF16 参考比对,并覆盖 token=1..16 全部受影响桶,比纯 mock 校验更有价值。
| ":smoke_rocm_dense", | ||
| ":smoke_rocm_moe", | ||
| ":smoke_rocm_qwen35_mrope_cg", | ||
| ":smoke_rocm_qwen35_mtp", |
There was a problem hiding this comment.
[P2] 未证明 provision 就绪的 ROCm MTP smoke 套件被并入顶层共享聚合套件,且阻塞说明被同时删除
diff 有两处配对改动:smoke/BUILD 在顶层聚合套件 maga_model_smoke(72-93 行)中新增 :smoke_rocm_qwen35_mtp;suites_rocm_oss.bzl:117 把原注释「Keep this suite standalone until Qwen3.6-27B is provisioned on the shared ROCm CI workers」改为「Keep this as a dedicated suite so CI and local runs can select it directly」。PR 内无任何 provisioning 变更作为依据,fixture 的 --sp_checkpoint_path 仍指向共享存储上的 27B 权重。该用例是 27B、PD 双角色、MTP step3 的重型 dense case,不经过本 PR 修改的 RocmExpertsFp8PerChannel。maga_model_smoke 同时聚合 h20/sm100 等 CUDA 套件,单点失败...
建议: 请二选一:(1) 在 PR 描述中给出该 checkpoint 已在共享 ROCm CI worker 就绪的证据(例如一次绿色的 smoke_rocm_qwen35_mtp 记录),并说明它与本 PR 的关系;(2) 从 maga_model_smoke 撤回该条目、恢复原注释与 standalone 状态,把 CI 纳管拆到独立提交——可参照仓内 smoke_rocm_mxfp4/suites_sm100.bzl 一类「不并入聚合、由独立 job 触发」的既有做法。鉴于该 fixture 对本 PR 的 overlay 无覆盖价值,建议按 (2) 拆分,避免 CI 拓扑变更与 FMoE tuning 功能在同一提交里相互掩盖失败原因,也便于 CI 二分定位。
Checklist: [6.1] Commit 原子、message 与行为匹配;[6.1] Mega-PR 已拆分为独立变更;[6.1] 逻辑变更未混入无关格式化
| config_paths = [*stock_configs, overlay_config] | ||
| os.environ["AITER_CONFIG_FMOE"] = os.pathsep.join(map(str, config_paths)) | ||
|
|
||
| _CONFIG_STATUS = _status(True, "RTP AITER FMoE overlay configured", version) |
There was a problem hiding this comment.
[P2] applied=True 只代表环境变量已写入,无法证明 AITER 真正消费了 overlay,兜底调用还发生在 import aiter 之后
fmoe.py:260-262 写入 env 后直接置 applied=True,全程未回读 AITER 侧解析结果。而 require_aiter_fmoe_tuning 的兜底调用发生在 RocmExpertsFp8PerChannel.__init__(rocm_moe.py:253),此时 rocm_moe.py:4,6 的 import aiter / from aiter.fused_moe import fused_moe 早已执行。只要启动期未跑到 provider(registry.py:22 宽泛 except Exception 吞掉 arch 探测异常,或进程不经 local_rank_start),兜底会在 import 之后写 env 却仍报 applied=True 且不抛错。新增 GPU 用例只断言 shape/finite/mean cosine>0.99,overlay 完全未生效时同样通过,PR 唯一的安全网可能在 overlay 实际失效时放行。
建议: 补一道后置校验使「overlay 未真正生效」无法通过守卫,二选一或并用:(1)配置完成后回读 AITER 已加载的 FMoE dispatch 表,确认 overlay 的 5 条 key 在其中才置 applied=True;(2)在 configure_aiter_fmoe_overlays 开头检测 "aiter" in sys.modules,已导入则返回 applied=False 并在 reason 中说明「配置时机过晚」。同时把最终生效的 AITER_CONFIG_FMOE 取值写入 reason 便于线上定位,并在 ROCm 用例中断言目标形状实际命中的 kernel 名为 overlay 声明的 ..._1tg_ps_32x128 变体,使 fail-open 可被测试发现。
| ) | ||
| return _CONFIG_STATUS | ||
| else: | ||
| config_paths = [*stock_configs, overlay_config] |
There was a problem hiding this comment.
[P2] 启动期用 glob 重建的列表整体覆写 AITER_CONFIG_FMOE,波及进程内所有 gfx942 MoE 负载
fmoe.py:259-260 在 env 未设置时写入 os.pathsep.join([default_config, *model_configs, overlay])。主动重列 stock 文件说明作者认定该变量是替换语义,因此需同时成立三个假设:AITER 按 os.pathsep 拆分多路径、在首次 FMoE lookup 时才读取、_stock_fmoe_configs(fmoe.py:104-111,glob model_configs/*tuned_fmoe*.csv 并排除 untuned)重建的清单与 AITER 自身发现结果等价。全仓检索 AITER_CONFIG_FMOE 仅命中本 PR 两个文件,三点均无断言或注释支撑。一旦不成立,gfx942 上全部 MoE 形状都会丢失 stock tuned 行。且 registry.py:11-13 只按 arch 注册,非 80 CU 的 gfx942 与纯 dense 模型也被改写。
建议: 把 env 改写收敛到确实需要的场景:让 provider 注册 key 带上 cu_num,或改为在 require_aiter_fmoe_tuning 命中受影响签名时惰性配置,把影响面从「全部 gfx942 进程」压回目标形状。若必须在启动期注入,则写入前调用 AITER 自身的配置解析入口取回默认清单并断言与重建结果一致,不一致时返回 applied=False 而非继续覆写。同时在 _stock_fmoe_configs 与写入点补注释,写明「该变量为替换语义」以及 glob 复刻的是哪个 AITER 版本的目录约定,使后续升级有明确复核依据。
Checklist: [6.1] 分层边界:新概念在正确层级,不泄漏内部
| status = configure_aiter_fmoe_overlays() | ||
| if status.applied: | ||
| return | ||
| raise RuntimeError( |
There was a problem hiding this comment.
[P2] fail-closed 缺少运维逃生开关,版本与哈希门位于 env 分支之前使显式配置也无法兜底
require_aiter_fmoe_tuning 在 fmoe.py:283 无条件抛 RuntimeError,调用点在 RocmExpertsFp8PerChannel.__init__(rocm_moe.py:253),异常会让权重加载失败、backend rank 起不来。触发条件包括 aiter 版本字符串与 pin 不符、stock CSV 哈希变化、overlay 在 runfiles/wheel 中缺失、_tag 不对称导致的误判冲突、运维显式设置了不含 overlay 的 env。这些全部属于性能调优前提而非数值正确性前提;且版本校验(fmoe.py:192)与 sha256 校验(fmoe.py:210)都排在 env 分支(fmoe.py:245)之前,运维即使手动把 overlay 路径写进环境变量也无法绕过版本 pin。代码中不存在任何显式开关,线上只有「带 overlay 跑」或「加载失败」两态。
建议: 增加一个显式逃生开关(例如 RTP_ALLOW_UNTUNED_AITER_FMOE=1,默认保持现有 fail-closed 语义):置位时把 RuntimeError 降级为高等级错误日志(打印完整 reason 与命中签名,并提示「小 token 延迟可能显著上升」)并放行 stock 分发,同时把开关状态写入 KernelTuningStatus.reason 以便可观测;RuntimeError 文案中直接给出该开关名与「需重新 tuning 并更新 overlay」的操作指引。这样 aiter wheel 临时升级或打包漏文件时,线上表现为小 token 延迟回退而非整体不可用,运维具备不发版即可回滚的手段。
| return [default_config, *model_configs] | ||
|
|
||
|
|
||
| def _dispatch_keys(config: Path) -> set[tuple[str, ...]]: |
There was a problem hiding this comment.
[P2] 两条 CSV 解析路径整段重复,且 _tag 过滤语义不对称可致误判 dispatch 冲突
_validated_overlay_dispatch_keys(fmoe.py:140-145)明确以「AITER 会把 _tag 非空的行排除在普通 FMoE dispatch 之外」为依据拒绝带 tag 的 overlay 行;但同一文件里用于 stock 配置的 _dispatch_keys(fmoe.py:114-126)完全不看 _tag,把带 tag 的行也算作 dispatch key。_stock_fmoe_configs 扫描的正是 model_configs/*tuned_fmoe*.csv——按 AITER 目录约定,这些按模型区分的文件恰恰最可能带 _tag。一旦其中出现与 overlay 同 key 但带 tag 的行,overlap 检查误判(fmoe.py:229-238)→ overlay 不启用 → 受影响 workload 在 executor 构造期抛 RuntimeError,服务无法启动。此外两函数的缺列校验与 key 元组提取逐字重复。
建议: 抽出一个共用的 CSV reader 统一两处对 _tag 的语义:读取 stock 配置时同样跳过 _tag 非空的行(它们不参与普通 dispatch),overlay 侧继续保留「不允许带 tag」的强校验。这样 overlap 判定与 AITER 实际的 dispatch 集合一致,同时消除当前两段 CSV 解析代码的重复,后续新增 dispatch key 列时也只需改一处。建议补一条用例:stock model_configs 中存在与 overlay 同 key 但带 tag 的行时,overlay 仍应正常生效。
| py_env_configs.server_config.set_local_rank(local_rank) | ||
| py_env_configs.distribute_config.set_local_rank(local_rank) | ||
| setup_cuda_device_and_accl_env(local_rank) | ||
| configure_kernel_tuning() |
There was a problem hiding this comment.
[P2] 启动期可选性能 overlay 未做 fail-open 保护,其 I/O 异常会击穿全部 rank 启动
本文件对辅助子系统一律 fail-open:_install_hot_hook_runtime(37-44 行)try/except 后仅 log;JIT cache 初始化异常时打日志后冷启动。而第 92 行的裸调用落在 local_rank_start 的 except BaseException 内(116-122 行),异常会经第 122 行 re-raise 拖垮该 rank 并连带 terminate 全部 rank。被调方设计意图本是 fail-open(返回 applied=False + warning),但 fmoe.py:209 的 _sha256(default_config) 与 226 行的 _stock_fmoe_configs 都在 227 行 try 之外,兜底也只捕 (OSError, ValueError);读第三方 wheel 内 csv 出现权限或 I/O 异常时,纯性能 overlay 会变成 gfx942 全量 rank 的启动阻断项。真正的 fail-closed 保障已由 `rocm_moe.py:...
建议: 把第 92 行包成与本文件一致的 fail-open 形式(try/except Exception + 明确前缀的 error 日志),或在 registry.configure_kernel_tuning 内对每个 provider 调用做兜底并视作 applied=False,让 overlay 自检异常只降级为「未加速」,由 require_aiter_fmoe_tuning 在真正命中受影响签名时再 fail-closed。同时在第 92 行补一行注释,说明该调用必须早于任何传递性 import aiter 的模块导入,把当前仅由行序隐式维持的排序不变量显式化。
Checklist: [6.1] 回滚路径:风险行为存在运维回滚手段;[6.1] DRY:重复非平凡逻辑被抽取或显式复用
| return None | ||
| try: | ||
| properties = torch.cuda.get_device_properties(torch.cuda.current_device()) | ||
| return str(getattr(properties, "gcnArchName", "")).split(":", 1)[0] or None |
There was a problem hiding this comment.
[P3] arch 与 dispatch key 依赖 getattr 字面量探测与第三方枚举的 str,跨版本易静默漂移
registry.py:21 用 str(getattr(properties, "gcnArchName", "")) 字面量探测架构(违反 P.P.A.0),rocm_moe.py:67 同样写法;该属性一旦更名或缺失会静默回落空串 → _current_rocm_arch() 返回 None → provider 不执行,而 registry.py:22 的宽泛 except Exception 只 warning。更关键的是签名的 act_type/q_type 直接取 str(aiter.ActivationType.Silu)、str(aiter.QuantType.per_Token) 并与 CSV 中的 ActivationType.Silu/QuantType.per_Token 文本逐字符比对;AITER 若调整枚举的 __repr__/__str__,签名会不再命中白名单,require_aiter_fmoe_tuning 随即变为 no-op(fmoe.py:274-279 只有 debug ...
建议: 把 gcnArchName 缺失从静默降级改为一次性 warning,异常捕获收窄到具体类型;并在 configure_aiter_fmoe_overlays 成功分支中加一条一次性自检,把本进程推导出的枚举字符串与 overlay CSV 对应列比对,不一致时返回 applied=False 并说明「AITER 枚举文本已变更,overlay 可能失效」,使跨版本漂移在启动期显式暴露而非退化为静默 no-op。
Checklist: [6.1] 兼容性:外部 HTTP/RPC API、持久数据、配置、环境迁移安全;[P.A] 禁止 getattr/setattr literal 访问
| @@ -0,0 +1,30 @@ | |||
| py_library( | |||
| name = "kernel_tuning", | |||
| srcs = glob([ | |||
There was a problem hiding this comment.
[P3] kernel_tuning BUILD 的 srcs/data glob 只覆盖一层目录,新增 provider 会静默漏出 runfiles
srcs = glob(["*.py", "aiter/*.py"])、data = glob(["aiter/configs/*.csv"]) 都只匹配单层。按当前目录结构功能正确,但后续新增 provider(如放在 xxx/yyy/*.py)或把配置分子目录存放时,Bazel 不会报错,只会在运行期表现为 RTP AITER FMoE overlay is missing(fmoe.py:220-224 返回 applied=False)→ 受影响 workload 在 executor 构造期抛 RuntimeError,失败点距根因很远。同仓 models_py/BUILD:40-44 的 tile_kernels_mhc 已使用 **/*.py 递归 glob。
建议: 改为 glob(["**/*.py"], exclude = ["test/**"]) 与 glob(["**/configs/*.csv"]),让目录结构演进自动被打包覆盖(同时确认 test/ 不会被 srcs 意外吸入而与 py_test 的 srcs 重复);并在 overlay 缺失的 reason 中显式提示「检查 BUILD 的 data glob 与 wheel 打包」,缩短从现象到根因的距离。
Checklist: [6.1] 错误语义:fail-fast/retry/fallback/silent 行为显式;[6.1] 新逻辑有聚焦单测 + 相关集成/smoke 测试
| with self.assertRaisesRegex(RuntimeError, "Revalidate"): | ||
| fmoe.require_aiter_fmoe_tuning(self._affected_signature()) | ||
|
|
||
| def test_supported_version_matches_pinned_rocm_wheel(self): |
There was a problem hiding this comment.
[P3] AITER 版本护栏漏掉第三处 pin,且非 Bazel fallback 路径可能读到与 CI 不同的文件
同一 aiter wheel 在三处被 pin:deps/http.bzl:83-89 的 http_archive(name = "aiter")(带独立 sha256)、deps/requirements_rocm.txt:8、deps/requirements_lock_rocm.txt:114。test_supported_version_matches_pinned_rocm_wheel 只遍历后两者,单独升级 http.bzl 不会被发现,而 _SUPPORTED_DEFAULT_CONFIG_SHA256 校验的正是 wheel 内的 stock CSV。此外 _runfile(20-24 行)在无 TEST_SRCDIR 时把 rtp_deps/ 替换为 deps/,读的是开源 deps 目录;而内部构建用 --override_repository 把 @rtp_deps 指向内部 deps,本地直跑通过不代表 Bazel 下校验的是同一份文件。
建议: 把 deps/http.bzl(deps/BUILD:5-10 已 exports_files)一并加入该 py_test 的 data 并纳入 _AITER_WHEEL_VERSION_PATTERN 的扫描集合(现有正则可直接复用),让三处 pin 必须同时一致;_runfile 的 fallback 建议在缺少 TEST_SRCDIR 时直接 skip,避免读到与 CI 不同的文件而给出假绿。
Checklist: [I] 同一功能用统一工具函数
| class AiterFmoeTuningTest(unittest.TestCase): | ||
| def setUp(self): | ||
| self._old_env = os.environ.pop("AITER_CONFIG_FMOE", None) | ||
| fmoe._CONFIG_STATUS = None |
There was a problem hiding this comment.
[P3] 单测直接读写模块私有全局状态,并断言未 resolve 的临时路径
测试在 setUp/tearDown 直接赋值 fmoe._CONFIG_STATUS = None(39、46 行),并在多处引用 fmoe._DISPATCH_KEY_FIELDS、fmoe._AFFECTED_TOKEN_BUCKETS、fmoe._status、fmoe._sha256 等私有符号,缓存语义变更时测试与实现会一起漂移而不报错。另外生产写入 env 的路径均经 .resolve()(fmoe.py:200-202、219 行),而 test_configures_additive_overlay_and_keeps_model_configs(107-110 行)断言的是未 resolve 的 str(default_config) 等;在 TMPDIR 含符号链接分量的环境下两边字符串不等,会产生与被测逻辑无关的假失败。
建议: 为 _CONFIG_STATUS 提供一个显式的公开重置入口(如 reset_kernel_tuning_status())供测试与多进程场景使用,避免直接写私有全局;断言前对期望路径统一 Path(...).resolve(),或改为断言集合/顺序关系(stock 在前、overlay 在末)而非逐字符串相等,降低对宿主文件系统布局的耦合。
Checklist: [6.1] 边界 case 覆盖(空、单元素、最大值);[P.G] mock/fake/stub 不得替代本次声称覆盖的生产边界
Summary
models_py/kernel_tuningregistry for runtime kernel-tuning overlaysH=2048, localI=128,E=256,topk=8, BF16 output, per-token FP8)Validation
//rtp_llm/models_py/kernel_tuning:aiter_fmoe_test//rtp_llm/models_py/kernel_tuning:registry_test//rtp_llm/models_py/modules/factory/fused_moe/impl/rocm/test:rocm_fp8_fused_moe_test//rtp_llm/test/smoke:smoke_rocm_qwen35_mtpMaintenance
The overlay is additive and version/hash guarded. An AITER upgrade or an upstream stock dispatch entry for the same key requires an explicit review instead of silently retaining stale RTP tuning.