【昇腾CANN训练营·深潜篇】混合计算之美:AI Core与AI CPU的协同编程实战
AI CPU 是昇腾全栈能力的“补完计划”。定位:它是兜底方案,不是主力输出。优势:支持标准 C++ 和 STL,开发效率极高,逻辑处理能力强。劣势:算力弱于 AI Core,且存在引擎切换开销。协同:优秀的异构应用,总是将 95% 的 FLOPs 交给 AI Core,将 5% 的复杂控制逻辑交给 AI CPU。掌握了 AI CPU 开发,你就再也不用担心遇到“Ascend C 实现不了”的算法
训练营简介
2025年昇腾CANN训练营第二季,基于CANN开源开放全场景,推出0基础入门系列、码力全开特辑、开发者案例等专题课程,助力不同阶段开发者快速提升算子开发技能。获得Ascend C算子中级认证,即可领取精美证书,完成社区任务更有机会赢取华为手机,平板、开发板等大奖。
报名链接:https://www.hiascend.com/developer/activities/cann20252#cann-camp-2502-intro

前言
在 Ascend C 的开发旅途中,我们一直追求的是 “All in AI Core”。因为 AI Core 的向量和矩阵计算能力是 CPU 的数十倍甚至上百倍。
但在实际落地大模型或 CV 算法时,我们常会遇到这样的“硬骨头”:
-
逻辑极度复杂:比如
NonMaxSuppression(NMS),充满了条件判断和动态循环,Vector 单元很难通过 Mask 高效处理。 -
不支持的数据类型:比如处理
String或复杂的结构体。 -
极不规则的内存访问:比如复杂的图采样算法。
这时候,强行用 Ascend C 写 AI Core 算子,不仅开发极其痛苦,性能可能还不如 CPU。 AI CPU 正是为了解决这些“长尾问题”而存在的。本期我们将深入探讨这一异构架构的另一半拼图。
一、 核心图解:左脑与右脑的协作
我们可以把昇腾芯片比作一个人类大脑:
-
AI Core (右脑):擅长直觉、图像、大规模并行计算(矩阵/向量),算力极强,但逻辑处理能力弱。
-
AI CPU (左脑):擅长逻辑、推理、复杂控制流(标量),算力较弱,但非常灵活。

二、 什么时候呼叫 AI CPU?
在算子开发中,选择计算引擎是第一步。
|
场景特征 |
推荐引擎 |
原因 |
|---|---|---|
|
矩阵乘、卷积、Transformer |
AI Core |
计算密度极高,Cube 单元优势明显。 |
|
Element-wise (Add, Relu) |
AI Core |
Vector 单元吞吐量大,带宽利用率高。 |
|
排序 (Sort, TopK) |
AI Core / AI CPU |
小规模用 Bitonic Sort (AI Core);大规模或全排序建议 AI CPU。 |
|
非极大值抑制 (NMS) |
AI CPU |
串行逻辑重,依赖标量判断,AI Core 分支效率低。 |
|
去重 (Unique), 集合操作 |
AI CPU |
输出 Shape 未知,且需要哈希表等复杂数据结构。 |
|
打印日志, 异常抛出 |
AI CPU |
AI Core 很难输出格式化日志或抛出 Python 异常。 |
黄金法则:能用 AI Core 绝不用 AI CPU(因为调度和搬运有开销),除非逻辑无法向量化或者开发成本过高。
三、 实战:编写一个 AI CPU 算子
AI CPU 算子的开发体验更接近标准的 C++ 开发。它不使用 Ascend C 的 Device 语法,而是使用原生的 C++ 标准库。
3.1 算子工程结构
在 msopgen 生成的工程中,AI CPU 算子通常位于独立的目录(或配置项)。 关键点在于:OpType 的注册。
3.2 核心代码实现 (cpu_kernel.cpp)
AI CPU 算子继承自 CpuKernel 基类。
#include "cpu_kernel.h"
#include "cpu_types.h"
#include <algorithm> // 可以直接用 STL!
namespace aicpu {
uint32_t MySortKernel(CpuKernelContext &ctx) {
// 1. 获取输入 Tensor
Tensor *input = ctx.Input(0);
auto input_data = reinterpret_cast<float *>(input->GetData());
uint64_t num_elements = input->NumElements();
// 2. 获取输出 Tensor
Tensor *output = ctx.Output(0);
auto output_data = reinterpret_cast<float *>(output->GetData());
// 3. 执行逻辑
// 直接使用 std::copy 和 std::sort,就像写普通 C++ 一样!
std::copy(input_data, input_data + num_elements, output_data);
// AI Core 写排序很难,但 AI CPU 直接调 STL
std::sort(output_data, output_data + num_elements);
return 0; // Success
}
// 注册
REGISTER_CPU_KERNEL("MySort", MySortKernel);
} // namespace aicpu
3.3 编译与部署
AI CPU 算子会被编译成独立的 .so 库,打包在 OPP 中。ATC 转换模型时,如果发现算子被标记为 AICPU 引擎,会自动链接到这个库。
四、 进阶:混合流水线的性能陷阱
虽然 AI CPU 很灵活,但它有一个致命弱点:上下文切换(Context Switch)。
4.1 任务切换开销
当模型执行流从 AI Core 切换到 AI CPU 时,需要:
-
AI Core 任务挂起。
-
Stream 同步,等待数据写回 Global Memory。
-
CPU 唤醒,读取数据(可能涉及 Cache 刷新)。
-
计算完成,写回 GM。
-
唤醒 AI Core 继续下一层。
这一过程的延迟(Latency)通常在 几十微秒 级别。对于大算子(耗时毫秒级)没问题,但对于小算子,这个开销是毁灭性的。
4.2 优化策略:算子融合与异步
-
融合:尽量不要在两个 AI Core 算子中间插一个微小的 AI CPU 算子。尝试将那个 AI CPU 算子的逻辑合并到前后的 AI Core 算子中,哪怕用低效的方法实现,也可能比切换引擎快。
-
异步并行:如果是多流(Multi-Stream)场景,可以让 AI CPU 处理一条分支,AI Core 处理另一条分支,掩盖切换延迟。
五、 总结
AI CPU 是昇腾全栈能力的“补完计划”。
-
定位:它是兜底方案,不是主力输出。
-
优势:支持标准 C++ 和 STL,开发效率极高,逻辑处理能力强。
-
劣势:算力弱于 AI Core,且存在引擎切换开销。
-
协同:优秀的异构应用,总是将 95% 的 FLOPs 交给 AI Core,将 5% 的复杂控制逻辑交给 AI CPU。
掌握了 AI CPU 开发,你就再也不用担心遇到“Ascend C 实现不了”的算法了。你总有一个强大的后盾,虽然慢一点,但无所不能。
鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。
更多推荐



所有评论(0)