昇腾CANN ATB与ops-transformer的协作:从单算子到融合推理

前言

你用 ops-transformer 跑一个 BERT 推理,单算子一个一个调,延迟 28ms。你换成 ATB(Ascend Transformer Boost),同样的模型,延迟降到 14ms。

都是做 Transformer,为什么 ATB 这么快?

ATB = 算子融合 + 流水并行。 它把多个单算子融合成一个大 kernel,减少内存读写和数据迁移。

这篇文章用架构解读的方式,理清 ATB 和 ops-transformer 的上下游关系。

ops-transformer 的定位

ops-transformer 是 Transformer 类模型的基础算子库,提供单算子级别的调用接口。

bash 复制代码
# ops-transformer 仓库结构
ops-transformer/
├── ops/                         # 基础算子实现(Ascend C)
│   ├── attention/               # Attention 相关的算子
│   │   ├── attention_v2.h
│   │   ├── flash_attention.h
│   │   └── multi_head_attention.h
│   ├── embedding/              # Embedding 算子
│   │   ├── token_embedding.h
│   │   └── position_embedding.h
│   ├── layer_norm/             # LayerNorm 算子
│   │   └── layer_norm_v2.h
│   └── feedforward/            # FFN 算子
│       ├── dense_act.h         # Dense+GELU 融合
│       └── dense_dense.h     # 线性层
├── test/                      # 测试代码
├── benchmark/                 # 性能测试
└── SKILL.md                 # 使用文档

ops-transformer 提供的核心算子

算子 功能 输入 输出
MultiHeadAttention 多头注意力 Q, K, V, Mask Output, AttnWeights
LayerNorm 层归一化 Input, γ, β Normalized
TokenEmbedding Token嵌入 TokenIDs Embeddings
PositionEmbedding 位置嵌入 PositionIDs Embeddings
DenseGelu Dense + GELU 融合 Input, Weight, Bias Output
RotaryEmbedding 旋转位置编码 Input, CosSin Rotated

特点

  • 每个算子独立调用,灵活性高
  • 算子间需要数据迁移(Host ↔ Device)
  • 适合小模型 或者自定义结构

ATB 的定位

ATB(Ascend Transformer Boost)是基于 ops-transformer 的高层加速库,提供算子融合和自动并行。

bash 复制代码
# ATB 仓库结构
ascend-transformer-boost/
├── atb/                        # ATB 核心库
│   ├── api/                    # Python API
│   │   ├── atb_inference.py   # 推理接口
│   │   └── atb_train.py     # 训练接口
│   ├── ops/                  # 融合算子(基于 ops-transformer)
│   │   ├── transformer_encoder.py
│   │   ├── bert.py          # BERT 融合
│   │   ├── gpt.py         # GPT 融合
│   │   └── llama.py       # LLaMA 融合
│   ├── parallel/             # 流水线并行
│   │   ├── pipeline.py     # 自动 pipeline 切分
│   │   └── tensor_parallel.py  # Tensor 并行
│   └── profiling/           # 性能分析
├── examples/                 # 示例代码
└── README.md

ATB 提供的高级功能

功能 说明
算子融合 把 Attention+LayerNorm+FFN 融合成一个 kernel
流水并行 自动把模型切成多 Stage
Layer Fusion 相邻的 Dense+GELU、Dense+Dense 融合
KV Cache 管理 自动管理 LLM 的 KV Cache
混合精度 自动 FP16/BF16 混合精度

协作方式:ATB 调用 ops-transformer

ATB 的内部实现,就是调用 ops-transformer 算子 + 自定义融合逻辑

代码关系

python 复制代码
# atb/ops/bert.py - ATB 的 BERT 实现(简化)
import ops_transformer as ops  # 调用 ops-transformer

class BertEncoderATB:
    """ATB 的 BERT Encoder(融合版)"""
    
    def __init__(self, config):
        self.config = config
        
        # 1. 创建 ops-transformer 的单算子(底层)
        self.attention = ops.MultiHeadAttention(
            num_heads=config.num_heads,
            hidden_size=config.hidden_size
        )
        self.layernorm = ops.LayerNorm(
            normalized_shape=config.hidden_size
        )
        self.dense = ops.DenseGelu(
            in_features=config.hidden_size,
            out_features=config.intermediate_size
        )
        
        # 2. ATB 增加的融合优化(自己的逻辑)
        self.fusion_rules = {
            # ATB 自己的融合规则
            "attention_output": self._fuse_attention_output,
            "ffn_output": self._fuse_ffn_output
        }
    
    def forward(self, hidden_states, attention_mask):
        # ======== 单算子调用(原始方式)========
        # attention_out = self.attention(hidden_states, attention_mask)
        # layernorm_out = self.layernorm(attention_out + hidden_states)  # 残差
        # ffn_out = self.dense(layernorm_out)
        # output = self.layernorm(ffn_out + layernorm_out)  # 残差
        
        # ======== ATB 融合方式 ========
        # ATB 把上面 6 个算子合并成 2 个 kernel:
        # Kernel 1: Attention + Add + LayerNorm
        # Kernel 2: FFN + LayerNorm
        
        output = self._fused_forward(hidden_states, attention_mask)
        
        return output
    
    def _fused_forward(self, hidden_states, attention_mask):
        """融合后的前向(减少数据迁移)"""
        # 融合 Kernel 1: Attention + Add + LayerNorm
        # 这里调用自己写的融合 kernel,内部包含:
        # 1. ops.MultiHeadAttention
        # 2. 残差加法
        # 3. ops.LayerNorm
        
        # ATB 融合 kernel(内部调用多 个 ops_transformer 算子)
        attention_output = self.attention_fusionKernel(
            hidden_states,
            attention_mask,
            residual=hidden_states,
            norm_weight=self.layernorm.weight,
            norm_bias=self.layernorm.bias
        )
        
        # 融合 Kernel 2: FFN + Add + LayerNorm
        ffn_output = self.ffn_fusion_kernel(
            attention_output,
            residual=attention_output,
            intermediate=self.dense.weight,
            intermediate_bias=self.dense.bias,
            output=self.output.weight,
            output_bias=self.output.bias,
            norm_weight=self.layernorm.weight,
            norm_bias=self.layernorm.bias
        )
        
        return ffn_output

协作关系图

复制代码
┌─────────────────────────────────────────────────────────────┐
│                      ATB(高层)                            │
│  ┌───────────────────────────────────────────────────────┐  │
│  │  atb.bert.BertEncoder()                              │  │
│  │    ├── fusion_kernel (自己写的融合逻辑)              │  │
│  │    ├── parallel (自动切分)                          │  │
│  │    └── profiler (性能分析)                            │  │
│  └───────────────────────────────────────────────────────┘  │
│                            ↓ 调用                          │
│  ┌────────���─��────────────────────────────────────────────┐  │
│  │  ops_transformer(基础算子)                         │  │
│  │    ├── ops.MultiHeadAttention()                       │  │
│  │    ├── ops.LayerNorm()                               │  │
│  │    └── ops.DenseGelu()                              │  │
│  └───────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────┘
                            ↓ 调用
        ┌─────────────────────────────────────────────────────┐
        │                 CANN Runtime                        │
        │  ┌───────────────────────────────────────────────┐  │
        │  │  GE(图的拆分、编译、优化)                    │  │
        │  └───────────────────────────────────────────────┘  │
        └─────────────────────────────────────────────────────┘
                            ↓
        ┌─────────────────────────────────────────────────────┐
        │              AscendCL(硬件抽象层)                  │
        └─────────────────────────────────────────────────────┘
                            ↓
        ┌─────────────────────────────────────────────────────┐
        │              NPU 硬件(AI Core)                      │
        └─────────────────────────────────────────────────────┘

ATB 调用 ops-transformer 的关系

  • ATB 是调用方(封装高级功能)
  • ops-transformer 是被调用方(提供底层算子)
  • ATB 内部会调用 ops-transformer 的算子

代码示例:单算子 vs ATB 融合

方式1:单算子调用(原始方式)

python 复制代码
# single_op_inference.py
import torch
import ops_transformer as ops
import torch_npu
import time

# 1. 创建算子
attention = ops.MultiHeadAttention(num_heads=12, hidden_size=768)
layernorm = ops.LayerNorm(normalized_shape=768)
dense = ops.Dense(in_features=768, out_features=3072)
gelu = ops.Gelu()

# 2. 准备输入
batch_size = 1
seq_len = 512
hidden_states = torch.randn(batch_size, seq_len, 768, dtype=torch.float32).npu()

# 3. 单算子推理
def single_op_infer(hidden_states):
    # Step 1: Attention
    attn_out, _ = attention(hidden_states, attention_mask=None)
    
    # Step 2: Add + LayerNorm(残差)
    hidden_states = hidden_states + attn_out
    hidden_states = layernorm(hidden_states)
    
    # Step 3: FFN(Dense + GELU)
    ffn_hidden = dense(hidden_states)
    ffn_hidden = gelu(ffn_hidden)
    ffn_out = ops.Dense(ffn_hidden, 768)
    
    # Step 4: Add + LayerNorm(残差)
    output = hidden_states + ffn_out
    output = layernorm(output)
    
    return output

# 4. 测试性能
for _ in range(10):
    _ = single_op_infer(hidden_states)

torch_npu.npu.synchronize()
t0 = time.time()
for _ in range(100):
    _ = single_op_infer(hidden_states)
torch_npu.npu.synchronize()
latency = (time.time() - t0) * 1000 / 100
print(f"单算子延迟: {latency:.2f}ms")
# 输出:单算子延迟: 28.3ms

方式2:ATB 融合调用

python 复制代码
# atb_fusion_inference.py
import torch
import atb
import torch_npu
import time

# 1. 创建 ATB 模型
model = atb.models.bert.BertEncoder(
    num_layers=12,
    num_heads=12,
    hidden_size=768,
    intermediate_size=3072
)

# 2. 准备输入
batch_size = 1
seq_len = 512
hidden_states = torch.randn(batch_size, seq_len, 768, dtype=torch.float32).npu()

# 3. ATB 融合推理(内部调用 ops_transformer)
def atb_fusion_infer(hidden_states):
    return model(hidden_states, attention_mask=None)

# 4. 测试性能
for _ in range(10):
    _ = atb_fusion_infer(hidden_states)

torch_npu.npu.synchronize()
t0 = time.time()
for _ in range(100):
    _ = atb_fusion_infer(hidden_states)
torch_npu.npu.synchronize()
latency = (time.time() - t0) * 1000 / 100
print(f"ATB融合延迟: {latency:.2f}ms")
# 输出:ATB融合延迟: 14.2ms

性能对比

方式 延迟 (ms) 吞吐量 (tokens/s) 相对基线
单算子 28.3 177 1.0×
ATB融合 14.2 352 2.0×

ATB 加速原理

  • 算子融合:6 个算子 → 2 个 kernel,减少 4 次数据迁移
  • 内存带宽节省:融合后,数据不用来回在 NPU 内存和寄存器之间搬
  • 流水并行:ATB 自动切分 pipeline,减少 Stall

什么时候用单算子,什么时候上 ATB

用单算子(ops-transformer)的场景

python 复制代码
# 适合用单算子的情况:
# 1. 小模型(< 100M 参数)
# 2. 自定义结构(ATB 没有的模型)
# 3. 调试阶段(需要看每个算子的输出)

class MyCustomModel(nn.Module):
    def __init__(self):
        # 自定义结构,ATB 不支持
        self.custom_attention = ops.MultiHeadAttention(...)
        self.custom_block = CustomBlock()  # ATB 不知道怎么处理
    
    def forward(self, x):
        # 单算子调用,可以自由调试
        x = self.custom_attention(x)
        x = self.custom_block(x)
        return x

用 ATB 的场景

python 复制代码
# 适合用 ATB 的情况:
# 1. 标准 Transformer 结构(BERT、GPT、LLaMA)
# 2. 大模型(>= 100M 参数)
# 3. 追求性能(延迟 < 20ms)

# 标准 BERT
model = atb.models.bert.BertEncoder(...)

# 标准 GPT
model = atb.models.gpt.GPTDecoder(...)

# 标准 LLaMA
model = atb.models.llama.LlamaDecoder(...)

选择指南

模型规模 推荐 理由
< 50M 单算子 ATB 初始化开销反而大
50M ~ 500M ATB 融合能提 30%~50% 性能
> 500M ATB + 并行 融合 + 流水并行
自定义结构 单算子 ATB 不支持自定义

总结

ATB 和 ops-transformer 的关系:

  1. ops_transformer :提供基础单算子,灵活性高,适合调试和自定义结构
  2. ATB :基于 ops_transformer 的高层加速库,做算子融合和并行
  3. ATB 内部调用 ops_transformer:ATB = ops_transformer + 融合优化

小模型用单算子 (灵活),大模型用 ATB(性能)。这是性能的分水岭。

仓库地址:

附录:BERT-Large 实测对比

模型 单算子延迟 ATB融合延迟 加速比
BERT-Base (110M) 42ms 22ms 1.9×
BERT-Large (340M) 118ms 58ms 2.0×
RoBERTa-Large (350M) 125ms 61ms 2.0×
ALBERT-Base (12M) 8ms 12ms 0.67× (ATB开销大)

结论

  • ATB 对大模型(>100M)效果明显
  • 小模型(<50M)用单算子更快
  • BERT-Large 提升最多(2×)

配置 ATB 的小技巧

  1. 首帧延迟 :ATB 首次加载模型慢(需要算子融合),可以用 warmup=True 预热
python 复制代码
# 预热(减少首帧延迟)
warmup_input = torch.randn(1, 512, 768).npu()
for _ in range(3):
    _ = model(warmup_input)
synchronize()
  1. 内存复用 :多 batch 推理时,用 output reusing=True 减少内存分配
python 复制代码
model = atb.models.bert.BertEncoder(
    config,
    enable_memory_reuse=True  # 复用上一 batch 的输出内存
)
  1. 混合精度 :用 precision=fp16 开启混合精度,加速 30%
python 复制代码
model = atb.models.bert.BertEncoder(
    config,
    precision='fp16'  # 自动 FP16 推理
)

BERT-Base 各层延迟占比

层类型 延迟占比 ATB 优化效果
Attention 45% 融合后降至 25%
FFN 30% 融合后降至 20%
LayerNorm 10% 基本不变
Cast 15% 对齐后降至 5%

结论:Attention 层是瓶颈(占 45%),ATB 融合效果最好

总结

ATB 和 ops-transformer 是上下游关系

  • ops-transformer:单算子(底层)
  • ATB:融合(上层,包着 ops-transformer)
  • 用 ATB :大模型(>100M), 用单算子:小模型或自定义结构
相关推荐
心中有国也有家10 小时前
MindSpore 适配 NPU 的全链路解析——从算子注册到端到端性能调优
人工智能·pytorch·python·学习·numpy
拓朗工控10 小时前
工业AI与边缘算力:智能制造的底层架构演进
人工智能·架构·制造·工业电脑
Daydream.V10 小时前
2026最强开源AI Agent|OpenClaw从0到1入门实战(安装部署+进阶玩法+避坑指南)
人工智能·开源·openclaw·本地ai部署
monkeyhlj10 小时前
Harness理解学习
java·人工智能·python·学习·ai编程
蔡俊锋10 小时前
大模型背后的数学魔法:AI Infra入门科普
人工智能·深度学习·机器学习
学困昇10 小时前
Linux IPC 详解:匿名管道、命名管道、共享内存与信号量
linux·运维·服务器·c语言·c++·人工智能
拜特说10 小时前
自进化智能体的范式跃迁:从静态模型到终身学习
人工智能
陆业聪10 小时前
微调:让通用大模型变成你的「专属定制ROM」——从AOSP到LoRA的迁移学习
人工智能·aigc