已开启
[Requirement|需求建议]: SwigluGatedMlp 算子AscendC实现 #2576
wuxs68创建于  5月21日
wuxs68
5月21日 创建

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

Backgroud(背景信息)

SwigluGatedMlp 算子是一种将两次 MatMul 与 SwiGLU 激活进行组合的门控 MLP 算子。在深度学习领域,特别是 LLaMA 等大语言模型(LLM)中,SwiGLU 是 FFN/MLP 结构的核心组件,其计算流程为 gate_up = MatMul(x, gate_up_weight),再执行 hidden = silu(gate) * up,最后通过 MatMul(hidden, down_weight) 得到输出。本项目对 timers1 中 SwigluGatedMlp 算子进行 AscendC 适配和优化,提升其在昇腾硬件上的执行效率。

Origin(信息来源)

联通(广东)产业互联网有限公司

Benefit / Necessity (价值/作用)

使用 AscendC 对 timers1 中 SwigluGatedMlp 算子进行优化,实现 MatMul + SwiGLU + MatMul 计算流程在昇腾硬件上的适配。该实现通过 ACLNN 接口组织执行流程,中间 SwiGLU 阶段使用 AscendC 自定义 Kernel 完成,可减少框架侧拆分调度开销,提升大模型 MLP 模块推理性能。
支持设备:
Atlas A3 训练系列产品/Atlas A3 推理系列产品
Atlas A2 训练系列产品/Atlas A2 推理系列产品

Design(设计方案)

目前支持的场景:

  • 支持数据类型:float32float16bfloat16

host 侧设计:

tiling 策略:

  1. 分核策略
  • 计算展开后的行数(totalRows = inputShapeSize / hiddenSize)。
  • 根据 gate_up_weight 第二维计算 intermediateSize = gateUpSize / 2,并结合 down_weight 获取输出维度 outSize
  • MatMul 阶段根据平台 AIC 核数和 MatMul tiling 结果确定使用核数;SwiGLU 阶段根据 AIV 核数和 totalRows * intermediateSize 确定使用核数。
  • 若计算结果为 0,强制设置为 1,保证任务正常下发。
  1. 单 core 内切分策略
  • MatMul 阶段生成 mm1BaseM/N/Kmm2BaseM/N/K,用于控制矩阵乘分块。
  • SwiGLU 阶段根据 UB 大小、数据类型字节数和 32B 对齐要求计算 swiBaseRowsswiBaseCols
  • 根据 UB 大小判断是否启用双缓冲,用于提升搬运与计算流水效率。
  1. 结构体写回
  • SwigluGatedMlpTilingData 中记录数据类型、执行阶段、动态 shape 标识、使用核数、数据类型大小等信息。
  • 记录全局计算规模:totalRowshiddenSizegateUpSizeintermediateSizeoutSize
  • 记录分块信息:baseRowsPerCoretailRowstileRowsswiBaseRowsswiBaseCols
  1. tilingkey 规划
  • 根据输入数据类型和执行阶段映射到不同 tilingKey,用于区分 Kernel 侧分支:Float16 对应 1101/1102/1103,Float 对应 2101/2102/2103/2104,Bfloat16 对应 3101/3102/3103
  • 其中 MM1、SwiGLU、MM2 分别对应不同 stage,FP32 额外支持 fused 分支。
  1. 数据检测与容错:
  • 检查 x 输入维度是否小于 2,若满足则报错。
  • 检查 gate_up_weightdown_weight 是否为 2D,若不满足则报错。
  • 检查 gate_up_weight.shape[1] 是否为偶数,down_weight.shape[0] 是否等于 gate_up_weight.shape[1] / 2,若不满足则报错。
  • 检查输入输出数据类型是否一致,输出 shape 是否与 xdown_weight 匹配。
  • MatMul 阶段设置固定 Workspace 大小为 16MB(16 * 1024 * 1024)。

kernel 侧设计:

进行 Init 和 Process 两个阶段,其中 SwiGLU 阶段的 Process 包括数据搬入(CopyIn)、计算(Compute)、搬出(CopyOut)三个阶段。

2.1 初始化(Init)

获取 Tiling 参数:包括 totalRowshiddenSizegateUpSizeintermediateSizeoutSizeusedCoreNumswiBaseRowsswiBaseCols
初始化全局内存映射:MatMul 阶段设置 xGmweightGmyGm;SwiGLU 阶段设置 gateUpGmhiddenGm
初始化 UB 缓冲区:通过 pipe.InitBuffer 初始化 gate、up、out 队列和 float 临时计算缓冲区。
确定核索引:获取 blockIdx,根据当前核编号和总 tile 数分配本核处理的数据块。

2.2 计算流程(Compute)

gateUp 按最后一维拆分为 gate 和 up 两部分。
类型转换(分支处理):
若数据类型为 bfloat16_thalf,调用 Cast 将 gate 和 up 转换为 float 类型存储于临时 Tensor 中,并插入 PipeBarrier 同步。
核心计算(SwiGLU 逻辑):

  1. Sigmoid 计算:调用 Sigmoid(tmp, gateFp32)
  2. SiLU 计算:调用 Mul(gateFp32, gateFp32, tmp),实现 gate = gate * Sigmoid(gate)
  3. 最终乘法:调用 Mul(tmp, gateFp32, upFp32),实现 hidden = SiLU(gate) * up
    插入 PipeBarrier 确保向量计算指令完成。

2.3 数据搬入(CopyIn)与搬出(CopyOut)

  • CopyIn:根据 rowStartcolStart 计算偏移,通过 DataCopyPad 将 GM 中的 gate 和 up 数据切分搬入 UB,并对尾块进行对齐填充。
  • CopyOut:根据需要将计算结果进行类型转换(Cast),在同步确保计算完成后,利用 DataCopyPad 将 hidden 结果从 UB 搬运至 GM 对应位置,并释放缓冲区供下一轮循环使用。

2.4 流程调度(Process)

  • 循环处理本核分配的所有 tile,并针对末尾非对齐数据调整处理规模。
  • 严格按“CopyIn → Compute → CopyOut”顺序调度每个 tile,利用单双缓冲机制掩盖内存搬运延迟。
  • ACLNN 整体流程按“MM1 → SwiGLU → MM2”执行,通过 MatMul 计算单元和向量计算单元配合完成全量数据回写。
likedislike
wuxs68
5月21日 评论:

/assign

likedislike
CANN-robotCANN-robot成员
5月21日 将 wuxs68 设为负责人
Wwuxs68
5月21日 关联了pull request:SwigluGatedMlp 算子AscendC实现贡献
Wwuxs68
5月21日 关联了pull request:SwigluGatedMlp 算子AscendC实现贡献
Wwuxs68
5月29日 关联了pull request:SwigluGatedMlp 算子AscendC实现贡献