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

简介: MIGraphX是一款用于DCU上的深度学习推理引擎,它的目的是为了简化和优化端到端的模型部署流程,包括模型优化、代码生成和推理。MIGraphX能够处理多种来源的模型,如TensorFlow和Pytorch,并提供用户友好的编程界面和工具,使得用户可以集中精力在业务推理开发上,而不需要深入了解底层硬件细节。

MIGraphX是一款用于DCU上的深度学习推理引擎,它的目的是为了简化和优化端到端的模型部署流程,包括模型优化、代码生成和推理。MIGraphX能够处理多种来源的模型,如TensorFlow和Pytorch,并提供用户友好的编程界面和工具,使得用户可以集中精力在业务推理开发上,而不需要深入了解底层硬件细节。

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

image.png

MIGraphX的架构分为三个主要层次:
•中间表示层:这一层将训练好的模型(例如ONNX格式)转换成MIGraphX的内部表示(IR)格式,即计算图。所有的模型优化和代码生成都是基于这个计算图完成的。
•编译优化层:在这一层,MIGraphX对中间表示进行各种优化,如常量折叠、内存复用和算子融合等,从而提高推理性能。
•计算引擎层:这一层包含底层计算库的接口,例如MIOpen和rocblas。MIGraphX的后端实现主要通过调用这些库来完成。
MIGraphX采用单级IR设计,简化编译优化过程。它支持各种模型,包括CNN、LSTM、Transformer等。 我们可以使用migraphx-driver onnx -l查看支持的onnx算子。
安装方法
MIGraphX可以通过镜像或安装包的方式进行安装。使用镜像是推荐的安装方法,用户可以从指定的下载地址获取合适的镜像。此外,也可以选择根据系统不同下载相应的安装包。安装过程中需要设置环境变量和路径,确保MIGraphX能够正常使用。具体如下:

  • 使用镜像(推荐) 下载地址,根据需要选择合适的镜像
    例如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_PATHexport 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(): 返回指向常量数据的指针。不同于 ArgumentLiteral 中的数据不可修改。

    target

    表示支持的硬件平台,如CPU或GPU。

    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模型中的一个层。指令由操作符(算子)和操作数组成。

    view

    视图(view)操作是一种重要的内存管理技术。它允许不同的张量(tensor)共享相同的数据存储,而不需要复制数据。这种方法既节省内存,又提高效率。
    假设你有一个4x4的随机张量t:

    t = torch.rand(4,4)
    

    你可以使用view()方法创建一个2x8的视图b:

    b = t.view(2, 8)
    

    在这个例子中,b是t的一个视图。如果你更改b中的任何元素,t中相应的元素也会改变。例如:

    b[0][0] = 3.14
    print(t[0][0])  # 输出将会是 3.14
    

    MIGraphX中的视图操作与PyTorch相似,但用于处理argument对象。你可以创建一个argument的视图,这个视图与原始`argument共享内存。支持的操作有broadcast、slice、transpose、reshape。
    考虑一个4行6列的数组,它按照行主序存储。如果你想对这个数组进行切片操作(比如取出中间的一部分),你可以创建一个视图,这个视图会指向原始数组的一个特定区域,而不复制任何数据。

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

    你可以创建一个视图来实现切片操作,该切片操作参数为:starts=[0,2],ends =[4,5],steps = [1, 1] ,切片操作的结果为原二维数组的一个视图,该视图与原数据共享内存,该视图如下所示。
    切片左闭右开,实际上应该是[0,2]到[3,4]

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

    原来的二维数据的shape用{migraphx::shape::float_type, {4,6},{6,1}}表示,通过切片变成了4×3的数值,但由于与原始数据共享内存,因此视图的步长仍然是[6,1],即新建的数据shape是{migraphx::shape::float_type, {4,3},{6,1}}

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

    当你使用PyTorch的view()方法创建了一个视图后,可以像访问普通张量一样访问视图中的元素。
    假设我们有一个4x4的张量A,并且创建了一个2x8的视图B。要访问B中的特定元素,你可以直接使用索引。

    import torch
    A = torch.rand(4, 4)
    B = A.view(2, 8)
    # 访问B中的第1行第2列的元素
    element = B[1][2]
    print("Accessed Element:", element)
    

    在这个例子中,当你通过索引[1][2]访问B时,你实际上访问的是A中对应位置的数据,因为它们共享内存。
    在MIGraphX中,访问视图元素的原理类似。
    在视图中访问元素时,通过形状可以正确访问数据。例如,访问视图中第2行第1列的元素"🫣",其二维索引为[1,0],在实际内存中的索引为索引与步长的内积,即1 6 + 0 1 = 6。因此,这个元素在内存中的位置为data_ptr + 6,“😜”是视图的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了。

    附录

  • https://rocm.docs.amd.com/projects/AMDMIGraphX/en/latest/
  • https://cancon.hpccube.com:65024/4/main/inferexamples
目录
相关文章
|
8天前
|
机器学习/深度学习 PyTorch 算法框架/工具
ChatGPT初体验——让他写代码,走起
ChatGPT初体验——让他写代码,走起
26 0
|
1月前
|
存储 机器学习/深度学习 人工智能
【LangChain系列】第一篇:文档加载简介及实践
【5月更文挑战第14天】 LangChain提供80多种文档加载器,简化了从PDF、网站、YouTube视频和Notion等多来源加载与标准化数据的过程。这些加载器将不同格式的数据转化为标准文档对象,便于机器学习工作流程中的数据处理。文中介绍了非结构化、专有和结构化数据的加载示例,包括PDF、YouTube视频、网站和Notion数据库的加载方法。通过LangChain,用户能轻松集成和交互各类数据源,加速智能应用的开发。
149 1
|
6月前
|
机器学习/深度学习 PyTorch 算法框架/工具
还没了解MIGraphX推理框架?试试这篇让你快速入门
MIGraphX是一款用于DCU上的深度学习推理引擎,旨在提供端到端的模型优化、代码生成和推理业务部署能力。它支持将TensorFlow、Pytorch等框架的训练模型转换成MIGraphX IR表示的计算图。MIGraphX 提供灵活、易用的编程接口和工具,让用户能够专注于推理业务开发和部署,而不必过多关注底层硬件细节。
108 0
|
1月前
编程笔记 01工具及参考资料
编程笔记 01工具及参考资料
|
1月前
|
机器学习/深度学习 存储 算法
【轻量化:实操】动手实现神经网络中的裁枝操作(附演示代码&yolo系列)
【轻量化:实操】动手实现神经网络中的裁枝操作(附演示代码&yolo系列)
113 1
|
1月前
|
机器学习/深度学习 PyTorch 算法框架/工具
还不会使用MIGraphX推理?试试这篇让你快速入门
使用MIGraphX进行推理一般包括下面几个步骤: 1. 创建模型 2. 低精度优化 3. 编译 4. 执行推理,并返回结果
127 2
|
运维 Kubernetes 监控
K8S学习-当我们部署应用的时候都发生了什么?(第一篇)
第一篇笔记定的主题是“调度-当我们部署应用的时候都发生了什么?”,先从大的框架上记录一下K8S的架构与原理;对于卷、网络、configmap等组件会放在第二篇。初学者级别的学习笔记,有问题的地方大佬们及时勘误。
31281 17
K8S学习-当我们部署应用的时候都发生了什么?(第一篇)
|
存储 并行计算 API
【CUDA学习笔记】第九篇:基本计算机视觉操作【上】(附实践源码下载)(一)
【CUDA学习笔记】第九篇:基本计算机视觉操作【上】(附实践源码下载)(一)
93 0
|
存储 并行计算 计算机视觉
【CUDA学习笔记】第九篇:基本计算机视觉操作【上】(附实践源码下载)(二)
【CUDA学习笔记】第九篇:基本计算机视觉操作【上】(附实践源码下载)(二)
95 0
|
算法 PyTorch 算法框架/工具
从零开始学Pytorch(十四)之优化算法进阶(一)
从零开始学Pytorch(十四)之优化算法进阶
从零开始学Pytorch(十四)之优化算法进阶(一)