NVIDIA TensorRT一个成熟的数据中心推理库,已迅速成为 NVIDIA GeForce RTX 和 NVIDIA RTX GPU 的理想推理后端。现在,部署 TensorRT 借助预构建的 TensorRT 引擎,应用变得更加简单。
新发布的重量去除 TensorRT 10.0 引擎提供了一种独特的解决方案,通过将其缩小到仅执行代码来最大限度地减少引擎出货量,从而实现 > 95%的引擎尺寸压缩。
在本文中,我们将讨论如何构建轻量级引擎,以及如何使用 TensorRT 40MB 精简运行时直接在最终用户设备上对其进行改装。
什么是轻量级引擎?
TensorRT 10.0 中引入的权重剥离引擎包含无权重的执行代码 (CUDA 内核).在构建阶段启用权重剥离后,引擎的体积比传统引擎小 95%以上,并且仅保留必要的权重以优化性能。
这些引擎支持 ONNX 模型和其他网络定义,提供与 refittable 引擎类似的优势。在反序列化期间,可以直接在最终用户设备上使用模型中的原始权重对其进行 refit,从而将延迟降至最低,同时保持不影响 inference 性能。
为什么要进行重量去除?
传统上,TensorRT 引擎包含网络的所有权重,从而在特定于硬件的引擎之间产生冗余权重。除非直接在最终用户设备上构建引擎,否则这就需要为整个安装基础提供重磅的预构建引擎。
假设一个场景是,工作站 AI 应用通过 M 个独立的 GPU SKU,创建 P 个引擎用于各个优化配置文件的每个 N 个深度学习模型。这会导致最终应用二进制文件中的大量权重重复(M × P),可以通过使用权重 stripped 的引擎来避免。
对于卷积神经网络(CNN)和大型语言模型(LLM)用例,Weight-stripped 引擎可实现超过 95% 的引擎大小压缩,从而在不增加应用程序大小的情况下打包更多的人工智能功能。这些引擎在 TensorRT 小更新之间版本兼容,并且在使用 kVERSION_COMPATIBLE 标志构建时可以使用约 40 MB 的 lean runtime。
NVIDIA TensorRT Cloud,目前精选合作伙伴抢先体验还提供在各种 NVIDIA GPU 上构建轻量级引擎的选项。即将支持构建和改装轻量级 NVIDIA TensorRT-LLM 引擎。
构建轻量级引擎
在本地构建权重受限的引擎时,TensorRT 构建器仍然需要模型权重来做出优化决策,从而确保与普通或有权重的引擎相比,稍后改装时的性能保持一致。
在构建过程中使用真实权重使 TensorRT 能够通过不断折叠静态节点和引入融合优化来优化计算,例如,在引擎构建过程中 GELU 文字未标记为可改装时,将其直接嵌入到单个 CUDA 内核中。
TensorRT Cloud 还有助于从 ONNX 模型中创建权重受限的引擎。
有关更多信息,请参阅开始使用稍后的部分。
部署权重受限的引擎
如果您的应用附带权重剥离的引擎,您可以在最终用户设备上使用 ONNX 文件中的权重,在数秒内轻松地对其进行重装。在序列化后,重装的引擎可以消除重复性的重装成本,同时保持 TensorRT 所知的快速反序列化效率。
您可以通过提供精简的运行时(~40 MB in TensorRT 10.0)来使用 refit 功能,而无需整个 TensorRT 构建器。这样改装的权重剥离引擎保留了版本前向兼容性(VFC)和硬件前向兼容性(HFC)的优势,使其能够在下一代 GPUs 上运行,而无需应用程序更新。
案例研究
我们使用 SDXL 实现了 99%以上的压缩率,demoDiffusion在 NVIDIA GeForce RTX 4090 GPU 上运行 (表 1)。
SDXL fp16 | Full engine size (MB) | Weight-stripped engine size (MB) |
clip | 237.51 | 4.37 |
clip2 | 1329.40 | 8.28 |
unet | 6493.25 | 58.19 |
虽然我们即将支持权重受限的 TensorRT-LLM 引擎,但以下是基于 NVIDIA GeForce RTX 4090 GPU 内部构建的一些测量结果,在多个 LLM 上实现了 99%以上的压缩 (表 2)。
Model | Full engine size (MB) | Weight-stripped engine size (MB) |
chatglm-6b int4 | 3831.09 | 4.50 |
chatglm-6b int8 | 6470.10 | 34.12 |
gemma2.5b int4 | 2987.81 | 6.62 |
gemma2.5b int8 | 3905.64 | 26.03 |
gemma7b int4 | 6826.14 | 7.86 |
gemma7b int8 | 10409.58 | 54.07 |
llama2-7b fp16 | 12856.44 | 4.04 |
llama2-7b int4 | 3691.12 | 5.41 |
llama2-7b int8 | 6683.72 | 41.54 |
mistral fp16 | 13831.44 | 4.06 |
mistral int4 | 3954.45 | 8.12 |
mistral int8 | 7178.73 | 41.91 |
phi2 fp16 | 5304.53 | 4.04 |
即使在NVIDIA H100等数据中心GPU上,您也可以在 TensorRT LLM Llama 模型上看到类似的压缩(表3)。
Model | Full engine size (MB) | Weight-stripped engine size (MB) |
llama-7b fp16 + WoQ int8 | 6704.55 | 28.69 |
llama2-70b fp8 + TP=2 | 66341.72 | 60.61 |
开始使用
在 TensorRT 10.0 中,一个新的标志 kREFIT_IDENTICAL
优化了 builder,以便在引擎使用 identical 权重进行 refitted 时发挥作用。当与 kSTRIP_PLAN
标志一起使用,因为在 build-time 和 refit-time 期间使用所有 identical 权重,可以确保实现最大限度的性能,从而最大限度地减小引擎尺寸。
新的序列化标志SerializationFlag::kEXCLUDE_WEIGHTS
此外,在 refit 过程中进行设置时,它还会将 refitted weight-stripped 引擎永久保存到磁盘中,从而避免在未来应用启动期间产生 recurring refit 成本。如果不设置,它支持使用 refit API 使用新的权重进行 continuous refitting。
以下是完整重量减轻和改装工作流程的说明:
- 构建轻量级引擎。
- 从 INetworkDefinition 中改装权重受限的引擎。
- 通过 ONNX 解析器改装权重受限引擎。
- 序列化为全权重引擎。
构建轻量化引擎
设置相应的构建器标志以启用权重限制构建。
config->setFlag(BuilderFlag::kSTRIP_PLAN);
config->setFlag(BuilderFlag::kREFIT_IDENTICAL);
builder->buildSerializedNetwork(*network, *config);
config.flags |= 1 << int(trt.BuilderFlag.STRIP_PLAN)
config.flags |= 1 << int(trt.BuilderFlag.REFIT_IDENTICAL)
builder.build_serialized_network(network, config)
构建引擎后,保存引擎计划文件,并通过应用安装程序分发。
改装轻量级引擎
根据指定网络的方式,TensorRTINetworkDefinition
API 或 ONNX 运行时 (ORT),请参阅相关的改装说明。
改装 INetworkDefinition 中的权重受限引擎
从引擎创建 refitter。
auto refitter = std::unique_ptr<nvinfer1::IRefitter>(
nvinfer1::createInferRefitter(*engine, logger));
refitter = trt.Refitter(engine, TRT_LOGGER)
在客户端上,首次启动网络时,更新引擎中的所有权重。在此处,使用getAllWeights
因为引擎计划中的所有权重都已删除。
int32_t const nbWts = refitter->getAllWeights(0, nullptr);
std::vector<char const*> allWtsNames(nbWts);
refitter->getAllWeights(nbWts, allWtsNames.data());
all_weights_names = refitter.get_all_weights()
逐一更新权重。
for (int32_t i = 0; i < nbWts; ++i)
refitter->setNamedWeights(allWtsNames[i], Weights{...});
for name in all_weights_names:
refitter.set_named_weights(name, trt.Weights(...))
通过 ONNX 解析器改装权重受限引擎
从引擎创建 refitter。
auto refitter = std::unique_ptr<nvinfer1::IRefitter>(
nvinfer1::createInferRefitter(*engine, logger));
refitter = trt.Refitter(engine, TRT_LOGGER)
创建 Refit 解析器。
auto parser_refitter = std::unique_ptr<nvonnxparser::IParserRefitter>(
nvonnxparser::createParserRefitter(*refitter, logger));
parser_refitter = trt.OnnxParserRefitter(refitter, TRT_LOGGER)
根据原始 ONNX 文件改装引擎。
if (parser_refitter->refitFromFile(onnx_model_path.c_str())) {
assert(refitter->refitCudaEngine());
}
parser_refitter.refit_from_file(onnx_model_path)
refitter.refit_cuda_engine()
序列化为全权重引擎
保存完整的引擎平面图文件。
auto serializationConfig = std::unique_ptr<ISerializationConfig>(engine->createSerializationConfig());
auto serializationFlag = serializationConfig->getFlags();
serializationFlag &= ~(1<< static_cast<uint32_t>(SerializationFlag::kEXCLUDE_WEIGHTS));
serializationConfig->setFlags(serializationFlag);
auto hostMemory = std::unique_ptr<nvinfer1::IHostMemory>(engine->serializeWithConfig(*serializationConfig));
serialization_config = engine.create_serialization_config()
serialization_config.flags &= ~(1 << int(trt.SerializationFlag.EXCLUDE_WEIGHTS))
binary = engine.serialize_with_config(serialization_config)
应用程序现在可以使用新的完整引擎计划文件进行未来推理。
限制
在 TensorRT 10.0 中,weight-stripped 功能仅限于使用相同的 build-time 权重进行 refitting,以确保正确的功能和最大性能。refit-time 和 build-time 权重之间的差异可能会导致未定义的行为。builder 控制要剥离的权重,用户无法做出 layer-level 决策。在将来的版本中,可能会取消此限制,以实现更加精细的控制。
在即将发布的版本中,我们将支持 TensorRT-LLM 中的权重限制引擎,并且同样需要使用相同的构建时权重来确保功能正确。
与 ONNX 运行时集成
TensorRT 10.0 权重剥离功能已经集成到 开源神经网络推理优化工具包(ORT)中,并将从 ORT 1.18.1 版本开始提供。ORT 在 Windows 生态系统中的多个硬件提供商中提供了一个标准推理平台。这种集成使 TensorRT 能够通过 ORT API 提供相同的功能,在满足不同客户硬件需求时减少了 shipment sizes。
在 ORT 中,weight-stripped 功能使用相同的基于 EP 上下文节点的逻辑,嵌入 serialized TensorRT 引擎在 ONNX 模型中绕过 builder 实例化。这种方法避免了 builder 资源的分配,并显著缩短了 TensorRT EP 会话设置时间。有关更多信息,请参阅ONNX Runtime: Accelerated AI Deployment for PC Apps(GTC 会议)。
现在,您可以提供权重剥离引擎,而不是完整引擎。为此,请使用 Boolean 创建具有权重剥离的 TensorRT 引擎 (稍后将进行调整)trt_weightless_engine_enable
TensorRT EP 会话选项以及现有的trt_dump_ep_context_model
标志。
生成的 ONNX EP 上下文元数据模型包含重构权重所需的原始 ONNX 模型的文件名。这意味着不再需要 builder 库进行运输。只需将原始 ONNX 模型的权重和嵌入式权重剥离引擎与主 nvinfer
库一起运输即可。
在针对该特定模型进行下一次 TensorRT EP 调用时,仍启用 trt_weightless_engine_enable 和 trt_dump_ep_context_model 后,引擎将使用原始权重进行改装。
结束语
借助 TensorRT 轻量级引擎,您可以在无需担心增加应用大小的情况下将大量 AI 功能融入应用,同时利用 NVIDIA GPU 上的 TensorRT 峰值性能。
设备上改装可实现持续更新,同时改进权重,而无需重建引擎。TensorRT-LLM 即将支持权重剥离和改装,为生成、部署和维护未来的生成式 AI 模型提供了一种新颖的方法。
有关 ONNX 模型的端到端权重剥离示例的更多信息,请参阅/NVIDIA/TensorRTGitHub 库或/NVIDIA/TensorRT notebook。