还没了解MIGraphX推理框架?试试这篇让你快速入门

简介: MIGraphX是一款用于DCU上的深度学习推理引擎,旨在提供端到端的模型优化、代码生成和推理业务部署能力。它支持将TensorFlow、Pytorch等框架的训练模型转换成MIGraphX IR表示的计算图。MIGraphX 提供灵活、易用的编程接口和工具,让用户能够专注于推理业务开发和部署,而不必过多关注底层硬件细节。

特性

  • 支持多种精度推理,比如FP32,FP16,INT8
  • 支持多语言API,包括C++和Python
  • 支持动态shape 、模型序列化
  • 支持调试
  • 提供性能分析⼯具

636ee506aeebdedd81977a22bbdec817.png

它的整体架构包括三个主要部分:中间表示层、编译优化层和计算引擎层。


中间表示层:将训练好的模型(如ONNX格式)转换为MIGraphX IR表示的计算图,后续的模型优化和代码生成都基于该计算图完成。

编译优化层:基于MIGraphX IR完成各种优化,比如常量折叠,内存复用优化,算子融合等,提高推理性能。

计算引擎层:主要包含底层计算库的接口,如MIOpen和rocblas。MIGraphX的后端实现主要通过调用这些计算库完成。

MIGraphX 使用单级 IR 设计,方便编译优化。在编译优化阶段,MIGraphX 实现了机器无关优化、内存复用优化和指令调度等多种优化措施。此外,MIGraphX 支持的模型包括但不限于 CNN、LSTM、Transformer、Bert 类型的模型,例如 AlexNet、VGG、Inception、ResNet、DenseNet、EfficientNet、SSD、YOLO、DBNet、FCN、UNet、MaskRCNN、CRNN、Vision Transformer(ViT)、BERT-Squad 等。我们还可以使用migraphx-driver onnx -l查看支持的onnx算子。

安装方法

  • 使用镜像(推荐) 下载地址,根据需要选择合适的镜像

例如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


使用安装包,安装包下载地址,根据不同的系统选择合适的安装包

安装dtk,上面的光源dtk镜像或者安装包,然后将下载好的安装包安装到/opt目录下,最后创建一个软连接/opt/dtk,使得该软连接指向dtk的安装目录,注意:一定要创建软连接/opt/dtk,否则MIGraphX无法正常使用。

安装halfwget https://github.com/pfultz2/half/archive/1.12.0.tar.gz,解压(tar -xvf ...tar.gz)后将include目录下的half.hpp拷贝到dtk目录下的include目录:cp half-1.12.0/include/half.hpp /opt/dtk/include/

安装sqlite:下载地址,解压,切换目录,然后./configure && make && make install,最后设置环境变量:export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH和export LD_LIBRARY_PATH=/usr/local/lib/:$LD_LIBRARY_PATH

下载MIGraphX: centos还要同时下载devel包

设置环境变量:source /opt/dtk/env.sh,如果需要在python中使用migraphx,还需要设置PYTHONPATH :export PYTHONPATH=/opt/dtk/lib:$PYTHONPATH

验证是否安装成功:/opt/dtk/bin/migraphx-driver onnx -l,输出支持的算子即可

编程模型

shape

Shape 用于描述数据的形状和类型。例如,假设有一个3通道的224x224的图像,其 Shape 可以这样表示:migraphx::shape{migraphx::shape::float_type, {1, 3, 224, 224}}

其中 float_type 表示数据类型为浮点型,{1, 3, 224, 224} 分别代表批量大小(batch size)、通道数(channel)、高度和宽度,如果是变量传入,它得是std::vector类型的。

构造函数还有第三个可选参考:std::vector类型,它用来表示每一维度的步长,如果没有指定步长,则按照shape为standard的形式根据l自动计算出步长,比如对于一个内存排布为 [N,C,H,W]格式的数据,对应的每一维的步长为[C * H * W,H * W,W,1]。


其中:


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

shape中常用的成员函数:


lens(): 返回每一维的大小。例如,shape.lens() 可能返回 {1, 3, 224, 224},表示批量大小、通道数、高度和宽度。

elements(): 返回所有元素的个数。例如,shape.elements() 可能返回 1*3*224*224。

bytes(): 返回所有元素的字节数。例如,对于浮点类型的数据,shape.bytes() 可能返回 1*3*224*224*sizeof(float)。

在shape中,无论是图像还是卷积,都要是NCHW格式的,例如有一卷积核大小为7x7,输出特征图个数为64,输入的是一个3通道的图像,则该卷积核的shape可以表示为migraphx::shape{migraphx::shape::float_type, {64, 3, 7, 7}},注意{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。一个float占4个字节。

argument

类似Pytorch中的Tensor,常用来保存模型的输入和输出数据。

假设 inputData 是一个 cv::Mat 对象,代表输入图像数据,则 Argument 可以这样构建:

migraphx::argument input = migraphx::argument{inputShape, (float*)inputData.data};

这里 inputShape 是数据的 Shape,(float*)inputData.data 是数据的指针。argument不会自动释放该数据。

当然,可以只需要提供shape就可以,系统会自动申请一段内存,该内存的大小等于shape的bytes()方法返回值的大小。

argument中常用的成员函数:

  • get_shape(): 返回数据的形状。例如,argument.get_shape()
  • data(): 返回指向数据的指针。例如,argument.data() 可以用来访问或修改存储在 Argument 中的推理结果

前面介绍了cv::Mat转换migraphx::argument,它也支持重新转回去的。

migraphx::argument result;// result表示推理返回的结果,数据布局为NCHW
int shapeOfResult[]={result.get_shape().lens()[0],result.get_shape().lens()
[1],result.get_shape().lens()[2],result.get_shape().lens()[3]};// shapeOfResult表
示的维度顺序为N,C,H,W
cv::Mat output(4, shapeOfResult, CV_32F, (void *)(result.data()));// 注意,cv::Mat
不会释放result中的数据

literal

使用literal表示常量,比如卷积的权重。实际上literal是一种特殊的 argument。


如果有一个权重数组 weights,其 Shape 为 weightShape,则可以这样创建一个 Literal:

migraphx::literal weightLiteral = migraphx::literal{weightShape, weights.data()};

这里设 weights 是一个包含权重数据的标准容器,如 std::vector。第二个参数可以传入一个连续的数据指针(data方法),或者直接使用weights变量。


literal中常用的成员函数:

get_shape(): 与 Argument 中的同名函数类似,返回常量的形状。

data(): 返回指向常量数据的指针。不同于 Argument,Literal 中的数据不可修改。

target

target表示支持的硬件平台,目前支持CPU模式和GPU模式,在编译模型的时候,需要指定一个target。


program表示一个神经网络模型

构造一个program,很简单:

migraphx::program net;

program中常用的成员函数:


compile(target, options): 编译模型。target 参数指定硬件平台,options 提供编译设置。比如可以通过options.device_id设 置使用哪一块显卡。

eval(params): 执行推理并返回结果。params 是一个包含模型输入的 parameter_map。parameter_map类型是std::unordered_map< std::string, argument>(哈希容器)的别名。注意这是一个同步的方法。

get_parameter_shapes(): 返回模型输入或输出参数的形状。返回哈希容器类型。

get_main_module(): 返回程序的主计算图,通常用于添加或修改模型层。

module

创建program的时候,会自动创建一个主计算图。而现代神经网络模型中可能存在多个子图,MIGraphX中使用module表示子图,每个子图又是由指令组成。

例如,在主模块中添加输入:

 //获取主计算图
 migraphx::module *mainModule = net.get_main_module();
 // 添加模型的输入
 migraphx::instruction_ref input =mainModule->add_parameter("input",
 migraphx::shape{migraphx::shape::float type, {1, 1,4,6}});

module中常用的成员函数:


add_parameter(name, shape): 添加模型输入。name 是输入的名称,shape 是输入的形状。返回值表示添加到模型中的该条指令的引用。

add_literal(literal): 向模块添加一个 Literal 对象。返回值表示添加到模型中的该条指令的引用。

add_instruction(op, args): 添加指令。op 是算子,args 是算子的参数。返回值表示添加到模型中的该条指令的引用。

add_return(args): 添加结束指令,通常表示模型的输出。

MIGraphX中使用instruction_ref这个类型表示指令的引用

instruction

instruction表示指令,可以通过module中的add_instruction()成员函数添加指令。MIGraphX中的指令相当于ONNX模型中的一个节点或者caffe模型中的一个层。指令由操作符(算子)和操作数组成。

视图

我们知道Pytorch中支持视图操作(view),Pytorch中一个tensor可以是另一个tensor的视图,视图tensor与原tensor 共享内存,视图可以避免不必要的内存拷贝,让操作更加高效。比如我们可以通过view()方法获取一个tensor的视 图:

t = torch.rand(4,4)
b = t.view(2,8)#创建视图
t.storage().data_ptr() == b.storage().data_ptr() #b和t共享内存,返回True
b[0][0] = 3.14
print(t[0][0]) # 3.14

与Pytorch一样,MIGraphX也支持视图,一个argument可以是另一个argument的视图,视图和原argument共享内存, MIGraphX中支持视图的操作有


broadcast

slice

transpose

reshape

下面表示一个4行6列的二维数组,该数组按照行主序的方式在内存中连续存储(与C语言中的数组一致),所以在列这个维度上步长为1,在行这个维度上的步长为6,假设该二维数组的数据类型为float类型,则该二维数组的shape可以表示为{migraphx::shape::float_type, {4,6}},这里没有显式指定每一维的步长,migraphx会自动计算出步长:{migraphx::shape::float_type, {4,6},{6,1}}。

□ □ □ □ □ □
□ □ □ □ □ □  
□ □ □ □ □ □
□ □ □ □ □ □

现在有一个切片操作(slice),该切片操作参数为:starts=[0,2],ends =[4,5],steps = [1, 1] ,切片操作的结果为原二维数组的一个视图,该视图与原数据共享内存,该视图如下所示。

切片左闭右开,实际上应该是[0,2]到[3,4]

  0 1 2 3 4 5
0 □ □ ■ ■ ■ □
1 □ □ ■ ■ ■ □  
2 □ □ ■ ■ ■ □
3 □ □ ■ ■ ■ □

具体实现的时候,视图包含一个数据指针以及该数据的shape,为了方便说明,将shape拆分为2个部分表示:每一 维的大小和步长,本示例中该视图的数据指针指向原数组第三个元素,该视图的shape可以表示为{migraphx::shape::float_type, {4,3},{6,1}},所以视图中的成员lens为[4,3],strides为[6,1],注意由于与原数据共享内 存,所以该视图的步长为[6,1]而不是[3,1]。

// 视图包含的成员
{
    float *data_ptr;
    std::vector<std::size_t> lens;
    std::vector<std::size_t> strieds;
}

视图中元素的访问

通过shape可以访问到正确的视图中的数据比如要访问该视图的第2行第1列的元素"🫣",该元素在视图中的二维索引index可以表示为[1,0],则在实际内存中的索引(相当于“😜”)为二维索引和步长的内积: index*strides=1 * 6 + 0 * 1 =6,“😜”是视图的data_ptr,则二维索引为[1,0]表示的数据在内存中对应的数据为data_ptr+6,所以可以通过二维索引与步长的内积得到实际的内存索引。

  0 1 2  3 4 5
0 □ □ 😜 ■ ■ □
1 □ □ 🫣 ■ ■ □  
2 □ □  ■ ■ ■ □
3 □ □  ■ ■ ■ □

MIGraphX中部分算子是不支持输入视图的,所以对于这些算子,如果输入的是一个视图,就需要通过contiguous操 作将内存变得连续。对于上面slice操作返回的视图,contiguous算子会创建一个新的内存空间,将转换后得到的内存连续的数据保存在新的内存空间中。contiguous算子的输出的shape可以表示为{migraphx::shape::float_type, {4,3},{3,1}},此时行步长是3而不是之前共享内存时的6了。

附录

目录
相关文章
|
4月前
|
人工智能 API 知识图谱
使用SiliconCloud尝试GraphRag——以《三国演义》为例(手把手教程,适合小白)
本文介绍了使用不同模型和平台体验GraphRAG的过程。首先通过OpenAI的GPT-4O Mini模型对沈从文的《边城》进行了分析,展示了如何安装GraphRAG并配置参数,最终实现了对文本的有效查询。随后,文章探讨了在国内环境下使用SiliconCloud作为替代方案的可能性,以《三国演义》为例,演示了使用SiliconCloud模型进行相同操作的步骤。此外,还讨论了使用本地模型如Ollama和LM Studio的可能性,尽管受限于硬件条件未能实际运行。最后,提出了混合使用在线对话模型API与本地或在线嵌入模型的方法,并列举了一些能够使GraphRAG流程跑通的大模型。
143 10
使用SiliconCloud尝试GraphRag——以《三国演义》为例(手把手教程,适合小白)
|
7月前
|
存储 机器学习/深度学习 人工智能
【LangChain系列】第八篇:文档问答简介及实践
【5月更文挑战第22天】本文探讨了如何使用大型语言模型(LLM)进行文档问答,通过结合LLM与外部数据源提高灵活性。 LangChain库被介绍为简化这一过程的工具,它涵盖了嵌入、向量存储和不同类型的检索问答链,如Stuff、Map-reduce、Refine和Map-rerank。文章通过示例展示了如何使用LLM从CSV文件中提取信息并以Markdown格式展示
311 2
|
7月前
|
存储 机器学习/深度学习 人工智能
【LangChain系列】第一篇:文档加载简介及实践
【5月更文挑战第14天】 LangChain提供80多种文档加载器,简化了从PDF、网站、YouTube视频和Notion等多来源加载与标准化数据的过程。这些加载器将不同格式的数据转化为标准文档对象,便于机器学习工作流程中的数据处理。文中介绍了非结构化、专有和结构化数据的加载示例,包括PDF、YouTube视频、网站和Notion数据库的加载方法。通过LangChain,用户能轻松集成和交互各类数据源,加速智能应用的开发。
385 1
|
7月前
编程笔记 01工具及参考资料
编程笔记 01工具及参考资料
|
7月前
|
机器学习/深度学习 PyTorch 算法框架/工具
还不会使用MIGraphX推理?试试这篇让你快速入门
使用MIGraphX进行推理一般包括下面几个步骤: 1. 创建模型 2. 低精度优化 3. 编译 4. 执行推理,并返回结果
197 2
|
7月前
|
机器学习/深度学习 存储 PyTorch
还没了解MIGraphX推理框架?试试这篇让你快速入门
MIGraphX是一款用于DCU上的深度学习推理引擎,它的目的是为了简化和优化端到端的模型部署流程,包括模型优化、代码生成和推理。MIGraphX能够处理多种来源的模型,如TensorFlow和Pytorch,并提供用户友好的编程界面和工具,使得用户可以集中精力在业务推理开发上,而不需要深入了解底层硬件细节。
226 0
|
运维 Kubernetes 监控
K8S学习-当我们部署应用的时候都发生了什么?(第一篇)
第一篇笔记定的主题是“调度-当我们部署应用的时候都发生了什么?”,先从大的框架上记录一下K8S的架构与原理;对于卷、网络、configmap等组件会放在第二篇。初学者级别的学习笔记,有问题的地方大佬们及时勘误。
31340 17
K8S学习-当我们部署应用的时候都发生了什么?(第一篇)
|
并行计算 算法 计算机视觉
【CUDA学习笔记】第十篇:基本计算机视觉操作【下】(附实践源码下载)(一)
【CUDA学习笔记】第十篇:基本计算机视觉操作【下】(附实践源码下载)(一)
143 0
|
并行计算 API 计算机视觉
【CUDA学习笔记】第十篇:基本计算机视觉操作【下】(附实践源码下载)(二)
【CUDA学习笔记】第十篇:基本计算机视觉操作【下】(附实践源码下载)(二)
128 0
|
存储 并行计算 API
【CUDA学习笔记】第九篇:基本计算机视觉操作【上】(附实践源码下载)(一)
【CUDA学习笔记】第九篇:基本计算机视觉操作【上】(附实践源码下载)(一)
136 0