ops-transformer 仓库概览
ascend-transformer-boost(ATB)是 Transformer 加速库,它封装了 ops-transformer 的算子,提供更上层的 API。ops-transformer 是 CANN(昇腾异构计算架构)第二层——昇腾计算服务层的核心算子库之一。ops-transformer 的算子实现大量复用 opbase 的能力。类别,与 ops-math、ops-nn、ops-cv
定位:CANN 生态中的位置
ops-transformer 是 CANN(昇腾异构计算架构)第二层——昇腾计算服务层的核心算子库之一。它专门为 Transformer 类大模型提供高性能算子实现。
在 CANN 的 55 个开源仓库中,ops-transformer 属于核心算子仓库类别,与 ops-math、ops-nn、ops-cv 等基础算子库并列。但它的定位更聚焦:只做 Transformer 相关的进阶算子。
核心能力:三大算子家族
1. FlashAttention 系列
FlashAttention 是 ops-transformer 的招牌算子。它解决了 Transformer 训算中显存占用和计算效率的双重痛点:
- 显存优化:从 O(N²) 降到 O(N),序列长度不再是瓶颈
- 计算优化:分块计算 + 在线 softmax,掩埋内存访问延迟
- 融合优化:mask、dropout、bias 全融合,减少中间结果读写
2. MoE(Mixture of Experts)系列
MoE 是大模型稀疏激活的关键技术。ops-transformer 提供了完整的 MoE 算子实现:
- Routing 算子:决定每个 token 去哪个 expert
- All-to-All 通信:跨 NPU 的 expert 数据交换,与 HCCL 深度协同
- 负载均衡:动态调整 expert 分配,避免热点
3. MC2(Model Parallelism Communication)系列
MC2 针对大模型并行训练的通信开销问题:
- 计算通信重叠:前向计算时发梯度,后向计算时收激活
- 流水线优化:多 stage 间的通信调度
- 张量并行支持:TP 组内的高效 AllReduce
架构位置:依赖与被依赖
ops-transformer 在 CANN 生态中的依赖关系:
上游依赖:
opbase ← ops-transformer(基础组件)
下游调用:
ops-transformer ← ascend-transformer-boost (ATB)
ops-transformer ← cann-recipes-infer
ops-transformer ← cann-recipes-train
code复制
依赖 opbase:opbase 提供了算子开发的基础工具,比如内存管理、并行调度、数学函数等。ops-transformer 的算子实现大量复用 opbase 的能力。
被 ATB 调用:ascend-transformer-boost(ATB)是 Transformer 加速库,它封装了 ops-transformer 的算子,提供更上层的 API。如果你用 ATB,不需要直接调 ops-transformer。
与其他算子库的关系
ops-transformer 不是孤立的,它与 CANN 其他算子库形成完整的计算栈:
| 算子库 | 定位 | 关系 |
|---|---|---|
| ops-math | 数学基础算子 | ops-transformer 可能调用其 matmul |
| ops-nn | 神经网络基础算子 | ops-transformer 可能调用其 LayerNorm |
| opbase | 算子基础组件 | ops-transformer 依赖其工具函数 |
| catlass | 算子模板库 | ops-transformer 可能借鉴其模板设计 |
性能收益:实测数据
根据 CANN 社区的 benchmark 数据:
推理场景:
- FlashAttention-2:吞吐提升 3.2x,首 token 延迟降低 65%
- PagedAttention:支持变长序列,显存利用率提升 40%
训练场景:
- MoE 算子:8 卡 NPU,64 experts,吞吐提升 2.5x
- MC2 算子:通信时间隐藏 85%,端到端训练时间缩短 40%
显存优化:
- FlashAttention:显存占用降低 70%(序列长度 8K)
- MoE:expert 缓存优化,显存占用降低 50%
使用场景:什么时候需要 ops-transformer?
场景 A:你在用 ATB 支持的模型
ATB 已经封装了 ops-transformer 的算子。直接用 ATB 的 API,它会自动调用最优算子。
from atb_speed import ModelRunner
model = ModelRunner("llama-7b", device="npu")
# 内部自动使用 ops-transformer 的 FlashAttention
场景 B:你在开发自定义模型
如果 ATB 不支持你的模型结构,你需要:
检查 ops-transformer 里有没有合适的算子
如果有,直接调用或基于它改
如果没有,用 Ascend C 自己写,参考 ops-transformer 的实现
场景 C:你在做性能调优
想榨干 NPU 性能,需要深入理解 ops-transformer 的算子实现:
读 FlashAttention 的 Ascend C 代码,学习分块策略
读 MoE 的通信调度,学习计算通信重叠技巧
读 MC2 的流水线实现,学习多 stage 调度
版本演进:从 CANN 8.0 到全面开源
CANN 8.0(2024年10月):
FlashAttention-2 完整实现
MoE 算子支持 64+ experts
MC2 支持 TP+PP 混合并行
CANN 8.5(2025年):
FlashAttention-3 支持(更激进的融合策略)
MoE 支持 expert 并行 + tensor 并行混合
性能持续优化
CANN 全面开源(2025年8月):
ops-transformer 代码完全开放
社区可贡献新算子
算子实现细节透明
仓库资源
源码地址:https://atomgit.com/cann/ops-transformer
相关仓库:
opbase:https://atomgit.com/cann/opbase
ascend-transformer-boost:https://atomgit.com/cann/ascend-transformer-boost
cann-recipes-infer:https://atomgit.com/cann/cann-recipes-infer
学习资源:
CANN 官方文档:算子开发指南
cann-learning-hub:社区教程和博客
cann-samples:示例代码
下一步行动建议
快速上手:先跑 ATB 的 LLaMA 示例,体验 ops-transformer 的性能
深入理解:读 FlashAttention 的 Ascend C 实现,理解 NPU 算子编程
贡献社区:发现算子优化机会,向 ops-transformer 提 PR
仓库链接
https://atomgit.com/cann/ops-transformer
code复制
---
## 文章 2:FlashAttention 算子深度解析
```markdown
# CANN FlashAttention:用计算换内存的 NPU 算子艺术
之前有人问我:"FlashAttention 不就是个分块计算吗?为什么在昇腾 NPU 上实现起来这么复杂?"
**分块计算是思路,NPU 实现是艺术。** 同样的算法,在不同硬件上实现,完全是两个世界。
## 背景:Attention 计算的显存瓶颈
Transformer 的 Attention 计算公式:
Attention(Q, K, V) = softmax(QK^T / √d) V
code复制
看起来简单,但问题藏在中间那个 QK^T 矩阵里。
假设序列长度 N=8192,batch_size=1,heads=32:
- QK^T 矩阵大小:[1, 32, 8192, 8192] = 2^28 个元素
- 如果用 bfloat16:4GB 显存
**这还只是一个 Attention 层的中间结果。** 多层堆叠,显存直接爆炸。
## FlashAttention 的核心思路
FlashAttention 的发明人 Tri Dao 意识到:**为什么要存完整的 QK^T 矩阵?**
传统实现:
1. 算算 QK^T,存起来
2. 算 softmax,存起来
3. 算加权和,输出
FlashAttention:
1. 把 QK^T 分成小块
2. 每块算完 softmax,直接乘 V
3. 边算边累加输出,不存中间结果
**本质:用计算换内存。** 多算几次 softmax(重计算),但省掉巨大的中间矩阵。
## NPU 实现的挑战
思路简单,但在昇腾 NPU 上实现,要面对三个挑战:
### 挑战 1:内存层级复杂
NPU 的内存层级:
- **GM(Global Memory)**:大但慢,所有核共享
- **UB(Unified Buffer)**:小但快,每个核独享
- **L1/L0**:更小的缓存层级
FlashAttention 的分块大小,必须精心设计:
- 块太小:频繁搬运数据,延迟掩埋不住
- 块太大:UB 放不下,溢出到 GM
**ops-transformer 的实现**:根据 NPU 型号(Ascend 910/910B)自动选择最优分块参数。
### 挑战 2:在线 Softmax 不直观
传统 softmax:
softmax(x_i) = exp(x_i) / Σ exp(x_j)
code复制
在线 softmax 要边算边更新,不能等所有 x 算完。这需要维护两个累加器:
- **m**:当前最大值(用于数值稳定)
- **l**:softmax 分母的累加
每处理一个新块,要更新 m 和 l,并修正之前块的输出。
**ops-transformer 的实现**:用 Ascend C 的向量指令并行更新,减少标量计算开销。
### 挑战 3:融合策略要平衡
FlashAttention 可以融合很多操作:
- Mask(causal attention)
- Dropout
- Bias
- Rotary Embedding
融合越多,性能越好,但实现复杂度指数增长。
**ops-transformer 的策略**:提供多个融合级别的实现:
- `FlashAttentionV1`:基础版,只融合 mask
- `FlashAttentionV2`:进阶版,融合 mask + dropout + bias
- `FlashAttentionV3`:终极版,融合所有 + 优化内存访问
## Ascend C 实现解析
ops-transformer 中 FlashAttention 的核心代码结构:
```cpp
template<typename T>
__aicore__ void FlashAttentionKernel(
GM_ADDR q, // Query [B, H, N, D]
GM_ADDR k, // Key [B, H, N, D]
GM_ADDR v, // Value [B, H, N, D]
GM_ADDR o, // Output [B, H, N, D]
uint32_t seq_len,
uint32_t head_dim
) {
// 1. 分块参数(根据 NPU 型号自动选择)
constexpr uint32_t BLOCK_M = 128; // Q 的分块大小
constexpr uint32_t BLOCK_N = 64; // K/V 的分块大小
// 2. 分配 UB 内存
LocalTensor<T> q_local = QBuf.Get<T>(BLOCK_M * head_dim);
LocalTensor<T> k_local = KBuf.Get<T>(BLOCK_N * head_dim);
LocalTensor<T> v_local = VBuf.Get<T>(BLOCK_N * head_dim);
LocalTensor<T> o_local = OBuf.Get<T>(BLOCK_M * head_dim);
// 3. 在线 softmax 累加器
LocalTensor<float> m_acc = MBuf.Get<float>(BLOCK_M); // max 累加
LocalTensor<float> l_acc = LBuf.Get<float>(BLOCK_M); // sum 累加
// 4. 分块循环
for (uint32_t i = 0; i < seq_len; i += BLOCK_M) {
// 4.1 搬运 Q 块到 UB
CopyGM2UB(q_local, q + i * head_dim, BLOCK_M * head_dim);
// 4.2 初始化累加器
InitAccumulator(m_acc, l_acc, o_local, BLOCK_M);
for (uint32_t j = 0; j < seq_len; j += BLOCK_N) {
// 4.3 搬运 K/V 块到 UB
CopyGM2UB(k_local, k + j * head_dim, BLOCK_N * head_dim);
CopyGM2UB(v_local, v + j * head_dim, BLOCK_N * head_dim);
// 4.4 计算 QK^T(矩阵乘法)
LocalTensor<T> qk_local = QKBuf.Get<T>(BLOCK_M * BLOCK_N);
Mmad<T>(qk_local, q_local, k_local, BLOCK_M, BLOCK_N, head_dim);
// 4.5 在线 softmax 更新
// 核心:更新 m, l,修正之前的输出
OnlineSoftmaxUpdate(
m_acc, l_acc, o_local,
qk_local, v_local,
BLOCK_M, BLOCK_N
);
}
// 4.6 写回输出
CopyUB2GM(o + i * head_dim, o_local, BLOCK_M * head_dim);
}
}
关键点:
BLOCK_M 和 BLOCK_N 是分块参数,直接影响性能
OnlineSoftmaxUpdate 是核心,实现在线更新逻辑
所有中间结果都在 UB 里,不写回 GM
性能数据:ops-transformer 的 FlashAttention
在 Ascend 910 上的实测数据:
配置
标准实现
FlashAttention
提升
seq_len=2048
1250 tokens/s
3200 tokens/s
2.56x
seq_len=4096
680 tokens/s
2100 tokens/s
3.09x
seq_len=8192
OOM
1050 tokens/s
∞
seq_len=16384
OOM
480 tokens/s
∞
显存占用对比:
标准实现:O(N²) —— seq_len=8192 时需要 4GB
FlashAttention:O(N) —— seq_len=8192 时仅需 256MB
使用方式:三种调用路径
路径 1:通过 ATB 调用(推荐)
python复制from atb_speed import ModelRunner
# ATB 自动选择 FlashAttention
model = ModelRunner("llama-7b", device="npu")
output = model.generate(input_ids)
路径 2:直接调用 ops-transformer
python复制import torch_npu
# 直接调用 FlashAttention 算子
from ops_transformer import flash_attention
q = torch.randn(1, 32, 8192,
...(truncated)...
更多推荐




所有评论(0)