已关闭
[Bug-Report|缺陷反馈]: Pad tiling 中 Brcb 尾块 repeat times 计算错误,尾轴元素不足 8 时 Brcb 不执行导致数据丢失 #1518
JacsonPile创建于  8月17日关闭于  8月18日
JacsonPile
JacsonPile
8月17日 创建

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

Describe the current behavior / 问题描述 (Mandatory / 必填)

PadTilingFunc 函数在计算 Brcb 尾块的 repeat times 时,使用整数除法 brcbFractalTail / 8 对尾块元素数进行 8 对齐切分。当尾块元素数 brcbFractalTail ∈ [1, 7] 时,brcbFractalTail / 8 经整数截断结果为 0,导致 brcbFractalTailRepeatTimesbrcbFractalTailRepeatTimesTail 均被计算为 0。

kernel 侧 pad_base_impl.h 的 2201 架构 UnAlignedPad 路径依据这两个 tiling 字段决定是否发射 Brcb 指令:

// pad_base_impl.h:215-228
if (brcbFractalCount == brcbFractal) {
    for (uint32_t i = 0; i < brcbFractalTailRepeatTimes; i++) {       // 0 次,不执行
        Brcb(...);
    }
    if (brcbFractalTailRepeatTimesTail) {                              // 0,条件为 false,不执行
        Brcb(...);
    }
    tmp1RowFull = brcbFractalTail;
}

两个循环/分支均不执行,尾块的 1~7 个元素不会从 srcTensor 加载到 tmp1,最终输出数据错误。

缺陷代码位置

impl/adv_api/tiling/pad/pad_tiling_impl.cpp 第 169-170 行:

uint32_t brcbFractalTailRepeatTimes = brcbFractalTail / 8 / maxRepeatTimes;       // [1,7]/8 = 0
uint32_t brcbFractalTailRepeatTimesTail = brcbFractalTail / 8 % maxRepeatTimes;   // [1,7]/8 = 0

其中 brcbFractalTail = srcHeight * srcWidth % brcbTiling,即总元素数对 brcbTiling 取余后的尾块剩余元素数。

对比:同文件中正确的向上取整写法

第 151-152 行的 widthFractalTailAlingned 已正确使用 ceiling division 处理非对齐尾块:

uint32_t widthFractalTailAlingned =
    ((widthFractalTail - 1) / (PAD_ONE_BLK_SIZE / typeSize) + 1) * (PAD_ONE_BLK_SIZE / typeSize);

说明 Brcb 尾块路径遗漏了同样的向上取整处理。

Environment / 环境信息 (Mandatory / 必填)

  • 仓库: cann/asc-devkit
  • 分支/Tag: 9.2.0-beta.1(master 与其完全一致,9.1.0 的 BRC 计算逻辑同样存在)
  • 受影响架构: NpuArch::DAV_2201(Ascend910B)
  • 不受影响架构:
    • DAV_3510 / DAV_5102:使用 SIMD Reg API(pad_3510_impl.h),不走 Brcb
    • __NPU_ARCH__ == 2002(Ascend910A):走 DuplicateLastDimImpl,已正确处理 tailM = srcSize % BRCB_BROADCAST_NUMBER
  • 触发条件: width * sizeof(T) % 32 != 0(非 32B 对齐,进入 UnAlignedPad 路径)且 srcHeight * srcWidth % brcbTiling ∈ [1, 7]

Steps to reproduce the issue / 重现步骤 (Mandatory / 必填)

触发条件推导

typeSize=2(half)、stackBufferSize=4096 为例:

baseBlockLen  = 16 * 32          = 512 (Byte)
baseBlockSize = 512 / 2          = 256 (ele)
tmpBuffer1BlockNum = 4096 / 2 / 256 / 2 = 4
brcbTiling    = 16 * 4           = 64  (ele)

srcHeight * srcWidth 对 64 取余结果落在 [1, 7] 时触发。例如 srcHeight=1, srcWidth=65(total=65,brcbFractalTail=1)。

数值验证

total 元素 brcbFractal brcbFractalTail /8 repeatTimes repeatTimesTail 实际 Brcb 处理元素 状态
65 1 1 0 0 0 0 BUG(1 个元素丢失)
66 1 2 0 0 0 0 BUG(2 个元素丢失)
67 1 3 0 0 0 0 BUG(3 个元素丢失)
70 1 6 0 0 0 0 BUG(6 个元素丢失)
71 1 7 0 0 0 0 BUG(7 个元素丢失)
72 1 8 1 0 1 8 OK

触发面扫描(width 非 32B 对齐,half 类型)

stackBufferSize brcbTiling bug 触发 shape 数(h∈[1,10], w∈[1,199] 非对齐)
1024 16 416
2048 32 213
4096 64 113
8192 128 58

复现步骤

  1. 拉取 cann/asc-devkit 仓库 9.2.0-beta.1 分支
  2. 构造一个 shape 为 [1, 65](half 类型)的 Pad 调用,leftPad=0, rightPad=0,使 width * sizeof(half) = 130 非 32B 对齐
  3. 提供 stackBufferSize=4096 的 sharedTmpBuffer
  4. 执行 Pad(dst, src, padParams, sharedTmpBuffer, tiling),tiling 由 PadTilingFunc 生成
  5. 对比输出与输入:尾块第 65 个元素未被加载到 tmp1,输出该位置数据错误

Describe the expected behavior / 预期结果 (Mandatory / 必填)

brcbFractalTail ∈ [1, 7] 时,Brcb 应至少执行 1 次 repeat(处理这 1~7 个元素),而非 0 次。

brcbFractalTail / 8 应使用向上取整,使 brcbFractalTailRepeatTimesTail >= 1,保证尾块数据被加载。

image.png

Special notes for this issue/备注 (Optional / 选填)

调用链

Pad (pad.h:52)
  └─ PadImpl (pad_common_impl.h:41)
       └─ PadCompute (pad_v220_impl.h:31)
            ├─ AlignedPad      (32B 对齐路径,不使用 Brcb,不受影响)
            └─ UnAlignedPad    (pad_base_impl.h:115)
                 └─ Brcb 尾块循环 (pad_base_impl.h:215-228)  <- 受影响

Tiling 字段定义(include/adv_api/pad/pad_tilingdata.h

BEGIN_TILING_DATA_DEF(PadTiling)
...
TILING_DATA_FIELD_DEF(uint32_t, brcbTiling);
TILING_DATA_FIELD_DEF(uint32_t, brcbFractal);
TILING_DATA_FIELD_DEF(uint32_t, brcbFractalTail);
TILING_DATA_FIELD_DEF(uint32_t, maxRepeatTimes);
TILING_DATA_FIELD_DEF(uint32_t, brcbTilingRepeatTimes);
TILING_DATA_FIELD_DEF(uint32_t, brcbTilingRepeatTimesTail);
TILING_DATA_FIELD_DEF(uint32_t, brcbFractalTailRepeatTimes);     // bug 字段 1
TILING_DATA_FIELD_DEF(uint32_t, brcbFractalTailRepeatTimesTail); // bug 字段 2
END_TILING_DATA_DEF;

分支对比

分支 与 9.2.0-beta.1 的 diff
master 完全一致(无 diff)
9.1.0 BRC 计算逻辑一致,仅 ge::ShapeTensorShape、新增 DAV_5102 等无关改动
likedislike
shaonaiteshaonaite成员
8月17日 将 chenyiyuan 设为负责人
Cchenyiyuan成员
8月17日 将 m0_56712298 设为负责人
m0_56712298m0_56712298成员
8月17日 关联了pull request:fix: 修复Pad tiling中Brcb尾块repeat times计算错误(#1518)
JacsonPileJacsonPile
8月17日 issue状态由 待办的 改变为 修复中
JacsonPileJacsonPile
8月17日 关联了pull request:【Fix]】修复 Reduce compact 输出与 aligned 输入融合时的精度问题
chenyiyuan成员
8月18日 评论:

你好,该问题已确认,正在修复中。

likedislike
CANN-robotCANN-robot成员
8月18日 关闭了 issue
CANN-robotCANN-robot成员
8月18日 添加了label:resolved
JacsonPileJacsonPile
8月19日 issue状态由 修复中 改变为 已解决