ATB activation 算子源码导航:路由文件、Runner 决策与 Kernel 实现的完整阅读路径
2026/9/19 9:21:28 网站建设 项目流程

ATB activation 算子源码导航:路由文件、Runner 决策与 Kernel 实现的完整阅读路径

【免费下载链接】ascend-transformer-boost本项目是CANN提供的是一款高效、可靠的Transformer加速库,基于华为Ascend AI处理器,提供Transformer定制化场景的高性能融合算子。项目地址: https://gitcode.com/cann/ascend-transformer-boost

本文以 CANN ascend-transformer-boost(ATB)仓库内的 activation 路由文件 为核心骨架,结合 activation 知识条目 与 src/ops/ops_infer/activation/ 下的真实实现,系统梳理 activation 复合算子的 10 个源码文件、四种 Runner 决策逻辑、ACLNN 封装模式、原生 Ops 调用链、参数定义与 Kernel 目录结构。读者读完可以掌握:activation 算子由路由定位到源码的标准路径、不同平台下 Runner 如何被选择、ACLNN 与原生 Ops 两条执行链路的差异,以及各激活函数 Kernel 的落点。

1. 算子坐标:activation 在 ATB 知识库中的定位

在 ATB Agent 知识库主索引(.agent/knowledge/README.md)中,activation 被归类为infer(推理)类别、M 级复杂度,共10 个文件,支持ACLNN路径。路由文件头部的元信息给出了第一手定义:

分类: infer |复杂度: M |文件数: 10Runner 类型: OpsRunner, ACLNNRunner, Operation |ACLNN: yes预估阅读时间: 5-10 分钟

知识条目(index.md)进一步明确了它的本质:

  • 类型:composite(复合算子),包含 GELU、SiLU/SwiGLU、ReLU、Tanh、Sigmoid 等多种激活函数;
  • Runner 决策:ActivationAclnnRunner/GeluAclnnRunner/SwigluForwardAclnnRunner/ActivationOpsRunner四种;
  • Pipeline: 逐元素单阶段,部分支持量化和 dtype 转换;
  • 相关算子:swiglu_quant(激活+量化)、fast_gelu(GELU 变体)。

路由文件的核心价值在于它是一张"地图":它告诉读者 activation 算子的源码分布在哪些文件、每个文件承担什么角色、按什么顺序阅读最高效、以及 Kernel 与参数定义在哪里。

2. 文件清单:10 个文件的角色分工

路由文件第 1 节完整列出了 activation 涉及的 10 个文件(目录见 src/ops/ops_infer/activation/),按角色分为三类:

#文件角色
1activation_aclnn_runner.cppACLNN Runner
2activation_aclnn_runner.hACLNN Runner
3activation_operation.cppOperation 定义
4activation_operation.hOperation 定义
5activation_ops_runner.cppOps Runner
6activation_ops_runner.hOps Runner
7gelu_aclnn_runner.cppACLNN Runner
8gelu_aclnn_runner.hACLNN Runner
9swiglu_forward_aclnn_runner.cppACLNN Runner
10swiglu_forward_aclnn_runner.hACLNN Runner

这 10 个文件构成三层架构:

  • Operation 层(2 个文件):对外暴露的算子定义,负责参数校验、InferShape、Runner 创建;
  • ACLNN Runner 层(6 个文件):封装 CANN 标准 ACLNN API,是 ASCEND_950 等平台的主执行路径;
  • Ops Runner 层(2 个文件):走 ATB 原生 Ops API 的执行路径,用于其他平台。

activation 是知识库中少有的同时拥有 3 个 ACLNN Runner 的算子(activation / gelu / swiglu_forward),说明不同激活函数在底层采用了不同的算子封装,而非一个 Runner 通吃所有激活类型。

3. 推荐阅读顺序:从接口到实现

路由文件第 2 节给出的 10 步阅读顺序,实际反映了 activation 算子的代码依赖方向——先看对外接口,再看决策逻辑,最后深入到 Workspace 计算与平台适配:

顺序文件重点关注
1activation_operation.h了解输入输出数量、InferShape 签名
2activation_operation.cppCreateRunner() 决策逻辑
3activation_aclnn_runner.hACLNN API 封装接口
4gelu_aclnn_runner.hACLNN API 封装接口
5swiglu_forward_aclnn_runner.hACLNN API 封装接口
6activation_aclnn_runner.cppWorkspace 计算 + ACLNN API 调用
7gelu_aclnn_runner.cppWorkspace 计算 + ACLNN API 调用
8swiglu_forward_aclnn_runner.cppWorkspace 计算 + ACLNN API 调用
9activation_ops_runner.h原生 Ops 执行接口
10activation_ops_runner.cpp原生 Ops 调用链 + 平台适配

这条路径设计合理:activation_operation.h是入口,声明了GetInputNum()GetOutputNum()InferShapeCheckImplInferShapeImplCreateRunnerSetupCheckImpl等核心虚函数签名(见 activation_operation.h),先建立接口心智模型,再在CreateRunner()中看到"平台 + 激活类型"的二维决策,随后分别进入 ACLNN 与 Ops 两条执行路径的细节。

4. 源码路径定位

路由文件第 3 节给出了三个关键路径锚点,这也是 ATB infer 算子的标准定位模式(见知识库 README 第 3.1 节的标准目录结构约定):

  • Op 目录:src/ops/ops_infer/activation/
  • Kernel 目录:src/kernels/kernels/activation
  • 参数头文件:include/atb/infer_op_params.h

Kernel 目录(src/kernels/kernels/activation/)按激活函数分子目录组织,每个子目录包含 kernel 实现,必要的子目录还分离了 tiling 逻辑:

子目录内容
relu/relu_kernel.cpp
gelu/gelu_forward/GELU kernel(后者含 kernel/tiling 分离结构)
fast_gelu/faster_gelu_forward/GELU 快速近似变体
swish/sigmoid/log/逐元素激活 kernel
swiglu_forward/swiglu_backward/SwiGLU 前向/反向(含 tiling)
tiling/activation_tiling.cpp/h 公共 tiling 逻辑

从目录结构可以推断,activation 覆盖了 Transformer 推理场景中最常用的激活函数集合;其中 SwiGLU 路径(前向 + 反向)拥有独立的 tiling 与 kernel 实现,复杂度明显高于纯逐元素的 ReLU/Sigmoid 等。

5. 参数定义:ActivationParam 与 ActivationType

参数头文件 include/atb/infer_op_params.h 定义了 activation 所需的两个核心类型。

5.1 ActivationType 枚举

enum ActivationType : int { ACTIVATION_UNDEFINED = 0, // 未定义 ACTIVATION_RELU, // RELU激活类型 ACTIVATION_GELU, // GELU激活类型 ACTIVATION_FAST_GELU, // FAST_GELU激活类型 ACTIVATION_SWISH, // SWISH激活类型 ACTIVATION_LOG, // LOG激活类型 ACTIVATION_SWIGLU_FORWARD, // SWIGLU_FORWARD激活类型 ACTIVATION_SWIGLU_BACKWARD, // SWIGLU_BACKWARD激活类型 ACTIVATION_SIGMOID, // SIGMOID激活类型 ACTIVATION_FASTER_GELU_FORWARD, // FASTER_GELU_FORWARD激活类型 ACTIVATION_MAX, // 枚举最大值, 非激活类型 };

枚举注释同时给出了关键约束:

  • ACTIVATION_FAST_GELU:快速运算的 GELU,对 Tensor 内每个 element 做近似计算,计算速度更快,同时保持较高的准确性;
  • ACTIVATION_SWIGLU_FORWARD:SwiGLU 正向激活函数,Atlas 推理系列产品中只支持 32 位对齐的数据
  • ACTIVATION_FASTER_GELU_FORWARD:简化后的 FastGelu,计算速度更快;
  • ACTIVATION_SWIGLU_BACKWARD:SwiGLU 正向激活函数的反向,求梯度时使用,只支持 Atlas 800I A2 推理产品

5.2 ActivationParam 结构体

struct ActivationParam { enum GeLUMode : int { TANH_MODE = 0, // 默认值,使用tanh估算 NONE_MODE, // 原GeLU计算公式 }; ActivationType activationType = ACTIVATION_UNDEFINED; // 激活函数类型 float scale = 1.0f; // SWISH激活函数的参数 int32_t dim = -1; // SWIGLU激活函数的参数 GeLUMode geluMode = TANH_MODE; // GeLU模式选择参数 uint8_t rsv[8] = {0}; // 预留参数 };

各字段语义与默认值:

字段默认值作用
activationTypeACTIVATION_UNDEFINED必须显式设置,决定走哪条执行路径
scale1.0fSwish 激活的缩放参数
dim-1SwiGLU 的切分维度,-1表示最后一维
geluModeTANH_MODEGELU 计算模式:tanh 近似或原始公式
rsv[8]{0}预留,保持 ABI 兼容

在 activation_operation.cpp 的CreateOperation模板特化中,参数被强校验:activationType必须落在(ACTIVATION_UNDEFINED, ACTIVATION_MAX)开区间内,否则返回ERROR_INVALID_PARAMdim != -1时仅允许ACTIVATION_SWIGLU_FORWARD/BACKWARD使用(SwiGLU 支持切分维度),其他激活类型一旦携带dim直接报错。

6. Runner 决策:CreateRunner() 的二维分派

CreateRunner()(见 activation_operation.cpp)的核心思想是按平台 × 激活类型二维分派

std::shared_ptr<Runner> ActivationOperation::CreateRunner(Context &context) const { if (Mki::PlatformInfo::Instance().GetPlatformType() == Mki::PlatformType::ASCEND_950) { if (param_.activationType == atb::infer::ActivationType::ACTIVATION_SWIGLU_FORWARD) { return std::make_shared<SwigluForwardAclnnRunner>(param_); } else if (param_.activationType == atb::infer::ActivationType::ACTIVATION_GELU) { return std::make_shared<GeluAclnnRunner>(param_); } else { return std::make_shared<ActivationAclnnRunner>(param_); } } return std::make_shared<ActivationOpsRunner>(param_); }

决策结果可归纳为:

平台激活类型Runner
ASCEND_950SWIGLU_FORWARDSwigluForwardAclnnRunner
ASCEND_950GELUGeluAclnnRunner
ASCEND_950其他(SWISH/SIGMOID 等)ActivationAclnnRunner
非 950 平台全部ActivationOpsRunner(原生 Ops)

与之配套,CreateOperation在 ASCEND_950 平台下会预加载对应的 ACLNN 动态符号:GELU 加载GeluAclnnRunner::LoadMethod(),SWISH/SIGMOID 加载ActivationAclnnRunner::LoadAclnnFunctions(),SWIGLU_FORWARD 加载SwigluForwardAclnnRunner::LoadMethod(),加载失败返回ERROR_CANN_ERROR。此外,构造函数还会按平台选择不同的 Operation IR:GetOperationIrForActivation950()GetOperationIrForActivation()(后者通过AtbOperationIrCfg单例按激活类型取 IR,如ActivationOperationRELUActivationOperationSWIGLUFORWARDActivationOperationSWISH950等),体现 950 平台在 IR 层面的差异化适配。

7. ACLNN Runner 深入:Workspace 计算与 API 调用

以 activation_aclnn_runner.cpp 为例,其设计模式是函数指针 + KernelAdapters 适配器

aclnnStatus (*ActivationAclnnRunner::fastGeluGetWorkspaceSizeFunc_)(const aclTensor *, aclTensor *, uint64_t *, aclOpExecutor **) = nullptr; aclnnStatus (*ActivationAclnnRunner::fastGeluExecuteFunc_)(void *, uint64_t, aclOpExecutor *, aclrtStream) = nullptr; // gelu / log / relu / sigmoid / swish 的函数指针同理

MakeAdaptersByType()activationType返回{算子名, GetWorkspaceSize 回调, Execute 回调}三元组。GELU 的回调会透传geluModeNONE_MODE映射为 0,否则为 1):

case infer::ActivationType::ACTIVATION_GELU: return {"gelu", mode = (param.geluMode == infer::ActivationParam::GeLUMode::NONE_MODE) ? 0 : 1 { int64_t modeTmp = mode; return ActivationAclnnRunner::geluGetWorkspaceSizeFunc_(In(vp), &modeTmp, Out(vp), wsSize, executor); }, [](void *ws, uint64_t wsSize, aclOpExecutor *executor, aclrtStream stream) { return ActivationAclnnRunner::geluExecuteFunc_(ws, wsSize, executor, stream); }};

Swish 的封装则额外携带scale参数(aclScalar),对应ActivationParam::scale字段。

整个 ACLNN 执行流程遵循 CANN 标准两步式调用:xxxGetWorkspaceSize计算 workspace 大小并创建aclOpExecutor,再xxxExecute在指定aclrtStream上执行。ATB 通过 src/atb/utils/aclnn_util.h 与 src/atb/kernel_cache/aclnn_executor_cache.cpp 对该流程做统一封装;函数指针通过LoadMethod()/LoadAclnnFunctions()运行时动态加载,规避编译期对具体 ACLNN 头文件的强依赖。gelu_aclnn_runner.cppswiglu_forward_aclnn_runner.cpp遵循同样的封装模式,分别对应aclnnGeluaclnnSwigluForward系列 API。

8. Ops Runner 调用链:原生 Ops 路径与平台适配

activation_ops_runner.cpp 的实现非常精简——继承OpsRunner,在构造函数中构建一个单节点的 Kernel Graph:

ActivationOpsRunner::ActivationOpsRunner(const infer::ActivationParam &param) : OpsRunner("ActivationOpsRunner"), param_(param) { kernelGraph_.nodes.resize(1); auto &activationNode = kernelGraph_.nodes.at(0); activationNode.opDesc = RunnerUtil::GetActivationNodeOpDesc(param_); // 普通激活:1 输入 x、1 输出;SWIGLU_BACKWARD:2 输入 (y_grad, x)、1 输出 }

关键点:

  • 输入输出张量数量与 Operation 层保持一致:普通激活 1 输入 1 输出,ACTIVATION_SWIGLU_BACKWARD为 2 输入(y_gradx)1 输出;
  • RunnerUtil::GetActivationNodeOpDesc(param_)(见 src/atb/utils/runner_util.cpp)负责将 ATB 的ActivationParam翻译为底层MkiOpDesc;
  • 文件末尾通过REG_RUNNER_TYPE(ActivationOpsRunner)注册 Runner 类型,通过REG_OP_PARAM(AsdOps::OpParam::Activation)绑定底层 AsdOps 参数类型。

这条路径在非 ASCEND_950 平台(含 Atlas 推理系列,如 310P)上作为默认执行方式。与之对应,CheckSwigluForwardInTensor中针对 310P 做了约束:hiddenSize(最后一维)必须是 32 的倍数(HIDDEN_SIZE_DIM_BASE = 32),与参数头文件中"SWIGLU_FORWARD 只支持 32 位对齐数据"的注释相互印证。

9. InferShape 与参数校验:SwiGLU 的特殊处理

InferShapeImpl体现了复合算子的形状推导差异:

激活类型输出形状规则
SWIGLU_FORWARD输出复制输入,但splitDimdim < 0时转为dim + dimNum)上的维度减半(/ SPLIT_NUM
SWIGLU_BACKWARD输出形状取inTensor[1](即 x)
其他输出形状与输入一致(逐元素)

校验逻辑CheckSwigluBackwardInTensor还要求:两个输入dimNum相同,splitDim处输入 1 的维度是输入 0 的 2 倍(SPLIT_NUM * dims[i]),其余维度一致。SetupCheckImpl在运行时对真实 Tensor 做同样的形状一致性检查,保证传入的 Tensor 满足 SwiGLU 的切分语义。

10. 知识条目与快速导航

路由文件第 5~6 节指向知识库中的详细条目与主索引(注意:原文中的相对链接需换算为以仓库根目录为起点的路径):

  • 详细知识条目: ops/activation/activation/index.md,状态为complete,YAML 元信息记录了算子属性(op: {name: "activation", category: "activation", tier: "M", type: "composite"})与源码锚点(src/ops/ops_infer/activation/src/kernels/kernels/activation/include/atb/infer_op_params.h);
  • 主索引: .agent/knowledge/README.md,覆盖 82 个 ATB 算子,可按功能分类、复杂度分层、ACLNN 支持三种维度检索;
  • 分类: infer: 在 .agent/knowledge/README.md 的 activation 分类下,activation 与 elewise、softmax、rope、swiglu_quant 等算子并列,其中仅有 activation 与 swiglu_quant 两个激活类算子同时支持 ACLNN 路径。

对 Agent 或开发者而言,定位 activation 的最小路径是:主索引搜索activation→ 读 routing/activation.md 获取文件清单 → 按需读知识条目与源码。这条链路同样适用于知识库中其他 81 个算子。

11. 实战定位速查

结合路由文件与源码,将 activation 算子最常用的定位目标汇总如下:

任务目标文件要点
了解算子对外接口activation_operation.h输入输出数量、InferShape/CreateRunner 签名
理解 Runner 如何选择activation_operation.cpp平台 × 激活类型二维分派、IR 选择、参数强校验
查看参数与枚举定义include/atb/infer_op_params.hActivationType 全枚举、ActivationParam 全字段与默认值
ACLNN 执行路径activation_aclnn_runner.cpp函数指针加载、Workspace 计算、GELU mode / Swish scale 透传
原生 Ops 执行路径activation_ops_runner.cpp单节点 Kernel Graph、OpDesc 翻译、Runner 注册
底层 Kernelsrc/kernels/kernels/activation/各激活函数的 kernel 与 tiling 实现

12. 小结

activation 路由文件篇幅不长,但精准刻画了一个 M 级复合算子的完整知识边界:10 个源码文件、4 种 Runner、3 个 ACLNN 封装、1 个复合激活函数族。顺着"路由文件 → 知识条目 → 源码"的路径可以确认:ATB 在 ASCEND_950 上优先走 ACLNN 标准 API(按激活类型细分为三个 Runner),在其他推理平台上回退到原生 Ops 路径,两者共享同一套 ActivationParam 参数定义与形状推导语义。这种"平台优先 + 类型分派"的 Runner 架构,也是理解 ATB 中其他支持 ACLNN 的 infer 算子(如 softmax、rope、rms_norm)的通用钥匙。

【免费下载链接】ascend-transformer-boost本项目是CANN提供的是一款高效、可靠的Transformer加速库,基于华为Ascend AI处理器,提供Transformer定制化场景的高性能融合算子。项目地址: https://gitcode.com/cann/ascend-transformer-boost

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询