Merged
【feat】: 支持子字节dtype(DT_INT4)的ND/FRACTAL_NZ格式转换与常量折叠防护 #5199
kantao1Add on Sep 28
【feat】: 支持子字节dtype(DT_INT4)的ND/FRACTAL_NZ格式转换与常量折叠防护 #5199
Merged
kantao1Add on Sep 28
kantao1Collaborators
Sep 28

Pull Request

描述

GE 侧适配子字节 dtype(如 DT_INT4 weight),打通 ND ↔ FRACTAL_NZ 显式 C0 变体的主机侧格式转换,并补齐各处将位宽编码值(GetSizeByDataType = kDataTypeSizeBitOffset + bits)误当字节数使用的防护:

  1. 子字节位级格式转换(format_transfer_fractal_nz.cc):新增 packed 位级搬移实现(GetBitsValue/SetBitsValue、CopyPackedSegment 对齐快路径+逐元素回退、ND→NZ/NZ→ND 两个方向的 SubByte 转换);新增 GetEffectiveC0 统一 C0 解析(组合位域→primary 枚举变体);注册 ND ↔ FORMAT_FRACTAL_NZ_C0_16/C0_32 转换路由
  2. 入口防护:位宽限定 1/2/4 bit(拒绝 FLOAT6 等无法按整字节打包的类型);CheckShapeForSubByteTrans 校验 NZ 形状不变量(末 4 维、w0>0、块内轴字节对齐、前缀乘积与块容量),防除零与越界访问
  3. TransDataFormat 门禁(formats.cc):子字节仅放行 ND ↔ 显式 C0 的 NZ 族互转,裸 FRACTAL_NZ 及其他组合直接拒绝,错误信息携带格式与放行条件
  4. 常量折叠防护(constant_folding_pass.cc):IsSubByteFoldingBlocked 覆盖 top/bottom 自定义算子与 legacy HostCpuOp 全路径,白名单(QuantBiasOptimization,已实现 INT4 packed 解包)放行输入检查,拦截后回落 GE 内置 kernel
  5. 位宽编码修复(fe_utils/fusion_turbo/eager_op_execution_context/kernel_utils):GetDataTypeBits 判断条件修正;内存大小改用 GetSizeInBytes CeilDiv 计算,防高估导致越界写
  6. 其他路径防护与口径统一:transpose 转换拒绝子字节;Pack kernel 跳过子字节折叠;GetNdToNzAlignedShape 改用 TransferShapeUtils::GetC0Value,与数据搬移侧 C0 口径一致

变更类型

关联的Issue

如何测试

  1. 前置条件:CANN 环境(cann-9.3.0),ge 仓 build_ut 构建目录
  2. make ge_common_base graph -j16(覆盖 formats.cc / format_transfer_fractal_nz.cc / transfer_shape_utils.cc)编译链接通过
  3. constant_folding_pass.cc 以 ge_compiler 同参数(-std=c++17)语法检查通过
  4. INT4 权重场景验证:ND(DT_INT4) → FRACTAL_NZ_C0_16/C0_32 转换及反向,W 非 C0 整数倍的尾部场景

核对清单

likedislike
Pull Request has been successfully merged by CANN-robot.
(Thank you for kantao1's contribution.)
Kkantao1Collaborators
Sep 28 Added label: enhancement
Kkantao1Collaborators
Sep 28 Created pull request, commit 2bf15f1b
atomgit-bot
atomgit-bot
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 自定义算子与 legacy HostCpuOp 路径,白名单 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 计算,避免高估导致越界写。
likedislike
Incorrect?
atomgit-bot
atomgit-bot
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

⛔ 需要修改

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

/lgtm

likedislike
CANN-robotCANN-robotCollaborators
26 days ago Added label: lgtm
yangyongqiang
yangyongqiangCollaborators
26 days ago Comments:

/approve

likedislike
CANN-robotCANN-robotCollaborators
26 days ago Added label: approved
CANN-robotCANN-robotCollaborators
26 days ago Merged pull request