编写算子步骤:
1、确定输入输出(数据类型和维度):明确算子功能,即要执行的操作
2、创建算子的头文件和源文件:使用C的语法,头文件和源文件分别用于声明和定义算子函数
3、在头文件中声明算子函数:头文件中使用extern关键字声明算子函数的原型,包括函数名、参数列表、返回值类型等
4、在源文件中定义算子函数:源文件中实现算子函数的具体逻辑。根据算子的功能和输入输出要求,编写相应的代码完成算子计算过程
5、编译和构建算子:使用Ascend C编译器将算子的源文件编译成可执行文件(可以根据需要把算子打包成库文件)
6、测试和验证算子:编写测试代码
算子融合
算子融合是一种深度学习模型优化技术,旨在将多个算子(操作)融合为一个算子,从而减少计算量和参数数量,提高模型性能和效率。在深度学习中,算子通常是指对张量(多维数组)进行操作的函数,如卷积(Convolution)、全连接层(Fully-Connected Layer)等。
通过将多个算子融合,可以减少计算量和参数数量,从而提高计算速度和内存使用效率。此外,算子融合还可以有助于减少模型大小,便于在移动设备等资源受限的设备上进行部署。
算子融合通常可以通过两种方式实现:
- 权重融合(Weight Fusion):将多个算子的权重矩阵融合为一个矩阵,从而减少参数数量。
- 算子调度融合(Operator Scheduling Fusion):通过调整算子的计算顺序,将多个算子融合为一个算子,从而减少计算量和内存使用。
需要注意的是,算子融合可能导致计算图变得更加复杂,因此可能需要更多的编译时间和优化时间。此外,并非所有的算子都可以进行融合,需要根据具体问题和硬件环境进行评估和调整。
在MindSpore中实现NMS算子
import mindspore as ms
import mindspore.ops as ops
class NMS(ms.nn.Cell):
def __init__(self, iou_threshold=0.5):
super(NMS, self).__init__()
self.iou_threshold = iou_threshold
self.transpose = ops.Transpose()
self.non_max_suppression = ops.NMSWithMask(0)
def construct(self, boxes, scores):
boxes = self.transpose(boxes, (1, 0))
scores = self.transpose(scores, (1, 0))
output, _ = self.non_max_suppression(boxes, scores, self.iou_threshold)
return output
# 创建NMS算子
nms_op = NMS(iou_threshold=0.5)
# 使用NMS算子进行非极大值抑制
output_boxes = nms_op(boxes, scores)
算子编译流程
前端编译(Frontend Compilation)
语法解析:将算子的代码文本解析成抽象语法树(AST)
语义分析:对AST进行静态分析,检查类型、作用域等,生成经过语义检查的AST
中间代码生成:将经语义检查的AST转换成一种中间表示(通常是GIMPLE形式的三地址代码)
优化编译(Optimization Compilation)
进行各种优化,如常量折叠、未用代码删除、循环优化等,得到更高效的中间代码
针对特定架构做目标代码优化,如SIMD向量化等
代码生成(Code Generation)
将优化后的中间代码转换成特定架构的汇编代码或机器码
进行寄存器分配、指令选择和指令排序等
后端编译
将生成的汇编代码组装成目标代码,完成链接,生成最终的算子库
进行代码校验,确保编译正确性
编译过程中常用的工具和框架包括LLVM、GCC、TVM等。通过编译,高效地将算子的高级语言代码转换成特定硬件可以执行的机器码,从而充分发挥硬件性能。
————————————————————————————————————
对于深度学习神经网络的算子来说,编译流程与通用算子略有不同,主要是如下几点:
张量化
为神经网络中的张量数据表示设计合适的数据类型,如float16、int8等
降低数据存储和传输成本,同时控制精度损失
针对特定硬件优化
如GPU:考虑线程块划分,共享内存使用,循环展开等
如TPU:考虑在管线数组架构下的优化,提高并行度
自动微分
自动生成反向传播所需的求导代码
支持动态形状变化,加速训练过程
图级(Graph-level)优化
跨算子的整体优化,如算子融合、内存复用
更高层次的性能提升
动态形状支持
训练时各层形状可能变化,编译需要考虑形状不确定性
通过动态调度来支持变化的形状
深度学习编译需要自动化地支持更多优化来生成高效的代码,以充分利用硬件性能,达到训练和推理的低延迟和高吞吐量。