免费算力集群准入判断:本地演练 Free-Path Dwell

用 dwell 与截止松弛的准入数学,判断免费路径是否仍是正确押注。
文章指出夜间批处理中「资源空闲」与「队列年龄攀升」可以同时成立,因为利用率不承诺服务时间。作者提出 free-path dwell = 队列年龄 + 预期服务时间 + 重试税,并将其与剩余截止松弛比较:只有 dwell 装得下 slack 才允许走免费路径,否则推迟或转预留 Worker。核心陷阱是免费重试——它只有额外秒数仍能装进 slack 时才真正更便宜。文章给出一个本地 Python 演练脚本,用 admit_free / defer / reserved 三种决策演示六个样本,并注入非正服务时间与负 slack 两个失败关闭守卫。最后落到工程实践:按墙钟秒数给 token 定价、对 slack 错过而非空闲主机告警、用功能标志做 5% 金丝雀并保留可排空的回滚路径,以及该方法的适用边界。
在夜间批处理窗口,你的免费 Worker 显示内存空闲、CPU 核空闲,但队列年龄已爬至 41 秒。距离原始入队截止还剩 90 秒,作业策略里还有两次未用的重试。提高并发看起来是温和的选择,而这一解读恰恰是错误的。

核心矛盾:空闲资源不等于服务时间承诺
主机利用率显示机器还有余量,队列年龄却显示批处理已经在滑向超时。你需要一个能调和两种视角的指标——本文称之为免费路径驻留时间(free-path dwell)。
计算方式很简单:dwell = queue_age + expected_service + retry_tax。把它与剩余截止松弛(deadline slack)比较,只有 dwell 仍能装进 slack 时,才允许走免费路径。若 dwell 超出 slack,免费容量就是错误押注,应当推迟作业或交给预留 Worker。
核心原则:不要在你不拥有的槽位上购买额外重试。便宜的令牌价格无法偿还错过的截止时间,真正会过期的是墙钟时间预算。
本地演练的声明式输入
在触碰任何主机之前,先把条件写下来。这个演练运行在本地进程,不在你的集群上。以下为示例输入,需要根据你的截止时间调整并记录变更,不要在看见通过结果后才调参:
- 批大小 40 个作业,每个先尝试一次
- 每个作业预估 1200 tokens 完成
- 免费路径预期服务时间 8 秒
- 入队时截止松弛 90 秒
- 重试税为一个完整服务间隔
- 可容忍的最大队列年龄 30 秒
注意 token 数是你的估算,不是厂商配额,也不是任何供应商的计费账单。这里测试的是准入数学,不是模型质量。
拓扑保持在一页内
保持组件足够小,让失败局部化。一个 gate 位于入队与所有 Worker 选择之间,它可以 admit、defer 或 shift 到 reserved:
enqueue -> dwell_gate -> free_path
|-> defer_queue
|-> reserved_path
Gate 读取四个字段并写入一个决策,每次尝试都要记录这些字段,包括拒绝的:
queue_age_s:作业入队后的秒数expected_service_s:已声明的服务时间retry_tax_s:一次未使用尝试的墙钟秒数价格deadline_slack_s:截止时间减去已流逝墙钟时间decision:admit_free、defer或reserved
利用率留在仪表盘上,不进入 gate 内部——它解释的是主机热不热,不是队列晚不晚。Slack 才是阈值,因为截止时间是绝对事实。队列年龄拥有一票否决权,而非全部决策权:一个年轻的队列如果重试税很肥,仍然可能输掉。
在笔记本上运行 Gate
将以下脚本保存为 dwell_gate.py,用 Python 3 运行,不要放到集群上。它不调用模型,也不开放端口。
#!/usr/bin/env python3
# Local admission drill. Expected lines are comments, not your metrics.
from dataclasses import dataclass
@dataclass
class Job:
queue_age_s: float
expected_service_s: float
retry_tax_s: float
deadline_slack_s: float
max_queue_age_s: float = 30.0
def dwell(job: Job) -> float:
return job.queue_age_s + job.expected_service_s + job.retry_tax_s
def decide(job: Job) -> str:
if job.queue_age_s > job.max_queue_age_s:
return 'defer'
if dwell(job) > job.deadline_slack_s:
return 'reserved'
return 'admit_free'
def decide_safe(job: Job) -> str:
if job.expected_service_s <= 0 or job.deadline_slack_s <= 0:
return 'defer'
return decide(job)
samples = [
Job(12, 8, 8, 90), # expected admit_free
Job(41, 8, 8, 90), # expected defer, age cap
Job(20, 8, 8, 30), # expected reserved, dwell over slack
Job(20, 8, 0, 30), # expected admit_free, retry tax removed
Job(10, 0, 8, 90), # expected defer, non-positive service
Job(10, 8, 8, -1), # expected defer, negative slack
]
if __name__ == '__main__':
for i, job in enumerate(samples, start=1):
choice = decide_safe(job)
print(
'job=%s dwell=%.0f slack=%.0f decision=%s'
% (i, dwell(job), job.deadline_slack_s, choice)
)
用一条本地 Python 命令运行文件,保持在保存脚本的目录下。文件缺失是演练错误,不是容量信号。
python3 dwell_gate.py
预期输出
把以下内容视为预期输出,而不是测量结果:
job=1 dwell=28 slack=90 decision=admit_free
job=2 dwell=57 slack=90 decision=defer
job=3 dwell=36 slack=30 decision=reserved
job=4 dwell=28 slack=30 decision=admit_free
job=5 dwell=18 slack=90 decision=defer
job=6 dwell=26 slack=-1 decision=defer
逐条解读:Job 1 装得下,免费路径是可接受押注;Job 2 在 slack 上年轻但在队列年龄上已老,推迟它而不是指望共享槽位清空;Job 3 队列年龄仍在帽下,但 dwell 超出 slack,因此离开免费路径;Job 4 去掉重试税后又装得下了——这正是重试策略里的陷阱,免费重试只有在额外秒数仍能装下时才真正更便宜;Job 5 服务时间为零,守卫推迟;Job 6 slack 为负,不予准入。两个守卫都失败关闭,这正是演练的意义。
| queue_age_s | dwell_s | slack_s | decision | why |
|---|---|---|---|---|
| 12 | 28 | 90 | admit_free | dwell 装得下且年龄年轻 |
| 41 | 57 | 90 | defer | 年龄帽先于 slack 触发 |
| 20 | 36 | 30 | reserved | 年龄没问题,dwell 不行 |
| 20 | 28 | 30 | admit_free | 重试税移除后 dwell 装得下 |
| 10 | 18 | 90 | defer | 服务时间猜测非正 |
| 10 | 26 | -1 | defer | 截止时间已过 |
注入一个无聊的失败
在信任打印出的 gate 之前,先注入一个卡住的尝试:队列年龄设为 50,slack 设为 40,强制重试税为完整服务间隔 8。Dwell 变为 66 对 40 秒 slack,年龄帽先触发,打印决策应为 defer。如果脚本仍打印 admit_free,停止上线。
第二次注入把预期服务时间设为零。Dwell 会少算,gate 会过早准入——在比较之前拒绝非正的服务时间猜测。负 slack 意味着截止时间已经过去,应当推迟、告警,不要把这次错过藏在重试里。
清理工作就是删除本地脚本并停止进程:
rm -f ./dwell_gate.py
如果有 unit 或 cron 复制了这个演练,先禁用该 unit,再确认进程表不再显示脚本。在生产标志上保持不动,直到下文的金丝雀部分。
按占用的秒数给 token 定价
一次免费完成仍然花费你无法退回的墙钟时间。把估算 token 数乘以 dwell 秒数,得到一个压力计——这个乘积不是账单,也不是基准。
1200 tokens 持续 66 秒是很重的等待;同样的 tokens 在 8 秒的预留轮次上分量要轻得多。你买的是时钟时间,不只是补全文本。把重试算作额外的 token 副本,而不是免费的再来一次——两次尝试可能让 token 负载和 dwell 翻倍。如果模型跳转有自己的队列,也要把那个年龄加进去,零价格不会让第二个队列瞬间完成。
**墙钟时间(wall-clock time)**与 CPU 时间是两种不同的计量口径。CPU 时间只累计进程真正占用处理器执行指令的秒数,一个因等待 I/O、排队或限流而阻塞的进程几乎不消耗它。墙钟时间则是从起点到终点真实流逝的物理秒数,无论进程处于运行、就绪还是阻塞状态都在走。对于截止时间敏感的批处理,有意义的永远是墙钟时间:作业在队列里等待的每一秒都在吃掉 deadline slack,但主机利用率指标看不到这段等待。这就是「内存空闲、CPU 空闲,队列年龄却爬到 41 秒」能同时成立的根源——利用率统计的是资源占用,而不是你的作业距离截止还有多远。因此准入判断必须建立在墙钟量(队列年龄、服务时间、重试税)之上,把利用率降到解释性仪表盘的位置。
免费路径被允许帮助的边界
披露:本文是作为 MonkeyCode 产品推广的一部分准备的。本稿的操作员笔记提到两项可用性声明:一是免费模型访问,二是免费服务器选项。
这两项声明都没有说明配额、芯片或过期时间。在规划之前,请在当前产品文档中确认这些事实。免费路径对这批作业仍可能是错误押注。
只在 dwell gate 返回 admit_free 时使用它。 免费服务器适合这类本地工作——用它来重放 gate,而不是吸收晚到的队列。如果该选项明天消失,你的 SLO 仍必须成立,不要把回退放在同一个免费主机上。预留意味着一个你可以排空和回滚的 Worker。共享免费容量不能成为回滚目标。把较长的试验放在可以安全推迟的作业上,只把 slack 充裕的作业指向免费模型路径。把截止时间工作留在你已经信任的预留路径上——免费访问可以承载演练,不能承载承诺。
值得在评审中争论的阈值
选择截止松弛作为主要的准入阈值。截止时间是墙钟事实,不是利用率指标。队列年龄是你在一旁观察的领先指标。利用率排第三,而且它不应该有投票权——冷 GPU 仍可能坐在别人的队列后面,热 GPU 只要你的 dwell 装得下仍可以服务你。
针对上述声明工作负载的起始帽:队列年龄超过 30 秒推迟;dwell 超出剩余 slack 时离开免费路径;每个未使用的重试按一个完整服务间隔计价;拒绝零或负的服务时间猜测。用一周真实日志后重新审视 30 秒帽。如果推迟聚集在 20 秒附近,收紧该帽;如果预留切换占主导,说明你的服务时间猜测太胆小。
**截止松弛(deadline slack)**指作业的绝对截止时刻减去当前墙钟时刻所剩的秒数,它是一个随时间单调递减、归零即失败的硬预算。把它设为准入主阈值,而不是用利用率或队列年龄,是因为只有 slack 直接编码了「还来得及吗」这一事实。实践中 slack 分两层:入队时授予的初始松弛(示例中的 90 秒)与决策时刻的剩余松弛(示例中的 30 秒)。dwell 必须与剩余松弛比较才有意义——用初始松弛做判断会系统性高估余量。当 slack 为负,说明截止已过,任何重试都是把失败藏进后续尝试,正确动作是推迟并告警。同理,队列年龄只是领先指标:它年轻不代表安全(重试税可能很肥),它老也不必然致命(若服务极快且 slack 充裕),这也是为什么 gate 里年龄帽一票否决但其余决策交给 dwell 与 slack 的比较。
对错过告警,而不是对空闲主机告警
当 admit_free 决策后来记录到 slack 错过时才叫醒人。不要仅因为内存看起来满或空就告警——错过才是你着手避免的面向用户的失败。
decision=admit_free AND slack_miss=true
把该告警路由到与队列年龄页相同的频道,并在事件记录中附上 dwell、slack 和重试次数。缺了这三个字段,值班人员又会去追利用率。如果错过超过免费准入的 1%,冻结该标志。这个 1% 只是本次演练的起始线,投产前应替换为你的错误预算。
不排空错误队列的回滚方式
把 gate 放在标志后面发布,默认关闭。只准入 5% 批处理作业的金丝雀切片,观察 slack 错过、推迟率和预留切换率。如果错过率上升,关闭功能标志,排空已按前一稳定路径准入的作业,不要把推迟队列冲进免费 Worker。
在金丝雀开始之前把以下步骤粘贴进 runbook:禁用名为 dwell_gate_enabled 的功能标志;确认新作业在一分钟内跳过 gate;让在途预留作业完成,然后停止金丝雀主机;删除本地演练文件,防止 cron 复活它们。
当新决策不再出现在日志中时,回滚完成。保持预留池温暖,直到该日志行安静下来。半禁用的 gate 比没有 gate 更糟。
谁应该跳过这个方法
- 工作不能等也不能移动时跳过:没有预留回退的 pager 路径需要另一种设计,这个 gate 只在 admit、defer、reserved 之间选择。
- 需要亚秒级 slack 的交互式租约跳过:那种失败模式需要不同的保持时间控制,不要混入这个批处理截止演练。
- 需要模型质量基准时跳过:脚本从不发送 prompt,也从不给答案打分,不会告诉你哪个模型每 token 更便宜。
- 服务时间仍是未知分布时跳过:单一猜测的间隔会在长尾下说谎,自动化切换前先测量 p95 服务时间。
下一次评审前应该记录什么
每次决策保留一行,而不是每台主机一行。存储队列年龄、dwell、slack、决策和重试次数,从日志中丢弃原始 prompt,让成本文件保持小。
一周日志结束时审视三个比率,保持窗口固定以便可比:免费准入中后来错过 slack 预算的数量;本可在预留 Worker 上装下的推迟数量;dwell 本可免费装下的预留切换数量。
第一个比率意味着服务时间猜测太善良;第二个意味着你推迟了预留轮次本可以拯救的工作;第三个意味着年龄帽比截止时间更严格。一次只调整一个帽,然后重跑本地样本——同时改变年龄和 slack 规则会隐藏原因。把新帽写在旧预期输出行旁边。
免费容量是工具,不是常驻预留。当 dwell 装进你的 slack 时使用免费模型路径;装不下时,为你真正能排空的 Worker 付费。如果这些选项在你的账户中可用,重放样本,在任何批量附加之前在免费服务器上运行该重放——先检查当前文档,因为可用性不是 SLO。
相关推荐

OpenAI与Shield合作:Astra智能体如何革新IT故障修复
OpenAI与Shield合作推出Astra智能体,可自动登录电脑和遗留系统,实时修复IT故障,比传统模型快35%到40%,仅在需要人类判断时引入人工。

iPhone Duo续航实测:一天一充跑不掉,大屏是耗电元凶
iPhone Duo续航实测:重度使用一天需至少充电一次,6.5小时亮屏约剩30%电量。大屏展开频率是耗电关键,MagSafe电池背夹可救场,长期衰减同样值得关注。

Kimi K3.1 Pro开源发布:2.8万亿参数逼近Opus
Moonshot发布开源MoE模型Kimi K3.1 Pro,2.8万亿总参数、1040亿激活参数,Terminal Bench 4.0仅落后Opus 5.5不到1分,单任务成本约三分之一,API价格减半,开源权重11月4日开放。