异构系统与编程模型
【免费下载链接】asc-devkit本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言,原生支持C和C++标准规范,主要由类库和语言扩展层构成,提供多层级API,满足多维场景算子开发诉求。项目地址: https://gitcode.com/cann/asc-devkit
本文作为算子编程快速入门章节,将从昇腾异构系统基础入手,逐步拆解编程模型核心要素,帮助您快速建立昇腾算子编程的整体认知,为后续实操开发奠定基础。
什么是异构系统?
基于昇腾处理器的异构系统,核心是通过两类功能互补的处理器协同工作,兼顾通用计算与高密度并行计算,实现整体性能最优。
| 角色 | 组成 | 职责 |
|---|---|---|
| Host(主机) | CPU + Host Memory | 通用计算、资源管理、任务调度、统筹协调 |
| Device(设备) | 昇腾NPU + Device Memory | 高密度并行计算(深度学习推理/训练、图像处理等) |
💡通俗理解:Host如同项目经理,负责规划、分配、协调;Device如同专业工程师团队,专注于高效完成高强度、重复性的计算工作。两者分工协作,提升整体效率。
昇腾应用程序的组成
基于昇腾异构系统的应用程序必然包含两部分代码,分工明确、协同运行:
| 代码类型 | 运行位置 | 编程语言 | 核心职责 |
|---|---|---|---|
| Host代码 | CPU(Host侧) | 标准C/C++ | 管理Device设备、搬运数据、启动NPU任务、同步状态 |
| Device代码 | NPU(Device侧) | Ascend C | 执行具体的并行计算任务,称为核函数 |
✅便捷提示:Host代码与Device代码可编写在同一个
.asc文件中,由毕昇编译器自动识别、分别编译,简化开发流程。
Host与Device的协作流程
Host侧通过调用CANN Runtime API完成与Device的协同工作。典型流程如下:
- 分配内存:在Device Memory中申请输入/输出所需的空间。
- 数据搬入:将输入数据从Host Memory拷贝到Device Memory(数据需进入Device侧才能被NPU访问)。
- 启动NPU计算任务:调用Device侧预先编写的核函数,NPU开始并行计算。
- 同步等待:Host端等待NPU执行完成,确保数据计算完整(避免未完成就读取结果)。
- 数据搬出:将计算结果从Device Memory拷贝回Host Memory,供后续处理。
📌关键点:Host与NPU是异步执行的,第4步的同步必不可少,否则可能读取到未完成的数据。
AI Core:NPU的核心计算单元
NPU是Device侧的计算核心,而AI Core则是NPU内部的“最小计算单元”。一枚NPU芯片通常集成多个AI Core,可并行处理不同的数据块,大幅提升整体计算吞吐量。
每个AI Core内部结构高度优化,专门适配并行计算需求,核心组件包括:
- 标量处理单元:处理控制流(如分支、循环)和地址计算,类似传统CPU核心,是AI Core的“控制核心”。
- 向量处理单元:执行向量运算,是SIMD/SIMT两种并行模型的主要载体。不同昇腾芯片架构对两种模式的支持有所差异。
- 矩阵运算单元:专门优化矩阵乘加运算,仅兼容SIMD模式,是深度学习卷积、全连接层等算子的“性能加速核心”。
- 本地存储:用于缓存计算所需的数据,有效降低对全局Device Memory的访问延迟,提升计算效率。
🧬架构演进:Ascend 950PR/Ascend 950DT架构之前,AI Core仅支持SIMD;从Ascend 950PR/Ascend 950DT架构开始,向量处理单元同时支持SIMD和SIMT,为不同算子任务提供更灵活的选择。
SIMD与SIMT并行模型
SIMD(Single Instruction Multiple Data)与SIMT(Single Instruction Multiple Threads)是昇腾AI Core支持的两种核心并行执行模型,也是算子编程的关键。两者在核心逻辑、适用场景上差异显著,对比如下:
| 模型 | 全称 | 核心思想 | 通俗比喻 | 适用场景 |
|---|---|---|---|---|
| SIMD | 单指令多数据 | 一条指令同时操作多个同构数据 | 一个厨师同时翻炒多份相同的菜 | 规整、高密度计算(矩阵乘、卷积、逐元素运算) |
| SIMT | 单指令多线程 | 一条指令驱动多个独立线程 | 一个厨师指挥多个助手,各切各的菜 | 不规则访问、分支密集、稀疏计算(如稀疏卷积) |
SIMD核函数编程基本步骤(遵循SPMD模型)
SPMD(Single Program, Multiple Data):将每个AI Core抽象成一个Block,通过内置变量block_idx作为Block索引。每个Block执行同一份算子Kernel代码,基于block_idx划分每个Block的数据处理范围,实现多核负载均衡与并行调度。
- Tiling(分块):将数据划分为均匀的块,每个AI Core负责一块,实现负载均衡。
- 数据搬入:需要显式调用数据搬运API将数据从Device Memory搬到本地存储。
- 数据计算:调用SIMD指令对应的API完成计算。注意数据搬运与计算异步,需插入同步指令。
- 数据搬出:需要显式调用数据搬运API将本地存储中的结果写回Device Memory。
SIMT核函数编程基本步骤(遵循SPMD模型)
SPMD(Single Program, Multiple Data):每个线程运行同一份程序,但每个线程处理不同的数据元素。
- Tiling(分块):建立线程索引与数据索引的一一对应关系。
- 数据搬入:通过指针直接访问Device Memory,硬件自动加载到寄存器,无需显式调用数据搬运API。
- 数据计算:编写标量代码(支持分支、循环);多线程协作时需插入同步指令。
- 数据搬出:可通过指针将结果直接写回Device Memory,无需显式调用数据搬运API。
📌提示:Host端可通过
<<<>>>语法糖或CANN Runtime API调用并运行核函数。
编程模型选型指南
为提升向量计算在复杂控制流、离散访存等场景下的编程灵活性,在采用SIMD与SIMT深度融合的新同构架构中:矩阵计算单元延续SIMD设计,向量计算单元则在SIMD的基础上引入SIMT能力。这一设计确立了以SIMD为主、SIMT为辅的新同构编程模型。在该模型下,矩阵计算和向量计算中的SIMD部分配置了超过90%的算力,为密集计算带来高性能与高算力利用率;向量计算中的SIMT则作为灵活性补充,专门应对复杂控制流、离散访存等不规则场景,提升这类场景下算法开发和优化的效率。
| 编程模型 | 支持范围 | 适用场景 | 芯片支持 |
|---|---|---|---|
| SIMD(主) | 向量、矩阵、融合计算 | 规整、高密度任务(卷积、矩阵乘、逐元素变换) | 昇腾全系列 |
| SIMT(辅) | 仅向量计算 | 离散访问、复杂分支、稀疏计算 | 仅限Ascend 950PR/Ascend 950DT |
| SIMD+SIMT混合 | 向量、矩阵、融合计算 | 用SIMT处理不规则逻辑,用SIMD批量高效计算 | 仅限Ascend 950PR/Ascend 950DT |
📌快速选型建议:
- 开发常规高性能算子(如矩阵乘、逐元素算子)时,建议使用SIMD编程模型。该模型支持昇腾全系列产品,且具有较高的能效比。
- 对于涉及离散数据或复杂分支逻辑的算子,建议使用SIMT编程模型。
小结
昇腾异构计算的核心逻辑可概括为:Host(CPU)调度 + Device(NPU)执行
- Host侧:统筹资源、调度任务。
- Device侧:核心是AI Core,支持以SIMD为主、SIMT为辅的新同构编程模型。
算子编程的关键:根据数据的规整度、访存模式、分支密度,选择合适的编程模型,充分发挥AI Core的硬件性能,即可高效开发出高性能的Ascend C算子。
【免费下载链接】asc-devkit本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言,原生支持C和C++标准规范,主要由类库和语言扩展层构成,提供多层级API,满足多维场景算子开发诉求。项目地址: https://gitcode.com/cann/asc-devkit
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考