昇腾CANN cann-competitions:办一场算子优化竞赛的完整流程
本文介绍了CANN社区通过组织算子优化竞赛提升开源社区活跃度的实践。竞赛采用标准化流程,包含赛题设计、平台搭建、竞赛进行、评审答辩和开源合入五个阶段。重点分享了赛题选择标准、基线代码设计、自动化评测系统搭建等关键环节,并总结了硬件异构导致成绩不可比、基线代码bug、优胜方案License问题等典型教训。通过竞赛机制,社区成功吸引了高质量贡献,如第二届竞赛中3个优胜方案的性能超越了社区基线,最终被合
开源社区的活跃度不只靠日常 PR,还需要有组织的竞赛活动。cann-competitions 是 CANN 社区的竞赛管理仓库:组织开发者围绕具体算子做性能优化,优胜方案合入社区主干。一场竞赛从策划到颁奖,经过赛题设计 → 平台搭建 → 基线模型 → 评测系统 → 开源审查,全套流程标准化。
一场竞赛的五个阶段
| 阶段 | 时长 | 核心产出 |
|---|---|---|
| 赛题设计 | 2-3 周 | 赛题说明书、基线代码、评测 harness |
| 平台搭建 | 1-2 周 | 报名系统、提交系统、实时排行榜 |
| 竞赛进行 | 4-8 周 | 参赛者提交、每周 office hour、bug 修复 |
| 评审 & 答辩 | 1-2 周 | 最终排名、代码审查、现场答辩 |
| 开源合入 | 2-4 周 | 优胜方案 upstream、博客总结、下一届预告 |
赛题设计:选对算子
不是所有算子都适合当赛题。选算子的标准:
选算子 Checklist(赛题设计阶段)
必须:
[ ] 有明确的性能优化空间(不是「实现功能」)
[ ] 有公认的性能基线(可以对比 CPU/GPU/已有 NPU 实现)
[ ] 有清晰的评测指标(TFLOPS、延迟、带宽利用率)
[ ] 实现复杂度适中(选手 4-8 周能出结果)
禁止:
[ ] 涉及未开源的华为内部算子
[ ] 依赖特定硬件特性(只跑在 950PR,910 跑不了)
[ ] 优化空间过于狭窄(改一处 tiling 就到顶)
实战案例:第二届 CANN 竞赛的赛题是 ops-transformer/flash_attention。优化空间明确(分块策略、双缓冲、Cube/Vector 并行),基线用社区已有的实现(~40% HBM 带宽利用率),评测指标用 TFLOPS 和延迟。
基线代码和评测 harness
赛题发布时,必须提供可运行的基线代码和自动评测 harness。选手在这个基础上优化,评测系统自动跑分。
# cann-competitions/2025-ops-optimization/baseline/bench_flashattn.py
import torch
import time
import numpy as np
def benchmark_flash_attention(
B, H, N, D,
dtype=torch.float16,
warmup=10,
repeat=100
):
"""
基线 benchmark:调用 ops-transformer 的 FlashAttention 实现
输出:latency (ms), TFLOPS, HBM 带宽利用率
"""
q = torch.randn(B, H, N, D, dtype=dtype, device=torch.device("npu"))
k = torch.randn(B, H, N, D, dtype=dtype, device=torch.device("npu"))
v = torch.randn(B, H, N, D, dtype=dtype, device=torch.device("npu"))
# 预热
for _ in range(warmup):
o = torch_npu.flash_attention(q, k, v)
torch.npu.synchronize()
# 正式计时
start = time.perf_counter()
for _ in range(repeat):
o = torch_npu.flash_attention(q, k, v)
torch.npu.synchronize()
end = time.perf_counter()
latency_ms = (end - start) / repeat * 1000
# TFLOPS 计算:FlashAttention 的 FLOPs = 4 * B * H * N * D
flops = 4 * B * H * N * D
tflops = flops / (latency_ms / 1000) / 1e12
# HBM 带宽利用率:理论峰值 1.2 TB/s,实测搬运量 / 时间
hbm_accessed = B * H * N * D * 2 # Q,K 读 + O 写(简化)
hbm_bw_util = (hbm_accessed / (latency_ms / 1000)) / 1.2e12
return {
"latency_ms": latency_ms,
"tflops": tflops,
"hbm_bw_util": hbm_bw_util,
}
评测 harness 自动跑这个脚本,把结果写到排行榜。
提交系统和实时排行榜
选手通过 GitHub PR 提交优化后的算子实现。提交后 CI 自动跑评测 harness,把结果推到实时排行榜。
# .github/workflows/competition-score.yml
name: Competition Scoring
on:
pull_request:
paths:
- "submissions/**/*.py"
- "submissions/**/*.cpp"
jobs:
score:
runs-on: asc-p6000-8x910 # 固定硬件,消除硬件差异
steps:
- name: Check out
uses: actions/checkout@v3
- name: Build & Install Candidate
run: |
cd submissions/${{ github.actor }}
mkdir build && cd build
cmake .. && make -j
- name: Run Benchmark
run: |
python baseline/bench_flashattn.py \
--candidate=submissions/${{ github.actor }}/build/libfa.so \
--output=result.json
- name: Update Leaderboard
run: |
python scripts/update_leaderboard.py \
--pr=${{ github.event.number }} \
--result=result.json \
--leaderboard=leaderboard.json
- name: Push Leaderboard
run: |
git config user.name "competition-bot"
git add leaderboard.json
git commit -m "Update leaderboard: PR#${{ github.event.number }}"
git push
排行榜实时更新,所有选手能看到自己当前的排名。
踩坑一:硬件异构导致成绩不可比
第一届竞赛用公有云上的随机 NPU 实例跑分——不同实例的固件版本不一样,同份代码跑两次结果差 5%。选手投诉「成绩不稳定」。
根因:NPU 固件版本影响算子性能(尤其是 Cube 单元的调度策略)。随机分配实例 → 固件版本随机 → 成绩不可比。
正确做法:竞赛用固定硬件池(同一批 910,同一固件版本),在 CI 的 runs-on 里写死。
# 错误:runs-on: ubuntu-latest + 动态申请 NPU 实例
# 正确:
runs-on: asc-p6000-8x910 # 固定硬件池,固件版本一致
踩坑二:基线代码有 bug 导致全体成绩无效
基线代码里 torch.npu.synchronize() 写成了 pass——没有等 NPU 算完就计时,所有人的成绩都比实际快 10×。
发现方式:一个选手优化后的代码反而比基线慢——review 代码发现计时不正确。
正确做法:基线代码发布前必须经过「反向验证」——故意写一个慢的基线(加 sleep),验证评测 harness 能正确捕捉到延迟。
# 基线代码发布前的反向验证
def test_benchmark_correctness():
# 注入一个人为变慢的版本
slow_kernel = make_slow_kernel(base_kernel, slowdown_factor=10)
result = benchmark_flash_attention(slow_kernel)
assert result["latency_ms"] > baseline_latency_ms * 9 # 应该慢 ~10x
踩坑三:优胜方案的 License 不清晰
第二届竞赛第一名的方案里用了 CUDA 代码(作为参考实现)——但竞赛要求「全部代码必须能在 NPU 上运行」。选手辩解说「CUDA 代码只是参考,不影响 NPU 实现」。
正确做法:竞赛报名时要求签署附加条款——「提交代码中的所有源文件必须能在昇腾 NPU 上编译运行,引用第三方代码必须附 License 声明」。
## 参赛条款(报名时勾选)
- [ ] 我确认提交代码中的所有源文件均为本人/本人队伍编写,
或已获得原作者的开源授权(附 License 文件)。
- [ ] 我确认提交代码不含任何闭源组件、不含任何只能跑在
GPU/其他厂商硬件上的代码。
- [ ] 我同意优胜方案的代码以 Apache 2.0 协议合入
CANN 社区主干分支。
cann-competitions 的价值不只是办比赛——它把「算子优化」这件门槛很高的事,用标准化赛题 + 自动评测 + 实时排行榜的方式降低了参与门槛。第一届竞赛收到的 60+ 份提交里,有 3 份的性能超过了社区基线——这 3 份后来都合入了 ops-transformer 仓库。
鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。
更多推荐



所有评论(0)