目录
4.3.1 使用migraphx::quantize_fp16
11.3.1 onnx的upsample算子与pytorch不等价
1 MIGraphX简介
MIGraphX是一款用于DCU上的高性能深度学习推理引擎。MIGraphX能将深度学习框架(Tensorflow,Pytorch等)训练好的算法模型转换为MIGraphX IR表示的计算图,并提供端到端的模型优化、代码⽣成以及推理业务部署能力。MIGraphX致力于为用户提供高性能、灵活、易用的编程接口以及配套⼯具,让用户能够专注于推理业务开发和部署本⾝ ,而无需过多关注底层硬件细节,显著提高用户的开发效率。
1.1 MIGraphX适用场景
- 图像处理,比如分类(VGG16,ResNet50)、检测(SSD,YOLO)、分割(UNet)等
- 视频处理
- 自如语言处理,比如BERT
- 搜索、推荐
1.2 MIGraphX特性
- 支持多种精度推理,比如FP32,FP16,INT8
- 支持多语言API,包括C++和Python
- 支持动态shape
- 支持模型序列化
- 支持调试
- 提供性能分析⼯具
1.3 MIGraphX整体架构
图1.1:MIGraphX整体架构
MIGraphX整体架构主要分为三层:
- 中间表示层:用户训练好的算法模型会统⼀转换为用MIGraphX IR 表示的计算图,后续的模型优化和代码生成都基于该计算图完成。
- 编译优化层:基于MIGraphX IR完成各种优化,比如常量折叠,内存复用优化,算子融合,代码生成等,提高推理性能。
- 计算引擎层:主要包含了底层计算库的接口,包括MIOpen和rocblas。
1.3.1 MIGraphX IR
AI编译中的IR从层级上分一般可以分为两种类型:多级IR和单级IR。使用多级IR可以使得系统优化更加灵活,各级IR只需要负责本级优化,多级IR的代表就是MLIR,但是多级IR会带来如下的问题:
- 需要在不同IR之间进行转换,IR转换做到完全兼容很难而且工作量大。
- 不同IR转换可能带来信息的损失。
- 多级IR有些优化既可以在上一层IR进行, 也可以在下一层IR进行, 让系统开发者很难选择。
MIGraphX采用了单级IR的设计,MIGraphX IR以基于SSA的线性IR为基本组成形式 ,这种形式的IR可以表达计算图中的控制流信息和数据依赖关系,方便后面的编译优化。MIGraphX IR由program,module,instruction等基本结构组成,关于这些基本结构的详细介绍参考第3章编程模型。
1.3.2 编译
MIGraphX采用静态图模式,在编译阶段,MIGrahpX会执行如下操作:
- 机器无关优化:比如删除公共子表达式,删除无用的代码,常量传播,常量折叠,代数化简等。
- 内存复用优化:MIGraphX采用了图着色的方法实现无计算依赖的节点间的内存复用,显著减低内存消耗。
- 指令调度:根据计算图分析指令之间的依赖关系,根据这些依赖关系优化各指令的执行顺序,从而提高计算性能。
- 代码生成:MIGraphX利用代码生成技术生成算子的实现,然后利用JIT编译为可执行代码。
1.4 支持的ONNX算子
MIGraphX4.0.0支持ONNX Opset 17,建议导出ONNX模型的时候Opset不低于13,如果Opset版本过低,可能会由于部分算子定义不同导致模型精度有差异或者模型推理报错。最新的ONNX算子信息可以在这里查看。 MIGraphX支持的ONNX数据类型有DOUBLE, FLOAT32, FLOAT16, INT8, 和 BOOL。具体支持情况见下表:
算子 | 是否支持 | 数据类型 |
---|---|---|
Abs | Y | FP32, FP16, INT32 |
Acos | Y | FP32, FP16 |
Acosh | Y | FP32, FP16 |
Add | Y | FP32, FP16, INT32 |
And | Y | BOOL |
ArgMax | Y | FP32, FP16, INT32 |
ArgMin | Y | FP32, FP16, INT32 |
Asin | Y | FP32, FP16 |
Asinh | Y | FP32, FP16 |
Atan | Y | FP32, FP16 |
Atanh | Y | FP32, FP16 |
AveragePool | Y | FP32, FP16, INT8, INT32 |
BatchNormalization | Y | FP32, FP16 |
Bernoulli | N | |
BitShift | N | |
BlackmanWindow | N | |
Cast | Y | FP32, FP16, INT32, INT8, UINT8, BOOL |
Ceil | Y | FP32, FP16 |
Celu | Y | FP32, FP16 |
Clip | Y | FP32, FP16, INT8 |
Compress | N | |
Concat | Y | FP32, FP16, INT32, INT8, BOOL |
ConcatFromSequence | N | |
Constant | Y | FP32, FP16, INT32, INT8, BOOL |
ConstantOfShape | Y | FP32 |
Conv | Y | FP32, FP16, INT8 |
ConvInteger | Y | INT8,INT32 |
ConvTranspose | Y | FP32, FP16, INT8 |
Cos | Y | FP32, FP16 |
Cosh | Y | FP32, FP16 |
CumSum | Y | FP32, FP16 |
DFT | N | |
DepthToSpace | Y | FP32, FP16, INT32 |
DequantizeLinear | Y | INT8 |
Det | N | |
Div | Y | FP32, FP16, INT32 |
Dropout | Y | FP32, FP16 |
DynamicQuantizeLinear | N | |
Einsum | Y | FP32, FP16 |
Elu | Y | FP32, FP16, INT8 |
Equal | Y | FP32, FP16, INT32 |
Erf | Y | FP32, FP16 |
Exp | Y | FP32, FP16 |
Expand | Y | FP32, FP16, INT32, BOOL |
EyeLike | Y | FP32, FP16, INT32, BOOL |
Flatten | Y | FP32, FP16, INT32, BOOL |
Floor | Y | FP32, FP16 |
Gather | Y | FP32, FP16, INT8, INT32, BOOL |
GatherElements | Y | FP32, FP16, INT8, INT32, BOOL |
GatherND | Y | FP32, FP16, INT8, INT32, BOOL |
Gemm | Y | FP32, FP16, INT8 |
GlobalAveragePool | Y | FP32, FP16, INT8 |
GlobalLpPool | Y | FP32, FP16, INT8 |
GlobalMaxPool | Y | FP32, FP16, INT8 |
Greater | Y | FP32, FP16, INT32 |
GreaterOrEqual | Y | FP32, FP16, INT32 |
GridSample | Y | FP32, FP16 |
GroupNormalization | Y | FP32, FP16 |
GRU | Y | FP32, FP16 |
HammingWindow | N | |
HannWindow | N | |
HardSwish | Y | FP32, FP16, INT8 |
HardSigmoid | Y | FP32, FP16, INT8 |
Hardmax | N | |
Identity | Y | FP32, FP16, INT32, INT8, BOOL |
If | Y | FP32, FP16, INT32, BOOL |
ImageScaler | Y | FP32, FP16 |
InstanceNormalization | Y | FP32, FP16 |
IsInf | Y | FP32, FP16 |
IsNaN | Y | FP32, FP16, INT32 |
LayerNormalization | Y | FP32, FP16 |
LeakyRelu | Y | FP32, FP16, INT8 |
Less | Y | FP32, FP16, INT32 |
LessOrEqual | Y | FP32, FP16, INT32 |
Log | Y | FP32, FP16 |
LogSoftmax | Y | FP32, FP16 |
Loop | Y | FP32, FP16, INT32, BOOL |
LRN | Y | FP32, FP16 |
LSTM | Y | FP32, FP16 |
LpNormalization | Y | FP32, FP16 |
LpPool | Y | FP32, FP16, INT8 |
MatMul | Y | FP32, FP16 |
MatMulInteger | Y | INT8,INT32 |
Max | Y | FP32, FP16, INT32 |
MaxPool | Y | FP32, FP16, INT8 |
MaxRoiPool | N | |
MaxUnpool | N | |
Mean | Y | FP32, FP16, INT32 |
MeanVarianceNormalization | Y | FP32, FP16 |
MelWeightMatrix | N | |
Min | Y | FP32, FP16, INT32 |
Mod | Y | FP32, FP16, INT32 |
Mul | Y | FP32, FP16, INT32 |
Multinomial | Y | FP32, FP16, INT32 |
Neg | Y | FP32, FP16, INT32 |
NegativeLogLikelihoodLoss | N | |
NonMaxSuppression | Y | FP32, FP16 |
NonZero | Y | FP32, FP16 |
Not | Y | BOOL |
OneHot | Y | FP32, FP16, INT32, BOOL |
Optional | N | |
OptionalGetElement | N | |
OptionalHasElement | N | |
Or | Y | BOOL |
Pad | Y | FP32, FP16, INT8, INT32 |
ParametricSoftplus | Y | FP32, FP16, INT8 |
Pow | Y | FP32, FP16 |
PRelu | Y | FP32, FP16, INT8 |
QLinearConv | N | |
QLinearMatMul | N | |
QuantizeLinear | Y | FP32, FP16 |
RandomNormal | Y | FP32, FP16 |
RandomNormalLike | Y | FP32, FP16 |
RandomUniform | Y | FP32, FP16 |
RandomUniformLike | Y | FP32, FP16 |
Range | Y | FP32, FP16, INT32 |
Reciprocal | Y | FP32, FP16 |
ReduceL1 | Y | FP32, FP16 |
ReduceL2 | Y | FP32, FP16 |
ReduceLogSum | Y | FP32, FP16 |
ReduceLogSumExp | Y | FP32, FP16 |
ReduceMax | Y | FP32, FP16 |
ReduceMean | Y | FP32, FP16 |
ReduceMin | Y | FP32, FP16 |
ReduceProd | Y | FP32, FP16 |
ReduceSum | Y | FP32, FP16 |
ReduceSumSquare | Y | FP32, FP16 |
Relu | Y | FP32, FP16, INT8 |
Reshape | Y | FP32, FP16, INT32, INT8, BOOL |
Resize | Y | FP32, FP16 |
ReverseSequence | Y | FP32, FP16, INT32, INT8, BOOL |
RNN | Y | FP32, FP16 |
RoiAlign | Y | FP32, FP16 |
Round | Y | FP32, FP16, INT8 |
STFT | N | |
ScaledTanh | Y | FP32, FP16, INT8 |
Scan | Y | FP32, FP16 |
Scatter | Y | FP32, FP16, INT8, INT32 |
ScatterElements | Y | FP32, FP16, INT8, INT32 |
ScatterND | Y | FP32, FP16, INT8, INT32 |
Selu | Y | FP32, FP16, INT8 |
SequenceAt | N | |
SequenceConstruct | N | |
SequenceEmpty | N | |
SequenceErase | N | |
SequenceInsert | N | |
SequenceLength | N | |
SequenceMap | N | |
Shape | Y | FP32, FP16, INT32, INT8, BOOL |
Shrink | Y | FP32, FP16, INT32 |
Sigmoid | Y | FP32, FP16, INT8 |
Sign | Y | FP32, FP16, INT8, INT32 |
Sin | Y | FP32, FP16 |
Sinh | Y | FP32, FP16 |
Size | Y | FP32, FP16, INT32, INT8, BOOL |
Slice | Y | FP32, FP16, INT32, INT8, BOOL |
Softmax | Y | FP32, FP16 |
SoftmaxCrossEntropyLoss | N | |
Softplus | Y | FP32, FP16, INT8 |
Softsign | Y | FP32, FP16, INT8 |
SpaceToDepth | Y | FP32, FP16, INT32 |
Split | Y | FP32, FP16, INT32, BOOL |
SplitToSequence | N | |
Sqrt | Y | FP32, FP16 |
Squeeze | Y | FP32, FP16, INT32, INT8, BOOL |
StringNormalizer | N | |
Sub | Y | FP32, FP16, INT32 |
Sum | Y | FP32, FP16, INT32 |
Tan | Y | FP32, FP16 |
Tanh | Y | FP32, FP16, INT8 |
TfIdfVectorizer | N | |
ThresholdedRelu | Y | FP32, FP16, INT8 |
Tile | Y | FP32, FP16, INT32, BOOL |
TopK | Y | FP32, FP16, INT32 |
Transpose | Y | FP32, FP16, INT32, INT8, BOOL |
Trilu | Y | FP32, FP16, INT32, INT8, BOOL |
Unique | N | |
Unsqueeze | Y | FP32, FP16, INT32, INT8, BOOL |
Upsample | Y | FP32, FP16 |
Where | Y | FP32, FP16, INT32, BOOL |
Xor | Y | BOOL |
1.5 支持的模型
目前 MIGraphX支持常用的 CNN 、LSTM 、Transformer和BERT等模型:
- Classification:AlexNet,VGG,Inception,ResNet,DenseNet,EfficientNet等
- Detection :SSD,YOLO,DBNet等
- Segmentation :FCN,UNet,MaskRCNN等
- LSTM:CRNN等
- Transformer:Vision Transformer(ViT)等
- BERT:BERT-Squad等
- GPT:GPT2等
以下是已测试通过的模型列表
支持的模型 |
---|
AlexNet |
VGG16,VGG19 |
GoogLeNet,InceptionV3 |
ResNet50 |
DenseNet |
ShuffleNet |
SqueezeNet |
MobileNetV1,MobileNetV2,MobileNetV3 |
EfficientNet-B3,EfficientNet-B5,EfficientNet-B7 |
FasterRCNN |
MTCNN |
SSD-VGG16 |
RetinaNet |
RetinaFace |
YOLOV3,YOLOV4,YOLOV5,YOLOV7,YOLOV8 |
FCN |
UNet |
MaskRCNN |
DBNet |
EAST |
CRNN |
Vision Transformer(ViT) |
Swin Transformer |
BERT |
GPT2 |
1.6 示例程序
MIGraphX提供了丰富的示例程序帮助用户更快的部署深度学习模型,示例程序可以在ModelZoo中下载,在搜索框中通过"MIGraphX"关键字可以搜索MIGraphX相关的示例程序。
2 安装MIGraphX
2.1 使用DTK中的MIGraphX
2.1.1 安装DTK
有两种方式安装DTK:
- 使用DTK镜像,镜像下载地址:光源 Find source, find chance.
- 使用DTK安装包,安装包下载地址:https://cancon.hpccube.com:65024/1/main, 将下载好的安装包解压到/opt目录,解压后的目录结构应为:/opt/dtk-xx.xx,最后创建一个软连接/opt/dtk指向该目录。
2.1.2 设置环境变量
安装好DTK后需要设置环境变量:
source /opt/dtk/env.sh
如果需要在python中使用MIGraphX,还需要设置PYTHONPATH :
export PYTHONPATH=/opt/dtk/lib:$PYTHONPATH
2.2 使用MIGraphX镜像
除了可以使用DTK中自带的MIGraphX,还可以通过MIGraphX镜像获取MIGraphX,镜像下载地址:光源 Find source, find chance. , 用户可以根据需要选择合适的镜像,比如需要在Centos7.6中使用DTK23.04.1和MIGraphX4.0.0,可以通过下面的命令下载镜像:
docker pull image.sourcefind.cn:5000/dcu/admin/base/migraphx:4.0.0-centos7.6-dtk23.04.1-py38-latest
在使用MIGraphX之前,需要设置容器中的环境变量:
source /opt/dtk/env.sh
如果需要在Python中使用MIGraphX,还需要设置PYTHONPATH :
export PYTHONPATH=/opt/dtk/lib:$PYTHONPATH
3 MIGraphX编程模型
本章简要阐述MIGraphX中的一些基本概念和基本设计思想,希望帮助读者更好的使用和理解MIGraphX。
3.1 shape
shape类型表示数据的形状。
可以通过如下方式构造一个shape对象:
- shape(type_t t, std::vector < std::size_t > l)
- shape(type_t t, std::vector < std::size_t > l, std::vector < std::size_t > s)
各参数含义如下:
- t:shape的数据类型,shape支持的数据类型包括:
- bool_type
- half_type
- float_type
- double_type
- uint8_type
- int8_type
- uint16_type
- int16_type
- int32_type
- int64_type
- uint32_type
- uint64_type
- l:每一个维度的大小
- s:每一个维度的步长,如果没有指定步长,MIGraphX会根据l自动计算出步长,比如对于一个内存排布为[N,C,H,W]格式的数据,对应的每一维的步长为[C H W,H * W,W,1]
shape中常用的成员函数:
- const std::vector< std::size_t >& lens() const 返回每一维的大小,维度顺序为(N,C,H,W)
- std::size_t elements() const 返回所有元素的个数
- std::size_t bytes() const 返回所有元素的字节数
示例:
resnet50中第一个卷积层的卷积核大小为7x7,输出特征图个数为64,即有64个7x7的卷积核,如果输入的是一个3通道的图像,则该卷积核的shape可以表示为{migraphx::shape::float_type, {64, 3, 7, 7}},其中float_type表示shape的数据类型,这里采用float类型,{64, 3, 7, 7}表示每一个维度的大小,对应的是NCHW的内存排布,由于这里没有提供每一维的步长,所以步长会自动计算,自动计算出来的每一维的步长为{147,49,7,1},所以完整的shape表示为{migraphx::shape::float_type, {64, 3, 7, 7},{147,49,7,1}}。对于该卷积核的shape,lens()函数的返回值为{64, 3, 7, 7},elements()的返回值为9408,bytes()的返回值为9408*4=37632。
3.2 argument
argument类型用来保存数据,类似Pytorch中的Tensor,常用来保存模型的输入和输出数据。
可以通过如下方式构造一个argument对象:
- argument(const shape& s)
- template argument(shape s, T* d)
第1种方式只需要提供shape就可以,系统会自动申请一段内存,该内存的大小等于shape的bytes()方法返回值的大小。第2种方式除了提供shape之外,还需要提供该argument的数据指针,argument不会自动释放该数据。
argument中常用的成员函数:
-
const shape& get_shape() const 返回数据的形状
-
char* data() const 返回argument的数据,可以通过data()的返回值访问推理结果。
3.3 literal
MIGraphX中使用literal表示常量,比如可以使用literal表示卷积的权重。实际上literal是一种特殊的argument,literal中的值不能修改,而argument中的值可以修改。
可以通过如下方式构造一个literal对象:
- template literal(const shape& s, const std::vector& x)
- template literal(const shape& s, T* x)
- template literal(const shape& s, const std::initializer_list& x)
第一种构造方法是使用std::vector来创建一个常量,第二种使用数据指针来构造,第三种是使用std::initializer_list来构造。也可以通过generate_literal()方法创建一个随机值的literal:
migraphx::literal liter = migraphx::generate_literal(migraphx::shape{migraphx::shape::float_type, {64, 3, 7, 7}}, 0);
其中generate_literal()的第2个参数表示随机数的种子,不同种子会生成不同的随机数。
literal中常用的成员函数:
- const shape& get_shape() const 返回常量的形状
- const char* data() const 返回常量的数据指针,注意:不能通过data()返回的指针修改literal的值
3.4 target
target表示支持的硬件平台,目前支持CPU和GPU,在编译模型的时候,需要指定一个target。
3.5 program
MIGraphX中使用program类型表示一个神经网络模型。
program中常用的成员函数:
- void compile(const target& t, compile_options options = compile_options{}) 编译模型。第一个参数t是一个target,第二个参数options表示编译的一些设置,比如可以通过options.device_id设置使用哪一块显卡。
- std::vector< argument > eval(std::unordered_map< std::string, argument > params,const std::vector< std::string > &output_names) const 执行推理并返回推理结果。参数params表示模型的输入