TensorRT 中的converter.build() 有啥用?

Posted

技术标签:

【中文标题】TensorRT 中的converter.build() 有啥用?【英文标题】:What's the use for converter.build() in TensorRT?TensorRT 中的converter.build() 有什么用? 【发布时间】:2020-05-12 20:38:54 【问题描述】:

official documentation on TensorRT 列出了两种将 TensorFlow SavedModel 转换为 TensorRT SavedModel 的方法:第一种是

from tensorflow.python.compiler.tensorrt import trt_convert as trt
converter = trt.TrtGraphConverterV2(input_saved_model_dir=input_saved_model_dir)
converter.convert()
converter.save(output_saved_model_dir)

第二个是

import tensorflow as tf
from tensorflow.python.compiler.tensorrt import trt_convert as trt

conversion_params = trt.DEFAULT_TRT_CONVERSION_PARAMS
conversion_params = conversion_params._replace(
    max_workspace_size_bytes=(1<<32))
conversion_params = conversion_params._replace(precision_mode="FP16")
conversion_params = conversion_params._replace(
    maximum_cached_engiens=100)

converter = trt.TrtGraphConverterV2(
    input_saved_model_dir=input_saved_model_dir,
    conversion_params=conversion_params)
converter.convert()
def my_input_fn():
  for _ in range(num_runs):
    Inp1 = np.random.normal(size=(8, 16, 16, 3)).astype(np.float32)
    inp2 = np.random.normal(size=(8, 16, 16, 3)).astype(np.float32)
    yield inp1, inp2
converter.build(input_fn=my_input_fn)
converter.save(output_saved_model_dir)

saved_model_loaded = tf.saved_model.load(
    output_saved_model_dir, tags=[tag_constants.SERVING])
graph_func = saved_model_loaded.signatures[
    signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY]
frozen_func = convert_to_constants.convert_variables_to_constants_v2(
    graph_func)
output = frozen_func(input_data)[0].numpy()

去掉所有用于导入、推理等的样板代码,区别似乎在于对 converter.build() 的调用。文档解释了这个函数:

“此方法通过构建 TensorRT 引擎来优化转换后的函数(由 convert() 返回)。这在用户想要在运行前执行优化的情况下很有用。优化是通过使用从参数 input_fn 接收的输入数据。此参数是一个生成器函数,可将输入数据生成为列表或元组。"

在这种情况下,“运行前”是什么意思? “优化”会在模型加载时、第一次推理时还是在使用转换后的模型的每一次推理时执行?这些优化是什么?将模型转换为 TensorRT 本身不是优化吗?

我问是因为如果我打电话给converter.build() 转换似乎在花费大量时间(超过两个小时)运行而没有产生任何合理输出之后以不可预测的方式失败,所以我想知道我损失了多少通过不调用它以及是否有关于使用 TF2.x SavedModels 和 TensorRT 的更全面的文档。

先谢谢能回答的人!!

【问题讨论】:

哇,nVidias 文档中有一个明显的拼写错误:Inp1 vs inp1。他们不可能在没有注意到的情况下尝试过那段代码。 【参考方案1】:

据我了解(在阅读TensorFlow's docs 之后)converter.convert() 函数将图形转换为 tf-trt,用 TRTEngineOp 替换它可以使用的任何节点,但它不会创建推理期间使用的实际引擎文件。

然而,对converter.build() 的调用会创建引擎文件,但对于 input_fn 提供的输入的输入大小,并且对于正在运行构建的平台 >。因此,不调用converter.build() 的原因是您事先不知道输入形状,或者无法在您要运行推理的平台上进行构建。

我发现很难想象每次前向传递都会创建新的引擎文件,但肯定是为每个新的输入形状创建的。从示例中不清楚来自input_fn 的输入是否用于提供有关输入形状的信息之外的任何其他方式,但如果您返回不同形状的输入,则应为每个输入大小创建一个引擎文件。

例如,提供以下输入函数将生成一个用于输入大小 (112,112,3) 的引擎和一个用于 (224,224,3) 的引擎:

def input_fn():
  input_sizes = [[112, 112], [224, 224]]
  for size in input_sizes:
    inp1 = np.random.normal(size=(1, *size, 3)).astype(np.float32)
    yield [inp1]

至于您的 input_fn,您是否有两个图像作为网络的输入?对我有用的是在上面的示例中返回一个列表中的单个图像(元组由于某种原因不起作用,即使文档说它应该)。

希望这会有所帮助。

【讨论】:

谢谢,我没有意识到我必须在我将运行推理的平台上运行它。对我来说,这是一个 Jetson Nano。首先,它每次都耗尽了 GPU 内存。将max_workspace_size_bytes=(1&lt;&lt;32) 减少到max_workspace_size_bytes=(1&lt;&lt;25) 对我有用。

以上是关于TensorRT 中的converter.build() 有啥用?的主要内容,如果未能解决你的问题,请参考以下文章

TensorRT8 meets Python TensorRT快速入门介绍

模型部署Tensorrt学习记录

带有 CTC 层的 TensorRT

tensorRT 使用过程中的Bug记录

TensorRT-C++ API使用:mnist手写体识别

TensorRT 如何处理数据?