第72期 | 醒来的任务,能插队吗

操作系统 · · 九羲科技

第六章第七期。前面几期排了队、算了账、讲了堵车,这一期问一个更日常的瞬间:一个睡着的任务醒来,能不能立刻插队?键盘敲一下、网络包到了、锁放下了,醒来的任务站在正在跑的任务面前,内核让不让它先走?

一、醒来先问:你欠了多少

任务醒来的原因五花八门:等的数据到了,等的锁放下了,定的闹钟响了。内核不会因为"刚醒来"就无条件让它插队。CFS 时代的判断写成了一行算式:正在跑的任务的 vruntime,减去醒来任务的 vruntime,差值要大于一把按权重折算过的尺子,抢占才成立¹。这把尺子就叫 sched_wakeup_granularity_ns,权重大的任务,尺子按比例缩得更短。

差值不够,正在跑的先把手头一小段跑完,醒来的等下一个节拍。而且抢占也不是立刻换人,是先给正在跑的挂一块"需要重调度"的牌子,到系统调用返回、中断退出这样的安全点再换人。阈值存在的理由很实在:要是每次唤醒都插队,键盘、定时器、网络包轮番敲门,系统会在一次次切换里空转,缓存刚暖热又冷下来,吞吐先掉下来。尺子调小,响应快、切换多;尺子调大,吞吐稳、醒来的等得久——这是同一块跷跷板的两头。

敲键盘是最好的例子。敲一个键,终端进程醒来回显,慢了手指立刻感觉得到;可要是每个数据包、每个定时器都享有插队权,批量任务就永远跑不完一整段。EEVDF 把问法换了:醒来的任务先看有没有资格——lag 大于等于零才算系统欠它的,再算各自的虚拟截止期,谁的截止期更早谁先跑²。睡久了攒下的账也不会无限期有效,随虚拟时间慢慢衰减,醒来霸占 CPU 的老路被堵死了。

维纳的回路在这里正好套上³(思想化用):唤醒是感知,差值与尺子的比较是比较,抢占与否是执行。没有比较阈值的回路会抖个不停,有了阈值,才稳得住。

二、醒来不是特权,是意图到场

如果 AI 的操作系统先出现,它不会只问"欠了多少",还会问"为什么醒来"。一个 agent 醒来的原因各不相同:用户发来新问题,工具返回了结果,定时心跳到了,后台爬取完成了。旧调度器对这些一视同仁,只看账本上的欠账,不看醒来的理由。

原生的做法,是让每次唤醒带一张票:截止期是什么时候,预计跑多久,打断正在跑的任务要丢掉多少进度。票越急、跑得越短,越值得插队;一张"醒来要跑一小时批量活"的票,排队等下一个节拍更划算。按时间片切指令流的旧抽象,在这里又露一次馅:它能量一段代码跑了多久,却量不出"这一次醒来值不值得打断别人"。向量阵列时代还多一笔账:醒来的推理任务不只占 CPU 时间,还要看 KV 缓存还在不在显存里、权重需不需要重新暖——醒来的成本,不在时间账上。

还有一层平时看不见的东西:谁在受益,谁在买单。如果醒来总能插队,任务可以靠频繁醒来霸占 CPU,吵的比急的先跑。门口那把尺子不只是调响应速度的旋钮,也是一道防刷的护栏——跟第 68 期 min_vruntime 防"睡醒霸占"是一个道理。公平不只在队列里排,也在门口查票。

三、先数唤醒次数,再调那把尺

可以试的一步,是先别调任何参数,量一量你机器上"醒来"到底有多准。写个每 10 毫秒醒一次的小程序,记下每次实际睡了多久:

import time

mx = 0

for _ in range(600):

t = time.monotonic(); time.sleep(0.01)

mx = max(mx, time.monotonic() - t - 0.01)

print(f"最大多睡:{mx*1000:.1f} ms")

先单独跑一遍,记下最大多睡的毫秒数;再用 taskset 把一个空转任务和它钉在同一颗 CPU 上跑一遍,对比这个数被拉大了多少:

taskset -c 0 bash -c 'while true; do :; done' &

taskset -c 0 python3 wake.py

再看一对现成的数,知道它让出 CPU 的方式:

grep -E 'ctxt_switches' /proc/<进程号>/status

voluntary 是它自己睡着、等资源时自愿让出的次数,nonvoluntary 是它被别人抢占的次数。两个数对上,才知道抖动来自等醒,还是来自被抢。

一个提醒:今天的内核已经是 EEVDF,CFS 时代那把 sched_wakeup_granularity_ns 旋钮,在本机 7.0.0 内核上已经找不到了——别硬找文件,问法换成了截止期早晚。调参之前先看数,数没看清,旋钮拧哪边都是猜。

落到普遍场景里,同一条规矩:一台跑本地模型的机器上,在线问答醒来要回得快,批量评测醒来可以等,两种醒来不该用同一张票;一台边缘算力盒上关键控制环醒来是硬截止,日志整理醒来可以排队;视频 AI 平台里一帧解码完成醒来的推理任务,跑得短就值得插队;企业私有智能中心里 agent 被用户消息唤醒时,先看这条消息的截止期,再决定打断谁。先给醒来分类,再谈插队。

觉 然 小 注

醒来不是特权,是欠账到了该还的时候。门口那把尺,量的是急不急,不是吵不吵。

引 用 与 出 处

  1. [1] SysTutorials. How sched_min_granularity_ns, sched_latency_ns and sched_wakeup_granularity_ns in CFS affect the timeslice of processes. SysTutorials. https://www.systutorials.com/239998/sched_min_granularity_ns-sched_latency_ns-cfs-affect-timeslice-processes/
  2. [2] Linux 内核文档. EEVDF Scheduler. kernel.org. https://www.kernel.org/doc/html/next//scheduler/sched-eevdf.html
  3. [3] Norbert Wiener. Cybernetics: Or Control and Communication in the Animal and the Machine. John Wiley & Sons, 1948. (思想化用)

· · ·

← 返回资讯中心