☰
Paddle Serving C++ 服务化部署测试开发实战:基于 TIPC 的 Linux GPU/CPU 模型转换与部署全流程
2026/10/9 4:37:16 网站建设 项目流程
  • 人工智能
  • 深度学习
  • 计算机视觉
  • NLP
  • 语音

【免费下载链接】models

Officially maintained, supported by PaddlePaddle, including CV, NLP, Speech, Rec, TS, big models and so on.

项目地址:https://gitcode.com/gh_mirrors/mo/models
点击查看免费下载

导读

本文以 Paddle Serving 的 C++ 服务化部署为对象,讲解如何在飞桨训推一体全流程(TIPC)框架下,为任意飞桨模型开发「部署模型转换 + C++ 服务部署」的一键自动化测试。读者将掌握serving_infer_cpp.txt配置文件的字段语义、test_serving_infer_cpp.sh的解析执行原理,以及从数据准备、环境搭建、脚本组织到配置验证的完整开发与核验流程,可直接迁移到自己的模型仓库。

Paddle Serving 是飞桨官方推荐的服务化推理框架,长期目标是为人工智能落地的"最后一公里"提供专业、可靠且易用的在线服务。本文档主要关注 Linux GPU/CPU 环境下模型的C++ 服务化部署功能测试,具体测试点如下:

  • 模型转换:部署模型转换流程跑通(Paddle 静态图模型 → Serving 部署模型);
  • 模型部署:C++ 服务端部署与服务端/客户端交互流程跑通。

为了一键跑通上述所有功能,TIPC 提供了「训推一体全流程」功能自动化测试工具,它包含3 个脚本文件和 1 个配置文件:

文件作用是否需要修改
test_serving_infer_cpp.sh测试部署模型转换和 C++ 服务部署预测的脚本,会解析serving_infer_cpp.txt得到具体执行命令无需修改
prepare.sh准备测试所需的数据或预训练模型无需修改(按模型定制数据下载)
common_func.sh提供配置文件解析、状态检查等通用函数无需修改
serving_infer_cpp.txt配置文件,其内容会被test_serving_infer_cpp.sh解析为具体的执行命令字段按模型修改

在 mobilenetv3_prod/Step6/test_tipc 目录下可以看到这套工具的真实实现:test_serving_infer_cpp.sh、prepare.sh、common_func.sh三个脚本与configs/mobilenet_v3_small/serving_infer_cpp.txt配置文件,是本文讲解的最佳参照物。

命令与配置文件解析

客户端启动命令的拆解

Paddle Serving 的 C++ 服务客户端启动命令一般由 Python 程序编写,可以拆解为 2 个部分:

python run_script

例如对于通过 argparse 传参的场景:

  • python:替换为具体的 Python 解释器,如python3.7;
  • run_script:替换为实际的客户端脚本,如resnet50_client.py。

即python3.7 resnet50_client.py。TIPC 测试脚本正是按照"解释器 + 脚本路径"两个字段的组合方式来拼接客户端命令的。

配置文件与运行命令的映射

完整的serving_infer_cpp.txt配置文件共有 16 行(原文档描述为 13 行,仓库实际文件为 16 行,其中包含 2 行注释分隔行),包含 3 个方面的内容:

  • Serving 部署模型转换:第 4~9 行(trans_model及其 5 个转换参数);
  • Serving 启动部署服务:第 10~14 行(服务端启动参数);
  • Serving 启动客户端:第 15~16 行(客户端脚本与 prototxt 路径)。

具体内容见 serving_infer_cpp.txt,以 mobilenet_v3_small 为例的完整文件如下:

===========================serving_params=========================== model_name:mobilenet_v3_small python:python3.7 trans_model:-m paddle_serving_client.convert --dirname:./inference/mobilenet_v3_small_infer/ --model_filename:inference.pdmodel --params_filename:inference.pdiparams --serving_server:./deploy/serving_cpp/serving_server/ --serving_client:./deploy/serving_cpp/serving_client/ serving_dir:./deploy/serving_cpp --model:serving_server --op:GeneralClasOp --port:9997 --gpu_id:"0"|null cpp_client:serving_client.py proto_path:deploy/serving_cpp/preprocess/serving_client_conf.prototxt

配置文件中主要有以下 3 种类型的字段:

  • key:value形式:该行可以被解析为key:value格式,需要根据实际含义修改该行内容;
  • ======xxxxx=====形式:注释信息,无需修改;
  • ##形式:段落分隔符,没有实际意义,无需修改。

从 test_serving_infer_cpp.sh 的源码可以看到,脚本通过awk 'NR==1, NR==18{print}' $FILENAME读取配置文件的前 18 行,再按行索引依次解析(lines[1]~lines[15]对应上面的 16 行有效配置),因此配置文件的行顺序不可随意调整。

模型转换配置参数

在配置文件中,可以通过下面的方式配置模型转换所需的超参数,如 Paddle 模型路径、部署模型路径等。下表给出了常用配置及其需要修改的内容:

行号参考内容含义key 是否需要修改value 是否需要修改修改内容
2model_name:mobilenet_v3_small模型名字否是value 修改为自己的模型名字
3python:python3.7python 环境否是value 修改为自己的 python 环境
4trans_model:-m paddle_serving_client.convert模型转换模块入口否否使用内置转换模块,无需修改
5--dirname:./inference/mobilenet_v3_small_infer/Paddle inference 模型保存路径否是value 修改为自己 Inference 模型的路径
6--model_filename:inference.pdmodelpdmodel 文件名否是value 修改为 pdmodel 文件名
7--params_filename:inference.pdiparamspdiparams 文件名否是value 修改为 pdiparams 文件名
8--serving_server:./deploy/serving_cpp/serving_server/转换出的部署模型(服务端)目录否是value 修改为部署模型保存路径
9--serving_client:./deploy/serving_cpp/serving_client/转换出的服务模型(客户端)目录否是value 修改为服务模型保存路径

以模型转换命令为例,总共包含 5 个超参数,解析后拼接出的完整命令为:

python3.7 -m paddle_serving_client.convert --dirname=./inference/resnet50_infer/ --model_filename=inference.pdmodel --params_filename=inference.pdiparams --serving_server=./deploy/serving_cpp/serving_server/ --serving_client=./deploy/serving_cpp/serving_client/

其中:

  • 推理模型路径--dirname=./inference/resnet50_infer/,对应修改第 5 行;
  • pdmodel 文件名--model_filename=inference.pdmodel,对应修改第 6 行;
  • 其他参数以此类推(第 7、8、9 行)。

paddle_serving_client.convert是paddle_serving_clientwheel 包内置的转换函数,无需修改。转换完成后会在本地生成serving_server和serving_client两个文件夹,后续服务端部署主要使用serving_server中的模型。

C++ 服务端部署配置参数

C++ 服务的服务端使用命令行启动,解析后拼接出的命令形如:

python3.7 -m paddle_serving_server.serve --model ./deploy/serving_cpp/serving_server/ --op GeneralClasOp --port 9997 --gpu_id "0"

服务端启动配置参数如下:

行号参考内容含义key 是否需要修改value 是否需要修改修改内容
10serving_dir:./deploy/serving_cppserving 服务执行路径否是value 修改为实际路径
11--model:serving_server部署模型名称否是value 修改为实际部署模型名称
12--op:GeneralClasOp自定义 OP 名称否是value 修改为自定义模型的 OP 名称
13--port:9997端口号否是value 修改为实际使用的端口号
14--gpu_id:"0"\|null是否使用 GPU否否默认在 "0" 号 GPU 卡和 CPU 卡上运行,以\|分隔多卡

其中第 14 行的"0"|null是典型的 TIPC 多值字段:以|作为分隔符,"0"表示在 0 号 GPU 上启动服务端,null表示在 CPU 上启动服务端。test_serving_infer_cpp.sh中通过for gpu_id in ${gpu_value[*]}遍历该字段,为每个取值分别启动一次服务端 + 客户端测试,并将日志分别写入cpp_server_gpu.log/cpp_client_gpu.log或cpp_server_cpu.log/cpp_client_cpu.log。

客户端配置参数

C++ 服务的客户端采用 Python 语言编写,解析后拼接出的命令为:

python3.7 serving_client.py

客户端配置参数如下:

行号参考内容含义key 是否需要修改value 是否需要修改修改内容
15cpp_client:serving_client.py客户端服务执行路径否是value 修改为实际路径
16proto_path:deploy/serving_cpp/preprocess/serving_client_conf.prototxt准备好的 prototxt 路径否是value 修改为实际的 prototxt 文件路径

proto_path指向的serving_client_conf.prototxt是客户端与服务端通信的协议描述文件。由于客户端输入的是原始图像,可能与推理时需要的输入数据类型不同,建议将输入数据类型统一修改成 string 类型。仓库中的示例文件 serving_client_conf.prototxt 内容如下:

feed_var { name: "input" alias_name: "input" is_lod_tensor: false feed_type: 20 shape: 1 } fetch_var { name: "softmax_1.tmp_0" alias_name: "softmax_1.tmp_0" is_lod_tensor: false fetch_type: 1 shape: 1000 }

其中feed_type: 20即表示 string 类型的输入数据,shape: 1表示单样本输入。TIPC 测试时会在模型转换完成后执行cp ${proto_path} ${serving_client_value}(见test_serving_infer_cpp.sh第 59 行),用该文件覆盖自动生成的serving_client/serving_client_conf.prototxt,以保证客户端发送 base64 图像数据时协议一致。

C++ 服务化部署功能测试开发

服务化部署功能测试开发主要分为以下 6 个步骤:

  1. 准备待测试的命令;
  2. 准备数据与环境;
  3. 准备开发所需脚本;
  4. 填写配置文件;
  5. 验证配置正确性;
  6. 撰写说明文档。

其中设置了 2 个核验点:启动服务端成功与启动客户端成功。下面详细介绍开发过程。

准备待测试的命令

【基本内容】

准备模型转换、模型推理的命令,后续会将这些命令按照上文第 2 节所述内容,映射到配置文件中。

【实战】

MobileNetV3 的 Serving 模型转换、服务部署运行命令如下所示:

# 模型转换 python3.7 -m paddle_serving_client.convert \ --dirname=./inference/mobilenet_v3_small_infer/ \ --model_filename=inference.pdmodel \ --params_filename=inference.pdiparams \ --serving_server=./deploy/serving_cpp/serving_server/ \ --serving_client=./deploy/serving_cpp/serving_client/ # 服务端部署 python3.7 -m paddle_serving_server.serve --model ./deploy/serving_cpp/serving_server/ --op GeneralClasOp --port 9997 --gpu_id "0" # 客户端访问 python3.7 serving_client.py

这三条命令分别对应配置文件中的模型转换段(第 4~9 行)、服务端启动段(第 10~14 行)和客户端启动段(第 15~16 行)。mobilenet_v3_small 的完整参考配置见 serving_infer_cpp.txt。

准备数据与环境

【基本内容】

  1. 数据集:为方便快速验证训练/评估/推理过程,需要准备一个小数据集(训练集和验证集各 8~16 张图像即可,压缩后数据大小建议在20M以内),放在lite_data文件夹下。相关文档可以参考论文复现赛指南 3.2 章节。

  2. 环境:安装好 PaddlePaddle 和 PaddleServing 即可进行服务化部署测试开发。项目仅支持 Python3.6/3.7/3.8/3.9,接下来所有与 Python/Pip 相关的操作都需要选择正确的 Python 版本。

为了将模型预处理放在 C++ 端,需要自行开发自定义 op 并重新编译 PaddleServing,参考如下步骤将自定义 op 放在 Serving repo 目录下:

cp deploy/serving_cpp/preprocess/general_clas_op.* {Serving_repo_path}/core/general-server/op cp deploy/serving_cpp/preprocess/preprocess_op.* {Serving_repo_path}/core/predictor/tools/pp_shitu_tools

仓库中这两组文件的真实实现位于 deploy/serving_cpp/preprocess 目录:

  • general_clas_op.cpp / general_clas_op.h:自定义 OP,继承OpWithChannel<GeneralBlob>,在其inference()方法中完成 base64 解码、BGR2RGB 转换、Resize(短边 256)、CenterCrop(224×224)、Normalize(mean 为[0.485, 0.456, 0.406],scale 为1/0.229, 1/0.224, 1/0.225)、Permute 转 CHW,再调用InferManager::instance().infer()执行推理;
  • preprocess_op.cpp / preprocess_op.h:复用的工具类函数(ResizeImg、Normalize、Permute、CenterCropImg等)。

上述预处理参数与训练时完全一致,这正是保证服务化部署结果与 Paddle Inference 推理结果一致的关键。

完成代码开发后,参考 Serving 编译文档重新编译 Serving,并设置SERVING_BIN环境变量。仓库提供了针对registry.baidubce.com/paddlepaddle/paddle:latest-dev-cuda10.1-cudnn7-gcc82镜像的一键编译脚本 build_server.sh,其中完成了 Go 依赖安装、OpenCV 库下载、Serving 源码 clone、自定义 OP 拷贝(L49-L50处替换自定义 OP 的文件名)以及cmake + make编译流程,使用其他镜像需手动修改 CUDA 和 TensorRT 相关 path。

【注意事项】

为方便管理,建议在上传至 github 前,首先将lite_data文件夹压缩为 tar 包,直接上传 tar 包即可,在测试训练评估与推理过程时,可以首先对数据进行解压。

  • 压缩命令:tar -zcf lite_data.tar lite_data
  • 解压命令:tar -xf lite_data.tar

准备开发所需脚本

【基本内容】

在 repo 中新建test_tipc目录,将文件 common_func.sh、prepare.sh 和 test_serving_infer_cpp.sh 分别拷贝到test_tipc目录中。

【注意事项】

上述 3 个脚本文件无需改动,在实际使用时,直接修改配置文件即可。

从源码看这三个脚本的职责分工:

  • common_func.sh 提供func_parser_key(以:分割取 key)、func_parser_value(以:分割取 value)、func_set_params(拼接key=value,null或空值返回空串)和status_check(根据退出码输出Run successfully with command - ...或Run failed with command - ...);
  • prepare.sh 的serving_infer分支负责解压lite_data.tar、下载并解压mobilenet_v3_small_infer.tar到./inference目录,同时执行unset https_proxy/unset http_proxy避免代理影响访问;
  • test_serving_infer_cpp.sh 负责解析配置并依次执行「模型转换 → 服务端启动 → 客户端访问」三个阶段,每个阶段均通过status_check记录成功/失败状态,并将日志写入test_tipc/output/${model_name}/${MODE}目录。

填写配置文件

【基本内容】

在 repo 的test_tipc/目录中新建configs/model_name,将文件 serving_infer_cpp.txt 拷贝到该目录中,其中model_name需要修改为您自己的模型名称。

【实战】

配置文件的含义解析可以参考上文「配置文件与运行命令的映射」部分。mobilenet_v3_small 的测试开发配置文件可以参考 serving_infer_cpp.txt,需要修改的核心字段汇总如下:

  • 第 2 行model_name:改为自己的模型名(同时决定日志目录名);
  • 第 3 行python:改为实际使用的 Python 解释器;
  • 第 5~9 行:分别改为自己的 inference 模型目录、pdmodel文件名、pdiparams文件名、serving_server/serving_client输出目录;
  • 第 10~13 行:改为实际的 serving 执行路径、部署模型名、自定义 OP 名、端口号;
  • 第 15~16 行:改为实际的客户端脚本路径与 prototxt 路径。

验证配置正确性

【基本内容】

基于修改完的配置,运行:

bash test_tipc/prepare.sh ${your_params_file} serving_infer bash test_tipc/test_serving_infer_cpp.sh ${your_params_file} serving_infer

其中第一个参数${your_params_file}为配置文件的路径,第二个参数serving_infer为测试模式,prepare.sh会据此进入serving_infer分支完成数据与模型准备。

【注意事项】

如果运行失败,会输出具体的报错命令,可以根据输出的报错命令排查配置文件的问题并修改,示例报错如下所示:

Run failed with command - python3.7 serving_client.py > ../../log/mobilenet_v3_small/serving_infer/server_infer_batchsize_1.log 2>&1 !

【实战】

以 mobilenet_v3_small 的Linux GPU/CPU 服务化部署测试为例,命令如下所示:

bash test_tipc/prepare.sh test_tipc/configs/mobilenet_v3_small/serving_infer_cpp.txt serving_infer
bash test_tipc/test_serving_infer_cpp.sh test_tipc/configs/mobilenet_v3_small/serving_infer_cpp.txt serving_infer

输出结果如下,表示命令运行成功:

Run successfully with command - python3.7 serving_client.py > ../../log/mobilenet_v3_small/serving_infer/server_infer_batchsize_1.log 2>&1 !

测试通过时,在test_tipc/output/mobilenet_v3_small/serving_infer/目录下会生成cpp_server_gpu.log、cpp_client_gpu.log(GPU 模式)以及cpp_server_cpu.log、cpp_client_cpu.log(CPU 模式)等日志文件,可用于进一步核对服务端启动与客户端预测的输出。

从 test_serving_infer_cpp.sh 源码可以确认完整执行链路:

  1. 模型转换(第 48~64 行):拼接python3.7 -m paddle_serving_client.convert ...命令并执行,随后cp ${proto_path} ${serving_client_value}用自定义 prototxt 覆盖客户端配置,再cd ${serving_dir_value}进入部署目录,最后取消代理设置;
  2. 启动服务端(第 66~88 行):遍历gpu_id字段,对 GPU/CPU 分别以python -m paddle_serving_server.serve --model serving_server --op GeneralClasOp --port 9997 [--gpu_id "0"]形式启动,日志重定向到cpp_server_*.log,status_check记录状态后sleep 5s等待服务就绪;
  3. 启动客户端(第 76~94 行):执行python ${cpp_client_value} > cpp_client_*.log 2>&1并检查状态,结束后ps ux | grep -i ${port_value} | awk '{print $2}' | xargs kill -s 9清理占用端口 9997 的服务进程,避免影响后续测试轮次。

客户端脚本 serving_client.py 展示了完整的数据处理逻辑:通过cv2_to_base64将图像字节编码为 base64 字符串,preprocess返回{"input": image}作为 feed 字典、["softmax_1.tmp_0"]作为 fetch 列表(key 与serving_client_conf.prototxt中feed_var/fetch_var的 name 字段一一对应),postprocess从fetch_map["softmax_1.tmp_0"]中取出概率向量,取最大值得到class_id与prob并返回。当客户端成功访问服务端时,会输出形如{'class_id': 8, 'prob': 0.909...}的预测结果(见 serving_client_result.png 运行截图),与基于 Paddle Inference 的推理结果一致。

【核验】

基于修改后的配置文件,测试通过,全部命令成功。

撰写说明文档

【基本内容】

撰写 TIPC 功能总览和测试流程说明文档,分别为:

  1. TIPC 功能总览文档:test_tipc/README.md;
  2. C++ 服务化部署测试说明文档:test_tipc/docs/test_serving_infer_cpp.md。

2 个文档模板可以直接拷贝到自己的 repo 中,根据自己的模型进行修改。功能总览文档可参考 mobilenetv3_prod/Step6/test_tipc/README.md,其中以表格形式汇总了各功能的打通情况(基础训练预测、更多训练方式、更多部署方式、Slim 训练部署、更多训练环境),并在「开始测试」一节按功能列出对应的测试文档入口。

【实战】

mobilenet_v3_small 中test_tipc目录结构如下所示(tutorials/mobilenetv3_prod/Step6/test_tipc 为仓库中的真实示例):

test_tipc |--configs # 配置目录 | |--model_name # 您的模型名称 | |--serving_infer_cpp.txt # C++ 服务化部署测试配置文件 |--docs # 文档目录 | |--test_serving_infer_cpp.md # C++ 服务化部署测试说明文档 |----README.md # TIPC说明文档 |----test_serving_infer_cpp.sh # C++ 服务化部署解析脚本,无需改动 |----common_func.sh # TIPC基础训练推理测试常用函数,无需改动

【核验】

基于test_serving_infer_cpp.md文档,跑通C++服务化部署功能测试流程。

服务化部署全链路可视化

为了直观理解"测试开发"所覆盖的部署目标,可以参考 Paddle Serving C++ 服务化部署的真实运行效果。当服务端启动成功时,终端会输出推理引擎初始化(插入PADDLE_INFER标签的推理引擎工厂)与 IR 分析优化流程日志(ir_graph_build_pass、ir_analysis_pass、memory_optimize_pass、ir_graph_to_program_pass等):

当客户端成功访问服务端后,会输出模型预测的分类结果:

这两张运行截图是核验点「启动服务端」「启动客户端」的直观判据:客户端输出与基于 Paddle Inference 的推理结果一致,即表明服务化部署测试整体跑通。

FAQ

如果访问不成功,可能是设置了代理影响导致的,可以用下面命令取消代理设置:

unset http_proxy unset https_proxy

需要注意的是,这条处理同样内置于测试链路中:prepare.sh的serving_infer分支和test_serving_infer_cpp.sh的模型转换阶段都会执行unset https_proxy/unset http_proxy,以保证数据下载与服务访问不受代理干扰。

小结

本文完整梳理了基于 TIPC 的 Linux GPU/CPU C++ 服务化部署测试开发流程:从命令准备、数据与环境准备、脚本组织、配置文件填写,到一键验证与文档撰写,并深入剖析了 serving_infer_cpp.txt 的字段语义与 test_serving_infer_cpp.sh 的执行原理。开发者只需将待测模型的转换命令与部署命令映射到配置文件中,即可复用这套"无需改动脚本、只改配置"的自动化测试方案,将任何飞桨模型的 C++ 服务化部署能力纳入一键可验证的工程化体系。

  • 人工智能
  • 深度学习
  • 计算机视觉
  • NLP
  • 语音

【免费下载链接】models

Officially maintained, supported by PaddlePaddle, including CV, NLP, Speech, Rec, TS, big models and so on.

项目地址:https://gitcode.com/gh_mirrors/mo/models
点击查看免费下载

相关推荐

上一篇:时序数据异常检测完全指南:10个高效识别方案解析
下一篇:终极指南:如何使用Dangerzone安全处理PDF、Office文档和图像

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询