Ascend C算子开发学习笔记

1.什么是Ascend C?

Ascend C是一门面向算子开发场景的编程语言,原生支持C和C++标准规范。

特点:

Ascend C基于C/C++ 与一个额外类库,支持原语编程

编程模型可以屏蔽硬件差异,用户无需关注

拥有多层计算api封装,可根据实际任务需要选用某一类api

孪生调试:可以在cpu侧模拟npu行为,便于快速调试

2.算子基础概念

基本概念:算子对应(神经)网络中层或节点的计算逻辑

数学含义:一个函数空间到另一个函数空间上的映射

算子的重要属性有:

算子名称:用于标志网络中某个算子,需要为唯一值。

算子类型:相同类型算子的实现逻辑相同

数据容器:张量(tensor),即为存储算子输入输出的容器

tensor的属性包括:名称(name)、形状(shape)、数据类型(dtype)、数据排布格式(format:也即数据的物理排布格式:在深度学习领域,多维数据是用多维数组存储的。因为数据在计算机中只能线性存储,因此需要按照不同的顺序存储数据。例如NCHW将同一通道的所有像素值顺序存储在一起、NHWC则将不同通道的同一位置的像素值顺序存储在一起)

轴(Axis): 张量中维度的下标 例如张量x shape为(5,6) axis=0即为x中的第一维

Ascend C算子即为Ascend c编程语言开发出的算子,其运行在npu的ai core上

3.硬件架构简介

Ai Core逻辑架构使用达芬奇架构

其主要部分包含:

计算单元(包括标量计算单元、向量计算单元、矩阵计算单元,负责输入数据的计算)

存储单元(负责管理ai core片上存储和数据通路)

控制单元(指令经过指令缓存->标量指令处理队列->指令发射模块送至三个运算队列以进一步控制计算任务的执行)

ai core硬件架构抽象

在进行编程实践时,主要基于硬件抽象架构进行编程。上图中Scalar计算单元主要负责指令分发给相应计算单元的指令队列和标量计算(为性能考虑,尽量让Scalar计算单元只进行指令分配的任务)。ai core内部数据处理基本流程是:搬运单元将输入数据从外部内存搬运至LocalMemory,各计算单元可从LocalMemory取数据进行计算与结果写回,最后搬运单元再将计算结果从LocalMemory搬回外部内存。

4.Ascend C矢量编程范式与案例实践

本次实践中应用到了矢量编程范式:即算子实现由数据搬入(CopyIn)、计算(Compute)、数据搬出(CopyOut)三个流水任务组成。在各个任务间使用queue进行同步管理,并且使用Pipe模块进行内存资源管理。

以sinh算子为例:

CopyIn负责搬入数据操作,将输入数据从GlobalMemory搬运到LocalMemory供给计算单元使用。

此部分主要使用的api包括:AllocTensor(通过队列申请内存)、DataCopy(数据搬运实现)、EnQue(数据送入队列)

    __aicore__ inline void CopyIn(int32_t progress, uint32_t length) {
        LocalTensor<DTYPE_X> xLocal = inQueueX.AllocTensor<DTYPE_X>();
        DataCopy(xLocal, xGm[progress * this->tileLength], length);
        inQueueX.EnQue(xLocal);
    }

Compute负责矢量指令计算操作,通过调用相关计算api实现具体算法。
sinh算法:

    __aicore__ inline void Compute(int32_t progress, uint32_t length) {
        LocalTensor<DTYPE_X> xLocal = inQueueX.DeQue<DTYPE_X>();
        LocalTensor<DTYPE_Y> yLocal = outQueueY.AllocTensor<DTYPE_Y>();
        //sinh(x)=(exp(x)-exp(-x))/2
        //exp(x)
        Exp(yLocal, xLocal, this->tileLength); 
        //-x
        Muls(xLocal, xLocal, (DTYPE_X)(-1), this->tileLength);
        //exp(-x) 
        Exp(xLocal, xLocal, this->tileLength); 
        //exp(x) - exp(-x)
        Sub(xLocal, yLocal, xLocal, this->tileLength); 
        //(exp(x)-exp(-x))/2
        Muls(yLocal, xLocal, (DTYPE_X)(0.5), this->tileLength);

        outQueueY.EnQue<DTYPE_Y>(yLocal);
        inQueueX.FreeTensor(xLocal);
    }

CopyOut负责搬出操作:完成队列出队后,将计算结果从LocalMemory搬运到GlobalMemory,流程类似数据搬入。

    __aicore__ inline void CopyOut(int32_t progress, uint32_t length) {
        LocalTensor<DTYPE_X> yLocal = outQueueY.DeQue<DTYPE_X>();
        DataCopy(yGm[progress * this->tileLength], yLocal, length);
        outQueueY.FreeTensor(yLocal);
    }

5.参考资料 

CANN社区版文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值