尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Serialization assertion safeVersionRead == safeSerializationVersion failed:TensorRT engine 版本不匹配的 CM

Serialization assertion safeVersionRead == safeSerializationVersion failed:TensorRT engine 版本不匹配的 CM 1. 报错现场engine 反序列化时版本断言失败你拿到的报错长这样[TensorRT] ERROR: 1: [stdArchiveReader.cpp::StdArchiveReader::35] Error Code 1: Serialization (Serialization assertion safeVersionRead safeSerializationVersion failed. Version tag does not match. Note: Current Version: 0, Serialized Engine Version: 89)这句话翻译成人话就是你正在用的 TensorRT 运行时和当初生成这个 engine 文件时的 TensorRT不是同一个版本。safeVersionRead是当前运行时读到的版本号safeSerializationVersion是 engine 文件里写死的序列化版本号两者对不上TensorRT 直接拒绝反序列化程序在deserializeCudaEngine这一步就崩了。这个坑最常出现在 tensorrtx 这类工程里你在 A 机器上用 TensorRT 8.5 把 ONNX 转成.engine拷到 B 机器上跑 demoB 机器装的是 TensorRT 8.6 或者 10.x于是版本标签一个 0 一个 89断言失败。注意Current Version: 0不代表你装的是 0 版本它表示运行时没能匹配到任何已知的序列化版本属于「读不懂」的状态。面向在CMakeLists.txt里集成 TensorRT 的 C 工程这篇会给你三样东西一套能自动探测 TensorRT 版本并正确链接的 CMake 骨架、一段带版本校验的序列化/反序列化代码、以及用最小样例复现并验证版本对齐的完整步骤。适合正在用 tensorrtx 或自研推理 demo、被这个断言卡住的同学。2. 前置TaoToken 与 TensorRT 版本对齐的关系先说清楚一件事这个报错本身是本地 TensorRT 版本问题跟网络服务无关。但在实际工程里很多人会用 TaoToken 这类平台来跑模型对话、验证推理结果、或者用 Coding Plan 辅助写 CMake 和 C 代码所以顺手把环境说清楚。TaoToken 是一个聚合多家大模型能力的 API 平台官网在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。它能做什么统一接口调用不同模型适合做推理结果对照、写工程脚本、排查编译报错。适合谁需要多模型对比验证、或者想让 AI 帮忙读 CMake 报错和 C 编译日志的开发者。它和本篇的关系在于当你搞不清 TensorRT 版本对应关系、或者 CMake 链接报错看不懂时可以把报错贴给模型对话快速定位。模型对话入口在 https://taotoken.net/api API Keys 在 https://taotoken.net/api-keys 接入文档在 https://taotoken.net/doc 。如果你长期写推理工程、要反复调 CMake 和 CUDA 代码Coding Plan 会更顺手https://taotoken.net/coding-plan 。注意TaoToken 是模型 API 服务不替代本地 TensorRT 安装也不做 engine 转换。版本对齐必须在你的机器上完成。3. 可复制配置CMakeLists.txt 版本探测与链接骨架核心思路不要硬编码 TensorRT 路径让 CMake 去环境里探测真实版本并把版本号传给编译期宏这样运行时校验才有依据。3.1 探测 TensorRT 安装路径与版本TensorRT 的头文件里NvInferVersion.h定义了NV_TENSORRT_MAJOR/MINOR/PATCH我们可以让 CMake 读出来。cmake_minimum_required(VERSION 3.16) project(trt_version_check LANGUAGES CXX CUDA) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 允许外部传入 TensorRT 根目录默认走环境变量 if(NOT DEFINED TENSORRT_ROOT) if(DEFINED ENV{TENSORRT_ROOT}) set(TENSORRT_ROOT $ENV{TENSORRT_ROOT}) else() set(TENSORRT_ROOT /usr/local/TensorRT) endif() endif() message(STATUS TENSORRT_ROOT ${TENSORRT_ROOT}) find_path(TENSORRT_INCLUDE_DIR NAMES NvInfer.h NvInferVersion.h HINTS ${TENSORRT_ROOT}/include PATHS /usr/include /usr/local/include ) find_library(TENSORRT_LIBRARY NAMES nvinfer HINTS ${TENSORRT_ROOT}/lib ${TENSORRT_ROOT}/lib64 PATHS /usr/lib /usr/local/lib ) if(NOT TENSORRT_INCLUDE_DIR OR NOT TENSORRT_LIBRARY) message(FATAL_ERROR TensorRT not found. Set TENSORRT_ROOT correctly.) endif() message(STATUS TensorRT include: ${TENSORRT_INCLUDE_DIR}) message(STATUS TensorRT library: ${TENSORRT_LIBRARY})3.2 从版本头文件解析出版本号用 CMake 的file(STRINGS ...)把宏抠出来转成编译期定义。file(READ ${TENSORRT_INCLUDE_DIR}/NvInferVersion.h TRT_VERSION_HEADER) string(REGEX MATCH define NV_TENSORRT_MAJOR ([0-9]) _ ${TRT_VERSION_HEADER}) set(TRT_MAJOR ${CMAKE_MATCH_1}) string(REGEX MATCH define NV_TENSORRT_MINOR ([0-9]) _ ${TRT_VERSION_HEADER}) set(TRT_MINOR ${CMAKE_MATCH_1}) string(REGEX MATCH define NV_TENSORRT_PATCH ([0-9]) _ ${TRT_VERSION_HEADER}) set(TRT_PATCH ${CMAKE_MATCH_1}) message(STATUS Detected TensorRT version: ${TRT_MAJOR}.${TRT_MINOR}.${TRT_PATCH}) add_executable(trt_version_check main.cpp) target_include_directories(trt_version_check PRIVATE ${TENSORRT_INCLUDE_DIR}) target_link_libraries(trt_version_check PRIVATE ${TENSORRT_LIBRARY} cudart) target_compile_definitions(trt_version_check PRIVATE TRT_MAJOR${TRT_MAJOR} TRT_MINOR${TRT_MINOR} TRT_PATCH${TRT_PATCH} )这样编译出来的程序里TRT_MAJOR等宏就是当前环境真实链接的版本而不是你手写的常量。这一步是解决断言失败的关键链接的库和头文件必须来自同一套安装。3.3 关键参数对照表参数作用常见错误TENSORRT_ROOT指定 TensorRT 安装根目录指向了旧版本目录TENSORRT_INCLUDE_DIR头文件路径头文件是新版库是旧版TENSORRT_LIBRARYlibnvinfer.so路径链接到系统残留的旧 soTRT_MAJOR/MINOR/PATCH编译期版本宏手写常量导致与实际不符提示头文件和库必须来自同一次安装。混用是safeVersionRead断言失败的头号原因。4. 序列化/反序列化版本校验代码光靠 CMake 对齐还不够运行时也要主动校验把问题在反序列化之前暴露出来而不是等 TensorRT 抛断言。4.1 打印运行时版本并做前置检查#include NvInfer.h #include NvInferVersion.h #include iostream #include fstream #include vector using namespace nvinfer1; int main(int argc, char** argv) { if (argc 2) { std::cerr usage: argv[0] model.engine std::endl; return 1; } // 编译期版本来自 CMake 探测 std::cout Compiled against TensorRT TRT_MAJOR . TRT_MINOR . TRT_PATCH std::endl; // 运行时版本来自实际链接的库 std::cout Runtime TensorRT version: NV_TENSORRT_MAJOR . NV_TENSORRT_MINOR . NV_TENSORRT_PATCH std::endl; if (TRT_MAJOR ! NV_TENSORRT_MAJOR) { std::cerr [WARN] header/library major version mismatch! std::endl; } // 读取 engine 文件 std::ifstream file(argv[1], std::ios::binary); if (!file) { std::cerr cannot open engine file std::endl; return 1; } file.seekg(0, std::ios::end); size_t size file.tellg(); file.seekg(0, std::ios::beg); std::vectorchar blob(size); file.read(blob.data(), size); std::cout engine file size: size bytes std::endl; // 反序列化 IRuntime* runtime createInferRuntime(gLogger); ICudaEngine* engine runtime-deserializeCudaEngine(blob.data(), size); if (!engine) { std::cerr [FAIL] deserializeCudaEngine returned nullptr. Check TensorRT version alignment. std::endl; return 1; } std::cout [OK] engine deserialized, nbBindings engine-getNbBindings() std::endl; delete engine; delete runtime; return 0; }4.2 一个简单的 loggerclass Logger : public ILogger { public: void log(Severity severity, const char* msg) noexcept override { if (severity Severity::kWARNING) { std::cout [TRT] msg std::endl; } } }; static Logger gLogger;把gLogger定义在main之前即可。这样当断言失败时你能在日志里同时看到编译期版本和运行时版本一眼判断是不是版本错位。4.3 序列化侧也要记录版本如果你自己负责生成 engine建议在文件名或旁挂的.meta里写上生成时的版本避免拷来拷去搞混。std::string engineName model_trt std::to_string(NV_TENSORRT_MAJOR) _ std::to_string(NV_TENSORRT_MINOR) _ std::to_string(NV_TENSORRT_PATCH) .engine;命名带版本是成本最低的防呆手段。5. 最小样例复现与版本对齐验证5.1 复现步骤第一步确认当前环境版本dpkg -l | grep -i tensorrt ls -l /usr/lib/x86_64-linux-gnu/libnvinfer.so*第二步用上面的 CMake 骨架编译观察输出的Detected TensorRT version。第三步拿一个用不同版本生成的 engine去跑你会看到[TRT] Error Code 1: Serialization (Serialization assertion safeVersionRead safeSerializationVersion failed. Version tag does not match. Note: Current Version: 0, Serialized Engine Version: 89) [FAIL] deserializeCudaEngine returned nullptr.第四步用当前版本重新生成 engine再跑同一个程序输出变成[OK] engine deserialized, nbBindings55.2 版本对齐的三种做法做法操作适用场景统一运行时把 demo 机器的 TensorRT 升/降到与生成机一致生产部署最稳重新生成 engine在目标机器上用当前 TensorRT 重新转版本无法改动时容器隔离用固定版本镜像跑生成和推理多项目共存注意engine 文件不跨大版本兼容。TensorRT 8.x 生成的 engine 拿到 10.x 上基本必挂这不是配置问题是设计如此。5.3 验证版本是否真正对齐# 查看链接到的实际库 ldd ./trt_version_check | grep nvinfer # 查看库内版本字符串 strings /usr/lib/x86_64-linux-gnu/libnvinfer.so | grep -i TensorRT v如果ldd指向的 so 和你TENSORRT_ROOT里的不是同一个说明系统里有多个 TensorRTCMake 链接到了错误的那个。这时候要么清理旧版本要么在 CMake 里用绝对路径强制指定。6. 本篇常见错排查报错一Version tag does not match但版本号看起来一样。多半是头文件和库不同源。检查TENSORRT_INCLUDE_DIR和TENSORRT_LIBRARY是否来自同一目录用ldd确认实际加载的 so。报错二CMake 探测到的版本和nvcc/dpkg显示的不一致。说明环境里有多个 TensorRT。用find_library时加NO_DEFAULT_PATH只在你指定的TENSORRT_ROOT下找。报错三deserializeCudaEngine返回 nullptr 但没有明显日志。logger 的 severity 过滤太严把kWARNING以上都打出来。另外确认 engine 文件读取时用的是二进制模式std::ios::binary不能漏。报错四重新 cmake 后仍然报旧版本。构建目录有缓存。删掉build/重新cmake ..或者cmake --fresh。报错五tensorrtx 生成的 engine 在 demo 上失败。tensorrtx 的CMakeLists.txt里 TensorRT 路径是写死的改成用find_library探测或者把TENSORRT_ROOT指到 demo 机器实际安装的位置。排查时如果 CMake 报错看不懂可以把完整报错贴到模型对话里让它帮你定位https://taotoken.net/api 。接入方式看文档https://taotoken.net/doc Key 在 https://taotoken.net/api-keys 生成。长期写这类推理工程、要反复调 CMake 和 CUDA 的Coding Plan 更省事https://taotoken.net/coding-plan 。最后给你一个我常用的判断口诀engine 报版本断言先看 ldd 再看头文件两者同源再谈重新生成。绝大多数safeVersionRead safeSerializationVersion失败都死在「头文件一套、库另一套」上而不是 TensorRT 本身有 bug。
返回列表