想象你走进一家烘焙工作室,主人阿林刚从巴黎学艺归来,手里攥着一本从法国名师那儿抄来的蛋糕配方。配方上写着“蛋白分三次加入、180 度烤 35 分钟”,看起来无懈可击。可阿林没有照搬——她先打量自己的厨房:32 升小烤箱、四根加热管、没有风炉,和巴黎那间商用厨房完全是两回事。她决定改配方:分蛋改全蛋、温度降到 160 度、时间延长到 40 分钟,最终写出一本只适用于自家烤箱的“操作手册”。 TensorRT 的 Engine Build(引擎构建)就是 AI 世界里的“阿林”。深度学习模型训练完后,拿到的通常是一份“通用配方”——网络定义(比如 ONNX 图),它描述了计算步骤,却完全不关心你的 GPU 长什么样。构建阶段,TensorRT 仔细打量目标显卡:SM 数量决定并行火力,内存带宽决定数据搬运速度,然后把网络层逐个审视:能合并的层直接融合,能降精度的算子换成 FP16 或 INT8,最后产出一个只属于这块 GPU 的引擎文件。部署时照着这份“手册”执行,又稳又快。
对 AI 从业者而言,掌握 Engine Build 是推理部署的核心技能。它决定了同一个模型在不同硬件上的延迟与吞吐差距,直接关乎线上服务的成本与体验。
可视化演示
本节配有交互动效(进入视口后自动加载,约 3KB)。
构建流程总览
当烘焙师阿林第一次拿到巴黎名师的手写配方时,她没有急着开烤箱,而是先把配方通读一遍:有哪些步骤、要用到什么工具、哪些环节可能失败。她心里知道,这份配方是写给“任何一个厨房”看的,不是写给“我家厨房”看的。接下来的半小时,她一边默写步骤,一边在脑海里把每一步映射到自己的烤箱和操作台上——这就是引擎构建的起点。
在 TensorRT 里,Engine Build(引擎构建)做的事情一模一样。它接过一个训练好的网络定义(最常见的是 ONNX 格式),这个定义描述了“有哪些算子、按什么顺序连接、权重是多少”,但它完全不知道你的 GPU 长什么样。Builder(构建器)登场,它把这个通用定义放进一条优化流水线:先解析计算图,再做图优化(层融合、算子替换),再针对目标硬件选内核,最后把所有信息打包成一份“只属于这块 GPU”的引擎文件。
整个构建过程可以浓缩成一个映射关系:
阿林把那本法语配方扔进抽屉,把写好的操作手册贴在灶台上。此后每一天,她都不需要重新理解配方——照着手册做就行。TensorRT 的 Engine 也一样:构建一次,部署无数次。
- B(构建器)负责执行编译优化的核心角色——解析计算图、应用层融合、挑选内核,是这一节的“烘焙师本人”。
- Network 网络定义输入的通用计算图,描述算子与张量流向,但不绑定具体硬件,相当于“从巴黎寄来的配方”。
- Config 构建配置一组控制优化方向的参数,比如最大工作空间、是否开启 FP16,相当于“阿林决定用多大的操作台”。
- GPU 目标硬件特征SM 数量、内存带宽、计算能力版本等,决定内核选择方向,相当于“烤箱的脾性和容量”。
- Engine 引擎序列化后的可执行计划,包含算子内核、内存布局和执行顺序,相当于“阿林装订好的操作手册”。
构建器配置
阿林来到厨房第一件事,是看一眼今天的操作台:她只申请了一米宽的台面,但配方里“同时摊开三个盆”的步骤明显需要更大空间。她想了想,决定把台面扩展到两米,并为每一步腾出足够操作空间——反正台面再大也不会同时全用上。
在 TensorRT 里,这个“台面”叫工作空间(workspace),它是构建阶段算子求解内核时临时缓存的上限。设置多大的 workspace,由 BuilderConfig 决定。Builder 是构建器的入口对象,BuilderConfig 则是控制面板,上面有几个关键旋钮:最大工作空间、精度标志(FP16/INT8)、INT8 校准器等。此外,日志(Logger)像一位爱提醒的助手,把构建过程中的警告和错误如实报给你。
构建配置可以用一个三元组概括:
阿林最终把台面扩大到两米,又在助手提醒下临时换了个更快的小烤箱模式(FP16)。台面的选择不是越大越好——她见过同行把整个厨房都堆满烤盘,结果连转身的地方都没有。BuilderConfig 的每一个旋钮都是权衡,而理解权衡,正是构建优化的第一步。
- Workspace 工作空间构建期间允许使用的最大临时显存,越大越可能找到更优内核,但也会拉高构建期内存占用与最终引擎体积。
- PrecisionFlags 精度标志一组布尔开关,决定是否允许构建器把算子降到 FP16 或 INT8,例如
set_flag(trt.BuilderFlag.FP16)。 - Calibrator 校准器当启用 INT8 时,需要校准器用一批代表数据统计激活值分布,进而确定每层的量化参数。
硬件特征适配
阿林回到自己厨房做的第一件事,是“认识烤箱”:翻开说明书,确认容量 32 升、上下火 4 根加热管、没有风炉。做过几次失败的戚风后她明白了——烤箱决定了一切。容量小就少烤几盘,加热管少就靠延长烘烤时间补足;强行照搬商用烤箱的配方,只会收获一块石头蛋糕。
TensorRT 也有同样的“认识硬件”过程。构建时它会查询目标 GPU 的硬件特征:流多处理器(SM)数量、内存带宽、计算能力版本(如 8.6)。这些数字直接决定了策略:SM 多,并行火力就猛,内核可以多开线程;带宽高,数据搬运得快,访存密集算子更有优势。TensorRT 内部维护了一个庞大的内核库,每个算子在不同硬件上有多种内核实现,构建器根据硬件特征“自动挑选”延迟最小的那一个。
一个粗粒度的性能估计模型可以帮我们理解这种选择:
阿林对着说明书点点头,把烤箱的脾气记在心底。她没有去学别人 300 度的商用秘诀,而是给自己的 32 升小烤箱写下了 160 度、40 分钟的配方。TensorRT 也一样:同一个网络,在 A100 和 Jetson 上产出的内核截然不同——硬件不同,菜谱自然不同。
- FLOPs 计算量算子的浮点运算总数,比如一次大矩阵乘法有上亿次乘加,相当于“配方里要打发 12 个鸡蛋”。
- N_SM × Clock 并行算力SM 数量乘以核心频率近似等于 GPU 的“总火力”,SM 越多越能同时烤更多盘。
- DataSize / BW 访存时间需要搬运的数据量除以内存带宽,得出数据搬运耗时,相当于“从仓库搬面粉的时间”。
- 求和取最小总耗时约等于算和搬两项之和,构建器遍历候选内核,选估计延迟最低的那个。
层融合优化
阿林反复演练过整个制作流程后,发现一个可以让效率翻倍的机会:配方要求先“分蛋,蛋黄加糖打发”再“蛋白另打发”,但她注意到自家烤箱的预热曲线很平缓,完全可以改成“全蛋常温打发”——一步出更蓬松的组织,还少洗两个盆。省下的不只是洗盆的时间,更是两个盆在台面上占用的空间。
这种“把多个步骤合并成一个”的智慧,在 TensorRT 里叫层融合(Layer Fusion)。最经典的是卷积-批归一化-激活三合一:Conv 后面接 BN 再接 ReLU 是 CNN 里的“标准三段式”。三段各算各的,中间结果要在显存里写一次、读一次,像极了切好的葱姜蒜要分别摆三个碗。层融合把三个算子折叠成一个算子——切好的调味料直接下锅,不占碗、不往返。
数学上,批归一化在推理时是一个固定的线性变换,可以“折叠”进卷积的权重和偏置:
其中 $W' = \dfrac{\gamma W}{\sqrt{\sigma_{\text{bn}}^2 + \epsilon}}$,$b' = \gamma \cdot \dfrac{b - \mu_{\text{bn}}}{\sqrt{\sigma_{\text{bn}}^2 + \epsilon}} + \beta$。
阿林把“全蛋打发”写进手册后,制作时间缩短了三分之一,更关键的是,她终于不用在巴掌大的厨房里摆三个盆了。层融合做的是同一件事:把中间产物留在寄存器里,少一次进出显存,就快一大截。
- 卷积输出先看三层中的第一层,卷积对输入 x 作用,得到中间张量 z。
- 批归一化的线性形式推理时 BN 是固定的仿射变换:先按均值方差标准化,再缩放平移。
- 代入与合并把 z = Wx + b 代入 BN 公式,展开整理,全部吸收进新的权重 W' 和偏置 b'。
- 一层替换三层融合后算子数量从 3 变 1,运行内核数减少,中间张量不再落盘显存。
精度优化策略
阿林买过三台秤:一台千元级专业电子秤,精确到 0.1 克(FP32);一台百元厨房秤,精确到 1 克(FP16);还有一把只写了“少许”的铁勺(INT8)。做给自己吃,她总用专业秤;但接到一百份下午茶的订单时,她果断换成厨房秤——速度提升明显,而蛋糕的口感几乎没人吃得出差别。至于那把铁勺,她只在反复做过几十遍、把握十足之后才敢用。
TensorRT 的精度优化就是这套“秤”的逻辑。默认情况下模型以 FP32(32 位浮点)计算,精度最稳,但显存占用和计算量都大。FP16 半精度把数据砍半,计算单元吞吐翻倍,多数模型精度损失微乎其微。INT8 更激进:把每个数值映射到 256 个整数档位,速度最快、体积最小,但必须先“试做校准”——用一批代表性数据过一遍网络,统计每层激活值的分布,才能确定量化参数。
INT8 量化的核心是一个简单的映射:
下午茶的订单让阿林坚定了“按订单选秤”的原则:家常自用上专业秤,赶单用厨房秤,只有最经典的款式才会用铁勺冒险。TensorRT 的精度选择同样宽容——业务上线前,用校准集跑一遍评估掉点,再做决定,永远比盲目追求低精度更稳妥。
- scale 缩放因子把浮点动态范围 [r_min, r_max] 映射到 256 个整数档的步长,由校准器统计得出。
- round 取整浮点值除以 scale 后四舍五入到最近整数,得到初步量化结果。
- zero_point 零点偏移为了对齐浮点 0 和整数零点,加上一个偏移量,避免出现系统性的零点失配。
- clamp 截断把结果限制在 INT8 表示范围 [-128, 127] 内,防止溢出。
引擎序列化
经过一整天的打磨,阿林的手册终于定稿:从预热温度到出炉时间,每一步都有数值。她把手册打印了三份,一份贴灶台,一份放仓库,一份给了新来的学徒。手册装订成册的那一刻,她心里踏实了——这不再是记忆里的模糊配方,而是一份随时可以取用的实物。
TensorRT 的引擎同样需要“打印装订”。构建完成后,引擎还停留在显存和内存里,是一次性的对象。序列化(serialize)把它写成二进制字节流,通常保存为 .plan 文件(即“手册”)。部署时,Runtime 组件执行反序列化(deserialize),把文件读回引擎对象,立刻可以创建执行上下文开始推理。
序列化和反序列化是一对互逆操作:
手册贴着灶台,学徒照本宣科,出品稳定如初。但阿林知道,手册上写着“32 升烤箱专用”——哪天换了新烤箱,这本手册就得重写。序列化的引擎文件也一样,绑定硬件不是缺陷,而是它高效的原因:世界上没有一本手册能同时服务所有厨房。
- Serialize 序列化把内存中的引擎对象编码成二进制字节序列,相当于“把手册排版打印”。
- Engine_file 引擎文件磁盘上的
.plan文件,包含内核二进制、权重参数和内存布局信息,通常几 MB 到几十 MB。 - Deserialize 反序列化运行时用 TensorRT Runtime 从字节流还原引擎对象,相当于“把打印好的手册重新翻成可执行的工序”。
- 平台绑定与兼容性引擎内嵌了针对特定 GPU 编译的底层 CUDA kernel,换 GPU 或升级 TensorRT 主版本后通常需要重新构建。
部署运行管理
手册挂上墙,阿林的每一天都像一场流水线演出:6 点预热烤箱,7 点第一炉入炉,8 点高峰来临——四台烤箱同时工作,她调度着每个烤箱的开关时机,保证出炉节奏均匀。新来的学徒只需要记住一件事:每一步都按手册来,但具体哪只手先动,取决于当时的节奏。
TensorRT 部署阶段对应着阿林的“演出调度”。加载引擎后,需要创建执行上下文(ExecutionContext)——可以理解为“烤箱的一次运行实例”。上下文持有推理过程中的中间状态,负责把输入张量绑定到引擎规定的内存地址。在多请求高并发场景,我们还会使用 CUDA 流(stream)让多个推理任务并行执行,如同阿林同时照看四台烤箱。动态形状(dynamic shape)则让引擎支持不同 batch 的输入,相当于手册里写了“烤一炉 12 个和 24 个的通用节奏”。
引擎的显存占用并非所有中间张量之和,而是“同一时刻活跃张量”的最大值。TensorRT 用内存池复用机制精确计算这个峰值:
傍晚打烊,阿林关掉四台烤箱,确认最后一炉蛋糕已经送出。手册还在灶台上,明天的流程和今天一样,只是订单更多、节奏更快。部署阶段的每一个精细调度,都是对“手册执行效率”的最终考验——而这一切的高效,早在那次认真的“引擎构建”中就已注定。
- Alive(t) 活跃集合t 时刻仍被后续算子需要的张量集合;已经用完的张量会被释放回池子。
- Size(b) 张量大小每个活跃张量占用的字节数 = 元素数 × 每元素字节数,如 FP16 每元素 2 字节。
- 求和与取最大值对每个时刻求活跃张量总占用,再对整个生命周期取最大值——这个值决定了引擎运行时至少需要多少显存。
AI 应用场景
云端图像分类服务加速
阶段:模型部署与推理优化
解决的问题:PyTorch 模型直接上线推理,GPU 利用率低、单次推理延迟高,传统做法靠堆显卡数量硬扛,成本居高不下。
具体案例:某内容审核平台将训练好的 ResNet-50 导出为 ONNX,经 Engine Build 按 A10 GPU 的 SM 数量构建 FP16 引擎。构建时 TensorRT 自动完成 Conv+BN+ReLU 融合并选择最优内核,线上 batch=32 推理延迟从 8ms 降至 1.6ms,吞吐提升约 4 倍,GPU 数量从 6 卡缩减到 2 卡。
自动驾驶嵌入式部署
阶段:嵌入式/边缘端部署
解决的问题:车载 Jetson 设备显存小、算力有限,直接跑原始模型帧率不足,且内存带宽受限导致访存密集算子成为瓶颈。
具体案例:某自动驾驶团队把目标检测模型针对 Jetson Orin 重新构建 INT8 引擎。先用 2000 张代表场景图做校准,确定每层量化 scale,再以 FP16 结果为准评估掉点。最终 mAP 仅下降 0.3%,帧率从 30 FPS 提升到 80 FPS,显存占用减少约 60%。
多租户 GPU 推理服务
阶段:资源调度与管理
解决的问题:多个模型共享一张 GPU 时,各自推理的显存峰值叠加极易超限,传统做法是静态隔离导致资源浪费。
具体案例:某 MLOps 平台维护每个模型的引擎峰值显存记录(来自构建期的内存池分析),再按峰值大小把 8 个不同模型动态编排到同一张 A10 上。结合 CUDA 流并发推理,总吞吐提升近 3 倍,且未出现一次 OOM。
Python 演示
"""TensorRT 引擎构建全流程演示:ONNX -> Engine"""import tensorrt as trt class EngineBuilder: """把一个 ONNX 模型构建为部署引擎""" def __init__(self, onnx_path, logger): self.onnx_path = onnx_path self.logger = logger self.builder = trt.Builder(logger) self.network = self.builder.create_network( 1 << int(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH) ) self.config = self.builder.create_builder_config() def load_onnx(self): parser = trt.OnnxParser(self.network, self.logger) with open(self.onnx_path, "rb") as f: ok = parser.parse(f.read()) if not ok: for i in range(parser.num_errors): self.logger.log(trt.Logger.ERROR, parser.get_error(i)) raise RuntimeError("ONNX 解析失败") return self def set_workspace(self, gb): limit = int(gb * (1 << 30)) self.config.set_memory_pool_limit(trt.MemoryPoolType.WORKSPACE, limit) return self def enable_fp16(self): if self.builder.platform_has_fast_fp16: self.config.set_flag(trt.BuilderFlag.FP16) return self def build(self): plan = self.builder.build_serialized_network(self.network, self.config) runtime = trt.Runtime(self.logger) return runtime.deserialize_cuda_engine(plan) def inspect(engine): print("引擎信息:") for i in range(engine.num_io_tensors): name = engine.get_tensor_name(i) mode = engine.get_tensor_mode(name) shape = list(engine.get_tensor_shape(name)) print(f" {mode}: {name} {shape}") context = engine.create_execution_context() print("执行上下文创建成功:", bool(context)) def main(): logger = trt.Logger(trt.Logger.WARNING) builder = EngineBuilder("resnet18.onnx", logger) engine = builder.load_onnx().set_workspace(2).enable_fp16().build() if engine is None: print("引擎构建失败") return inspect(engine) if __name__ == "__main__": main()
create_network(1 << int(...EXPLICIT_BATCH))创建显式 batch 的网络定义,这是现代 TensorRT API 的标准入口。trt.OnnxParser(self.network, self.logger)把 ONNX 计算图“翻译”成 TensorRT 内部网络表示,相当于把法语配方翻译成中文。set_memory_pool_limit(trt.MemoryPoolType.WORKSPACE, limit)设置构建期工作空间上限,即“操作台大小”。builder.platform_has_fast_fp16查询当前 GPU 是否支持快速 FP16,相当于确认烤箱有没有快速预热模式。build_serialized_network(self.network, self.config)核心一步:执行优化流水线并直接输出序列化的引擎字节流。runtime.deserialize_cuda_engine(plan)运行时把引擎字节流“还原”成可用的引擎对象。engine.create_execution_context()创建执行上下文,相当于“烤箱的一次运行实例”。load_onnx().set_workspace(2).enable_fp16().build()链式调用让构建配置读起来像一段自然语言。
常见误区
误区我以为 `.plan` 文件和 `.onnx` 一样,随便拷贝到哪台机器上都能直接跑,换个 GPU 顶多慢一点,不会出错。
正解TensorRT 引擎是“平台绑定”的。构建时会针对目标 GPU 的 SM 数量、计算能力版本编译底层 CUDA kernel,换一块 GPU 或升级 TensorRT 主版本,引擎可能直接加载失败或产生错误结果。正确做法是把引擎文件与 GPU 型号、TensorRT 版本一起记录,迁移时重新执行 Engine Build。
为何常见:.onnx 是跨平台格式深入人心,容易把序列化文件也当成通用产物,忽视了内核编译的硬件特异性。
误区网上教程都说开 FP16 能白嫖速度,所以我每次构建都把 FP16 打开,反正精度不会掉。
正解FP16 确实能提升吞吐,但代价是精度风险。某些算子对数值范围敏感(如含大动态范围的归一化、检测框回归头),半精度可能导致掉点甚至 NaN。负责任的做法是:构建后拿验证集对比 FP32 与 FP16 的输出差异,再决定是否上线。
为何常见:速度提升是直观的、可量化的,而精度损失有时只在特定数据分布下才暴露,容易被忽视。
误区构建配置里的 workspace 应该是“越大越赚”,直接设为最大甚至无限,让 TensorRT 放开手脚优化。
正解workspace 是构建期的缓存上限,但它会影响构建器的内存分配策略和最终引擎的显存占用。设得过大可能导致显存不足而构建失败,设得太小则内核搜索空间受限。经验做法是从模型体积的 1-2 倍起步,逐步调优。
为何常见:名字叫"max workspace"容易让人以为是纯上限,忽略了它对资源占用和最终引擎体积的影响。
误区Engine Build 把所有优化都做完了,运行时只要调一下推理接口就行,不用再关心显存。
正解构建产生的是“执行计划”,运行期的输入输出绑定、CUDA 流同步、上下文生命周期仍需开发者管理。引擎的显存池只是被精确规划,不代表不需要正确使用——就像阿林的手册虽好,烤箱还是得有人盯着。
为何常见:构建期的自动化程度太高,容易让人误以为运行期也没有手动工作。
误区动态形状会让引擎为多种 shape 准备内核,构建时间变长,所以我坚持用固定 batch,避免性能损失。
正解动态形状确实会延长构建时间,因为 TensorRT 要为 shape 范围做更宽的优化搜索,但推理性能依然经过精心优化。在推理场景 batch 时常变化的线上服务中,动态形状往往利大于弊——省去了多次构建不同 batch 引擎的麻烦,也在运行期按实际输入选择最合适的内核。
为何常见:把“构建时间变长”直接等同于“推理变慢”,混淆了构建期与运行期的性能指标。
面试题
Q1. Engine Build 阶段的主要输入是什么?
- A.训练好的权重参数文件
- B.优化后的网络图定义← 正确答案
- C.大批量的测试集图像
- D.训练时用的超参数配置
答案:B。Engine Build 的直接输入是网络定义(如 ONNX 计算图),权重虽然参与计算,但构建器处理的是图结构。好比阿林照着配方做手册,配方是输入,食材重量只是其中的数值。训练超参和测试图像与构建无关。
Q2. 下列哪个不是 BuilderConfig 可以配置的内容?
- A.最大工作空间的容量
- B.INT8 校准器插件
- C.训练数据增强方式← 正确答案
- D.FP16 精度开关标志
答案:C。BuilderConfig 只关心构建期选项:工作空间、精度标志、校准器。数据增强属于训练阶段,构建器不碰数据,自然不会配置增强策略。
Q3. TensorRT 构建引擎时主要参考目标 GPU 的哪些特征?
- A.显卡的品牌与型号
- B.SM 数量与内存带宽← 正确答案
- C.显示器分辨率大小
- D.CPU 的主频高低
答案:B。TensorRT 根据 SM 数量决定并行能力、内存带宽决定访存瓶颈,还会看计算能力版本来挑选内核。品牌名只是 SM 数量和带宽的“包装”,真正起作用的是具体数值。
Q4. 层融合(Layer Fusion)最直接的好处是什么?
- A.显著减少网络层数
- B.减少中间显存读写← 正确答案
- C.大幅提升模型精度
- D.加快训练阶段收敛
答案:B。层融合把多个算子合并执行,省去了中间张量在显存中的写入和读回,延迟大幅下降。网络层数并非核心指标,融合不改变精度,更不影响训练。
Q5. 关于 INT8 量化,下列说法正确的有哪些?
- A.需要校准数据定尺度← 正确答案
- B.精度一定高于 FP32
- C.映射到 256 级整数← 正确答案
- D.无需校准即可使用
答案:AC。INT8 把浮点张量量化到 [-128, 127] 共 256 个整数档位,必须先通过校准数据统计激活值分布以确定 scale 和 zero_point。精度通常低于 FP32,且不校准根本无法确定量化参数。
Q6. 序列化后的 TensorRT 引擎文件(.plan)有什么特性?
- A.与目标 GPU 型号无关
- B.与 TensorRT 版本无关
- C.目标 GPU 版本绑定← 正确答案
- D.是明文可读的文本格式
答案:C。引擎文件内嵌了针对特定 GPU 和 TensorRT 版本编译的 CUDA 内核,跨平台使用可能加载失败。它像阿林手册上“32 升烤箱专用”的标注,是二进制而非文本。
Q7. TensorRT 在构建阶段会做哪些优化?
- A.层融合减少内存开销← 正确答案
- B.根据硬件选最优内核← 正确答案
- C.对训练集做数据增强
- D.应用 FP16 精度优化← 正确答案
答案:ABD。构建阶段的核心优化包括层融合、内核自动选择、精度优化(FP16/INT8)。数据增强是训练期的事,构建器从不接触训练数据。
Q8. 关于工作空间(workspace)说法正确的是?
- A.设置越大推理一定越快
- B.是构建期中间缓存上限← 正确答案
- C.设置越小推理性能越好
- D.只影响构建不影响推理
答案:B。workspace 是构建期求解内核时临时缓存的上限。过大可能让构建和运行期显存吃紧,过小则限制内核搜索空间;它还间接影响引擎体积和运行期内存占用。
Q9. Conv+BN+ReLU 融合后,新的卷积权重如何得到?
- A.直接沿用原卷积权重
- B.将 BN 参数折叠进权重← 正确答案
- C.随机初始化新的权重
- D.用全零矩阵替换权重
答案:B。推理时 BN 是固定线性变换,把均值、方差、γ、β 全部折叠进原卷积的权重和偏置,得到新权重 W' 和 b'。就像把“分蛋打法”和“混合”合并成“全蛋一步打发”。
Q10. 关于 TensorRT 引擎构建与部署,正确的说法有哪些?
- A.引擎文件可跨 GPU 部署
- B.反序列化后需创建上下文← 正确答案
- C.动态形状延长构建时长← 正确答案
- D.引擎构建与目标无关
答案:BC。引擎反序列化后必须创建 ExecutionContext 才能执行推理;动态形状会让构建期优化搜索空间扩大,构建时间变长。引擎文件绑定 GPU 型号,构建也高度依赖目标硬件特征。