先说一个判断:绝大多数 AI 项目的问题,并不是算力不够,而是还没有一套完整的评估流程,就急着采购 GPU、扩容集群、搭建大规模的推理平台。这个标题 "Don't Scale Yet, Because of AI" 本身就代表了一种工程态度——在模型效果、性能指标和业务流量都没有验证清楚之前,不要因为“别人都在上 AI”就跟着做基础设施层面的扩张。
本文按工程实践的角度来拆这件事。我会先讲清楚为什么 AI 项目不建议一上来就 Scale,然后给出一套从环境准备、小规模验证、压测评估到扩容决策的完整流程。文章不会给具体某个框架的安装命令,因为这不是一个软件安装教程,而是一套容量规划的方法论。但我会给出可复用的压测脚本、监控命令和决策清单,读者可以拿着这套方法去评估自己手上的 AI 服务。
如果你正在负责 AI 项目的架构选型、资源申请或平台建设,这篇文章值得收藏。先把评估链路跑通,再决定要不要扩容,能省下大量成本。
1. 核心决策点速览
在展开细节之前,先把整篇文章涉及的关键决策点列出来。下面这张表可以当作下一篇扩容评审会的检查清单。
| 决策点 | 核心内容 | 常见误区 | 建议动作 |
|---|---|---|---|
| 项目阶段判断 | 确定当前处于 POC、小规模试运行还是生产扩容阶段 | 跳过 POC 直接采购大规模 GPU 集群 | 用最小可运行环境完成效果验证 |
| 模型效果基线 | 明确模型的准确率、误报率、生成质量是否满足业务要求 | 只看演示效果好,不看边界场景失败率 | 准备带标签的评估数据集,量化效果指标 |
| 推理性能基线 | 测量单卡延迟、吞吐量、并发上限 | 用单条请求耗时推断整个系统容量 | 用压测工具模拟真实并发,拿到吞吐曲线 |
| 业务流量预估 | 确认真实的调用量、峰值时段、增长趋势 | 按最乐观的预测申请资源 | 先按最小成本上线,保留横向扩展能力 |
| 成本模型 | 计算单次推理成本、单卡月成本、人力维护成本 | 只看硬件采购价,忽略电费、运维和模型更新成本 | 用容量评估脚本换算每千次调用成本 |
| 扩容条件 | 建立触发扩容的量化指标 | 只要延迟变高就加机器,不做根因分析 | 延迟变高先查代码、推理参数和数据问题 |
这张表背后的逻辑是:扩容应该是数据驱动的结果,而不是焦虑驱动的动作。
2. 为什么 AI 项目不能上来就 Scale
很多团队在 AI 项目上犯的第一个错误,是把“上 AI”等同于“买算力”。实际运行一段时间后会发现,真正卡住项目的往往不是 GPU 数量,而是下列几个问题。
2.1 模型效果未验证,扩容没有任何意义
如果一个模型在业务数据上的准确率只有 70%,而业务要求是 90%,那么扩容一万张卡也无法解决效果问题。模型效果问题要靠数据清洗、微调、提示词优化或更换模型架构来解决,和 GPU 数量没有直接关系。
在没有量化效果基线之前做扩容,相当于把解决方案建立在未经验证的前提上。后面一旦发现模型效果不达标,前期采购的 GPU 资源就变成了沉没成本。
2.2 模型迭代速度快,硬件选型容易踩空
AI 模型的迭代周期比传统软件短得多。今天用 7B 模型,下个月可能换 14B 或 MoE 结构;今天用纯文本模型,下个月可能要接入多模态。如果一开始就按照某个具体模型的显存需求采购硬件,模型一换,硬件配置可能就不匹配了。
更稳妥的做法是:先小规模跑通当前模型,记录显存占用、吞吐量和延迟数据,用这些数据作为未来选型参考,而不是拍脑袋定配置。
2.3 扩容成本不只是 GPU 采购价
大规模扩容还意味着机房机柜、散热、电力、网络带宽、运维人力和监控体系的全面投入。一套 GPU 集群的年度总拥有成本,通常接近硬件采购价的两倍。
在业务流量还没有起来之前,这些成本无法被分摊。所以更合理的节奏是:小规模验证、逐步放量、按需扩容。
2.4 AI 技术栈的工程链路不成熟
模型部署之后还要处理 API 网关、鉴权、限流、日志、监控、模型热更新、多版本管理等问题。这些工程链路如果没有先在小流量下打磨成熟,直接上大规模集群,出了问题排查难度会成倍上升。
先让一套最小可运行环境承载真实业务流量,哪怕每天只有几百次调用,也能暴露大量工程问题。
3. 适用场景与使用边界
这套“先不扩容、先做验证”的思路,并不是所有场景都适用。下面区分一下边界。
3.1 适合先验证再扩容的场景
- 内部办公工具:比如文档摘要、智能问答,用户量有限,可以先跑小规模。
- 初创产品的 AI 功能:功能是否被用户接受还不确定,没必要大规模放量。
- 企业内部知识库问答:数据敏感,需要先验证效果和数据安全,再决定部署规模。
- 周期性业务:流量有明显波峰波谷,可以通过限流和任务队列控制规模,而不是盲目扩容。
3.2 不适合过度推迟扩容的场景
- 已明确有高并发需求的核心业务:比如电商大促期间的用户画像推理。
- 对延迟极其敏感的场景:比如实时风控、实时翻译,压测必须严格按峰值进行。
- 监管或合同明确要求的 SLA:如果 SLA 要求 99.95% 可用性,那么资源冗余必须提前准备。
即便在这些场景下,也应该先做小规模压测,用数据推算需要多少资源,而不是凭感觉买。
3.3 合规与安全边界
涉及用户数据、人脸信息、语音数据或版权素材的 AI 项目,扩容之前必须先确认数据来源合法、使用已获授权。隐私风险评估也要提前完成。大规模部署意味着数据集中度更高,一旦发生泄露,影响面更大。
如果项目涉及人脸分析、声音克隆或生成式内容,必须严格遵守相关法律法规,并在部署文档中保留授权记录。
4. 扩容前的环境准备与评估基线
在讨论扩容之前,先把“评估基座”搭好。下面这些准备工作可以在小规模环境内完成,不需要额外采购硬件。
4.1 评估数据样本
准备三份数据集:
- 训练/微调样本:用于验证模型在业务数据上的效果。
- 验证样本:带标准答案,用于计算准确率、召回率等指标。
- 压测样本:模拟真实业务请求的输入,用于压力测试。
压测样本尤其重要。不要用同一个输入反复请求,这样会命中缓存,压测结果失真。至少准备 1000 条不同的输入,按真实业务的长度和复杂度分布。
4.2 日志与监控体系
在扩容之前就要把监控建好,否则扩容之后根本不知道系统瓶颈在哪儿。以下指标必须覆盖。
| 监控对象 | 指标 | 采集方式 |
|---|---|---|
| GPU | 显存占用、利用率、温度、功耗 | nvidia-smi、dcgm-exporter |
| 容器 | CPU、内存、网络、磁盘 IO | docker stats、cAdvisor |
| 应用 | 请求延迟、吞吐量、错误率 | Prometheus + Grafana |
| 业务 | 调用量、成功率、平均响应时间 | 业务日志 + 链路追踪 |
4.3 小规模环境配置
准备一套最小可运行环境,建议包含 1 到 2 张 GPU 或按实际需求选择 CPU 环境,这台机器的核心作用是把模型跑起来,拿到第一手性能数据。
环境内需要锁定几个关键版本:模型版本、推理框架版本、依赖包版本。AI 依赖更新很快,不锁版本,后面复现性能数据会非常困难。
4.4 模型推理参数记录
同一个模型在不同推理参数下的性能差异可能达到数倍。记录以下参数,作为压测的固定配置:
- 上下文长度(sequence length)
- 生成长度(max_tokens)
- batch size
- 采样参数(temperature、top_p)
- 是否开启流式输出
- 量化方式(FP16、INT8、INT4 等)
参数记录得越细,后续容量估算就越准。
5. 小规模验证与效果基线测试
环境准备好之后,开始第一轮验证。这一轮不追求高并发,而是把模型效果和单机性能基线摸清楚。
5.1 模型效果验证
将验证数据集输入模型,记录输出结果,并与标准答案对比。这里要关注的是:
- 准确率是否能满足业务要求。
- 在边界输入(长文本、低质量图片、口音明显的语音)下的表现。
- 是否出现明显的幻觉或错误输出。
如果模型效果不达标,先不要扩容。此时应该回到数据清洗、提示词工程或微调环节。
5.2 单机性能基线测试
写一个简单的并发脚本,对单机推理服务发起请求,观察延迟和吞吐量。
import threading import time import requests from statistics import mean, median # 请替换为实际服务的地址和请求格式 url = "http://127.0.0.1:8000/generate" payload_template = { "prompt": "请用一句话总结:AI 基础设施建设中的容量规划方法。", "max_tokens": 128, "temperature": 0.7, } results = [] def send_request(index): payload = payload_template.copy() payload["prompt"] = payload["prompt"] + str(index) start = time.time() try: response = requests.post(url, json=payload, timeout=60) cost = time.time() - start results.append({"index": index, "status": response.status_code, "cost": cost}) except Exception as e: results.append({"index": index, "status": "error", "cost": time.time() - start}) threads = [] for i in range(20): t = threading.Thread(target=send_request, args=(i,)) threads.append(t) t.start() for t in threads: t.join() costs = [r["cost"] for r in results if r["status"] == 200] if costs: print("成功请求数:", len(costs)) print("平均延迟: {:.2f}s".format(mean(costs))) print("P50 延迟: {:.2f}s".format(median(costs))) print("最大延迟: {:.2f}s".format(max(costs)))这个脚本用 20 个并发线程做简单压测。如果平均延迟在可接受范围内,就继续加大并发;如果延迟显著拉高或出现失败请求,说明当前配置已经接近容量上限。
5.3 长文本与高分辨率压力测试
根据业务类型增加边界测试:
- 文本模型:用 8k、16k、32k 长度的输入分别测试,记录延迟和显存变化。
- 图像模型:用不同分辨率输入测试,观察生成时间和显存占用。
- 语音模型:用长音频和短音频分别测试。
边界测试的目的是找到单机能力的上限,为后续容量规划提供数据支撑。
5.4 判定基线是否达标的参考标准
- 效果指标:准确率/评分达到业务阈值。
- 单请求延迟:P95 延迟满足业务要求,通常建议预留 30% 的余量。
- 并发能力:在目标并发下,错误率低于 1%。
- 稳定性:连续运行 1 小时以上,无内存泄漏或显存持续增长。
6. 容量估算与压测方法
拿到单机基线数据后,下一步是估算“业务流量需要多少台机器”。
6.1 压测工具选择
按部署方式不同,选择不同压测工具。
| 场景 | 工具 | 特点 |
|---|---|---|
| 快速验证 | Python 脚本 | 灵活,适合自定义请求体 |
| HTTP 服务 | Apache Bench(ab) | 简单,适合小规模压测 |
| 复杂场景 | Locust | 支持分布式压测、自定义用户行为 |
| gRPC 服务 | ghz | 专用于 gRPC 接口 |
| 全链路压测 | 云厂商压测平台 | 流量真实,适合大促前验证 |
6.2 压测指标解读
压测过程中,重点关注四个指标:
- 吞吐量(QPS/TPS):每秒完成的请求数。
- 延迟(Latency):单次请求的响应时间,关注 P50、P95、P99。
- 错误率(Error Rate):失败请求占比。
- 资源利用率(GPU/CPU/内存):判断瓶颈在哪一侧。
压测完成后,画出“并发数-延迟”曲线。延迟从某个并发点开始急剧上升,这个点就是系统的容量拐点。
# 容量估算示例:根据压测结果估算所需节点数 def estimate_nodes(qps_per_node, peak_qps, safety_factor=1.5): """ qps_per_node: 单节点在可接受延迟下的最大吞吐量 peak_qps: 业务预估峰值吞吐量 safety_factor: 安全系数,建议 1.5 到 2.0 """ required_capacity = peak_qps * safety_factor nodes = required_capacity / qps_per_node return math.ceil(nodes) # 示例:单节点 50 QPS,业务峰值 300 QPS # 预估节点数 = 300 * 1.5 / 50 = 9 台这段代码的核心是:容量规划必须留安全余量,但不能按最坏情况无限放大。
6.3 从压测数据反推资源需求
假设压测得到以下数据:
- 单张 GPU 在延迟 2 秒内可承受 20 个并发。
- 每个并发平均占用显存 6GB。
- 业务峰值需要 200 个并发。
那么需要的 GPU 数量大约是 200 / 20 = 10 张。这就是从数据反推资源需求的基本方法。
7. 资源占用与性能观察方法
压测过程中要持续观察资源占用情况,判断系统瓶颈到底在 GPU、CPU、内存还是网络。
7.1 GPU 状态观察
# 实时查看 GPU 使用情况,每秒刷新 watch -n 1 nvidia-smi # 如果安装了 NVIDIA DCGM,可以用 dmon 看更细的指标 nvidia-smi dmon -s pucvmet -c 60观察重点:
- 显存占用是否接近上限。如果显存已经打满但 GPU 利用率很低,说明显存是瓶颈,可能需要换更大显存的卡或降低 batch size。
- GPU 利用率是否长期低于 50%。如果利用率很低,可能是数据加载或预处理环节拖慢了速度,扩容 GPU 解决不了问题。
- 温度是否过高。温度超过 85 度会触发降频,导致性能下降。
7.2 容器与进程资源观察
# 查看容器资源占用 docker stats # 查看进程级别的 CPU 和内存占用 top -p $(pgrep -f python)如果 GPU 利用率不高但 CPU 已经打满,大概率是数据预处理或 tokenizer 环节成为瓶颈。此时优先优化数据流水线,而不是扩容 GPU。
7.3 降低资源占用的常见手段
在追加硬件之前,先尝试这些手段:
- 减少 max_tokens 长度,很多业务场景并不需要很长的生成内容。
- 使用流式输出,改善用户感知延迟。
- 开启连续批处理(continuous batching),提高 GPU 利用率。
- 尝试模型量化(INT8、INT4),在效果损失可接受的前提下降低显存占用。
- 用缓存减少重复请求的推理开销。
8. 什么情况下才真正需要 Scale
先明确扩容的触发条件,避免“凭感觉扩容”。
8.1 量化触发条件
以下指标同时满足时,可以考虑扩容:
- 模型效果基线已达标,且经过业务方确认。
- 单机在合理延迟下的吞吐量已经摸清。
- 当前流量接近或超过单机容量的 70%,且持续一周以上。
- 通过代码优化、推理参数调优和量化等手段后,性能提升空间已不大。
- 业务流量预期有明确的增长曲线,有数据支撑。
8.2 分级扩容策略
扩容不一定要一次性到位,可以采用分级策略:
- 第一级:增加同规格 GPU 机器,纯横向扩展。
- 第二级:引入负载均衡和自动伸缩,根据流量动态调整节点数。
- 第三级:如果单机吞吐量长期不达标,再考虑更换更高算力的 GPU 或升级网络架构。
每一级扩容之后,都要重新压测,验证新增资源是否真正提升了吞吐量。
9. 常见误判与排查方法
下面是 AI 项目扩容决策中最常见的问题和排查方法。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 单卡显存不够用 | 模型参数量大且未量化 | 查看 nvidia-smi 显存占用 | 使用量化版本,或减小 batch size |
| GPU 利用率很低但响应慢 | 数据预处理或网络IO成为瓶颈 | 查看 CPU 和网络指标 | 优化数据加载、增加缓存 |
| 并发一高就报错 | 服务未配置连接池或限流 | 查看应用日志和错误码 | 增加连接池,配置限流策略 |
| 压测结果不稳定 | 压测数据量少或命中缓存 | 检查请求数据是否重复 | 使用 1000 条以上不同数据 |
| 扩容后吞吐量没有提升 | 负载均衡配置不当或单点瓶颈 | 检查流量是否均匀分发 | 排查网关和集群调度策略 |
| 显存持续增长 | 存在显存泄漏 | 连续运行并观察显存曲线 | 升级推理框架,排查长期运行任务 |
| 模型效果时好时坏 | 输入数据分布变化 | 对比在线数据和验证集差异 | 建立数据漂移监控 |
排查顺序很关键:先看应用日志,再看资源指标,最后才考虑扩容。很多时候问题出在代码或参数配置,而不是硬件不足。
10. 最佳实践与决策清单
10.1 建立可重复的评估流程
把效果验证、压测、容量估算做成一套可重复执行的流程。每次模型版本更新或业务流量变化,都重新走一遍评估流程。评估结果记录在文档中,作为扩容决策的依据。
10.2 通过小流量验证工程链路
即使业务量很小,也建议先上线真实服务,用小流量验证 API 网关、鉴权、日志、监控、模型更新等工程链路。这些环节在小流量下暴露的问题,比任何预压测都真实。
10.3 分批扩容并持续观察
扩容应分批进行。每新增一批节点,观察至少 24 小时的延迟、吞吐和错误率,确认没有引入新问题之后,再继续下一批。
10.4 记录成本数据
每批扩容后,记录 GPU 月成本、单次推理成本、运维人力成本。这些数据用于回答管理层最常问的问题:“这个 AI 项目到底值不值?”
10.5 合规提醒
涉及用户数据、人脸、声音、版权素材的 AI 项目,扩容前必须确认授权链条完整。数据存储和模型服务的部署位置需符合业务合规要求。大规模部署意味着数据集中度更高,风险评估和应急预案要提前做好。
10.6 决策清单
扩容评审会上,逐项确认以下内容:
- 模型效果基线已量化,且达到业务阈值。
- 压测数据完整,包括单机吞吐量、延迟分布、资源占用。
- 当前流量与扩容后流量的预期差异有数据支撑。
- 代码、推理参数、依赖版本已锁定并记录。
- 监控告警覆盖 GPU、容器、应用和业务四个层面。
- 成本模型已更新,扩容后的单位成本下降或可接受。
- 数据合规与授权检查已完成。
这七项全部满足,再启动扩容流程。任何一项不满足,都应该先回到对应环节补齐。
11. 总结与下一步
这套“先验证、再扩容”的方法,核心不是否定硬件投入,而是把扩容从“焦虑驱动的拍脑袋”转变成“数据驱动的工程决策”。实际操作时,建议先完成以下三件事:
第一,用最小可运行环境跑通模型,确认效果是否达标。这是扩容的前提。第二,用压测脚本拿到单机吞吐量、延迟和资源占用数据,建立一个性能基线。第三,建立监控和成本记录机制,让每一次扩容都有据可查。
最容易踩的坑有两个:一是拿演示效果当实际效果,二是用单次请求延迟推断整个系统的容量。这两点都会导致扩容决策严重失真。
如果评估后确实需要扩容,后续可以继续思考几个方向:自动伸缩策略、多模型混部调度、GPU 共享调度、推理缓存层设计。每一步都建立在实际数据之上,就不会白花钱。