可移植的高性能:cann/ops-nn 如何在异构硬件上实现“一次描述,处处高效”
开发者被迫在不同平台上维护多套算子实现,不仅效率低下,更导致行为不一致、调试困难、迭代缓慢。在这座桥上,算子不再是封闭的黑盒,而是可理解、可组合、可移植的公共资产。而我们,正共同走向一个更开放、更高效、更协作的AI基础设施未来。它通过清晰的抽象边界、可扩展的IR和开放的后端接口,构建了一座连接算法创新与硬件多样性的通用桥梁。同一份语义描述,通过不同调度脚本,可分别生成高效的CUDA Kernel或
可移植的高性能:cann/ops-nn 如何在异构硬件上实现“一次描述,处处高效”

在今天的AI基础设施领域,一个残酷的现实是:没有哪一种硬件能通吃所有场景。训练可能依赖大规模GPU集群,推理则分散在边缘设备、专用加速卡甚至定制芯片上。开发者被迫在不同平台上维护多套算子实现,不仅效率低下,更导致行为不一致、调试困难、迭代缓慢。
面对这一挑战,开源项目 cann/ops-nn 提出了一种根本性的解法:将算子的语义描述与硬件执行彻底解耦,并通过可编程的中间表示(IR)和后端编译器,实现“一次描述,处处高效”。它不绑定任何特定厂商,而是构建了一个面向未来异构计算的可移植高性能算子框架。本文将揭示其如何做到这一点。
一、 算子 = 语义 + 调度:分离关注点的架构革命
传统算子库(如cuDNN、oneDNN)将算法逻辑与硬件优化紧密耦合,导致代码难以复用。cann/ops-nn 则采用一种更现代的分层设计:
算子 = 声明式语义(What) + 可编程调度(How)
1. 声明式语义:纯数学表达
每个算子首先以接近数学公式的方式定义其计算逻辑,完全不涉及内存布局、并行策略或指令选择。
# ops-nn/ir/gemm.py
from tbe.ir import Tensor, compute
def matmul(A: Tensor, B: Tensor) -> Tensor:
"""
C[i, j] = sum_k A[i, k] * B[k, j]
纯声明式定义,无硬件信息
"""
i, j, k = A.shape[0], B.shape[1], A.shape[1]
return compute(
shape=(i, j),
fcompute=lambda i, j: sum(A[i, k] * B[k, j] for k in range(k)),
name="matmul_output"
)
这段代码只回答“做什么”,适用于任何支持矩阵乘的硬件。
2. 可编程调度:硬件专属优化
真正的性能魔法发生在调度阶段。ops-nn 允许为不同硬件后端编写独立的调度策略:
# ops-nn/schedule/gpu/matmul_schedule.py
def gpu_matmul_schedule(sch, output):
i, j = output.op.axis
i_block, i_thread = sch[output].split(i, factor=32)
j_block, j_thread = sch[output].split(j, factor=32)
sch[output].bind(i_block, "blockIdx.x")
sch[output].bind(j_block, "blockIdx.y")
sch[output].bind(i_thread, "threadIdx.x")
sch[output].bind(j_thread, "threadIdx.y")
sch[output].unroll(output.op.reduce_axis[0]) # 展开reduce轴
return sch
# ops-nn/schedule/npu/matmul_schedule.py (面向某类NPU)
def npu_matmul_schedule(sch, output):
sch[output].set_scope("local.L1")
sch[output].tensorize(output.op.axis[-1], "cube_gemm") # 映射到专用指令
sch[output].double_buffer()
return sch
同一份语义描述,通过不同调度脚本,可分别生成高效的CUDA Kernel或NPU指令序列。
二、 中间表示(IR):跨硬件的通用语言
cann/ops-nn 的核心是一个轻量级但表达力强的领域特定中间表示(DSIR),它成为连接前端语义与后端实现的桥梁。
1. IR结构示例
// ops-nn 编译过程中生成的IR片段(类MLIR风格)
func.func @matmul(%A: tensor<128x64xf16>, %B: tensor<64x256xf16>) -> tensor<128x256xf16> {
%C = linalg.matmul ins(%A, %B : tensor<128x64xf16>, tensor<64x256xf16>)
outs(%init : tensor<128x256xf16>)
return %C : tensor<128x256xf16>
}
该IR保留了高层语义(如 linalg.matmul),同时支持插入调度注解(如 tile, vectorize, map_to_unit)。
2. 后端编译器:IR到硬件指令的翻译器
每个硬件厂商(或社区)可贡献自己的后端编译器:
# 目录结构
ops-nn/
├── backends/
│ ├── cuda/ # NVIDIA GPU后端
│ ├── rocm/ # AMD GPU后端
│ ├── npu_v1/ # 某类AI加速器后端
│ └── cpu/ # 通用CPU后端(OpenMP/SIMD)
后端编译器负责:
- 将IR中的高阶操作(如
matmul)降级为硬件原语; - 应用目标硬件的内存层次优化;
- 生成最终可执行代码(PTX、HSACO、CCE、AVX512等)。
用户只需指定目标后端,即可自动获得最优实现:
# 用户代码(完全硬件无关)
from ops_nn import compile
compiled_fn = compile(
func=matmul,
inputs=[A_shape, B_shape],
target="cuda", # 或 "npu_v1", "rocm", "cpu"
dtype="float16"
)
result = compiled_fn(A_data, B_data)
三、 自动调优:让机器寻找最优调度
即便有调度接口,手动编写最优策略仍需专家知识。cann/ops-nn 内置自动调度器(AutoScheduler),通过搜索+学习找到最佳实现。
1. 搜索空间定义
# ops-nn/autoscheduler/search_space.py
def get_matmul_search_space(shape):
space = SearchSpace()
space.add_split_factor(axis="i", candidates=[16, 32, 64])
space.add_tile_size("L1_cache", max_bytes=64*1024)
space.add_vector_width(candidates=[8, 16, 32])
return space
2. 基于性能反馈的进化搜索
# ops-nn/autoscheduler/evolutionary_search.py
best_schedule = None
best_latency = float('inf')
for candidate in random_sample(search_space, n=1000):
sch = apply_schedule(matmul_ir, candidate)
code = backend.compile(sch)
latency = benchmark_on_device(code, device="cuda")
if latency < best_latency:
best_latency = latency
best_schedule = candidate
# 将最优调度缓存至本地
cache.save("matmul_128x64x256_fp16_cuda", best_schedule)
下次遇到相同形状的GEMM,直接加载缓存调度,无需重新搜索。
四、 生态价值:打破硬件孤岛,共建开放标准
cann/ops-nn 的真正野心,不是服务单一平台,而是推动一个开放、可互操作的高性能算子生态。
- 对硬件厂商:只需实现一个后端编译器,即可接入整个
ops-nn算子库,快速获得数千个高性能算子支持; - 对框架开发者:只需对接
ops-nn的统一IR,即可天然支持所有已接入的硬件; - 对算法工程师:只需编写一次算子语义,即可在任意支持的设备上运行。
这种“一次描述,处处高效”的模式,有望终结当前AI软件栈的碎片化局面。
结语:在分裂的世界里,建造一座通用的桥
当行业陷入“每家硬件都要求专属算子”的内卷时,cann/ops-nn 选择了一条更艰难但更长远的路:不迎合任何一家,而是服务于所有人。它通过清晰的抽象边界、可扩展的IR和开放的后端接口,构建了一座连接算法创新与硬件多样性的通用桥梁。
在这座桥上,算子不再是封闭的黑盒,而是可理解、可组合、可移植的公共资产。而我们,正共同走向一个更开放、更高效、更协作的AI基础设施未来。
相关链接:
- CANN开源组织主页: https://atomgit.com/cann
- ops-nn算子仓库地址: https://atomgit.com/cann/ops-nn
更多推荐


所有评论(0)