【2023 · CANN训练营第一季】了解3/2/0级接口API的概念

1 常用数据结构 GlobalTensor

GlobalTensor
用来存放Global Memory (外部存储)的全局数据定义原型
定义原型

void Init( __gm__ uint8_t *_restrict__ src_&, __gm__ uint8_t *__restrict__ dst_gm)
{
uint32_t dataSize = 256; //设置input_global的大小为256
GlobalTensorcint32_t inputGlobal;//类型为int32_t
//设置源操作数在Global Memmory上的起始地址为src_gn,所占外部存储的大小为256个int32_t
inputGlobal.SetGlobalBuffer(reinterpret_cast<__gm__ int32_t *>(src_gm),dataSize);
LocalTensor<int32_t> inputLocal - inQueuex.AllocTensor<int32_t>():
DataCopy(inoutLocal,inputGlobal, dataSize);//将Global Nemmory上的inputGlobal拷贝到Local Momory的inputLocal上
...
}

2 常用数据定义 LocalTensor

LocalTensor
用于存放核上Local Memory(内部存储)的数据
定义原型

template <typename T> class LocalTensor {
 T Getvalue(const uint32_t offset) const;//获取LocalTensor中的某个值,返回T类型的立即数
 template ctypename T1> void  Setvalue(const uint32_t offset,const T1 value)const;//设置tLcallensor中的某个值,ofset单位为element
 //获取距原LocalTensor起始地址偏移量为offset的新LocalTensor, 注意ofiset不能超过原有localTensor的sie大小ofiset单位为elementLocalTensor operator[](const uint32_t offset) const;
 uint32_t GetSize() const; l/获取当前LocalTensor size大小
}

3 矢量计算指令接口

矢量计算指令接口,能够启动Al Core中的Vector单元执行计算

  • 单目指令操作:Exp、Ln、Abs、Reciprocal、Sqrt、Rsqrt、Not、Relu、Sigmoid、Tanh、…
  • 双目指令操作:Add、Sub、Mul、Div、Max、Min、And、Or、…
  • 标量双目指令操作:Adds、Muls、Maxs、Mins、ShiftLeft、ShiftRight、LeakyRelu、…
  • 标量三目指令操作:Axpy…
  • 比较指令操作:Compare、…
  • 选择指令操作: Select、ReduceV2、…
  • 精度转换指令操作:Cast、…
  • 规约指令操作: ReduceMax、ReduceMin、ReduceSum、…
  • 特殊规约指令操作: WholeReduce.BlockReduce、PairReduce、…
  • 数据转换操作:Transpose、TransDataTo5HD、–.
  • 数据填充操作:Duplicate、Brcb…
  • 数据搬移操作:DataCopy.Copy…

image.png

4 指令API的3级接口

以下指令API拥有3级接口∶
Add : dstLocal = srceLocal + src1Local;
Sub : dstLocal = srceLocal - src1Local;
Mul : dstLocal = srceLocal * src1Local;
Div ; dstLocal = srceLocal / src1Local;
And : dstLocal = srceLocal & src1Local;
or : dstLocal = srceLocal | src1Local;
Compare
dstLocal = src0Local < src1Local;
dstLocal = srceLocal > src1Local;
dstLocal = srceLocal <= src1Local;
dstLocal = srceLocal >= src1Local;
dstLocal = srceLocal == src1Local;
dstLocal = srceLocal != src1Local;

注意∶ 三级接口会进行连续矢量运算,运算量为目的LocalTensor的总长度

5 指令API的2级接口

2级连续计算接口,针对源操作数srcLocal的连续cOUNT个数据进行计算,并连续写入目的操作数dstLocal,提供了一维Tensor的连续cONT个数据的计算支持

允许用户使用形如∶

void Operator(const LocalTensor<T>& dstLocal,const localTensor<T>& srcLocal,const int32_t& calCount)

大多数指令API拥有2级接口,2级接口相对于3级接口,可以自定义运算量

  • Exp(dstLocal, srcLocal,512);
  • Adds(dstLocal, srcLocal,scalarvalue,512);
  • Select(dstLocal,maskLocal,srceLocal,src1Local,SELMODE::VSEL_CNPMASK_SPR,256);
  • ReduceMin(dstLocal, srcLocal,workLocal,8328,true);
  • Duplicate(dstLocal,inputval,256);

注意: 二级接口会进行连续矢量运算,开发者指定的运算量不能超过参与运算Tensor本身的大小

6 指令API的0级接口

0级功能灵活计算接口,是最底层的开发接口,可以完整发挥硬件优势的计算API,可以进行非连续的计算
该功能可以充分发挥CANN系列芯片的强大功能指令,支持对每个操作数的Block stride ,Repeat stride,MASk的操作,允许用户使用诸多的通用参数来定制化所需要的操作

通用参数包括:

  • Repeat times (迭代的次数)
  • Block stride (单次迭代内不同block间地址步长)
  • Repeat stride (相邻迭代间相同block的地址步长)
  • Mask(用于控制参与运算的计算单元)
struct UnaryRepeatParams {
 uint32_t blockNumber = kDefau1tB1kNum;
 uint16_t dstBlkStride = kDefaultBlkStride;uint16_t   srcBlkStride = kDefaultBlkstride;
 uint8_t dstRepStride = kDefaultRepStride;
 uint8_t srcRepStride = kDefaultRepstride;
 bool repeatstrideMode = false;
 bool strideSizeMode = false;
 bool half_block = false;
};

允许用户使用形如∶

6.1 Mask逐比特模式

template <ctypename T> __aicore__ inline void Exp(const LocalTensor<T>& dstLocal, const LocalTensor<T>&srcLocal,uint64_t mask[2], const uint8_t repeatTimes,const UnaryRepeatPardms& repeatParams);

6.2 Mask连续模式

template <typename T> __aicore_ inline void Exp(const LocalTensor<T>& dstLocal, const LocalTensor<T>&srcLocal,uint64_t mask,const uint8_t repeatTimes,const UnaryRepeatParams& repeatParams);

7 指令API的O级接口——重复迭代次数-Repeat times

Repeat times表示迭代的次数
矢量计算单元,一次最多可以计算256Bytes的数据,每次读取连续的8个block (每个block 32Bytes,共256Bytes )数据进行计算,为完成对输入数据的处理,必须通过多次迭代( repeat )才能完成所有数据的读取与计算。
待处理数据大小为16个block ( 512Bytes ),每次迭代处理8个block ( 256Bytes ),需要两次迭代完成计算,Repeat times应设置为2
struct UnaryRepeatParams i
uint32_t blockNumber = kDefau1tB1kNum;
uint16_t dstBlkStride = kDefaultBlkStride;uint16_t srcBlkStride = kDefaultBlkstride;
uint8_t dstRepStride = kDefaultRepStride;
uint8_t srcRepStride = kDefaultRepstride;bool repeatstrideMode = false;
bool strideSizeMode = false;bool half_block = false;
);
image.png

8 指令API的O级接口——相邻迭代间相同block的地址步长

Repeat stride表示相邻迭代间相同block的地址步长
当Repeat times大于1,需要多次迭代完成矢量计算时,可以根据不同的使用场景合理设置相邻迭代间相同black的地址步长Repeat stride的值

8.1 连续计算场景

假设定义一个Tensor供目的操作数和源操作数同时使用(即地址重叠),Repeat stride取值为8。此时,矢量计算单元第一次迭代读取连续8个block,第二轮迭代读取下一个连续的8个block,通过多次迭代即可完成所有输入数据的计算
image.png

8.2 非连续计算场景

Repeat stride取值大于8(如取10 )时,则相邻迭代间矢量计算单元读取的数据在地址上不连续,出现2个block的间隔
image.png

8.3 反复计算场景

Repeat stride取值为o时,矢量计算单元会对首个连续的8个block进行反复读取和计算
image.png

8.4 部分重复计算

Repeat stride取值大于0且小于8时,相邻迭代间部分数据会被矢量计算单元重复读取和计算,此种情形一般场景不涉及
image.png

9 指令API的O级接口——同一迭代内不同block的地址步长

Block stride表示同意迭代内不同block的地址步长
如果需要控制单次迭代内,数据处理的步长,可以通过设置同一迭代内不同block的地址步长Block stride来实现。连续计算,Block stride设置为1,对同一迭代内的8个block数据连续进行处理

非连续计算,Block stride值大于1,同一迭代内不同block之间在读取数据时出现一个block的间隔
image.png

10 指令api的0级接口–Mask参数

Mask用于控制每次迭代内参与计算的元素。可通过连续模式逐比特模式两种方式进行设置

10.1 连续模式

表示前面连续的多少个元素参与计算.数据类型为uint 64_t.取值范围和操作数的数据类型有关,数据类型不同,每次迭代内能够处理的元素个数最大值不同(当前数据类型单次迭代时能处理的元素个数最大值为:256/size of(数据类型))。当操作数的数据类型占比特位16位时(如Half,uint 16_t),Maske[1,128];当操作数为3z位时(如Float,int 32_t),Maske[1,64]。

//int16_t数据类型单次迭代能处理的元素个数最大值为256/sizeof(int16_t) m 128, mask m64, maske[1, 128],所以是合法输入
//repeatTimes = 1,共128个元素,单次迭代能处理128个元素,故repeatTimes = 1
//dstBlkStride,srceBlkStnide,snc1BlkStride = 1,单次迭代内连续读取和写入数据
//dstRepStride,srceRepStnide,snc1RepStride = 8,迭代间的数据连续读取和写入
uint64_t mask = 64;
Add(dstLocal, srcBLocal, src1Local, mask,1,{ 1,1,18,8,8 ));
结果示例如下:
输入数据(src0Local): [1 2 3...64...128]
输入数据(src1Local): [1 2 3...64...128]
输出数据(dstLoca1):[2 4 6 ...128 undefined. . .undefined]
// int32_t数据类型单次迭代能处理的元素个数最大值为256/sizeof(int32_t) =64, mask =64, mask∈[1,64],所以是合法输入
// repeatTimes= 1,共64个元素,单次迭代能处理64个元素,故repeatTimes= 1
//dstBlkStride, srceBlkStride,snc1BlkStride = 1,单次迭代内连续读取和写入数据
//dstRepStride,srcORepStride,src1RepStride = 8,迭代间的数据连续读取和写入
uint64_t mask =64;
Add(dstLocal, srceLocal, src1Local, mask,1,{ 1118, 8, 8 ));
结果示例如下:
输入数据(srceLacal):[1 2 3 ...64]
输入数据(src1Local):[1 2 3 ...64]
输出数据(dstLocal):[2 4 6... 128j

10.2 逐比特模式

可以按位控制哪些元素参与计算,比特位的值为1表示参与计算,0表示不参与。

参数类型为长度为2的uint64_t类型数组
参数取值范围和操作数的数据类型有关,数据类型不同,每次迭代内能够处理的元素个数最大值不同。当操作数为16位时,mask[0]、mask[1]∈[0, 2 64 2^{64} 264 -1];当dst/src为32位时,mask[1]为o ,mask[0]∈[0, 2 64 2^{64} 264 -1]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值