ops-nn 仓中 30 个算子的 GE IR 原型头 <算子>/op_graph/*_proto.h,其 REG_OP 外层缺少 OPS_PROTO_DEF_<OPTYPE> 条件编译隔离宏。
<算子>/op_graph/*_proto.h
REG_OP
OPS_PROTO_DEF_<OPTYPE>
这些原型会被 scripts/util/merge_proto.py 合并成 ops_proto_nn.h/.cpp(cmake/gen_ops_info.cmake 的 merge_graph_headers),再由 cmake/symbol.cmake 的 gen_opgraph_symbol 编成内置 op_proto 库并安装到 ${OPP_PREFIX}/built-in/op_graph/inc。当同名算子在 canndev 侧的遗留原型头(nn_norm_ops.h、reduce_ops.h、nn_batch_norm_ops.h、ops_proto_legacy.h 等)也有 REG_OP 注册时,两份定义进入同一编译单元即构成重复定义。
scripts/util/merge_proto.py
ops_proto_nn.h
.cpp
cmake/gen_ops_info.cmake
merge_graph_headers
cmake/symbol.cmake
gen_opgraph_symbol
${OPP_PREFIX}/built-in/op_graph/inc
nn_norm_ops.h
reduce_ops.h
nn_batch_norm_ops.h
ops_proto_legacy.h
本仓已有 activation/relu6_d、optim/sgd、norm/in_training_reduce_v2、vfusion/normalize_bbox 等算子按此范式加了隔离宏,发布包 opp/built-in/op_graph/inc 中也已有 967 个同类隔离宏,但下列 30 个算子的原型头遗漏了该保护:
activation/relu6_d
optim/sgd
norm/in_training_reduce_v2
vfusion/normalize_bbox
opp/built-in/op_graph/inc
ApplyAdagrad、BatchNormExt2、BN3DTrainingUpdate、BNInfer、BNTrainingUpdateV2、BNTrainingUpdateV3、ChamferDistance、ClippedSwiglu、CosineEmbeddingLoss、DeepNorm、DeepNormGrad、DynamicQuantUpdateScatter、DynamicQuantUpdateScatterV2、GemmaRmsNorm、GroupNormSiluQuant、HardSigmoid、HardSwishGradV2、INInferV2、InplaceApplyRMSProp、InplaceSub、InstanceNormGrad、INTrainingUpdateGrad、L2NormalizeGrad、MultiAddRmsNormDynamicQuant、MultilabelMarginLoss、NonZeroWithValue、PoissonNllLoss、Relu6Grad、SoftmaxFocalLoss、SoftmaxFocalLossGrad
另有 5 个原型头(deep_norm、deep_norm_grad、gemma_rms_norm、multi_add_rms_norm_dynamic_quant、dynamic_quant_update_scatter_v2)文件末尾缺换行,pre-commit 的 end-of-file-fixer 钩子只扫改动文件,一旦改动这些文件即会被门禁拦截。
deep_norm
deep_norm_grad
gemma_rms_norm
multi_add_rms_norm_dynamic_quant
dynamic_quant_update_scatter_v2
pre-commit
end-of-file-fixer
本问题属于头文件与构建期问题,与运行硬件型号无关,在任意昇腾产品形态下构建均可复现。
cann/ops-nn
e7257e707
.pre-commit-config.yaml
以 DeepNorm 为例:
git clone https://gitcode.com/cann/ops-nn.git && cd ops-nn # 1) 确认原型头没有隔离宏 grep -c "OPS_PROTO_DEF" norm/deep_norm/op_graph/deep_norm_proto.h # 输出:0 # 2) 跑合并脚本,观察合并产物 python3 scripts/util/merge_proto.py D norm/deep_norm/op_graph/deep_norm_proto.h \ --output-file /tmp/merged.h grep -c "REG_OP(" /tmp/merged.h # 1,原型已并入 grep -c "#ifndef OPS_PROTO_DEF_" /tmp/merged.h # 0,无隔离宏 # 3) 对照 canndev 侧同名注册源 grep -n "REG_OP(DeepNorm)" <CANN安装路径>/opp/built-in/op_graph/inc/nn_norm_ops.h
合并产物 ops_proto_nn.h 与 nn_norm_ops.h 同时被包含时,REG_OP(DeepNorm) 展开出的类定义出现两次,构成重复定义。
REG_OP(DeepNorm)
文件末尾缺换行的复现:
tail -c1 norm/deep_norm/op_graph/deep_norm_proto.h | xxd # 末字节非 0a,end-of-file-fixer 钩子会改写该文件并使门禁失败
op_graph/*_proto.h
#ifndef/#define OPS_PROTO_DEF_<OPTYPE>
#endif
merge_proto.py
merge_proto.py 合并产物对比(以 deep_norm_proto.h 为例):
deep_norm_proto.h
master 合并产物: REG_OP=1 隔离宏=0 ← 原型进去了,但没有隔离保护 修复后合并产物: REG_OP=1 隔离宏=1 ← 隔离宏正确带出
修复后全量校验:
ops-nn: 改动文件=30 合并产物隔离宏=30/30 宏名与发布包不一致项=0 跨文件重名宏=0 每文件 OPS_PROTO_DEF 宏数=1(无嵌套/重复保护) clang-format(整文件)=30/30 通过 OAT 许可头=30/30 合规 trailing-whitespace / end-of-file-fixer / check-merge-conflict / detect-private-key / check-added-large-files 全部通过
common/inc/op_graph/op_nn_proto_extend.h
关联 PR:https://gitcode.com/cann/ops-nn/pull/9218
Describe the current behavior / 问题描述
ops-nn 仓中 30 个算子的 GE IR 原型头
<算子>/op_graph/*_proto.h,其REG_OP外层缺少OPS_PROTO_DEF_<OPTYPE>条件编译隔离宏。这些原型会被
scripts/util/merge_proto.py合并成ops_proto_nn.h/.cpp(cmake/gen_ops_info.cmake的merge_graph_headers),再由cmake/symbol.cmake的gen_opgraph_symbol编成内置 op_proto 库并安装到${OPP_PREFIX}/built-in/op_graph/inc。当同名算子在 canndev 侧的遗留原型头(nn_norm_ops.h、reduce_ops.h、nn_batch_norm_ops.h、ops_proto_legacy.h等)也有REG_OP注册时,两份定义进入同一编译单元即构成重复定义。本仓已有
activation/relu6_d、optim/sgd、norm/in_training_reduce_v2、vfusion/normalize_bbox等算子按此范式加了隔离宏,发布包opp/built-in/op_graph/inc中也已有 967 个同类隔离宏,但下列 30 个算子的原型头遗漏了该保护:ApplyAdagrad、BatchNormExt2、BN3DTrainingUpdate、BNInfer、BNTrainingUpdateV2、BNTrainingUpdateV3、ChamferDistance、ClippedSwiglu、CosineEmbeddingLoss、DeepNorm、DeepNormGrad、DynamicQuantUpdateScatter、DynamicQuantUpdateScatterV2、GemmaRmsNorm、GroupNormSiluQuant、HardSigmoid、HardSwishGradV2、INInferV2、InplaceApplyRMSProp、InplaceSub、InstanceNormGrad、INTrainingUpdateGrad、L2NormalizeGrad、MultiAddRmsNormDynamicQuant、MultilabelMarginLoss、NonZeroWithValue、PoissonNllLoss、Relu6Grad、SoftmaxFocalLoss、SoftmaxFocalLossGrad
另有 5 个原型头(
deep_norm、deep_norm_grad、gemma_rms_norm、multi_add_rms_norm_dynamic_quant、dynamic_quant_update_scatter_v2)文件末尾缺换行,pre-commit的end-of-file-fixer钩子只扫改动文件,一旦改动这些文件即会被门禁拦截。Environment / 环境信息
本问题属于头文件与构建期问题,与运行硬件型号无关,在任意昇腾产品形态下构建均可复现。
cann/ops-nnmaster(复现基线 commite7257e707)scripts/util/merge_proto.py.pre-commit-config.yaml)Steps to reproduce the issue / 重现步骤
以 DeepNorm 为例:
git clone https://gitcode.com/cann/ops-nn.git && cd ops-nn # 1) 确认原型头没有隔离宏 grep -c "OPS_PROTO_DEF" norm/deep_norm/op_graph/deep_norm_proto.h # 输出:0 # 2) 跑合并脚本,观察合并产物 python3 scripts/util/merge_proto.py D norm/deep_norm/op_graph/deep_norm_proto.h \ --output-file /tmp/merged.h grep -c "REG_OP(" /tmp/merged.h # 1,原型已并入 grep -c "#ifndef OPS_PROTO_DEF_" /tmp/merged.h # 0,无隔离宏 # 3) 对照 canndev 侧同名注册源 grep -n "REG_OP(DeepNorm)" <CANN安装路径>/opp/built-in/op_graph/inc/nn_norm_ops.h合并产物
ops_proto_nn.h与nn_norm_ops.h同时被包含时,REG_OP(DeepNorm)展开出的类定义出现两次,构成重复定义。文件末尾缺换行的复现:
tail -c1 norm/deep_norm/op_graph/deep_norm_proto.h | xxd # 末字节非 0a,end-of-file-fixer 钩子会改写该文件并使门禁失败Describe the expected behavior / 预期结果
op_graph/*_proto.h中,REG_OP外层带#ifndef/#define OPS_PROTO_DEF_<OPTYPE>…#endif,且宏名与发布包中同名算子的既有隔离宏逐字节一致。merge_proto.py正确带入合并产物(该正则要求 guard 与REG_OP严格相邻,位置写偏宏会被丢弃)。.pre-commit-config.yaml的全部钩子。Related log / screenshot / 日志 / 截图
merge_proto.py合并产物对比(以deep_norm_proto.h为例):修复后全量校验:
Special notes for this issue/备注
common/inc/op_graph/op_nn_proto_extend.h:merge_proto.py会按算子名把聚合头中与各算子原型头重复的条目去重,改它不会进入合并产物。REG_OP也没有隔离宏。彻底闭环还需遗留侧同步补同名宏(发布包中已有 967 个算子是成对做的)。该部分不在本 Issue 的修改范围内,供后续跟踪。关联 PR:https://gitcode.com/cann/ops-nn/pull/9218