已关闭
[Bug-Report|缺陷反馈]: AddLora 的 y_slice_size 默认值与 y_offset 写回边界校验不一致,存在默认参数失败和越界写回风险 #1579
xxyyhh创建于  5月17日关闭于  6月3日
xxyyhh
xxyyhh
5月17日 创建

Thanks for sending an issue! Please fill in the following template to help quickly solve your problem.

一、问题描述

AddLora 的 y_slice_size 默认值、tiling 参数校验和 kernel 实际写回范围存在不一致,可能导致以下问题:

  1. y_slice_size 在 op 定义和 GE 示例中默认值为 -1,但 tiling 中会先将其转换为 uint32_t 再校验,导致默认值 -1 被转换为 4294967295 后判定非法。
  2. y_offset 当前只校验 yOffset_ > H3_,会放过 y_offset == H3_。
  3. 当前只检查 H2_ <= H3_,没有检查 y_offset + H2_ <= H3_ 或 y_offset + y_slice_size <= H3_。kernel 写回地址中包含 y_offset + H2Offset,因此部分参数组合可能越过 y 当前行的边界。

二、环境信息

  • 昇腾硬件型号:Ascend 910/Ascend 310P
  • CANN版本:当前版本master分支
  • 涉及算子:addlora

三、重现步骤

可以通过以下两个最小场景复现或验证问题。

场景 1:默认 y_slice_size = -1 会在 tiling 阶段被误判非法
  1. 构造 AddLora 的最小输入形状:
参数 取值
y.shape [1, 16]
x.shape [1, 16]
weightB.shape [1, 1, 16, 16]
weightA.shape [1, 1, 16, 16]
indices.shape [1]
y_offset 0
y_slice_size -1
  1. 该参数组合符合当前 op 定义中的默认值:
// math/add_lora/op_host/add_lora_def.cpp
this->Attr("y_slice_size").AttrType(OPTIONAL).Int(-1);

// math/add_lora/op_graph/add_lora_proto.h
.ATTR(y_slice_size, Int, -1)

// math/add_lora/examples/test_geir_add_lora.cpp
ADD_INPUT_ATTR(y_slice_size, -1);
  1. 进入 tiling 校验时,y_slice_size 会被转换为 uint32_t:
// math/add_lora/op_host/add_lora_tiling.cpp
ySliceSize_ = static_cast<uint32_t>(*ySliceSizePtr);
OP_CHECK_IF(ySliceSize_ > H3_, ...);
  1. 此时 -1 会变成 4294967295,因此 ySliceSize_ > H3_ 成立,默认参数会被判定非法。
场景 2:y_offset + H2_ > H3_ 的参数组合可能通过 tiling 校验
  1. 构造如下输入:
参数 取值
y.shape [1, 16]
x.shape [1, 16]
weightB.shape [1, 1, 16, 16]
weightA.shape [1, 1, 16, 16]
indices.shape [1]
H2_ 16
H3_ 16
y_offset 8
y_slice_size 16
  1. 当前 tiling 中已有的校验包括:
// math/add_lora/op_host/add_lora_tiling.cpp
OP_CHECK_IF(H2_ > H3_, ...);

yOffset_ = static_cast<uint32_t>(*yOffsetPtr);
OP_CHECK_IF(yOffset_ > H3_, ...);

ySliceSize_ = static_cast<uint32_t>(*ySliceSizePtr);
OP_CHECK_IF(ySliceSize_ > H3_, ...);
  1. 对于上述参数:
H2_ = 16, H3_ = 16      => H2_ > H3_ 为 false
y_offset = 8, H3_ = 16  => yOffset_ > H3_ 为 false
y_slice_size = 16       => ySliceSize_ > H3_ 为 false

因此该参数组合可以通过当前 tiling 校验。

  1. 但 kernel 写回地址包含 y_offset + H2Offset:
// math/add_lora/op_kernel/add_lora_base.h
uint32_t dstOffset =
    mOffsetBatch.GetValue(mOffset) * y_column + y_offset
    + nidx * DEFAULT_UB_SPLIT_NUM + nIncoreOffset;

// math/add_lora/op_kernel/add_lora_310.h
uint32_t dstGmOffset = batchIdxOri * y_column + H2Offset + y_offset;
  1. 在该场景下,实际写回范围相当于从 y_offset = 8 开始写 H2_ = 16 列,即:
写回范围:[8, 24)
y 的第二维范围:[0, 16)

因此会超过 y.shape[1] = 16 的边界。

四、预期结果

  1. y_slice_size = -1 作为默认值时,应被明确定义并正确处理,例如解析为 H2_ 或 H3_ - y_offset,而不是因无符号转换导致非法。
  2. y_offset 应满足 0 <= y_offset < H3_,不应允许 y_offset == H3_。
  3. tiling 阶段应校验实际写回范围不会超过 y 的第二维边界:
    • 如果 kernel 实际写回宽度是 H2_,应校验 y_offset + H2_ <= H3_。
    • 如果语义上应按 y_slice_size 写回,则 kernel 写回逻辑也应使用有效的 y_slice_size。
  4. host、kernel、ST 参考实现应保持一致。当前 ST 参考实现使用的是:
y[:, y_offset:y_offset + y_slice_size] += ...

五、实际结果

  1. y_slice_size = -1 会在 tiling 中被转换为 uint32_t,导致默认参数不可用。
  2. y_offset == H3_ 当前不会被拒绝。
  3. y_offset + H2_ > H3_ 的参数组合可能通过 tiling 校验,但 kernel 写回地址存在越过当前行边界的风险。
  4. y_slice_size 被写入 tiling data,但从当前 kernel 写回路径看,写回边界主要由 H2_ / H2Offset 和 y_offset 决定,接口语义与实现不一致。

六、建议修复

  1. 在 tiling 中先使用 int64_t 原始 attr 做合法性校验,再转换为 uint32_t。
  2. 明确 y_slice_size == -1 的语义,并在 host 侧统一转换成有效写回宽度。
  3. 将 y_offset 校验调整为 0 <= y_offset < H3_。
  4. 增加组合边界校验,例如 y_offset + effective_update_size <= H3_。
  5. 补充 UT/ST:
    • y_slice_size = -1
    • y_offset == H3_
    • y_offset + H2_ > H3_
    • y_slice_size 与 H2_ 不一致时的预期行为
likedislike
east_yang成员
5月18日 评论:

感谢您的反馈,已安排开发分析对应的问题。

likedislike
Eeast_yang成员
5月18日 将 east_yang 设为负责人
RRobell
5月20日 关联了pull request:[Bugfix] Validate AddLora y slice bounds
Qqiansunchi159
5月27日 关联了pull request:[bugfix] AddLora新增对于参数ySliceSize和yOffset的校验
east_yang成员
6月3日 评论:
likedislike
Eeast_yang成员
6月3日 issue状态由 进行中 改变为 已完成
Eeast_yang成员
6月3日 关闭了 issue
CANN-robotCANN-robot成员
6月3日 添加了label:Accepted