已关闭
[Requirement|需求建议]: 【社区任务】Roll 算子需求 #1971
boxw987创建于  6月15日关闭于  7月2日
boxw987
boxw987
6月15日 创建

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

Roll 算子需求与设计说明

一、需求背景

Roll 算子用于沿指定维度对输入张量执行循环位移,常见于序列处理、窗口重排和特征对齐等场景。

本说明聚焦当前最终提交版本的真实能力,目标是明确:

  1. 功能边界
  2. 设计方案
  3. 关键优化思路
  4. 测试与验收标准
  5. 后续维护约束

二、目标与范围

2.1 功能目标

  • 提供 aclnnRollGetWorkspaceSizeaclnnRoll 两阶段 ACLNN 接口。
  • 支持沿单维或多维执行循环位移。
  • dims 为空时,行为等价于先展平再执行一维 roll,最后恢复原始形状。

2.2 支持范围

类别 当前支持范围
数据类型 uint8int8bfloat16float16float32int32uint32
数据格式 ND
维度范围 0-D 到 8-D
属性语义 shifts 为滚动量,dims 为滚动维度
特性 负维度归一化、重复维度合并、dims 为空的 flatten roll

2.3 非目标范围

当前版本不纳入以下支持范围:

  • bool
  • int64
  • ND 数据格式

三、输入约束与数学语义

3.1 输入约束

  1. 输入输出 dtype 必须一致。
  2. 输入输出 shape 必须一致。
  3. 输入张量 rank 不超过 8
  4. dims 为空时,shifts 长度必须为 1
  5. dims 非空时,shiftsdims 长度必须一致。
  6. dims 的取值范围为 [-rank, rank)
  7. 对重复维度上的多个 shift,需要先做归一化合并。
  8. 0 维输入时,shifts 长度必须为 1,且 dims 为空。

3.2 数学语义

对任意参与滚动的维度,输出元素满足:

y[i] = x[(i - s) mod n]

其中:

  • s 为该维度归一化后的滚动量
  • n 为该维度长度

多维滚动时,各维度上的归一化结果共同作用于输出索引映射。

四、问题分析

Roll 的定义简单,但高性能实现存在以下难点:

  1. dims 为空时需要退化为 flatten roll,不能仍按原始多维索引路径执行。
  2. 单维滚动、多维滚动、最后一维滚动和非最后一维滚动,对应的访存模式差异很大。
  3. 小宽度、非对齐、小块场景若统一走通用路径,性能容易明显回退。
  4. 在控制实现复杂度的同时,仍需要保证正式支持范围内的性能优于参考 TBE。

因此,当前实现采取的主线是:

  • Host 侧负责参数规范化、归一化和切分
  • Kernel 侧根据归一化后的形态选择搬运路径

五、总体方案

5.1 方案概述

整体实现分为两部分:

  1. Host 侧负责参数校验、维度归一化、重复维度合并和 tiling 数据生成。
  2. Kernel 侧根据 active dim 形态执行不同的 roll/copy 路径。
flowchart TD
    A[aclnnRollGetWorkspaceSize] --> B[参数校验]
    B --> C[dtype format shape 约束校验]
    C --> D[dims shifts 归一化]
    D --> E[重复维度合并]
    E --> F[识别 activeDim 与 activeDimCount]
    F --> G[生成 Tiling 信息]
    G --> H[aclnnRoll]
    H --> I[Kernel Process]
    I --> J{路径选择}
    J --> K[Identity]
    J --> L[Flatten Roll]
    J --> M[Leading Dim Roll]
    J --> N[Last Dim Row Roll]
    J --> O[Single Dim Block Roll]
    J --> P[Multi-Dim Last-Dim Roll]
    J --> Q[Multi-Dim Non-Last Roll]
    J --> R[Segmented Fallback]

5.2 Host 侧职责

Host 侧主要负责:

  1. 空指针校验
  2. dtype 支持校验
  3. ND 格式校验
  4. 输入输出形状一致性校验
  5. dims/shifts 规则校验
  6. 负维度归一化
  7. 重复维度 shift 合并
  8. 生成 kernel 所需 tiling 数据

5.3 Kernel 侧职责

Kernel 侧不做复杂策略搜索,只消费 Host 给出的 tiling 信息并执行对应搬运路径。

核心原则:

  1. 优先把 roll 转为连续段 copy。
  2. 最后一维优先按行处理。
  3. 非最后一维优先按 block 重排。
  4. 保留 segmented fallback 作为通用正确性兜底路径。

六、详细设计

6.1 Host 侧设计

6.1.1 归一化逻辑

Host 侧将输入整理成更适合 Kernel 消费的结构:

  1. dims 为空时,退化为一维 flatten roll。
  2. dims 非空时,将负维度转换为正维度。
  3. 对重复维度上的多个 shift 先累加,再按该维长度取模。
  4. 统计 activeDimCount
  5. 若仅存在一个 active dim,则进一步提取:
    • outerSize
    • dimSize
    • innerSize
    • activeShift

6.1.2 Tiling 数据

Host 侧向 Kernel 传递的核心信息包括:

  • totalNum
  • dimNum
  • shapes[]
  • strides[]
  • shifts[]
  • activeDim
  • activeDimCount
  • outerSize
  • dimSize
  • innerSize
  • activeShift
  • usedCoreNum
  • perCoreElements
  • lastCoreElements
  • ubElements

6.1.3 切分策略

当前版本的 tiling 重点是稳定切分,而非复杂搜索:

  1. 小数据量优先单核,降低调度开销。
  2. 大数据量按 perCoreElements 切分,保证多核负载基本均衡。
  3. 对最后一维滚动、非最后维 block roll、BF16 小宽度和部分 uint8 小块场景,调整对齐与切分粒度。
  4. 对大 inner stride 场景避免过粗切分。

6.2 Kernel 侧设计

6.2.1 路径选择树

flowchart TD
    A[Kernel Process] --> B{activeDimCount == 0?}
    B -->|Yes| C[CopyIdentity]
    B -->|No| D{dimNum == 1?}
    D -->|Yes| E[CopyFlattenRollBySource]
    D -->|No| F{single active dim?}
    F -->|Yes| G{activeDim == 0?}
    G -->|Yes| H[CopyLeadingDimRollBySource]
    G -->|No| I{innerSize == 1 and last dim?}
    I -->|Yes| J[CopyLastDimRollByRows]
    I -->|No| K[CopySingleDimRollByBlocks]
    F -->|No| L{last active dim is final dim?}
    L -->|Yes| M[CopyMultiDimLastDimRollByRows]
    L -->|No| N[CopyMultiDimNonLastRollByBlocks]
    N --> O[CopySegmentedRoll]

6.2.2 主要实现路径

  1. CopyIdentity
    • 所有归一化后的 shift 均为 0 时,直接拷贝。
  2. CopyFlattenRollBySource
    • flatten 后将输入视为线性数组,通过两段拼接完成 roll。
  3. CopyLeadingDimRollBySource
    • 仅第 0 维滚动时,优先使用大段连续搬运。
  4. CopyLastDimRollByRows
    • 仅最后一维滚动且 innerSize == 1 时,按行处理。
  5. CopySingleDimRollByBlocks
    • 单 active dim 但不适合纯按行路径时,按 block 重排。
  6. CopyMultiDimLastDimRollByRows
    • 多维滚动且最后 active dim 为最后一维时,按行组处理。
  7. CopyMultiDimNonLastRollByBlocks
    • 多维滚动且最后 active dim 不在末尾时,按 block 映射重排。
  8. CopySegmentedRoll
    • 通用回退路径,确保功能正确性。

6.2.3 核心辅助能力

Kernel 内部不是单一路径,而是按场景组合以下能力:

  • 连续段 copy
  • 源端对齐 copy
  • 跨 stride 段 copy
  • row gather patch
  • flat patch
  • UB 内按行 rotate

这些能力共同服务于不同的 roll 路径。

七、性能优化主线

当前保留下来的优化不是单点 shape 硬编码,而是四类可复用策略。

7.1 连续段优先

能转换为连续段搬运的场景,优先使用连续 copy 或源端对齐 copy,减少逐元素处理。

7.2 最后一维按行优化

最后一维滚动天然适合按行处理。当前版本围绕这条主线提供:

  1. UB 内 row roll
  2. full-row copy
  3. row-group copy
  4. segment patch copy

7.3 非最后维按 block 重排

中间维或多维组合滚动时,优先按 block 建模,而不是按元素重算索引:

  1. 先计算目标 block 对应源 block。
  2. 尝试合并连续源 block 区间。
  3. 完整 block 与残块分开处理。

7.4 小宽度定向增强

当前版本保留一部分收益明确、不过度特化的小宽度优化,主要包括:

  1. BF16 多 active dim 小宽度最后维路径
  2. 窄宽度 last-dim roll 路径
  3. 部分 uint8 小块路径

这些优化仍遵循同一原则:

  • 优化搬运策略
  • 不引入写死单一 shape 的独立实现
  • 通过 Host 对齐规则和 Kernel patch 路径增强收益

八、测试与验收标准

8.1 功能验收

应满足以下条件:

  1. 输出 shape 与输入一致。
  2. 输出 dtype 与输入一致。
  3. 支持范围内所有 dtype 功能正确。
  4. 0-D、单维、多维、负维度、重复维度归并场景结果正确。
  5. dims 为空与 dims 显式指定两类模式均正确。

8.2 性能验收

  1. 以正式支持范围为准,不额外宣称无关 stress 扩展能力。
  2. 在正式支持的 shape/dtype 范围内,性能目标优于参考 TBE。
  3. 若出现性能回退,应优先排查是否错误退回到 segmented、row 或 block 的非最优路径。

8.3 建议测试覆盖项

建议持续保留以下覆盖:

  • 1D / 2D / 3D / 4D / 8D
  • 单维滚动 / 多维滚动
  • 最后一维 / 非最后一维
  • shift / 正 shift / 负 shift / 超维长度 shift
  • BF16 / FP16 / FP32 / INT32 / UINT8 / INT8 / UINT32

九、维护约束

  1. 后续优化应优先保留通用路径收益,避免回到写死单点 shape 的实现方式。
  2. 文档说明、接口约束和真实支持范围必须同步更新。
  3. 若新增 dtype 或格式支持,需同步评估 Host 校验、Kernel 路径和测试覆盖。
  4. 若性能调整改变路径选择规则,需补齐对应场景的验证样例。
likedislike
boxw987boxw987
6月15日 关联了pull request:Add roll operator
sunchun成员
6月16日 评论:

/assign @boxw987

likedislike
CANN-robotCANN-robot成员
6月16日 将 boxw987 设为负责人
Ffulltower成员
6月23日 修改标题为 “[Requirement|需求建议]: 【社区任务】Roll 算子需求”,原标题为“[Requirement|需求建议]: Roll 算子需求”
CANN-robotCANN-robot成员
7月2日 关闭了 issue
CANN-robotCANN-robot成员
7月2日 添加了label:resolved