指出自托管成本计算常遗漏峰值冗余和人力运维成本,给出包含硬件峰值预留和3am故障处理等人力因素的修正公式。
标准计算取 GPU 实例的小时价格,乘以 730 小时,除以该实例理论上一个月能产生的 token 数,再与 API 价格比较。它产生了一个诱人的数字,却在两个方向上犯了错误,而且两个错误都指向同一侧。
首先,它假设加速卡整月都在忙。它不会:你必须按峰值容量配置,账单却要覆盖整个低谷期。其次,它忽略了人力。有人部署 serving 栈、升级它、在凌晨三点处理 OOM 崩溃、为下一个模型做基准测试、维护自动扩缩容。这些小时数才是往往决定结果的那一项,而它们恰恰是博客文章里永远缺失的那一项。
从诚实的单位开始。设 H 为实例的小时价格(所有加速卡的总价,不是一张),tps 为它在所有并发请求上持续达到的输出 token 每秒数——这是批处理下的总吞吐量,不是单流速率,后者要低好几倍,偏偏是人们不小心用的那个数字。
每百万输出 token 的成本,满载利用:
C_full = H * 1e6 / (tps * 3600)
代入计算,两个输入都明确声明为假设——用你实际会租的实例在云厂商定价页上的列表价格,以及在你自己的模型和序列长度上测量过的吞吐量,而不是供应商基准里的数字。取 H = $10.00/小时,tps = 1,500:
C_full = 10.00 * 1e6 / (1500 * 3600)
= 1e7 / 5.4e6
= $1.85 per million output tokens
对照比如说 $3.00/百万输出 token 的 API 价格,看起来节省了 38%,会议到此结束。但不应该是这样,因为 C_full 是一个你永远付不到的数字。
你按小时租用实例,无论它是否在工作。设 u 为利用率——你实际消耗的租用容量的比例,按月平均。
C_actual(u) = C_full / u
与 API 价格 P 的盈亏平衡点:
u* = C_full / P
C_full = $1.85,P = $3.00 时:
u* = 0.62 -- 需要 62% 的持续利用率才能盈亏平衡
现在问 u 能是多少。对于交互式流量你是按峰值配置的,所以利用率的上界是平均负载与峰值负载的比值。一个工作日 traffic 形态且峰值/均值比为 4:1 的产品,在固定集群上最高不超过 25%,这使得 C_actual = 1.85/0.25 = $7.40/百万——接近 API 价格的 2.5 倍——这还没算上任何维护人员的工资。
自动扩缩容有帮助,但不能拯救它,因为模型服务器的冷启动以分钟计:将数十 GB 的权重加载到加速卡上不是容器启动。你最终会保持预热余量,而预热余量不过是另一种叫法的空闲容量。
例外是真实存在的:批处理工作负载可以接近 u = 1。如果你有一个任务队列且没有延迟要求,你可以构造性地保持加速卡饱和——这与供应商提供异步请求折扣是同一个经济事实。离线 enrichment 的自托管和聊天端点的自托管是不同决策,答案也不同。
这个模型里一个令人欣慰的意外是:运维工作量不需要一条单独的、可以争辩的明细行。每月运维成本除以和所有其他项相同的分母,所以它等效于小时费率的增加:
H_eff = H + F / 730
F 每月运维成本(工程师小时数 * loaded rate,
加上监控、镜像仓库、权重存储、出口流量)
然后以上所有公式中用 H_eff 代替 H。
代入计算,延续上面的例子,假设每月 20 工程师小时,loaded rate $120/小时:
F = 20 * 120 = $2,400 / month
H_eff = 10.00 + 2400/730 = 10.00 + 3.29 = $13.29 / hour
C_full = 13.29 * 1e6 / (1500*3600) = $2.46 per million
u* = 2.46 / 3.00 = 0.82
盈亏平衡利用率从 62% 移动到了 82%。
在交互式流量上达到 82% 的持续利用率不是一个需要努力的目标,它在算术上就不可得。这就是本页诚实的主题:盈亏平衡点是一个利用率数字,而运维工作量才是把它推到够不着位置的推手。每月 20 小时也是一个温和的假设——第一个月远远不止,而且每次模型升级都是一个项目。
如果你想让模型完整,有两个精细化处理。输入 token 的服务成本比输出 token 便宜很多,所以与混合 API 价格做公平比较时,应该考虑你的输入:输出比,而不是把所有都按输出费率定价。预留实例或 spot 价格会大幅改变 H——尤其是 spot 可以减半,但它带来的中断对于有五分钟预热时间的推理服务器来说很难处理。
成本不是唯一的维度,对其他维度坦诚才能让成本分析可信。
自托管在数据驻留和可向审计员证明的处理保证上胜出;在有高、稳定、可批量化的工作负载(u 能真正接近 1)上胜出;在没有人托管的自定义或微调权重上胜出;在不受速率限制和弃用通知束缚上胜出;在极大规模下有可预测的单位成本(因为集群足够大,峰值/均值被平滑掉了)上胜出。
API 在持续高利用率以下的一切上胜出;在 traffic 波动大和交互式的场景上胜出;在获取不到权重的前沿模型上胜出;在通过修改一个配置值就能切换模型的能力上胜出;在不需要为一个推理服务器拥有 on-call 轮值上胜出。
混合方案很常见,而且不是妥协:在你自己的硬件上以高利用率承载稳定的可批处理基线流量,把交互峰值突发到 API。只有在这样一种配置下,比较好处的两边才都运行在它们便宜的区间里。
无论结果如何,用 u 作为一个显式变量来跑这些数字,并展示敏感性分析,因为 u 是所有人最乐观的那个输入,也是决定答案的那一个。