[runtime.cpp::parsePlan::314] Error Code 1: Serialization (Serialization assertion plan->header.magicTag == rt::kPLAN_MAGIC_TAG failed.)
这个错误和yolov8中因为元数据导致的情况不同
主要的原因是导出engine的TensorRT版本和推理的TensorRT版本不一致
提供onnx
要求cudnn是8x
TensorRT 8.6.1.6
#include<iostream>
#include<fstream>
#include<sstream>
#include"logging.h"
#include"NvInfer.h"
#include"NvOnnxParser.h"
#include"NvInferRuntime.h"
using namespace nvonnxparser;
using namespace nvinfer1;
void onnx2engine(const char* onnx_filename, const char* engine_filePath) {
// 创建日志记录器对象
sample::Logger logger;
// 通过 Logger 类创建 builder
IBuilder* builder = createInferBuilder(logger);
// 创建 network,kEXPLICIT_BATCH 代表显式 batch(推荐使用),即 tensor 中包含 batch 这个维度。
uint32_t flag = 1U << static_cast<uint32_t>(NetworkDefinitionCreationFlag::kEXPLICIT_BATCH);
INetworkDefinition* network = builder->createNetworkV2(flag);
// 创建 onnx 模型解析器
IParser* parser = createParser(*network, logger);
// 解析模型
parser->parseFromFile(onnx_filename, static_cast<uint32_t>(ILogger::Severity::kWARNING));
// 设置 config
IBuilderConfig* config = builder->createBuilderConfig();
// 设置工作空间大小
config->setMemoryPoolLimit(MemoryPoolType::kWORKSPACE, 16 * (1 << 20));
// 设置以半精度构建 engine,我们在 torch 模型中的数据是 32 位浮点数即 fp32,
// tensorrt 中可以直接将权重量化为 FP16,以提升速度,若要量化为 INT8,则需要设置数据校准。
// INT8 量化可以参照 YOLO 的代码。
// 这里不介绍模型量化的原理。
config->setFlag(BuilderFlag::kFP16);
// 创建 profile,设置 engine 序列化
IOptimizationProfile* profile = builder->createOptimizationProfile();
// 如果在导出 onnx 模型时,设置了动态 batch(可以看我上一篇博客),这里需要设置输入模型的维度范围。
// 最小维度
profile->setDimensions("onnx 导出时的输入名字,一定要一样", OptProfileSelector::kMIN, Dims4(1, 1, 256, 256));
// 最合适的维度
profile->setDimensions("onnx 导出时的输入名字,一定要一样", OptProfileSelector::kOPT, Dims4(1, 3, 1080, 1920));
// 最大维度,建议设置多 batch,后续如果要使用多 batch 推理,就不用重新导出 engine。
profile->setDimensions("onnx 导出时的输入名字,一定要一样", OptProfileSelector::kMAX, Dims4(8, 3, 1080, 1920));
// 设置 profile,并序列化构建 engine
config->addOptimizationProfile(profile);
IHostMemory* serializedModel = builder->buildSerializedNetwork(*network, *config);
std::ofstream p(engine_filePath, std::ios::binary);
p.write(reinterpret_cast<const char*>(serializedModel->data()), serializedModel->size());
// 最后别忘了清理内存空间
delete parser;
delete network;
delete config;
delete builder;
delete serializedModel;
}
int main(int argc, char** argv) {
if (argc!= 3) {
std::cout << "Usage: " << argv[0] << " <onnx_file_path> <engine_file_path>" << std::endl;
return -1;
}
const char* onnx_filename = argv[1];
const char* engine_filePath = argv[2];
onnx2engine(onnx_filename, engine_filePath);
return 0;
}