Triton Inference Server 测试指南:QA 模型仓库生成、镜像构建与 L0 测试全流程
Triton Inference Server 测试指南QA 模型仓库生成、镜像构建与 L0 测试全流程【免费下载链接】serverThe Triton Inference Server provides an optimized cloud and edge inferencing solution.项目地址: https://gitcode.com/gh_mirrors/server117/server本文是 Triton Inference Server下称 Tritonqa/测试体系的完整实战指南覆盖从生成 QA 模型仓库、构建 SDK 与 QA 镜像到进入容器逐项运行 L0 测试的端到端流程。读完本文你将能够独立搭建一套本地 QA 测试环境理解BACKENDS、ENSEMBLES、EXPECTED_NUM_TESTS等关键参数的作用并利用 docs/customization_guide/test.md 中描述的 sanity 测试对任意包括仅含部分后端的 Triton 构建做正确性验证。测试体系概览为什么需要手动运行 qa/ 测试按 docs/customization_guide/test.md 的说明当前 Triton 仓库尚未默认启用 CI 测试文档注明 CI 将在后续更新中启用。因此仓库在qa/目录下提供了一套可手动运行、覆盖面广的测试集。这些测试覆盖推理正确性L0_infer、批处理调度L0_batcher、序列批处理L0_sequence_batcher、HTTP/gRPC 协议L0_http、L0_grpc、指标L0_metrics、模型管理L0_model_management相关等数十个维度构成一套无需外部服务即可本地复现的回归验证手段。运行测试之前有一个前置条件必须先生成若干包含测试所需模型的模型仓库model repository。这些模型仓库由qa/common/下的生成脚本产出下文将详细介绍两种生成方式及其差异。生成 QA 模型仓库QA 模型仓库中包含用于验证 Triton 正确性的简单模型如addsub、identity、各种 batch/nobatch 组合、ensemble 模型等。仓库中提供了两个驱动原始的 shell 驱动脚本和功能更完善的 Python 封装。方式一Shell 驱动脚本在仓库根目录执行$ cd qa/common $ ./gen_qa_model_repository该脚本会一次性生成多个模型仓库输出到/tmp/version/qa_*目录下例如/tmp/24.12/qa_model_repository注意目录名中的version对应构建的容器版本号具体值由脚本内的版本映射决定。TensorRT 模型会针对 CUDA 视为 device 0 的 GPU 生成如果机器上有多个 GPU需要查看脚本内部文档以了解如何指定特定 GPU。从 qa/common/gen_qa_model_repository 的源码可以看到脚本默认通过NVIDIA_VISIBLE_DEVICES${NVIDIA_VISIBLE_DEVICES:all}读取 GPU 目标并支持TRITON_CONTAINER_VERSION、NVIDIA_UPSTREAM_VERSION、TRITON_SEMVER等版本变量以及CI_JOB_ID、RUNNER_ID等 CI 参数。方式二Python 驱动推荐与 shell 驱动并列qa/common/下提供了同功能的 Python 封装$ cd qa/common $ ./gen_qa_model_repository.py它最大的改进是支持按框架选择性生成修改某一个后端时无需重建整个语料库$ ./gen_qa_model_repository.py --onnx --pytorch该命令只运行 ONNX 与 PyTorch 两个阶段的生成。从 gen_qa_model_repository.py 的源码看四个阶段以固定顺序openvino - onnx - pytorch - tensorrt执行STAGE_ORDER无论命令行参数顺序如何且阶段之间从不并行——因为四个阶段会写入同一个模型仓库集合qa_model_repository会收到来自每个阶段的模型所以顺序是承重设计而非装饰。选择阶段的优先级为--all 各阶段 flag--openvino/--onnx/--pytorch/--tensorrt 环境变量 默认全部四个。Python 驱动的输出布局与 shell 驱动不同模型落在构建目录下的models/目录如build dir/models/qa_model_repository/...而不是/tmp/version/使用--output-dir指定最终拷贝目的地docker 引擎下结束时拷贝为output dir/models/enroot 引擎直接原地构建--output-dir不适用GPU 选择通过--nvidia-visible-devices接收容器工具包的取值默认all或指定设备索引/UUID而不是假设 device 0。源码中DEFAULT_NVIDIA_VISIBLE_DEVICES all注释明确解释all是请求当前存在的任意 GPU的文档化方式而0假设了某个节点未必存在的索引。此外Python 驱动还提供--list与--dry-run可以预览某组 flag 组合将要执行的内容而不真正启动多小时的 GPU 任务$ ./gen_qa_model_repository.py --all --list $ ./gen_qa_model_repository.py --tensorrt --dry-run更完整的 flag 集合、每个模型旁边生成的 manifest 以及归档说明参见 qa/common/README.md。参数一览每个环境变量都对应一个 flagPython 驱动读取的变量与 shell 驱动完全一致所以既有 CI 无需改动即可工作且每个变量都有对应 flag 可在单次调用中覆盖。下表摘自 qa/common/README.md 的参数对照flag变量默认值--frameworksTRITON_MODELS_FRAMEWORKS全部四个--upstream-versionNVIDIA_UPSTREAM_VERSION来自build.py的upstream_container_version--semverTRITON_SEMVER来自build.py的release_version--ubuntu-imageUBUNTU_IMAGEubuntu:22.04--pytorch-imagePYTORCH_IMAGEnvcr.io/nvidia/pytorch:version-py3--tensorrt-imageTENSORRT_IMAGEnvcr.io/nvidia/tensorrt:version-py3--onnx-versionONNX_VERSION1.22.0--onnx-opsetONNX_OPSET26--openvino-versionOPENVINO_VERSION2024.5.0--model-typeMODEL_TYPE未设置--runtime/--use-docker/--use-enrootTRITON_MODELS_USE_DOCKER/TRITON_MODELS_USE_ENROOT自动--nvidia-visible-devicesNVIDIA_VISIBLE_DEVICESall--docker-volumeDOCKER_VOLUMEvolume.gen_qa_model_repository.job id--build-dirTRITON_MDLS_BLD_DIRmount/job id--job-idCI_JOB_ID时间戳阶段选择也可以完全通过环境变量完成适合只设变量不拼命令行的 CI 任务TRITON_MODELS_FRAMEWORKSonnx,openvino ./gen_qa_model_repository.py TRITON_MODELS_FRAMEWORKSpytorch tensorrt ./gen_qa_model_repository.py TRITON_MODELS_FRAMEWORKSall ./gen_qa_model_repository.py取值以逗号或空白分隔、大小写不敏感同时接受config.pbtxt与 L0 测试套件中BACKENDS使用的后端别名——plan、libtorch、onnxruntime、trt、torch都会被解析到对应阶段因为为某后端请求模型与请求构建该模型的阶段是同一件事。未知名称会被拒绝而非静默跳过$ TRITON_MODELS_FRAMEWORKSonx ./gen_qa_model_repository.py error: --frameworks/TRITON_MODELS_FRAMEWORKS: unknown framework onx (did you mean onnx?); valid: openvino, onnx, pytorch, tensorrt, all这一校验是有意为之一个拼写错误如果安静地什么都没生成要到数小时后测试套件因缺少模型而失败时才会暴露届时已远离真正原因。容器引擎docker 与 enroot两个引擎在生成流程中并存。--runtime auto遵循既定优先级docker 可用则优先否则 enroot--runtime docker|enroot强制指定若未安装会直接报错而非静默回退。二者的差异如下来自 qa/common/README.md项dockerenroot存储挂载到/mnt的命名卷宿主机/tmpbind 挂载输出结束时docker cp到--output-dir直接写入/tmp/job id权限容器默认仅 apt 类阶段使用--rootGPU--runtimenvidia -e NVIDIA_VISIBLE_DEVICES-e NVIDIA_VISIBLE_DEVICESenroot 并非遗留设施——SLURM B200 任务正是通过TRITON_MODELS_USE_DOCKER0用它构建的。另一个细节GPU 只暴露给在 GPU 上生成模型的阶段PyTorch 与 TensorRTOpenVINO 与 ONNX 在 CPU 上构建若也传入 GPUnvidia runtime 会把nvidia-smi与驱动库挂进任何镜像导致探针探测到真实 GPU 并把其计算能力盖到不依赖 GPU 的产物上例如一个被标上compute_capability8.9的 ONNX 模型会读出它并不存在的可移植性约束。归档与上传进阶用法Python 驱动还支持把生成的模型树打包归档并上传到 Artifactory供下游测试任务按需拉取# 仅归档在宿主上执行生成结束后打包每个框架为一个 tar ./gen_qa_model_repository.py --all --archive # 归档并上传隐式启用 --archive需提供四项配置 ./gen_qa_model_repository.py --all --artifactory-upload--artifactory-upload需要的四项设置--artifactory-url/ARTIFACTORY_URL、--artifactory-token/ARTIFACTORY_TOKEN、--artifactory-path/ARTIFACTORY_PATH、--artifactory-properties/ARTIFACTORY_PROPERTIES会在第一个容器启动前检查完毕避免缺失 token 时浪费数小时后才发现无法交付。Token 只通过环境变量传给上传器绝不经过 argv驱动会记录其执行的每条命令argv 对宿主上任何进程可读。生成完成后每个模型目录旁的manifest.json会记录size_bytes与size_tierxs/s/m/l/xl 五档按目录字节数划分这些信息随上传以 Artifactory property 形式发布使消费方能在下载前通过 AQL 查询按体积过滤。构建 SDK 镜像QA 镜像的构建依赖 SDK 镜像包含客户端库、Model Analyzer、Perf Analyzer 与示例。构建tritonserver_sdk镜像的步骤来自 docs/customization_guide/test.md将client仓库的client branch分支检出到clientrepo/子目录将perf_analyzer仓库的perf analyzer branch分支检出到perfanalyzerrepo/子目录通常应把两个分支都设为与当前 server 分支一致在 server 仓库根目录执行$ cd server repo root $ git clone --single-branch --depth1 -b client branch client 仓库地址 clientrepo $ git clone --single-branch --depth1 -b perf analyzer branch perf_analyzer 仓库地址 perfanalyzerrepo $ docker build -t tritonserver_sdk -f Dockerfile.sdk .--single-branch --depth1保证只拉取指定分支的浅克隆加快速度。构建脚本 Dockerfile.sdk 位于仓库根目录。构建 QA 镜像接下来构建 Triton 的 QA 版 Docker 镜像该镜像包含 Triton 本体、QA 测试以及运行 QA 测试所需的全部依赖。步骤分为两步第一步先完成 Docker 镜像构建产出tritonserver_cibase与tritonserver两个镜像。其中tritonserver_cibase持有构建过程中生成的测试产物各测试二进制、libtriton_*.so后端库、triton*.whlPython 包等后续会被 QA 镜像复用。第二步构建真正的 QA 镜像$ docker build -t tritonserver_qa -f Dockerfile.QA .从 Dockerfile.QA 可以看到该镜像的组装逻辑以tritonserver为基底FROM ${BASE_IMAGE}从cibase阶段复制构建期测试产物bin/*、lib/*、各 L0 测试所需的模型与后端.so如L0_decoupled的repeat_int32/square_int32模型、L0_query的libtriton_query.so、L0_implicit_state的libtriton_implicit_state.so等从sdk阶段复制客户端库与工具并安装运行测试所需的系统包valgrind、nginx、openjdk-11-jdk、protobuf-compiler、swig等与 Python 依赖tritonclient[all]、grpcio、pillow、prettytable等。最终测试被安装到/opt/tritonserver/qa这也是容器内运行测试时的固定路径。运行 QA 测试启动 QA 容器运行 QA 镜像并将生成的 QA 模型仓库挂载进容器使测试能够访问它们$ docker run --gpusall -it --rm -v/tmp:/data/inferenceserver tritonserver_qa关键点说明--gpusall将宿主机全部 GPU 暴露给容器测试会通过nvidia-smi与 CUDA 设备探测 GPU-v /tmp:/data/inferenceserver将宿主机/tmp即 QA 模型仓库生成位置例如/tmp/version/qa_model_repository挂载为容器内/data/inferenceserver。L0 测试脚本正是从这个路径读取模型——例如 qa/L0_infer/test.sh 中的DATADIR${DATADIR:/data/inferenceserver/${REPO_VERSION}}随后从${DATADIR}/qa_model_repository/拷贝各后端模型构建测试用仓库容器内测试位于/opt/tritonserver/qa。运行单个测试进入容器后进入目标测试目录并执行其test.sh$ cd test directory $ bash -x ./test.shbash -x会打开 shell 的 xtrace逐条打印脚本执行的命令便于在失败时精确定位步骤。容器内 QA 测试的路径对应关系为/opt/tritonserver/qa/L0_*。以 qa/L0_infer/test.sh 为例其运行模式是读取环境变量确定后端集合与期望子测试数 → 从$DATADIR组装本地models/目录包括对 Python 后端动态改写 ONNXconfig.pbtxt、拷贝 ensemble 模型、追加instance_group等→ 启动 tritonserver → 运行infer_test.py客户端 → 调用check_test_results $TEST_RESULT_FILE $EXPECTED_NUM_TESTS校验实际执行的子测试数量。Sanity 测试与参数化很多测试要求使用包含所有后端与特性的完整 Triton 构建。但有三个sanity 测试做了参数化即使你只构建了部分后端的 Triton 也可以运行它们L0_infer、L0_batcher、L0_sequence_batcher。这三个测试支持以下环境变量控制行为BACKENDS控制测试哪些后端。各测试的默认值与允许值见其test.sh。例如 L0_infer/test.sh 默认BACKENDSonnx libtorch plan python python_dlpack openvinoL0_batcher/test.sh 默认BACKENDSonnx libtorch plan pythonL0_sequence_batcher/test.sh 默认BACKENDSonnx plan libtorch custom python。注意plan即 TensorRT 后端。ENSEMBLES是否测试 ensemble模型集成。置为0关闭置为1开启。开启时要求构建中包含identity后端——从源码看L0_infer的ENSEMBLES1分支会拷贝qa_ensemble_model_repository/qa_model_repository/下的模型与nop_*模型而这些 ensemble 依赖 identity 后端提供nop支持。EXPECTED_NUM_TESTS测试会对子测试总数量做校验。实际运行的子测试数取决于BACKENDS与ENSEMBLES的取值因此需要按你的测试配置调整该值。例如 L0_infer/test.sh 中EXPECTED_NUM_TESTS${EXPECTED_NUM_TESTS:47}启用共享内存场景时为34脚本会通过check_test_results将实际数量与期望值比对不一致即判定失败。例如只包含 TensorRT 后端的构建可以这样运行 L0_infer$ BACKENDSplan ENSEMBLES0 EXPECTED_NUM_TESTSexpected bash -x ./test.sh其中expected是仅 TensorRT、无 ensemble时预计运行的子测试数量。根据你实际测试的后端组合需要实验并确定正确的expected值——这通常通过先跑一次、观察失败信息中报告的实际子测试数来标定。测试结果的判定每个测试脚本的运行逻辑高度一致启动 server → 运行客户端脚本 → 比对子测试数量 → 检查测试结果文件 → 输出*** Test Passed ***或*** Test FAILED ***并以此作为进程退出码exit $RET。因此除了阅读日志还可以直接通过脚本退出码判断测试是否通过$ bash -x ./test.sh echo PASS || echo FAIL进阶把测试接入自动化虽然仓库当前未启用 CI但上述工具链已经为自动化铺好了路模型语料可归档分发--archive生成的按框架 tar 包与index.json配合 Artifactory 上的triton.size_tier等属性让 CI 任务可以在下载前按体积过滤例如跳过 12.78 GiB 的xl级 DLRM 模型每次运行的解析后命令行会被回显gen_qa_model_repository.py启动时打印invocation, with every value resolved把环境变量默认值、计算默认值与 shell 展开全部以字面值呈现token 以***打码可直接粘贴复现某次构建manifest 摘要可断言gen_qa_model_repository.py运行结束会写出tree/manifest-summary.jsonCI 可以基于其中的模型计数与字节总量做断言而不必 grep 日志文本。小结本文完整还原了 docs/customization_guide/test.md 描述的手动 QA 流程用qa/common/下的 shell 或 Python 驱动生成模型仓库后者支持按框架选择、--dry-run预览与更灵活的 GPU 指定构建tritonserver_sdk与tritonserver_qa镜像最后在容器内以bash -x ./test.sh运行L0_*测试并通过BACKENDS/ENSEMBLES/EXPECTED_NUM_TESTS三个环境变量让仅含部分后端的构建也能获得有效的回归验证。无论你是想验证自定义构建、调试某个后端的行为还是为 Triton 搭建内部回归流水线这套流程都提供了可靠、可复现的起点。更深入的内容——完整 flag 表、manifest 字段来源、模型体积分档tier与归档上传细节——可继续阅读 qa/common/README.md并对照 gen_qa_model_repository.py 与 Dockerfile.QA 的源码实现逐项印证。【免费下载链接】serverThe Triton Inference Server provides an optimized cloud and edge inferencing solution.项目地址: https://gitcode.com/gh_mirrors/server117/server创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考