Ollama total_duration远超阶段时长之和的原因及优化咨询
问题描述
在实现处理大型文档的服务时,调用Ollama Docker的Generate接口后发现,total_duration与load_duration、prompt_eval_duration、eval_duration三者之和存在超过5秒的差值,具体数据如下:
{ "total_duration": 8139553772, // 8.13秒 "load_duration": 44643610, // 0.04秒 "prompt_eval_count": 63859, "prompt_eval_duration": 205727569, // 0.20秒 "eval_count": 82, "eval_duration": 2676314808 // 2.67秒 }
请求携带了长token数组作为context(prompt_eval_count显示为63859个token),运行在本地环境,总载荷小于400kb,已排除网络带宽问题。仅当请求携带大context时会出现约5秒的差值,无context时该差值不存在。请求负载代码如下:
request_payload = { "model": "llama3.1", "prompt": "Who is the author of this document?", "context": contextualization_response["context"], "stream": False, "options":{ 'temperature': 0.5, 'num_ctx': 70000 } }
疑问:该差值的成因是什么?能否避免该额外耗时?
分析与解决方案
差值成因
- Context序列化/反序列化开销:大context是包含6万+token的数组,Ollama接收请求时需要将JSON格式的token数组反序列化为内部数据结构,返回响应前也要执行序列化操作。这部分CPU开销未被计入
prompt_eval_duration或eval_duration,但会被统计到total_duration中。 - Context内存预处理开销:Ollama需要将传入的context token加载到模型上下文窗口,涉及内存数据拷贝、对齐等预处理操作,这类操作的耗时未被拆分到公开的细分duration字段里。
- Docker容器调度开销:即使是本地环境,Docker容器处理大体积数据时,可能存在容器与宿主间的数据传输、内存页调度的额外开销,这部分耗时会被算入
total_duration但未被单独统计。
优化方案(避免额外耗时)
- 启用流式输出:将
stream设为True,Ollama无需等待完整响应生成再序列化返回,而是逐块输出,既能减少大context带来的序列化等待时间,也能让客户端更早获取部分结果。 - 调整Context传输方式:避免直接传输原始token数组,改为传输压缩后的文本(让Ollama自行完成tokenize)。虽然多了一步tokenize操作,但大context场景下,压缩文本传输+Ollama内部tokenize的总耗时,大概率低于传输大token数组的反序列化耗时。
- 扩容Ollama资源:给Ollama容器分配更多CPU核心和内存,减少内存页交换和CPU调度等待时间,缓解大context带来的预处理压力。
- 使用高效序列化格式:如果是自定义客户端,可尝试用MsgPack等比JSON更高效的序列化格式传输请求(部分Ollama版本已兼容),降低序列化/反序列化的CPU开销。
内容的提问来源于stack exchange,提问作者Marc Rosenfeld
相关产品推荐
相关产品推荐

