DEBUG.WIKI
丽萨主机;为跨境业务选好 IP;原生 / 住宅 IP · 按套餐选择;查看 IP →
阿里云;从建站到云上业务;云服务器 · 数据库 · 对象存储;查看产品 →
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

TensorRT 已创建 optimization profile,为什么构建时仍提示没有定义?

TensorRT 的 optimization profile 加入 config 后,构建调用也必须使用该配置。核对输入名、形状范围和 config 去向,再验证最小、典型与最大输入。

TensorRT 已创建 optimization profile,为什么构建时仍提示没有定义?

代码里已经调用了 create_optimization_profile() 和 add_optimization_profile(),构建仍停在:

Network has dynamic or shape inputs, but no optimization profile has been defined.

先检查构建引擎的最后一行。profile 加进 config 以后,实际构建调用也必须使用这个 config。

TensorRT 官方 issue #768 中就有这样一段代码:前面创建了配置和 profile,最后却调用 builder.build_cuda_engine(network)。这个例子使用 TensorRT 7.1.3.4、CUDA 10.2 和 Python 3.6。维护者明确建议构建时传入包含 profile 的配置,即 build_engine(network, config=config);讨论随后按此建议关闭,但没有作者成功复测的回报。维护者回复 问题代码

检查输入名和配置去向

在已经创建好 network 的构建脚本中,先输出实际输入:

for index in range(network.num_inputs):
    tensor = network.get_input(index)
    print(tensor.name, tuple(tensor.shape))

set_shape() 接收的名字必须与这里一致。还要沿着代码查看:添加了 profile 的 config 有没有被重新创建、替换,或者根本没有传给构建函数。

下面仅演示 TensorRT 7.x 的连接方式。假设网络只有一个普通动态输入,形状为 (-1, 3, 224, 224),业务需要 batch 1 到 8:

config = builder.create_builder_config()
profile = builder.create_optimization_profile()
input_name = network.get_input(0).name

if not profile.set_shape(
    input_name,
    (1, 3, 224, 224),
    (4, 3, 224, 224),
    (8, 3, 224, 224),
):
    raise ValueError("输入形状设置失败")

if config.add_optimization_profile(profile) < 0:
    raise ValueError("profile 添加失败")

engine = builder.build_engine(network, config)
if engine is None:
    raise RuntimeError("引擎构建失败,请查看 TensorRT 日志中的首个错误")

这里最重要的是最后的 build_engine(network, config)。类似写法也出现在 ONNX-TensorRT 的历史讨论中。TensorRT 7.1 相关讨论

已有配置中的 workspace、精度等设置仍需保留,不能为了照抄示例而全部替换。多个动态输入要分别配置;shape tensor 也不能直接照搬这个普通输入示例。

构建成功还不够

TensorRT 的动态形状流程还包括:运行时选择覆盖实际输入的 profile,设置执行上下文的输入尺寸,再提交计算。新版本的构建和执行 API 已有变化,应按所装版本改写,别把 7.x 示例与新接口拼接使用。官方动态形状说明

验收时至少运行最小、典型和最大输入,确认输出形状和结果正常。超出 profile 范围的请求应有明确处理方式。把所有 -1 强行改成 1,虽然可能绕过动态输入检查,也会改变原本需要支持的输入范围。