我们如何把客服大模型推理成本压到$0.07/千次:Triton+FP8+Spot实例实录

从OOM到$0.07/千次:高吞吐AI推理的实战血泪史
做高吞吐AI推理服务,说实话,不是靠堆GPU就能搞定的。
我之前负责过很多项目,印象最深的还是去年帮一个电商客户重构他们的客服大模型。第一天上线,直接OOM(显存溢出)报警,整个服务崩了。那之后几个月,我们一直在跟延迟、吞吐量和账单赛跑。现在回头看,那段日子踩过的每一个坑,都成了后来的优化经验。

今天想聊聊这段经历——不是教科书式的流程,而是真实场景下的取舍。毕竟在真实业务里,"完美方案"往往不存在的,只有"最能打的组合"。
一、 从OOM开始:显存与部署的生死局
上线第一天,我们的模型在A100上跑着跑着就炸了。排查后发现,问题出在显存管理上:模型权重、激活值、还有推理过程中的临时缓存,全挤在一起,谁都不让步。
我当时做了几件事,顺序很关键:
先换框架。 之前我们用原生的PyTorch服务,虽然灵活,但并发控制太弱。果断切到 Triton Inference Server。为什么?它原生支持多模型热加载,而且动态批处理是它的杀手锏。
动态批处理配置是重点。 我调了很久,最终定下的参数是:
{
"name": "customer_service_model",
"backend": "tensorrt",
"dynamic_batching": {
"max_queue_delay_microseconds": 500,
"preferred_batch_size": [4, 8, 16],
"max_batch_size": 32
}
}
注意:max_queue_delay_microseconds 不能设太大。我们一开始设了1000微秒,结果P99延迟在请求突增时抖动超200ms——后来发现,延迟越高,突发流量一来,队列里的请求全堆积,等待时间指数级上升。
改到500微秒后,GPU利用率从42%拉到89%,这才是关键转折点。
二、 量化不是银弹:FP8的坑我替你们踩了
模型并行、流水线批处理,这些概念大家可能都懂。但真正让我头疼的是量化。
量化确实是降本利器,但别一上来就搞FP8——我踩过坑。
当时为了追求极致性能,直接上FP8。结果呢?校准数据少20%,P99延迟直接翻倍,模型准确率还掉了1.5个点。亏大了。
修正: 截至 TensorRT 9.3,原生FP8校准在TensorRT里其实不好直接用。我们最终用的是 TRT-LLM 的量化工具链,特别是它的 calibrate.py 脚本生成 scale 文件,配合 NVIDIA 的 fp8 分支才稳定跑起来。
INT8 更稳,但 FP8 在 A100/H100 上确实能省一半显存。取舍看场景:如果延迟容忍度低,用 INT8;如果能接受一点精度损失换吞吐,再上 FP8。
代码层面,我现在这么写(示意,非直接运行代码):
# 注意:这是TRT-LLM的调用方式,非原生TensorRT API
import tensorrt_llm
builder = tensorrt_llm.Builder(...)
config = builder.net.execution_policy()
config.set_quantization("fp8") # 实际通过TRT-LLM工具链配置
三、 并发控制:别让GPU哭
高吞吐不等于高并发。我之前犯过一个低级错误:开了Semaphore限制并发,结果GPU利用率反而低了——因为请求全卡在信号量外面,GPU闲着,请求排队着。
教训: 动态批处理比手动Semaphore管用多了。Triton 内部的批处理机制比手写asyncio更优雅,也更贴近硬件。
但如果必须控制并发(比如防止上游雪崩),我会这样写:
import asyncio
from asyncio import Semaphore
semaphore = Semaphore(50) # 根据GPU容量定,别硬猜
async def process_request(request: dict) -> dict:
async with semaphore:
return await inference_model(request)
注意:semaphore的值要经过压测。我们用 locust 压测时发现,50个并发在A10上刚好打满,再多就OOM。
四、 成本优化:账单不会骗人
成本优化不是喊口号,是实打实的数字。我们当时的账单每月几万刀,看着心疼。
三个动作:
- Spot 实例:客服模型是非实时核心交易,用竞价实例能省70%。我们切了G5.12xlarge Spot,单价直接腰斩。
- HPA 自动扩缩容:K8s 里配好 HPA,CPU/GPU 利用率超过阈值就扩容,低于阈值就缩。别人工干预,人力成本高。
- 预留实例保底:稳定基线流量用预留实例,突发用Spot。我们算过账,预留 Instance 成本降30-40%,但灵活度差。所以比例很重要:我们70% Spot + 30% 预留。
成本追踪我写了个小工具,监控 GPU 使用时长:
class CostTracker:
def __init__(self, gpu_type: str, hourly_rate: float):
self.gpu_type = gpu_type
self.hourly_rate = hourly_rate
self.total_seconds = 0
def record_usage(self, seconds: int):
self.total_seconds += seconds
def calculate_cost(self) -> float:
return (self.total_seconds / 3600) * self.hourly_rate
这个简单,但够用。后来接了 Prometheus + Grafana,实时看账单曲线,爽。
五、 测试:不压测就是赌博
建立性能测试体系,别靠感觉。我们用 locust 压测,重点盯三个指标:
- QPS:每秒查询数,决定吞吐量上限。
- P99 延迟:99%的请求延迟,比平均延迟更重要——平均会被长尾掩盖。
- GPU 利用率:低于70%说明资源浪费,高于95%说明瓶颈。
真实数据: 加了动态批处理后,QPS 涨了 3.2 倍,但 P99 延迟在请求突增时抖动超 200ms——就是上面说的 max_queue_delay_microseconds 设太激进的问题。改参数后,P99 稳定在 85ms 以内。
每次迭代前跑基准测试,对比优化前后效果。没有数据支撑的优化,都是耍流氓。
六、 结语:没有最好,只有最合适
回头看,从 OOM 到成本压到 $0.07/千次,靠的不是某个神奇技巧,而是一步步踩坑、修正、再踩坑的过程。
- 框架选 Triton,因为它懂 GPU。
- 量化用 TRT-LLM,别硬刚 TensorRT 原生 API。
- 并发靠动态批处理,别手写 Semaphore。
- 成本靠 Spot + HPA,别依赖人工。
- 测试靠数据,别靠直觉。
每个公司、每个模型场景都不一样。我的经验不一定适合你,但希望至少让你避开几个大坑。
如果你也在折腾高吞吐 AI 推理,欢迎交流。毕竟,降低成本、提升体验,是我们这行的永恒命题。
本文首发于 我们如何把客服大模型推理成本压到$0.07/千次:Triton+FP8+Spot实例实录 — https://lyxq.com.cn/zh/blog/ai-inference-high-throughput-cost-optimization
转载或引用请注明出处,商业使用请联系作者获得授权。