Merged
【feat】: 支持子字节dtype(DT_INT4)的ND/FRACTAL_NZ格式转换与常量折叠防护 #5199
kantao1Add on Sep 28
【feat】: 支持子字节dtype(DT_INT4)的ND/FRACTAL_NZ格式转换与常量折叠防护 #5199
Merged
Merged fromkantao1/gesupport_onnx_int4intocann/gedevelop
Pull Request has been successfully merged by CANN-robot.
(Thank you for kantao1's contribution.)atomgit-bot
Sep 28 Comments:
Sep 28 Comments:
变更摘要
本 PR 为 GE 侧适配子字节 dtype(如 DT_INT4 weight),打通 ND ↔ FRACTAL_NZ 显式 C0 变体的主机侧格式转换,并补齐各处将位宽编码值(GetSizeByDataType 返回 kDataTypeSizeBitOffset + bits)误当字节数使用的防护。核心是在 format_transfer_fractal_nz.cc 中新增 packed 位级搬移实现与统一 C0 解析 GetEffectiveC0,注册 ND ↔ FORMAT_FRACTAL_NZ_C0_16/C0_32 转换路由;在 formats.cc 的 TransDataFormat 与 transpose 转换入口增加门禁;在常量折叠路径拦截子字节折叠;并将多处内存/位宽换算改为按位宽 CeilDiv 的 GetSizeInBytes 口径。
主要改动
- 子字节位级格式转换实现:
format_transfer_fractal_nz.cc新增GetBitsValue/SetBitsValue、CopyPackedSegment(字节对齐快路径 + 逐元素回退)以及TransFormatFromNdToFracNzSubByte/TransFormatFromFracNzToNdSubByte,并注册ND ↔ FORMAT_FRACTAL_NZ_C0_16/C0_32转换路由,支撑 packed 子字节数据的 ND↔NZ 搬移。 - 统一 C0 解析: 新增
GetEffectiveC0,优先取组合位域 C0、回退到 primary 枚举变体(FRACTAL_NZ_C0_2/4/8/16/32),并在TransFormat/TransShape中取代原GetC0Value调用;transfer_shape_utils.cc的GetNdToNzAlignedShape同步改用GetC0Value(dtype, dst_format)统一口径。 - 入口校验与门禁: 新增
CheckShapeForSubByteTrans校验 NZ 形状不变量(末 4 维、w0>0、块内轴字节对齐、前缀乘积与块容量),位宽限定 1/2/4 bit;formats.cc的TransDataFormat通过IsSubByteSupportedTransfer仅放行 ND 族 ↔ 显式 C0 的 NZ 族互转,format_transfer_transpose.cc拒绝子字节类型。 - 常量折叠防护:
constant_folding_pass.cc新增IsSubByteFoldingBlocked,覆盖 top/bottom 自定义算子与 legacyHostCpuOp路径,白名单QuantBiasOptimization放行输入检查,命中则返回UNSUPPORTED回落 GE 内置 kernel;pack_kernel.cc对子字节类型返回NOT_CHANGED跳过折叠。 - 位宽编码与内存换算修复:
fe_utils.cc的GetDataTypeBits修正判断条件为data_type_size > kDataTypeSizeBitOffset;kernel_utils.cc、eager_op_execution_context.cc、fusion_turbo.h中内存大小改用GetSizeInBytes的 CeilDiv 计算,避免高估导致越界写。


Incorrect?
atomgit-bot
Sep 28 Comments:
Sep 28 Comments:
代码审查
审查结论
发现清单(按优先级)
- P1 × 1:
base/formats/format_transfers/format_transfer_fractal_nz.cc:435-436— 新增的CheckShapeForSubByteTrans越界上界多算一个分形块,导致W % C0 == 0 && H > 1的合法子字节形状被误判为非法(ACL_ERROR_GE_SHAPE_INVALID)。由于 INT4/INT2 权重形状的 W 基本都是 C0(16/32) 的整数倍且 H>1,该缺陷会让新增的 ND↔FRACTAL_NZ_C0_16/C0_32 通路在常见形状下直接失败(PR 中仅验证了 W 非 C0 整数倍的尾部场景,恰好绕开此分支)。
变更文件逐一确认
| 文件 | 结论 |
|---|---|
| base/formats/format_transfers/format_transfer_fractal_nz.cc | 1 个问题(上述 P1);其余子字节位级搬移(GetBitsValue/SetBitsValue 掩码与移位、CopyPackedSegment 对齐快路径/逐元素回退、两方向寻址与 dst_size CeilDiv 上界)经核对与 NZ 布局偏移一致,未见越界;GetEffectiveC0 对裸 FORMAT_FRACTAL_NZ 返回 -1 的情况被 formats.cc 门禁与 (c0*bits)%8 校验拦下 |
| base/formats/format_transfers/format_transfer_transpose.cc | 无问题(子字节直接拒绝,与逐元素字节拷贝语义一致) |
| base/formats/formats.cc | 无问题(门禁只查 src_data_type,TransArgs 确实只有该 dtype 字段;放行集合与新注册的 ND↔C0_16/C0_32 路由口径一致) |
| compiler/engines/nn_engine/utils/common/fe_utils.cc | 无问题(data_type > offset 改为 data_type_size > offset,属正确修复) |
| compiler/graph/passes/standard_optimize/constant_folding/constant_folding_pass.cc | 无问题(拦截返回 UNSUPPORTED,调用链回落 HostCpuKernel→内置 kernel 成立) |
| compiler/host_kernels/kernel_utils.cc | 无问题(删除的 length 无其他引用;标量分支改用 GetSizeInBytes 口径正确) |
| compiler/host_kernels/split_combination_ops/pack_kernel.cc | 无问题(返回 NOT_CHANGED 即跳过折叠,符合该文件既有约定) |
| graph_metadef/exe_graph/runtime/eager_op_execution_context.cc | 无问题(CeilDiv 换算 + 负值断言,空张量行为与改动前一致) |
| graph_metadef/third_party/transformer/src/transfer_shape_utils.cc | 无问题(GetC0Value(dtype, dst_format) 裸 NZ 时回退 GetC0ByDtype,与改动前等价;C0 变体则取 16/32,与 TransferShape 既有口径一致) |
| inc/graph_metadef/register/graph_optimizer/fusion_common/fusion_turbo.h | 无问题(子字节按位宽 CeilDiv,非通用字节类型路径不变;ge::GetSizeInBytes 依赖的声明随现有 graph 头文件可见) |
总体风险判断
改动方向正确(多处把位宽编码值误当字节数使用的口径统一为 GetSizeInBytes/位级处理),但新增的 NZ 形状不变量校验条件存在一处真实逻辑缺陷,会使该特性在最常见的权重形状下不可用,建议修复后再合入;其余 9 个文件未发现由本次改动引入的问题。
| 类型 | 数量 |
|---|---|
| 🔴 阻塞 | 1 |
| 🟡 建议 | 0 |
⛔ 需要修改


Incorrect?
Sep 28 Added label: cann-cla/yes
96 messages are collapsed here。 See more
yangyongqiang
26 days ago Comments:
26 days ago Comments:
/lgtm


26 days ago Added label: lgtm
yangyongqiang
26 days ago Comments:
26 days ago Comments:
/approve


26 days ago Added label: approved
26 days ago Merged pull request
Pull Request
描述
GE 侧适配子字节 dtype(如 DT_INT4 weight),打通 ND ↔ FRACTAL_NZ 显式 C0 变体的主机侧格式转换,并补齐各处将位宽编码值(
GetSizeByDataType = kDataTypeSizeBitOffset + bits)误当字节数使用的防护:GetBitsValue/SetBitsValue、CopyPackedSegment对齐快路径+逐元素回退、ND→NZ/NZ→ND 两个方向的 SubByte 转换);新增GetEffectiveC0统一 C0 解析(组合位域→primary 枚举变体);注册ND ↔ FORMAT_FRACTAL_NZ_C0_16/C0_32转换路由CheckShapeForSubByteTrans校验 NZ 形状不变量(末 4 维、w0>0、块内轴字节对齐、前缀乘积与块容量),防除零与越界访问IsSubByteFoldingBlocked覆盖 top/bottom 自定义算子与 legacy HostCpuOp 全路径,白名单(QuantBiasOptimization,已实现 INT4 packed 解包)放行输入检查,拦截后回落 GE 内置 kernelGetDataTypeBits判断条件修正;内存大小改用GetSizeInBytesCeilDiv 计算,防高估导致越界写GetNdToNzAlignedShape改用TransferShapeUtils::GetC0Value,与数据搬移侧 C0 口径一致变更类型
关联的Issue
如何测试
make ge_common_base graph -j16(覆盖 formats.cc / format_transfer_fractal_nz.cc / transfer_shape_utils.cc)编译链接通过核对清单