
1. 项目概述这不是一次普通编译而是一场对AI推理底层链路的“外科手术式”解剖你有没有在深夜调试一个TensorRT模型时突然发现trtexec报错说找不到某个算子的插件或者PyTorch的torch.jit.trace输出的GraphModule在转换成ONNX时莫名其妙丢了一个分支又或者当你把YOLOv8模型从PyTorch导出为TensorRT引擎后推理速度没提升反而下降了20%翻遍文档却只看到一句模糊的“请确保使用最新版Torch-TensorRT”——这些不是玄学是编译期决策在运行时结出的果。而这篇评测就是我花了整整6周、拆解5393个源文件、在Ubuntu 22.04 CUDA 12.2 cuDNN 8.9 TensorRT 8.6.1 PyTorch 2.1.0的组合环境下亲手把Torch-TensorRT这个“黑盒子”一层层剥开的过程实录。核心关键词NVIDIA、Torch-TensorRT、PyTorch、TensorRT、编译这五个词串起来不是一条简单的工具链而是一条横跨三重抽象层的“降维通道”PyTorch的动态图语义 → ONNX的中间表示 → TensorRT的硬件原生引擎。但绝大多数人只关心首尾两端——怎么写PyTorch模型、怎么跑TensorRT推理——却对中间那个决定性能上限的“编译”环节视而不见。就像你买了一台顶级赛车却从不打开引擎盖看活塞环间隙和气门正时。这次评测我做的就是把引擎盖焊死然后用工业内窥镜高倍显微镜一帧一帧记录下从Python代码敲下model.to_tensorrt()那一刻起背后发生的每一场内存拷贝、每一次算子融合、每一处张量布局重排。它不教你“如何安装”而是告诉你“为什么必须这样安装”它不提供“一键脚本”而是给你一张精确到行号的源码地图。如果你正在为GPU利用率卡在35%发愁如果你的模型在A100上跑得比V100还慢如果你的CI流水线总在cmake .. -DTRT_ROOT...这一步失败——那么你不是缺教程你是缺一次对编译期真相的直面。2. 整体设计与思路拆解为什么是5393个文件一场“自顶向下”与“自底向上”的双向奔赴2.1 拆解策略拒绝黑盒调用坚持源码级追踪市面上90%的Torch-TensorRT教程止步于pip install torch-tensorrt和两行API调用。这就像教人修车只告诉你“拧开油箱盖加92号汽油”却不解释燃油泵压力传感器如何反馈信号、ECU如何根据进气温度修正喷油脉宽。要真正理解编译过程必须放弃wheel包直接克隆官方GitHub仓库https://github.com/pytorch/TensorRT并启用-DBUILD_PYTHON_BINDINGSON -DUSE_PYTHON_EXECUTABLE/usr/bin/python3等全量构建选项。我统计的5393个文件并非全部是C源码——它包含217个CMakeLists.txt这是整个编译逻辑的“宪法”。每一个add_subdirectory()都是一次模块加载指令每一个target_link_libraries()都暴露了依赖拓扑。比如csrc/python/CMakeLists.txt里那行find_package(TensorRT REQUIRED)表面是找库实则触发了对/usr/lib/x86_64-linux-gnu/libnvinfer.so版本号的硬性校验任何小数点后的版本不匹配都会导致CMake Error at .../FindTensorRT.cmake:123 (message): TensorRT version mismatch。1842个.cpp/.h文件构成核心转换引擎。其中csrc/compiler/目录下的Converter.cpp是真正的“翻译官”它把PyTorch的Node*抽象语法树节点逐个映射为TensorRT的INetworkDefinition接口调用。而csrc/lowerings/目录下的Conv2d.cpp、Matmul.cpp等文件则是每个算子的“方言词典”——这里定义了torch.nn.Conv2d的stride、padding参数如何被翻译成network-addConvolutionNd()的kernelSize、prePadding字段。3334个测试与示例文件这才是最珍贵的“活体文档”。tests/python/test_compile.py里第47行那个pytest.mark.parametrize(dtype, [torch.float32, torch.half])的测试用例直接揭示了混合精度编译的触发条件只有当模型权重和输入张量同时为torch.half时torch_tensorrt.compile()才会自动启用FP16模式否则即使你显式传入fp16_modeTrue也会因输入类型不匹配而静默降级为FP32。提示不要跳过测试文件它们比任何README都更真实地反映了API的边界条件。我曾在一个生产环境bug中发现官方文档说“支持GroupNorm”但tests/python/test_groupnorm.py里第89行明确标注# TODO: Fix GroupNorm lowering for dynamic shapes——这意味着该算子在动态batch size场景下根本未实现而文档对此只字未提。2.2 架构分层四层抽象每一层都在做“背叛式优化”Torch-TensorRT的编译不是线性流程而是四层抽象的接力赛且每一层都在“背叛”上一层的语义承诺PyTorch前端层Python用户编写model MyNet(); model torch.jit.script(model)。这一层承诺“动态图灵活性”但torch.jit.script已开始静态化——它会将所有if x 0:分支编译为prim::If节点丢失Python的运行时判断能力。TorchScript IR层Ccsrc/python/torch_script_compiler.cpp将JIT Graph解析为torch::jit::Block。关键转折点在这里torch::jit::toGraphExecutor函数会执行常量折叠Constant Folding把x * 1.0直接替换为x这看似无害但若你的模型里有x * scale_factor且scale_factor是训练时确定的超参这个优化就让scale_factor彻底消失后续TensorRT无法为其分配专用权重内存。ONNX中间层Protocol Buffercsrc/conversion/onnx.cpp调用torch.onnx.export()生成.onnx文件。注意陷阱默认opset_version14但TensorRT 8.6仅完全支持opset 17。我实测发现当模型含torch.nn.functional.silu()时opset 14会导出为HardSigmoid近似而opset 17才支持原生SiLU算子——后者在A100上快12%因为能利用Tensor Core的FP16 SiLU fused kernel。TensorRT后端层CUDA Ccsrc/runtime/engine.cpp最终调用nvinfer1::IBuilder::buildEngineWithConfig()。这才是真正的“魔法发生地”它把ONNX的ConvBatchNormReLU三节点序列识别为可融合的conv_bn_relupattern生成单个CUDA kernel避免三次global memory读写。但融合有严格前提——所有节点必须在同一IExecutionContext下且输入输出tensor的DataType、DimensionType完全一致。这就是为什么你有时手动融合BN到Conv权重后TensorRT反而变慢因为手工融合破坏了原始节点的维度一致性迫使TensorRT退回到逐节点执行。这种层层“背叛”本质是AI编译器的核心哲学用语义损失换取硬件效率。理解这一点你就不会纠结“为什么我的模型导出后精度掉了0.3%”而会主动检查torch.onnx.export()的dynamic_axes参数是否遗漏了input: {0: batch}——因为缺少这个声明TensorRT会假设batch size固定为1从而启用更激进的内存复用策略而这正是精度波动的根源。3. 核心细节解析与实操要点从Ubuntu驱动安装到编译期异常的致命细节3.1 环境基石驱动、CUDA、cuDNN、TensorRT的“四重奏”版本锁所有编译失败的80%源于环境版本的“错位共振”。这不是玄学是NVIDIA官方文档白纸黑字的硬性约束。以Ubuntu 22.04为例我踩过的坑与验证结论如下组件官方推荐版本实测兼容版本关键冲突现象根本原因NVIDIA Driver525.60.13≥515.65.01nvidia-smi has failed because it couldnt communicate with the nvidia driver驱动内核模块nvidia.ko与nvidia-uvm.ko版本不匹配。525驱动要求Linux kernel ≥5.15而Ubuntu 22.04默认5.15.0-xx但某些HWE更新会降级内核导致模块加载失败。CUDA Toolkit12.212.0~12.2nvcc: command not found或libcudnn.so.8: cannot open shared object fileCUDA安装包自带libcudnn.so.8软链接但TensorRT 8.6.1的libnvinfer.so在dlopen()时硬编码查找libcudnn.so.8.9.7。若你装的是cuDNN 8.9.5必须手动创建sudo ln -sf libcudnn.so.8.9.5 /usr/lib/x86_64-linux-gnu/libcudnn.so.8.9.7。TensorRT8.6.1仅8.6.1undefined symbol: _ZNK10nvinfer113IPluginV2Ext12getPluginTypeEvTensorRT ABI在8.5→8.6有重大变更。PyTorch 2.1.0的torch-tensorrtwheel预编译链接的是8.6.1的符号表若你装8.5.3dlsym()会找不到新符号。注意nvidia-smi命令本身不依赖CUDA toolkit只依赖NVIDIA driver。所以当你看到nvidia-smi报错第一反应不该是重装CUDA而是执行sudo dmesg | grep -i nvidia查看内核日志——90%的情况是nvidia-uvm模块未加载执行sudo modprobe nvidia-uvm即可修复。3.2 编译全流程从克隆到wheel的12个关键决策点我将完整编译流程拆解为12个原子操作每个操作都附带一个“为什么必须这样”的硬核解释git clone --recursive https://github.com/pytorch/TensorRT.git--recursive至关重要。Torch-TensorRT依赖third_party/onnx和third_party/pybind11子模块若忽略此参数CMake会报Could not find a package configuration file provided by onnx。实测发现third_party/onnx的commit hash必须与PyTorch 2.1.0的torch.onnx模块完全一致即onnx1.13.1否则torch.onnx.export()生成的graph会被onnx.shape_inference.infer_shapes()修改导致TensorRT解析失败。cd TensorRT git checkout v1.5.0版本号必须精确到tag。v1.5.0对应PyTorch 2.1.0而main分支已适配PyTorch 2.2.0其torch::jit::Node结构体新增了isBefore()方法会导致旧版PyTorch头文件编译报错‘class torch::jit::Node’ has no member named ‘isBefore’。mkdir build cd build强制out-of-source build。若在源码目录直接cmake .CMake会污染CMakeCache.txt导致后续切换CUDA版本时缓存残留。我曾因此浪费17小时排查CUDA_VERSION_STRING始终显示11.8的问题。cmake .. -DCMAKE_BUILD_TYPERelease -DTRT_ROOT/opt/tensorrt -DCUDA_ARCHITECTURES80;86-DCUDA_ARCHITECTURES是性能命门。80对应A10086对应RTX 3090/4090。若你只部署在A100删掉86可减少编译时间40%但若漏掉80生成的engine在A100上会fallback到通用kernel性能损失达35%。-DTRT_ROOT必须指向TensorRT解压目录如/opt/tensorrt而非/usr/lib/x86_64-linux-gnu——后者只有runtime库缺少include/和lib/cmake/CMake会找不到FindTensorRT.cmake。make -j$(nproc)并行编译数设为CPU核心数。超过此值会导致内存溢出OOM因为每个nvcc进程占用1.2GB RAM。在32核机器上-j32比-j64快2.3倍且零OOM。cd ../python python setup.py bdist_wheel这是Python绑定的构建入口。关键陷阱setup.py会自动检测torch.__version__若你系统中有多个PyTorch如conda env和system pip各一个它会优先取/usr/bin/python3的site-packages导致torch.__version__ ! 2.1.0报错。解决方案python -m pip install --force-reinstall torch2.1.0cu121 -f https://download.pytorch.org/whl/torch_stable.html再执行python setup.py。pip install dist/torch_tensorrt-1.5.0-cp310-cp310-linux_x86_64.whlwheel名中的cp310代表CPython 3.10。若你用Python 3.11必须先修改setup.py第28行python_requires3.10,3.11为3.12否则安装时报torch_tensorrt requires Python 3.10,3.11 but the running Python is 3.11.6。python -c import torch_tensorrt; print(torch_tensorrt.__version__)验证导入成功。若报ImportError: libnvinfer.so.8: cannot open shared object file说明LD_LIBRARY_PATH未包含/opt/tensorrt/lib。执行export LD_LIBRARY_PATH/opt/tensorrt/lib:$LD_LIBRARY_PATH并写入~/.bashrc。python -c import torch; x torch.randn(1,3,224,224).cuda(); m torch.hub.load(pytorch/vision, resnet18, pretrainedTrue).cuda(); m.eval(); trt_m torch_tensorrt.compile(m, inputs[x], enabled_precisions{torch.float})最小可行性测试。此处enabled_precisions{torch.float}显式禁用FP16规避驱动版本不兼容问题。若此步失败99%是TensorRT的builder-setMaxBatchSize(1)限制被突破——ResNet18的forward()隐含batch size1但若你传入x torch.randn(2,3,224,224).cuda()就会触发[E] [TRT] Parameter check failed at: ../builder/BuilderConfig.cpp::setMaxBatchSize::69, condition: batchSize 0 batchSize getMaxBatchSize()。trtexec --onnxresnet18.onnx --saveEngineresnet18.engine --fp16对比验证。用trtexec直接编译ONNX与Torch-TensorRT结果对比。关键指标Host LatencyCPU到GPU数据拷贝耗时应0.5msDevice Latency纯GPU计算耗时应比PyTorch原生低3.2倍以上。若Device Latency仅低1.1倍说明算子融合未生效需检查ONNX是否含Unsqueeze等TensorRT不支持的op。nvprof --unified-memory-profiling off --profile-child-processes --events all -o profile.nvvp python test_trt.py性能剖析。--unified-memory-profiling off关闭UM分析避免干扰。重点看gld_efficiency全局内存加载效率是否85%若70%说明kernel存在memory bank conflict需调整TensorRT的builder-setMemoryPoolLimit(nvinfer1::kWORKSPACE, 1ULL 30)增大workspace。python -m pytest tests/python/ -xvs -k test_resnet回归测试。-k指定测试名-x遇到第一个失败即停止-v输出详细信息。测试通过率必须100%否则证明你的编译产物有功能缺陷。我曾发现test_conv2d_dynamic失败根源是csrc/lowerings/Conv2d.cpp第156行auto input_dims input-getDimensions();未处理input_dims.nbDims 0的边界情况导致动态shape模型崩溃。3.3 编译期异常诊断从MSB6006到error: ‘xxx’ is not a member of ‘y’编译错误不是障碍是源码给你的定位信标。以下是高频错误的精准解读error MSB6006: “cmd.exe” exited with code 3Windows或make: *** [all] Error 2Linux这是CMake构建系统的“泛型错误”实际原因藏在前10行日志里。典型案例如/usr/bin/ld: cannot find -lnvinfer。这不是库缺失而是-L/opt/tensorrt/lib路径未被CMAKE_EXE_LINKER_FLAGS捕获。解决方案在CMakeLists.txt顶部添加set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} -L/opt/tensorrt/lib)。error: ‘getInput’ is not a member of ‘nvinfer1::IPluginV2DynamicExt’TensorRT ABI变更的铁证。IPluginV2DynamicExt在8.5版有getInput()8.6版改为getInput(int index)。此错误表明你的TRT_ROOT指向8.5但torch-tensorrt源码按8.6 API编写。唯一解法升级TensorRT到8.6.1。fatal error: ATen/core/jit_type.h: No such file or directoryPyTorch头文件路径错乱。torch-tensorrt需要PyTorch的include/目录但pip install torch不提供。正确做法git clone https://github.com/pytorch/pytorch cd pytorch git checkout v2.1.0 python setup.py develop然后在Torch-TensorRT的CMakeLists.txt中设置-DTORCH_INCLUDE_DIRS/path/to/pytorch/torch/csrc/api/include。undefined reference to ‘cudnnSetStream’cuDNN链接顺序错误。cudnn库必须在cublas之后链接。在CMakeLists.txt的target_link_libraries(torch_tensorrt PRIVATE ...)中确保cudnn出现在cublas之后顺序错误会导致符号解析失败。4. 实操过程与核心环节实现以YOLOv8模型为样本的全流程手把手复现4.1 模型准备为什么YOLOv8是最佳“解剖标本”选择YOLOv8而非ResNet因其具备三大编译压力测试特性动态Shape输入尺寸可变如640x640→1280x1280触发TensorRT的IOptimizationProfile机制多分支结构BackboneC2f、NeckSPPF、HeadDetect三层嵌套考验算子融合边界自定义OPDetect层含torch.nn.functional.sigmoid()和torch.nn.functional.softmax()需验证Torch-TensorRT的lowering实现完整性。我使用的YOLOv8s模型来自Ultralytics官方yolov8s.pt。第一步不是直接编译而是进行编译友好性预检# 1. 检查模型是否含不支持OP python -c import torch from ultralytics import YOLO model YOLO(yolov8s.pt) m model.model print(Model type:, type(m)) print(Forward signature:, m.forward.__code__.co_varnames) # 输出应为 (self, x)若含 profile 或 visualize 参数需重写forward # 2. 导出为TorchScript验证静态化 x torch.randn(1,3,640,640).cuda() traced_model torch.jit.trace(model.model, x) traced_model.save(yolov8s_traced.ts) # 若报错 Tracing failed..., 说明模型含动态控制流如for循环需改用torch.jit.script实操心得Ultralytics的YOLOv8默认forward()含profileFalse参数这会导致JIT trace失败。必须重写forwardclass TracedYOLO(torch.nn.Module): def __init__(self, model): super().__init__() self.model model def forward(self, x): return self.model(x) # 强制移除profile参数 traced torch.jit.trace(TracedYOLO(model.model), x)4.2 编译参数精调从“能跑”到“跑得飞起”的7个关键开关Torch-TensorRT的compile()函数有12个参数但90%的性能差异由以下7个决定参数推荐值原理与影响实测数据YOLOv8s on A100inputs[torch.TensorSpec((1,3,640,640), dtypetorch.float)]显式声明输入规格避免TensorRT runtime推断。若用[torch.randn(...)]会触发torch.jit.trace二次trace增加200ms启动延迟。启动时间1.2s → 0.8senabled_precisions{torch.float, torch.half}启用FP16需硬件支持。A100的Tensor Core FP16吞吐是FP32的2倍但需确保所有算子支持FP16。YOLOv8的Detect层在FP16下softmax精度不足故需{torch.float}。FPS124 → 18750.8%pass_through_build_failuresFalse设为True会跳过编译失败节点用PyTorch fallback但性能暴跌。生产环境必须False强制暴露问题。若设为TrueFPS跌至42-66%truncate_long_and_doubleTrue将torch.long转为torch.int32避免TensorRT不支持64位整数。YOLOv8的torch.arange()生成long tensor不设此参数会报Unsupported data type: int64。编译成功率0% → 100%min_block_size3小于3个节点的子图不尝试融合。YOLOv8的C2f模块含大量ConvSiLU对设为3可确保融合。GPU Utilization68% → 92%use_python_runtimeFalseTrue启用Python runtime调试友好但慢3倍。生产必须False用C runtime。Latency8.2ms → 2.7msdebugTrue生成debug_graph.dot用dot -Tpng debug_graph.dot -o graph.png可视化。这是定位融合失败的唯一途径。发现SPPF的MaxPool2d未融合因padding mode不匹配编译命令实录import torch import torch_tensorrt # 输入规格支持动态batch和height/width inputs [ torch_tensorrt.Input( min_shape(1, 3, 320, 320), opt_shape(1, 3, 640, 640), max_shape(4, 3, 1280, 1280), dtypetorch.float, nameinput ) ] # 编译配置 compile_spec { inputs: inputs, enabled_precisions: {torch.float, torch.half}, truncate_long_and_double: True, min_block_size: 3, use_python_runtime: False, debug: True, } # 执行编译耗时约4分30秒 trt_model torch_tensorrt.compile(model, **compile_spec) torch.jit.save(trt_model, yolov8s_trt.ts)4.3 性能剖析用nvprof和trtexec交叉验证的黄金法则编译完成不等于优化完成。必须用两套工具交叉验证第一套trtexec独立验证# 生成engine并测试 trtexec --onnxyolov8s.onnx \ --saveEngineyolov8s_fp16.engine \ --fp16 \ --best \ --avgRuns100 \ --duration10 \ --workspace2048 \ --verbose 21 | tee trtexec.log # 解析关键指标 grep -E (Host Latency|Device Latency|Throughput) trtexec.log # 正常输出应类似 # [I] Host Latency: min 0.221191 ms, max 0.312012 ms, mean 0.245117 ms # [I] Device Latency: min 1.82324 ms, max 2.10205 ms, mean 1.91234 ms # [I] Throughput: 523.123 QPS第二套nvprof深度剖析# 记录GPU kernel执行 nvprof --unified-memory-profiling off \ --profile-child-processes \ --events sms__sass_thread_inst_executed_op_fadd_pred_on,sms__sass_thread_inst_executed_op_fmul_pred_on \ --metrics sms__inst_executed_op_fadd,sms__inst_executed_op_fmul \ -o yolov8_profile.nvvp \ python run_trt.py # 调用trt_model的脚本 # 生成报告 nvvp yolov8_profile.nvvp # GUI查看 # 或命令行提取 nvprof --query-metrics | grep -E (sms__inst_executed_op_fadd|sms__inst_executed_op_fmul)实操心得trtexec的Device Latency是纯计算耗时而nvprof的sms__inst_executed_op_fadd是实际浮点加法指令数。若前者低但后者高说明kernel未充分利用Tensor Core——可能因输入未对齐16字节边界。解决方案在torch_tensorrt.Input中添加tensor_formattorch_tensorrt.TensorFormat.NCHW并确保输入tensor的x.data_ptr() % 16 0。4.4 推理部署C API与Python Runtime的终极抉择生产环境必须用C API因为Python GIL会锁死多线程推理。以下是C部署的核心骨架// main.cpp #include NvInfer.h #include torch/script.h #include torch_tensorrt/torch_tensorrt.h int main() { // 1. 加载TRT Engine auto engine torch::jit::load(yolov8s_trt.ts); // 2. 创建输入tensor必须与编译时shape一致 auto options torch::TensorOptions() .dtype(torch::kFloat) .device(torch::kCUDA); auto input torch::randn({1,3,640,640}, options); // 3. 推理无GIL可多线程 auto output engine.forward({input}); // 4. 后处理在CPU上 auto result output.toTensor().cpu(); return 0; }编译命令g -stdc14 main.cpp \ -I/opt/tensorrt/include \ -I/usr/local/lib/python3.10/site-packages/torch/include \ -L/opt/tensorrt/lib \ -L/usr/local/lib/python3.10/site-packages/torch/lib \ -lnvinfer -lcudnn -lcublas -ltorch -ltorch_cpu -ltorch_python \ -o yolov8_trt注意-ltorch_python是关键它提供torch::jit::load()的Python绑定。若省略链接时报undefined reference to torch::jit::load(std::string const)。5. 常见问题与排查技巧实录一份来自6周实战的“血泪清单”5.1 编译失败TOP5问题速查表问题现象根本原因一行解决命令预防措施CMake Error at CMakeLists.txt:123 (find_package): Could not find a package configuration file provided by TensorRTTRT_ROOT路径错误或/opt/tensorrt/lib/cmake/TensorRT/下缺少TensorRTConfig.cmakeexport TRT_ROOT/opt/tensorrt cmake .. -DTRT_ROOT$TRT_ROOT下载TensorRT时选tar.gz而非debdeb包不包含CMake配置文件error: ‘IPluginV2DynamicExt’ has no member named ‘getOutputDimensions’TensorRT头文件版本8.5与库文件版本8.6不一致sudo apt remove tensorrt sudo tar -xzf TensorRT-8.6.1.6.Ubuntu-22.04.x86_64-gnu.cuda-12.2.cudnn8.9.tar.gz -C /opt/在CMakeLists.txt中添加message(STATUS TensorRT version: ${TensorRT_VERSION})打印版本RuntimeError: Expected all tensors to be on the same device, but found at least two devices: cuda:0 and cpu输入tensor在CPU但模型在GPU。Torch-TensorRT不自动移动tensorinput input.cuda()beforetrt_model.forward({input})在compile()后立即执行trt_model trt_model.cuda()并统一输入设备Segmentation fault (core dumped)torch-tensorrtwheel与PyTorch版本不匹配。如PyTorch 2.1.0需torch-tensorrt1.5.0pip uninstall torch-tensorrt pip install torch-tensorrt1.5.0cu121 -f https://github.com/pytorch/TensorRT/releases/download/v1.5.0/torch_tensorrt-1.5.0-cp310-cp310-linux_x86_64.whl永远从https://github.com/pytorch/TensorRT/releases下载wheel勿用pip install torch-tensorrtERROR: Failed building wheel for torch-tensorrtgcc版本过高≥12.0。TensorRT 8.6.1的nvcc不兼容GCC 12sudo apt install gcc-11 g-11 export CC/usr/bin/gcc-11 CXX/usr/bin/g-11在setup.py中硬编码os.environ[CC] /usr/bin/gcc-115.2 运行时性能瓶颈TOP3诊断法瓶颈1GPU Utilization 70%诊断nvidia-smi -l 1观察Volatile GPU-Util是否持续低于70%根因CPU-GPU数据拷贝瓶颈。torch.tensor()创建的tensor默认在CPUto(cuda)触发同步拷贝解法预分配GPU内存池# 在推理循环外 input_pool torch.empty((4,3,640,640), dtypetorch.float, devicecuda) #