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<<32)
减少到max_workspace_size_bytes=(1<<25)
对我有用。以上是关于TensorRT 中的converter.build() 有啥用?的主要内容,如果未能解决你的问题,请参考以下文章