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

Microsoft.ML.OnnxRuntimeGenAI并行请求性能问题及优化咨询

问题分析与优化方案

一、单请求耗时随并行数增加的原因

  1. 模型资源竞争:你将Model注册为单例,多个并行请求会共享同一个ONNX Runtime会话资源。虽然会话本身支持多线程,但模型计算(如ComputeLogits)的底层资源(CPU核心、内存带宽)会被多个请求分摊,导致每个请求的计算等待时间增加。
  2. 内存带宽瓶颈:并行请求会生成更多中间张量,内存读写操作增多,当内存带宽达到饱和时,每个请求的张量加载、计算速度都会下降,直接拉长单请求耗时。
  3. CPU核心利用率不足:从测试数据看,4个并行请求时CPU使用率仅~50%,说明当前的线程配置或模型并行策略没有充分利用CPU资源,多个请求的线程调度存在冲突,导致单请求能获取的计算资源减少。

二、基于Microsoft.ML.OnnxRuntimeGenAI的性能优化方案

1. 优化ONNX Runtime会话配置

给Model添加自定义的SessionOptions,调整线程数、执行模式和内存复用策略,提升多线程下的资源利用率:

// Program.cs中修改Model的创建逻辑
var sessionOptions = new SessionOptions();
// 根据CPU核心数设置内部并行线程数
sessionOptions.IntraOpNumThreads = Environment.ProcessorCount;
// 启用并行执行模式
sessionOptions.ExecutionMode = ExecutionMode.ORT_PARALLEL;
// 启用内存复用,减少内存开销和竞争
sessionOptions.EnableMemoryPattern = true;
// 如果有GPU,添加对应的执行提供者(比如CUDA/DirectML)
// sessionOptions.AppendExecutionProvider_CUDA();

builder.Services.AddSingleton(new Model(modelDirectory, sessionOptions));

2. 批量处理请求

将多个并行请求合并为批量输入,利用模型的批量计算能力,减少重复的模型加载和资源竞争。可以修改API支持批量请求:

// 修改TestController的Generate方法支持批量
[HttpPost("generate-batch")]
public List<string> GenerateBatch([FromBody] List<Dto> dtos)
{
    var tokenLists = dtos.Select(d => tokenizer.Encode(d.test)).ToList();
    
    using var generatorParams = new GeneratorParams(model);
    generatorParams.SetSearchOption("max_length", 2048);
    generatorParams.SetInputSequences(tokenLists);
    
    var results = new List<string>();
    using var generator = new Generator(model, generatorParams);
    
    while (!generator.IsDone())
    {
        generator.ComputeLogits();
        generator.GenerateNextToken();
    }
    
    foreach (var seq in generator.GetAllSequences())
    {
        results.Add(tokenizer.Decode(seq));
    }
    
    return results;
}

3. 优化生成循环逻辑

当前逐token解码的方式会带来额外开销,可以攒多个token后再一次性解码,减少Decode调用次数:

// 修改Generate方法中的循环
var resultTokens = new List<int>();
using var generator = new Generator(model, generatorParams);

while (!generator.IsDone())
{
    generator.ComputeLogits();
    generator.GenerateNextToken();
    var outputTokens = generator.GetSequence(0);
    var newToken = outputTokens.Slice(outputTokens.Length - 1, 1);
    resultTokens.AddRange(newToken.ToArray());
}

return tokenizer.Decode(resultTokens);

4. 使用量化模型

使用INT8量化后的Phi-3 ONNX模型,可以显著减少内存占用和计算量,提升多请求下的运行速度。你可以通过ONNX Runtime的量化工具对原始模型进行量化,或者直接下载官方提供的量化版本。

5. 启用GPU加速

如果有可用的GPU,通过添加GPU执行提供者(如CUDA、DirectML),可以将模型计算转移到GPU,利用GPU的并行处理能力,大幅降低多请求下的单请求耗时。只需要在SessionOptions中添加对应的执行提供者即可(如上述代码中的注释部分)。

测试数据回顾

Number of parallel requestsTotal time to complete all requestsAverage request complete timeRAM usingProcessor using
100:01:50.3000:01:50.184.3 Gb< 20%
200:03:07.8200:03:07.645.4 Gb~ 25 %
300:04:19.0600:04:18.736.6 Gb~ 30%
400:05:36.7400:05:35.967.8 Gb~ 50%

内容的提问来源于stack exchange,提问作者Vladyslav Lishchyna

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 22:08:17