Ascend C的算子实现主要包含两个部分:
由于NPU中AI Core内部存储无法完全容纳算子输入输出的所有数据,需要每次搬运一部分输入数据进行计算然后搬出,再搬运下一部分输入数据进行计算,这个过程就称之为Tiling。切分数据的算法称为Tiling算法或者Tiling策略。根据算子的shape等信息来确定数据切分算法相关参数(比如每次搬运的块大小,以及总共循环多少次)的计算程序,称之为Tiling实现,也叫Tiling函数(Tiling Function)。由于Tiling实现中完成的均为标量计算,AI Core并不擅长,所以我们将其独立出来放在Host侧CPU上执行。
Kernel实现即算子核函数实现,在Kernel函数内部通过解析Host侧传入的Tiling结构体获取Tiling信息,根据Tiling信息控制数据搬入搬出Local Memory的流程;通过调用计算、数据搬运、内存管理、任务同步API,实现算子逻辑。其核心逻辑基本上都为计算密集型任务,需要在NPU上执行。
本章内容先介绍矢量编程、矩阵编程、融合算子编程三种典型场景下的算子Tiling、Kernel实现,是对上文中三种典型编程范式的具体应用,同时也介绍了编程的更多细节、API的使用方法等。
然后分别介绍基于Kernel直调工程的算子开发和基于自定义算子工程的算子开发,主要内容涉及两种开发工程的对比,如何将算子Tiling、Kernel实现通过开发工程进行组织,特别的对于自定义算子工程还介绍了工程编译、算子包部署的额外流程,因为Kernel直调工程的编译相关内容和算子调用程序比较紧密,会在后续的Kernel直调章节一同介绍。