昇腾软件介绍
| 软件类型 | 软件介绍 |
|---|---|
| 固件 | 固件包含昇腾AI处理器自带的OS 、电源器件和功耗管理器件控制软件,分别用于后续加载到AI处理器的模型计算、芯片启动控制和功耗控制。 |
| 驱动 | 部署在昇腾服务器,功能类似英伟达驱动,管理查询昇腾AI处理器,同时为上层CANN软件提供芯片控制、资源分配等接口。 |
| CANN | 部署在昇腾服务器,功能类似英伟达CUDA,包含Runtime、算子库、图引擎、媒体数据处理等组件,通过AscendCL(Ascend Computing Language)对外提供Device管理、Context管理、Stream管理、内存管理、模型加载与执行、算子加载与执行、媒体数据处理等API,帮助开发者实现在昇腾CANN平台上进行深度学习推理计算、图像预处理、单算子加速计算。 |
重要说明:如果是首次安装请按照“驱动 > 固件”的顺序,分别安装驱动和固件包;覆盖安装请按照“固件 > 驱动”的顺序,分别安装固件和驱动包,vision表示软件版本号。
Runtime
想要使用昇腾处理器提供的加速计算能力,需要对运行管理资源申请,包括Device、Context、Stream。且需要按顺序申请,主要涉及以下三个接口:
acl.rt.set_device(device_id)
这个接口指定计算设备,告诉运行时环境我们想要用哪个设备,或者更具体一点,哪个芯片。但是要注意,芯片和我们在这里传入的编号之间并没有物理上的一一对应关系。
acl.rt.create_context(device_id)
Context作为一个容器,管理了所有对象(包括Stream、Event、设备内存等)的生命周期。不同Context的Stream、不同Context的Event是完全隔离的,无法建立同步等待关系。个人理解为,如果计算资源足够的话,可以创建多个Context,分别运行不同的应用,来提高硬件利用率,而不用担心应用之间的互相干扰,类似于Docker。
acl.rt.create_stream()
Stream用于维护一些异步操作的执行顺序,确保按照应用程序中的代码调用顺序在Device上执行。基于Stream的kernel执行和数据传输能够实现Host运算操作、Host与Device间的数据传输、Device内的运算并行。
Stream
处理海量的数据,内存带宽经常会成为主要的瓶颈。在Stream的帮助下,CANN可以有效地将内存读取和数值运算并行,从而提升数据的吞吐量。
由于GPU和CPU不能直接读取对方的内存,CANN程序一般会有以下三个步骤:
1)将数据从CPU内存转移到GPU内存
2)GPU进行运算并将结果保存在GPU内存
3)将结果从GPU内存拷贝到CPU内存
如果不做特别处理,那么CANN会默认只使用一个Stream(Default Stream)。在这种情况下,刚刚提到的三个步骤就如菊花般蛋疼地串联,必须等一步完成了才能进行下一步。是不是很别扭?
数据和计算的并行也有一点合乎逻辑的限制:进行数值计算的kernel不能读写正在被拷贝的数据。
Stream正是帮助我们实现以上两个并行的重要工具。基本的概念是:
-
将数据拆分称许多块,每一块交给一个Stream来处理。
-
每一个Stream包含了三个步骤: 1)将属于该Stream的数据从CPU内存转移到GPU内存,
2)GPU进行运算并将结果保存在GPU内存, 3)将该Stream的结果从GPU内存拷贝到CPU内存。 -
所有的Stream被同时启动,由GPU的scheduler决定如何并行。
在这样的骚操作下,假设我们把数据分成A,B两块,各由一个Stream来处理。A的数值计算可以和B的数据传输同时进行,而A与B的数据传输也可以同时进行。由于第一个Stream只用到了数据A,而第二个Stream只用到了数据B,“进行数值计算的kernel不能读写正在被拷贝的数据”这一限制并没有被违反。
申请device内存
要使用 NPU 进行加速计算,首先要申请能够被 NPU 直接访问到的专用内存。在讲解内存申请之前,首先我们要区分如下两个概念:
Host:Host指与Device相连接的X86服务器、ARM服务器,会利用Device提供的NN(Neural-Network )计算能力,完成业务。
Device:Device指安装了芯片的硬件设备,利用PCIe接口与Host侧连接,为Host提供NN计算能力。
简而言之,我们的数据需要先从Host侧进行加载,即读进Host侧内存,随后将其拷贝到Device侧内存,才能进行计算。计算后的结果还要传回Host侧才能进行使用。
申请Device侧内存:
dev_ptr, ret = acl.rt.malloc(size, policy) # 申请device侧内存
其中,dev_ptr是device侧内存指针,size是device侧内存大小。
这里我们分配了跟Host侧同样大小的内存,准备用于在Device侧存放推理数据。本接口最后一个参数policy是内存分配规则。
ACL_MEM_MALLOC_HUGE_FIRST ----- 优先申请大页内存,如果大页内存不够,则使用普通页的内存。
ACL_MEM_MALLOC_HUGE_ONLY ----- 仅申请大页,如果大页内存不够,则返回错误。
ACL_MEM_MALLOC_NORMAL_ONLY ----- 仅申请普通页。
使用完别忘了释放申请过的内存:acl.rt.malloc-> acl.rt.free,切记!!!