You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化动态输入下的ONNX模型推理速度?

动态输入下ONNX Runtime推理初始速度过慢的优化问题

我用ONNX Runtime创建会话的代码如下:

so = ort.SessionOptions()
so.inter_op_num_threads = 10
so.intra_op_num_threads = 10
session = ort.InferenceSession('example.onnx',
                               sess_options=so,
                               providers=['CUDAExecutionProvider'])

当输入尺寸固定(比如200)时,推理速度很快且稳定:

for i in tqdm(range(1000)):
    array = np.zeros((1, 200, 80), dtype=np.float32)
    embeddings = session.run(output_names=['embs'], input_feed={'feats': array})

但使用动态输入(尺寸在200-1000之间随机)时,前几百到几千次迭代速度极慢,之后才会优化到和固定输入相当的速度。尝试过批处理,但输入尺寸差异太大导致输出精度下降,求其他加速方法。


可行优化方案
  • 启用提前优化:在创建会话时开启ORT的全量优化选项,强制提前完成动态形状适配的优化,避免运行时动态编译开销。修改SessionOptions配置:

    so = ort.SessionOptions()
    so.inter_op_num_threads = 10
    so.intra_op_num_threads = 10
    # 启用所有级别的图优化,包含动态形状适配逻辑
    so.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL
    # 保存优化后的模型,后续加载可直接复用优化结果
    so.optimized_model_path = "optimized_example.onnx"
    session = ort.InferenceSession('example.onnx',
                                   sess_options=so,
                                   providers=['CUDAExecutionProvider'])
    
  • 指定动态输入的形状范围:如果已知输入尺寸的上下限,在模型导出或会话创建阶段明确约束,让ORT提前生成适配该范围的优化代码,无需每次遇到新形状重新编译。
    以PyTorch导出ONNX为例,给动态维度设置明确范围:

    torch.onnx.export(model,
                      torch.randn(1, 200, 80),
                      "example.onnx",
                      dynamic_axes={"feats": {1: "seq_len"}},  # 标记第2维为动态维度
                      opset_version=17,
                      input_names=["feats"],
                      output_names=["embs"],
                      export_params=True,
                      do_constant_folding=True)
    

    或者给CUDA执行器配置提前搜索最优算法的策略:

    provider_options = [{
        "device_id": 0,
        "cudnn_conv_algo_search": "EXHAUSTIVE",  # 提前遍历最优卷积算法
        "enable_cuda_graph": True  # 启用CUDA Graph,配合形状缓存复用内核
    }]
    session = ort.InferenceSession('example.onnx',
                                   sess_options=so,
                                   providers=['CUDAExecutionProvider'],
                                   provider_options=provider_options)
    
  • 预热高频输入形状:提前用业务中常见的输入形状跑几轮推理,让ORT提前编译好对应内核,消除正式运行时的初始延迟:

    # 预热业务中高频出现的形状
    warmup_shapes = [200, 400, 600, 800, 1000]
    for seq_len in warmup_shapes:
        array = np.zeros((1, seq_len, 80), dtype=np.float32)
        session.run(output_names=['embs'], input_feed={'feats': array})
    
    # 正式推理流程
    for i in tqdm(range(1000)):
        array = np.zeros((1, random.randint(200, 1000), 80), dtype=np.float32)
        embeddings = session.run(output_names=['embs'], input_feed={'feats': array})
    
  • 调整形状缓存策略:ORT默认会缓存已编译的形状内核,可通过配置增大缓存容量,确保常用形状的内核都能被复用:

    so = ort.SessionOptions()
    so.inter_op_num_threads = 10
    so.intra_op_num_threads = 10
    so.enable_shape_inference = True
    so.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL
    # 增大形状缓存容量,避免频繁淘汰已编译内核
    so.set_session_config_entry("session.set_cache_capacity", "100")
    session = ort.InferenceSession('example.onnx',
                                   sess_options=so,
                                   providers=['CUDAExecutionProvider'])
    

内容的提问来源于stack exchange,提问作者Speсtra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 14:16:32