TIKC++算子与接口API
1 TIK C++ 算子
1.1 算子执行的不同模式
TIK C++算子可用CPU模式或NPU模式执行
CPU模式∶算子功能调试用,可以模拟在NPU上的计算行为,不需要依赖昇腾设备
NPU模式∶算子功能/性能调试,可以使用NPU的强大算力进行运算加速
使用**内置宏__CCE_KT_TEST__**标识被宏包括的代码在特定的模式下编译
#ifdef _CCE_Kr_TEST_表示在CPu模式下会编译该段代码
#ifndef _CCE_KT_TEST_ 表示在NPU模式下会编译该段代码
1.2 编写TIK C++的helloworld样例
进一步介绍函数
具体编译命令
实操步骤:
-
编写代码
-
CPU运行
-
NPU运行
2 了解3/2/0级接口API的概念
2.1 常用数据结构:GlobalTensor
GlobalTensor用来存放Global Memory (外部存储)的全局数据定义原型
定义原型
2.2 常用数据定义:LocalTensor
LocalTensor用于存放核上Local Memory(内部存储)的数据
定义原型
`
2.3 矢量计算指令接口
矢量计算指令接口,能够启动Al Core中的Vector单元执行计算
为了降低开发者的使用门槛,指令按照由易到难,分成了3级到0级接口。其中3级接口最为简单,O级接口最为复杂,(1级接口还未发布)多层级API封装的作用:
- 降低复杂指令的使用难度
- 跨代兼容性保障
- 保留最大灵活度的可能
2.4 指令API的3 2 0级接口
2.4.1 指令API的3级接口
注意∶三级接口会进行连续矢量运算,运算量为目的LocalTensor的总长度
2.4.2指令API的2级接口
允许用户使用形如∶
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本身的大小
2.4.3 指令API的0级接口
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;
};
允许用户使用形如∶
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);
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);
(1)指令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;
);
(2)指令API的O级接口——相邻迭代间相同block的地址步长
Repeat stride表示相邻迭代间相同block的地址步长
当Repeat times大于1,需要多次迭代完成矢量计算时,可以根据不同的使用场景合理设置相邻迭代间相同black的地址步长Repeat stride的值
-
连续计算场景∶ 假设定义一个Tensor供目的操作数和源操作数同时使用(即地址重叠),Repeat stride取值为8。此
时,矢量计算单元第一次迭代读取连续8个block,第二轮迭代读取下一个连续的8个block,通过多次迭代即可完成所有输入数据的计算
-
非连续计算场景:Repeat stride取值大于8(如取10 )时,则相邻迭代间矢量计算单元读取的数据在地址上不连续,出现2个block的间隔
-
反复计算场景:Repeat stride取值为o时,矢量计算单元会对首个连续的8个block进行反复读取和计算
-
部分重复计算∶Repeat stride取值大于0且小于8时,相邻迭代间部分数据会被矢量计算单元重复读取和计算,此种情形一般场景不涉及
(3)指令API的O级接口——同一迭代内不同block的地址步长
Block stride表示同意迭代内不同block的地址步长
如果需要控制单次迭代内,数据处理的步长,可以通过设置同一迭代内不同block的地址步长Block stride来实现。连续计算,Block stride设置为1,对同一迭代内的8个block数据连续进行处理
非连续计算,Block stride值大于1,同一迭代内不同block之间在读取数据时出现一个block的间隔
(4) 指令api的0级接口–Mask参数
Mask用于控制每次迭代内参与计算的元素。可通过连续模式和逐比特模式两种方式进行设置
连续模式:表示前面连续的多少个元素参与计算.数据类型为uint 64_t.取值范围和操作数的数据类型有关,数据类型不同,每次迭代内能够处理的元素个数最大值不同(当前数据类型单次迭代时能处理的元素个数最大值为:256/size of(数据类型))。
逐比特模式∶可以按位控制哪些元素参与计算,比特位的值为1表示参与计算,0表示不参与。