3天上手Ascend C编程 | Day2 通过Ascend C编程范式实现一个算子实例

释放双眼,带上耳机,听听看~!
本文介绍了Ascend C编程范式中的流水任务、任务间通信与同步以及内存管理机制,以及如何通过Ascend C编程范式实现一个算子实例。

本文分享自华为云社区《3天上手Ascend C编程 | Day2 通过Ascend C编程范式实现一个算子实例》,作者:昇腾CANN 。

一、Ascend C编程范式

Ascend C编程范式把算子内部的处理程序,分成多个流水任务( stage ),以张量( Tensor)为数据载体,以队列 ( Queue ) 进行任务之间的通信与同步,以内存管理模块( Pipe ) 管理任务间的通信内存。

1、流水任务

流水任务指的是单核处理程序中主程序调度的并行任务。在核函数内部,可以通过流水任务实现数据的并行处理,进一步提升性能。下面举例来说明,流水任务如何进行并行调度。以下面的流水任务示意图为例,单核处理程序的功能被拆分成3个流水任务:Stage1、Stage2、Stage3,每个任务专注于完成单一功能;需要处理的数据被切分成n片,使用Progress1~n表示,每个任务需要依次完成n个数据切片的处理。Stage间的箭头表达数据间的依赖关系,比如Stage1处理完Progress1之后,Stage2才能对Progress1进行处理。

3天上手Ascend C编程 | Day2 通过Ascend C编程范式实现一个算子实例

若n=3,即待处理的数据被切分成3片,则上图中的流水任务运行起来的示意图如下,从运行图中可以看出,对于同一片数据,Stage1、Stage2、Stage3之间的处理具有依赖关系,需要串行处理;不同的数据切片,同一时间点,可以有多个任务在并行处理,由此达到任务并行、提升性能的目的。

3天上手Ascend C编程 | Day2 通过Ascend C编程范式实现一个算子实例

矢量(Vector)编程范式把算子的实现流程分为3个基本任务:CopyIn,Compute,CopyOut。CopyIn负责搬入操作,Compute负责矢量计算操作,CopyOut负责搬出操作。

3天上手Ascend C编程 | Day2 通过Ascend C编程范式实现一个算子实例

2、任务间通信与同步

不同的流水任务之间存在数据依赖,需要进行数据传递。Ascend C中使用Queue队列完成任务之间的数据通信和同步,提供EnQue、DeQue等基础API。Queue队列管理NPU上不同层级的物理内存时,用一种抽象的逻辑位置(QuePosition)来表达各级别的存储,代替了片上物理存储的概念,开发者无需感知硬件架构。

矢量编程中使用到的逻辑位置(QuePosition)定义如下:

搬入数据的存放位置:VECIN搬出数据的存放位置:VECOUT矢量编程主要分为CopyIn、Compute、CopyOut三个任务:

CopyIn任务中将输入数据从Global内存搬运至Local内存后,需要使用EnQue将LocalTensor放入VECIN的Queue中;

Compute任务等待VECIN的Queue中LocalTensor出队之后才可以完成矢量计算,计算完成后使用EnQue将计算结果LocalTensor放入到VECOUT的Queue中;

CopyOut任务等待VECOUT的Queue中LocalTensor出队,再将其拷贝到Global内存。

3天上手Ascend C编程 | Day2 通过Ascend C编程范式实现一个算子实例

Ascend C使用GlobalTensor和LocalTensor作为数据的基本操作单元,它是各种指令API直接调用的对象,也是数据的载体。

3、内存管理机制

任务间数据传递使用到的内存统一由内存管理模块Pipe进行管理。Pipe作为片上内存管理者,通过InitBuffer接口对外提供Queue内存初始化功能,开发者可以通过该接口为指定的Queue分配内存。

Queue队列内存初始化完成后,需要使用内存时,通过调用AllocTensor来为LocalTensor分配内存,当创建的LocalTensor完成相关计算无需再使用时,再调用FreeTensor来回收LocalTensor的内存。

3天上手Ascend C编程 | Day2 通过Ascend C编程范式实现一个算子实例

编程过程中使用到的临时变量内存同样通过Pipe进行管理。临时变量可以使用TBuf数据结构来申请指定QuePosition上的存储空间,并使用Get()来将分配到的存储空间分配给新的LocaLTensor从TBuf上获取全部长度,或者获取指定长度的LocalTensor。

3天上手Ascend C编程 | Day2 通过Ascend C编程范式实现一个算子实例

使用TBuf申请的内存空间只能参与计算,无法执行Queue队列的入队出队操作。

二、使用Ascend C编程范式实现一个算子实例

矢量算子开发一般开发流程如下:

3天上手Ascend C编程 | Day2 通过Ascend C编程范式实现一个算子实例

下面以add作为例子介绍Ascend C矢量算子的开发流程。完整样例大家可以参考Ascend C官方教程

3天上手Ascend C编程 | Day1 Ascend C基本概念及常用接口3天上手Ascend C编程 | Day2 通过Ascend C编程范式实现一个算子实例3天上手Ascend C编程 | Day3 Ascend C算子调试调优方法

点击关注,第一时间了解华为云新鲜技术~

本网站的内容主要来自互联网上的各种资源,仅供参考和信息分享之用,不代表本网站拥有相关版权或知识产权。如您认为内容侵犯您的权益,请联系我们,我们将尽快采取行动,包括删除或更正。
AI教程

深入剖析Linux网络IO与epoll

2023-11-27 20:07:14

AI教程

PAI-Diffusion中文模型家族及其部署工具详解

2023-11-27 20:21:14

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索