2
DCU技术达人
新人贴
海光DCU MigraphX 推理实战: ResNet50 推理
2026-09-29 19:53:05
10
## 1. 环境搭建 安装MIGraphX之前,需要先安装dtk,有两种方式安装dtk: 使用dtk镜像(推荐),镜像中已经安装好dtk环境,dtk镜像下载地址:[光合开发者社区](https://sourcefind.cn/#/image/dcu/dtk?activeName=overview "光合开发者社区"),根据需要选择合适的镜像。 下载dtk安装包,dtk安装包下载地址:[https://cancon.hpccube.com:65024/1/main](https://cancon.hpccube.com:65024/1/main "https://cancon.hpccube.com:65024/1/main"),根据需要选择合适的版本,然后将下载好的安装包安装到/opt目录下,最后创建一个软连接/opt/dtk,使得该软连接指向dtk的安装目录,注意:一定要创建软连接/opt/dtk,否则MIGraphX无法正常使用。 例如,如果是ubuntu系统,下载DTK-23.10.1-Ubuntu20.04.1-x86\_64.tar.gz,并解压: ```shell tar -zxvf DTK-23.10.1-Ubuntu20.04.1-x86_64.tar.gz -C /opt ``` ![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "点击并拖拽以移动") 创建软连接: ```shell ln -s /opt/dtk-23.10.1/ /opt/dtk ``` ![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "点击并拖拽以移动") MIGraphX的安装包下载地址:[https://cancon.hpccube.com:65024/4/main/migraphx](https://cancon.hpccube.com:65024/4/main/migraphx "https://cancon.hpccube.com:65024/4/main/migraphx") ,选择合适的安装包下载,比如下载了DAS1.1中的MIGraphX4.3.0版本,可以通过如下命令安装: ```shell bash migraphx-4.3.0+das1.1.git0a2480f.abi0.dtk2404-cp38-cp38-linux_x86_64.run ``` ![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "点击并拖拽以移动") 安装时会出现两次询问,第一次询问为 ```plaintext 请输入安装路径(直接回车将安装到默认路径: /opt/dtk) ``` ![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "点击并拖拽以移动") 一般情况下,默认安装到/opt/dtk目录下即可。第二次询问为: ```plaintext 是否安装migraphx-diffusers?(安装需要环境pip能访问网络。默认不安装,直接回车将不进行安装) [y/n]: ``` ![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "点击并拖拽以移动") migraphx-diffusers是一款支持文生图任务的Python插件,如果需要使用MIGraphX执行文生图任务,则建议安装该插件。如果安装过程报错,可能原因是设备无网络,无法安装migraphx-diffusers库所需的依赖。 安装完成后,需要设置环境变量: ```shell source /opt/dtk/env.sh ``` ![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "点击并拖拽以移动") 如果需要在python中使用migraphx,还需要设置PYTHONPATH : ```shell export PYTHONPATH=/opt/dtk/lib:$PYTHONPATH ``` ![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "点击并拖拽以移动") ## 2. 模型转换 使用MIGraphX进行推理前需要将训练好的ResNet50模型转换为ONNX格式,本示例使用如下的ResNet50模型:[https://download.pytorch.org/models/resnet50-19c8e357.pth](https://download.pytorch.org/models/resnet50-19c8e357.pth "https://download.pytorch.org/models/resnet50-19c8e357.pth"),下载该模型后使用如下代码可以转换为ONNX格式: ```python # Pytorch模型文件 pathOfPytorchModel = "resnet50-19c8e357.pth" # 创建ResNet50模型 net = torchvision.models.resnet50(pretrained=False) # 定义输入 input = torch.randn(32,3,224,224) # 生成的ONNX模型的路径 pathOfONNX = "ResNet50.onnx" net.load_state_dict(torch.load(pathOfPytorchModel)) net.eval() # 导出ONNX模型 torch.onnx.export(net,input,pathOfONNX,input_names = ["input"]) ``` ![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "点击并拖拽以移动") 生成好ResNet50.onnx模型后就可以进行推理了。 ## 3. c++ API 推理 使用C++ API加载ONNX模型进行推理主要包含三个步骤: 1. 加载ONNX模型 2. 编译模型 3. 执行推理 主要步骤示例代码如下: ```cpp // 头文件 #include #include // 加载模型 migraphx::program net = migraphx::parse_onnx("path/to/your/onnx/model"); // 编译模型 migraphx::compile_options options; net.compile(migraphx::gpu::target{},options); // 加载数据 std::unordered_map inputData; ... // 执行推理 std::vector results = net.eval(inputData); ``` ![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "点击并拖拽以移动") 下面以ResNet50.onnx模型为例说明如何使用C++ API进行分类模型的推理: ```cpp #include #include #include int main(int argc, char *argv[]) { // 加载模型 migraphx::program net = migraphx::parse_onnx("ResNet50.onnx"); // 获取模型输入/输出节点信息 std::cout << "inputs:" << std::endl; std::unordered_map inputs = net.get_inputs(); for (auto i : inputs) { std::cout << i.first << ":" << i.second << std::endl; } std::cout << "outputs:" << std::endl; std::unordered_map outputs = net.get_outputs(); for (auto i : outputs) { std::cout << i.first << ":" << i.second << std::endl; } std::string inputName = inputs.begin()->first; migraphx::shape inputShape = inputs.begin()->second; int N = inputShape.lens()[0]; int C = inputShape.lens()[1]; int H = inputShape.lens()[2]; int W = inputShape.lens()[3]; // 编译模型 migraphx::compile_options options; options.device_id = 0; // 设置GPU设备,默认为0号设备 options.offload_copy = true; net.compile(migraphx::gpu::target{}, options); // 数据预处理并转换为NCHW格式 int batchSize = N; cv::Mat srcImage = cv::imread("Test.jpg"); std::vector srcImages; for (int i = 0; i < batchSize; ++i) { srcImages.push_back(srcImage); } cv::Mat inputBlob; cv::dnn::blobFromImages(srcImages, inputBlob, 0.0078125, cv::Size(W, H), cv::Scalar(127.5, 127.5, 127.5), false, false); // 创建输入数据 std::unordered_map inputData; inputData[inputName] = migraphx::argument{inputShape, inputBlob.data}; // 推理 std::vector results = net.eval(inputData); // 获取输出节点的属性 migraphx::argument result = results[0]; // 获取第一个输出节点的数据 migraphx::shape outputShape = result.get_shape(); // 输出节点的shape std::vector outputSize = outputShape.lens(); // 每一维大小,维度顺序为(N,C,H,W) int numberOfOutput = outputShape.elements(); // 输出节点元素的个数 float *resultData = (float *)result.data(); // 输出节点数据指针 // 打印推理结果 for (int i = 0; i < numberOfOutput; ++i) { std::cout << resultData[i] << ","; } std::cout << std::endl; return 0; } ``` ![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "点击并拖拽以移动") 1. 首先通过parse\_onnx()函数加载onnx模型,加载好模型之后,可以通过program的get\_inputs()和get\_outputs()函数获取模型的输入和输出节点信息,两个函数返回值类型都是std::unordered\_map类型,每个输入节点或者输出节点都有一个节点名和shape,由于ResNet50模型只有一个输入,所以这里可以通过inputs.begin()获取模型的输入。 2. 如果需要采用FP16模式进行推理,可以通过quantize\_fp16()函数实现,具体实现见4.3小节,MIGraphX同时也支持int8推理,具体实现见4.4小节。 3. 加载onnx模型之后,需要使用compile()方法编译模型,这里将模型编译为GPU模式,如果需要编译为CPU模式,需要使用migraphx::cpu::target{},注意:如果你的输入数据在host端,则在设置编译选项的时候,需要设置offload\_copy为true。 4. 编译好模型之后,需要输入数据,输入数据需要经过预处理并转换为NCHW的格式,这里使用了OpenCV的blobFromImage函数将图像转换为了NCHW格式。并通过构造一个std::unordered\_map类型的对象保存输入数据,模型的每个输入都会对应一个输入数据,输入数据使用argument保存。 5. 最后通过program的eval()方法执行推理计算,推理结果是一个std::vector< migraphx::argument >类型,由于offload\_copy参数设置为true,所以推理的结果是host端数据,然后我们就可以通过argument提供的方法访问推理结果了。
全部评论(0)
只看楼主
暂无数据
--
楼主
Level.2
0 帖子
楼主热帖
暂无数据