已关闭
[Requirement|需求建议]: BroadcastTo 算子单轴场景性能优化 #2755
tan_xin创建于  11 天前关闭于  9 天前
tan_xin成员
11 天前 创建

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

一、背景信息 (必填)

BroadcastTo 算子在单轴广播场景(输入/输出经 MergeAxis 合并后维度为 1)下,原先走通用 tiling 路径(Tiling4BroadcastToAscendC),该路径针对多维场景设计,对单轴场景存在以下问题:

  1. tiling 切分不优:通用路径按多维轴切分,单轴场景无法充分利用 UB 空间
  2. B 轴浪费 buffer:标量广播(B 轴)只需 1 块 UB 常驻,但通用路径固定双 buffer,导致 tileSize 被砍半,MTE3 搬运次数翻倍
  3. 缺少专用模板:单轴场景的数据搬运模式简单(连续搬入/搬出),通用模板的流水线编排开销不必要

二、价值/作用 (必填)

  • 提升单轴广播场景性能:B 轴 tileSize 翻倍(MTE3 搬运次数减半),A 轴 Double Buffer 流水并行
  • 典型应用场景
    • 标量广播:[1] → [N](如 torch.broadcast_to(torch.tensor([1.0]), (1000000,)))
    • 多维全广播合并为单轴:[1,1,1] → [535,535,536](经 MergeAxis 合并为 [1] → [153319760]
    • 纯拷贝:[N] → [N](A 轴,输入输出 shape 相同)
  • 影响范围:BroadcastTo 算子在 ascend950 上的所有单轴场景,包括 aclnn 直调和 PyTorch 训练推理

三、设计方案 (必填)

3.1 使能方式
  • aclnn 直调:通过 aclnnBroadcastTo API 调用,host tiling 自动判断是否走单轴路径
  • PyTorch 训练/推理:通过 CANN backend 的 torch.broadcast_to 触发
  • 其他算子复用broadcast_to_impl 已暴露给其他算子(如 tile)使用,单轴路径自动生效
3.2 总体设计
3.2.1 算子支持的数据类型
数据类型 支持
float32 (DT_FLOAT)
float16 (DT_FLOAT16)
bfloat16 (DT_BF16)
int8 (DT_INT8)
int16 (DT_INT16)
int32 (DT_INT32)
int64 (DT_INT64)
uint8 (DT_UINT8)
uint32 (DT_UINT32)
bool (DT_BOOL)
hifloat8 (DT_HIFLOAT8)
float8_e5m2 (DT_FLOAT8_E5M2)
float8_e4m3fn (DT_FLOAT8_E4M3FN)
3.2.2 host 侧设计

触发条件:在 Tiling4BroadcastTo 中,经 MergeAxis 合并后 outShape.GetDimNum() == 1 时进入 Tiling4SingleAxis

Tiling 流程

Tiling4BroadcastTo
  ├─ GetShapeInfo (获取输入输出 shape)
  ├─ MergeAxis (合并相同类型轴)
  ├─ IsSingleAxisBrcAfterMerge(outShape) ?
  │   ├─ YES → Tiling4SingleAxis
  │   └─ NO  → Tiling4BroadcastToAscendC (通用路径)

Tiling4SingleAxis 逻辑

  1. 判断 A/B 轴isBrc = (inDim != outDim),B 轴为标量广播,A 轴为纯拷贝
  2. 选择 buffer 数:B 轴单 buffer(BUFFER_NUM_B=1,可用全部 UB),A 轴双 buffer(BUFFER_NUM_A=2
  3. 计算 tileSizemax(min(blockFactor, bufferSizeElements), minUbElements),128B 对齐
  4. 负载均衡totalTiles = CeilDiv(totalOutElems, tileSize),按核数分配 blockFactor,主核多 1 块
  5. 设置 tilingKey:A 轴 11006(SINGLE_AXIS),B 轴 11007(SINGLE_AXIS_BRC)
  6. workspacebrcto::kSyncWorkSpaceSize(16MB)

TilingData 结构

struct SingleAxisBrcTilingData {
    uint64_t shapeSize;     // 输出总元素个数
    uint32_t tileSize;      // 每块 tile 元素个数
    uint32_t blockNum;      // 使用核数
    uint64_t blockFactor;   // 主核 tile 块数, 尾核 blockFactor-1
};
3.2.3 kernel 侧设计

模板类BroadcastSingleAxis<T, IsBrc>,使用 LocalMemAllocator 静态 Tensor 编程 + Mutex 流水线同步。

A 轴(IsBrc=false)

流水线: MTE2(DataCopyPad搬入) → MTE3(DataCopyPad搬出)
同步:   Mutex 双 ID 交替 (mutexId0_/mutexId1_), Ping/Pong Double Buffer

for (i = 0; i < loopNum; i++) {
    curMutex = (i & 1) ? mutexId1_ : mutexId0_;
    curBuf   = (i & 1) ? ubPong    : ubPing;

    Lock<MTE2>(curMutex) → DataCopyPad(curBuf, inGM[offset]) → Unlock<MTE2>(curMutex)
    Lock<MTE3>(curMutex) → DataCopyPad(outGM[offset], curBuf) → Unlock<MTE3>(curMutex)
}
// MTE2[i+1] 与 MTE3[i] 并行 (不同 mutexId)

B 轴(IsBrc=true)

流水线: MTE2(DataCopyPad标量→scalarBuf) → V(Duplicate广播填充ubPing) → MTE3(循环搬出)
同步:   Mutex 单 ID (mutexId0_), MTE2→V→MTE3 串行依赖

Init:
  ubPing = ubAlloc.Alloc<T>(tileSize)
  scalarBuf = ubAlloc.Alloc<T>(32/sizeof(T))

CopyDataInWithDMA:
  Lock<MTE2> → DataCopyPad(scalarBuf, inGM[0]) → Unlock<MTE2>
  Lock<V>    → Duplicate(ubPing, scalarBuf, tileSize) → Unlock<V>

Process:
  Lock<MTE3> → for (loopNum) DataCopyPad(outGM[offset], ubPing) → Unlock<MTE3>

Dispatch 逻辑broadcast_to.h):

if (TILING_KEY_IS(SINGLE_AXIS) || TILING_KEY_IS(SINGLE_AXIS_BRC)) {
    GET_TILING_DATA_PTR_WITH_STRUCT(SingleAxisBrcTilingData, saTilingData, tiling);
    if (TILING_KEY_IS(SINGLE_AXIS)) {
        BroadcastSingleAxis<DTYPE_X_, false> op;  // A轴
    } else {
        BroadcastSingleAxis<DTYPE_X_, true> op;   // B轴
    }
    op.Init(x, y, saTilingData);
    op.Process();
}
3.3 支持硬件
硬件 支持
ascend950
mc62
ascend910b ❌(走 legacy TBE 路径)

3.4 算子约束限制

  1. 触发条件:仅当输入输出经 MergeAxis 合并后维度为 1 时走单轴路径,否则走通用多维路径
  2. A 轴约束inDim == outDim(纯拷贝),tileSize 需 128B 对齐
  3. B 轴约束inDim == 1(标量广播),Duplicate(tensor版) 要求 tileSize 128B 对齐
  4. workspace:需 16MB workspace 用于核间同步
  5. 不支持的场景
    • 多维非广播轴与广播轴混合(如 [1,5] → [3,5],合并后维度 > 1,走通用路径)
    • ascend910b(走 legacy TBE tbe.broadcast + auto_schedule

💡 备注(选填)

likedislike
Ttan_xin成员
11 天前 添加了label:requirement
Ttan_xin成员
11 天前 修改了issue 的描述
Ttan_xin成员
11 天前 修改标题为 “[Requirement|需求建议]: BroadcastTo 算子单轴场景性能优化”,原标题为“[Requirement|需求建议]: ”
陈思
陈思成员
11 天前 评论:

/assign @tan_xin

likedislike
CANN-robotCANN-robot成员
11 天前 将 tan_xin 设为负责人
CANN-robotCANN-robot成员
9 天前 关闭了 issue
CANN-robotCANN-robot成员
9 天前 添加了label:resolved