异构计算架构(CANN)
对标英伟达的CUDA + CuDNN的核心软件层,向上支持多种AI框架,向下服务AI处理器,发挥承上启下的关键作用,是提升昇腾AI处理器计算效率的关键平台。主要包括有各种引擎、编译器、执行器、算子库等。
MindSpore AI框架
MindSpore是面向“端-边-云”全场景设计的AI框架,旨在弥合AI算法研究与生产部署之间的鸿沟。在算法研究阶段,为开发者提供动静统一的编程体验以提升算法的开发效率;在生产阶段,自动并行可以极大加快分布式训练的开发和调试效率,同时充分挖掘异构硬件的算力;在部署阶段,基于“端-边-云”统一架构,应对企业级部署和安全可信方面的挑战。
算子基本概念
(1)算子名称(Name)
算子的名称,用于标志网络中的某个算子,同一网络中算子的名称需要保持唯一。如右图所示Conv1,Pool1,Conv2都是此网络中的算子名称,其中Conv1与Conv2算子的类型为Convolution,表示分别做一次卷积运算。(2)(2)算子类型(Type)
网络中每一个算子根据算子类型进行算子实现的匹配,相同类型的算子的实现逻辑相同。在一个网络中同一类型的算子可能存在多个,例如右图中名称为Conv1的算子与Conv2算子的类型都为Convolution。
(3)数据容器(Tensor)
前面介绍了算子的类型与算子的名称。我们再看下网络中的算子,如右图所示,算子在网络中执行时,还需要一个重要的输入:数据,算子执行完后,也会有对应的数据输出。这种承载算子数据的容器定义为:张量(Tensor)。
张量(Tensor)
- 张量是算子计算数据的容器,包括输入数据与输出数据。
- 张量描述符(TensorDesc)是对输入数据与输出数据的描述,主要包含如下属性:
形状(Shape)
张量的形状,比如形状(3,4)表示第一维有3个元素,第二维有4个元素,是一个3行4列的矩阵数组。在形状中有多少个数字,就代表这个张量有多少维。形状的第一个元素要看张量最外层的中括号中有几个元素,形状的第二个元素要看张量中从左边开始数第二个中括号中有几个元素,依此类推。
什么是Ascend C?
Ascend C是CANN针对算子开发场景推出的编程语言,原生支持C和C++标准规范,最大化匹配用户开发习惯;通过多层接口抽象、自动并行计算、孪生调试等关键技术,极大提高算子开发效率,助力AI开发者低成本完成算子开发和模型调优部署。
使用Ascend C开发自定义算子的优势
- C/C++原语编程,最大化匹配用户的开发习惯
- 编程模型屏蔽硬件差异,编程范式提高开发效率
- 多层级API封装,从简单到灵活,兼顾易用与高效
- 孪生调试,CPU侧模拟NPU侧的行为,可优化在CPU侧调试
SPMD编程模型介绍
Ascend C算子编程是SPMD的编程,将需要处理的数据拆分并行分布在多个计算核心上运行多个AI Core共享相同的指令代码,每个核上的运行实例唯一的区别是block_idx不同block的类似于进程,block_idx就是标识进程唯一性的进程ID,编程中使用函数GetBlockIdx()获取ID
核函数编写及调用
核函数(Kernel Function)是Acend C算子设备侧的入口。Ascend C允许用户使用核函数这种C/C++函数的语法扩展来管理设备侧的运行代码,用户在核函数中实现算子逻辑的编写,例如自定义算子类及其成员函数以实现该算子的所有功能。核函数是主机侧和设备侧连接的桥梁。
Ascend C编程范式
Ascend C采用矢量编程范式,将算子的实现流程分为三个基本任务:CopyIn、Compute和CopyOut。CopyIn负责数据搬入操作,Compute负责矢量计算操作,CopyOut负责数据搬出操作。通过并行计算和流水线式的编程范式,Ascend C可以实现算子的高效运行。此外,Ascend C还提供了多层接口抽象,使开发者可以更方便地进行算子开发。开发者只需关注算子核函数的实现,而底层的指令同步和并行调度由Ascend C框架自动完成。这样,开发者可以更专注于算子的逻辑实现,而无需过多关注底层细节,从而提高开发效率。
矢量算子开发一般开发流程如下: