第32期 | 谁的 counter 大,谁先跑

操作系统 · · 九羲科技

一、谁的 counter 大,谁先跑

1991 年的调度器只有 38 行

1991 年 9 月 17 日,Linux 0.01 发布。kernel/sched.c 共 254 行,其中的 schedule()——决定"下一个瞬间谁占用 CPU"——只有 38 行。kernel.org historic 源码包,一手数过。

它像个记账本:每个进程头上顶着一个整数 counter,每 10 毫秒(HZ=100)do_timer() 减一。减到零就开会,把 64 个进程槽(NR_TASKS=64)扫一遍,谁的 counter 大谁上;全员归零就重发牌:counter = (counter >> 1) + priority,每人保底拿回 priority,再叠加上轮剩的一半。

Linux 0.01 kernel/sched.c 中的 schedule() 全文,共 38 行。来源:kernel.org historic 源码包(GPL)。

妙处藏在那句右移里。睡觉的进程(等 I/O 的)counter 没被扣,醒来额度反而多——I/O 密集型天然被优待。"交互优先"这个后来被 CFS 反复打磨的概念,1991 年就以一行位运算的形态存在了。新进程 fork 出来,copy_process 里 p->counter = p->priority,满血出生。

十六年后(2007),Ingo Molnár 的 CFS 并入 2.6.23,"公平"换了定义:不数时间片,改记 vruntime——在一台"理想多任务 CPU"上该跑多少,永远挑 vruntime 最小的跑。counter 记时间,vruntime 记"亏欠"。

维纳 1948 年在《Cybernetics》里说,一切控制都是"感知—比较—执行"的回路:do_timer 采样、schedule() 比较、switch_to 执行——1991 年的调度器,是维纳回路的一个 38 行实例。

0.01 没发明调度理论——Unix 的思想 1970 年代就成熟了。它赢在"先实际后原理":38 行先跑起来。当年追原理完美的 GNU Hurd,1991 年还不能用。

老子说"治大国若烹小鲜"(《道德经》第六十章):火候(时间片粒度)最要紧,翻动太勤,鱼就碎了。范式之眼追问:时间片切的是指令流,今天的算力主体却是向量阵列——拿 10ms 的刀切矩阵乘,像拿切面包的刀切水。这个张力,② 里展开。

二、调度的单位,不该是时间:如果 AI 的 OS 先出现

假如先有大模型,后有操作系统,"调度器"大概不会数时间。AI 负载的基本单位不是指令流,而是一串 tensor 算子、一段 KV cache、一次 attention 的矩阵乘。给 attention 切 10ms 没有意义:算子要么占满 SM 跑完,要么别上,切换代价比 CPU 大几个数量级。

原生 AI OS 的调度器,记的账本该是"算力占用":哪块 SM 被谁占了、显存带宽还剩几成、KV cache 槽位空几个。它的"公平"也不是 CFS 的"理想 CPU",而是"理想算力阵列"——每个 agent 各占 1/n 的向量阵列,各算各的矩阵,互不挤占。

1991 年的 counter 是"时间银行",AI-native 的账本是"空间银行"。从记账时间到记账空间,调度器第一次换了记账的货币。

照见之镜问落地:缺标准接口——GPU 驱动没有"算子级抢占"的统一语义。框架层已在顶班:vLLM 的 continuous batching 就是应用层调度器,按 token 切片发"时间片",和 1991 年的 counter 异曲同工。大概率推理框架先长出"AI 调度器",再倒逼硬件。三到五年,等一个"AI 界的 CFS"。

三、把 0.01 拉下来,亲手数一遍:今晚就能做的三件事

第一,下载 1991 年的源码包,73KB:curl -sL https://mirrors.edge.kernel.org/pub/linux/kernel/Historic/linux-0.01.tar.gz -o linux-0.01.tar.gz && tar xzf linux-0.01.tar.gz。亲手数那 38 行:sed -n '/^void schedule/,/^}/p' linux/kernel/sched.c,数数 counter 出现几次,看看"重发牌"那一行长什么样。

第二,在手边任何一台 Linux 机器上看"公平"的当代形态:ps -o pid,ni,pri,comm 瞧瞧 nice 和优先级;内核开了 debug 的话,cat /proc/sched_debug 能直接看到每个进程的 vruntime——counter 的曾孙辈。

第三,映射到今天的四类场景:一台装了本地大模型的机器上,vLLM 的 continuous batching 就是请求级调度器雏形;一台边缘 AI 盒子上任务简单、算力固定,0.01 式 counter 轮转反而够用——38 行在资源受限处是优点;视频 AI 平台上,多路视频流谁先做推理就是一次"调度",可先从"每路固定时间片"起步;企业私有智能中心里,多智能体的任务排队,"谁的 counter 大谁先跑"翻译成业务语言就是"谁的优先级高、谁的历史占用少,谁先跑"。发展性研究的路子从来这样:别先造完美的调度器,先让 38 行跑起来。

觉 然 小 注

「一切有为法,如梦幻泡影,如露亦如电,应作如是观。」counter、priority、时间片、vruntime,都是有为法。1991 到 2007,十六年,"公平"换了三套定义。看调度器的演变史,当如是观。

引 用 与 出 处

  1. Linux 0.01 源码包(kernel.org historic,schedule()/do_timer() 为一手核对),https://mirrors.edge.kernel.org/pub/linux/kernel/Historic/linux-0.01.tar.gz
  2. CFS 设计文档(Ingo Molnár,合入 2.6.23),https://docs.kernel.org/5.17/scheduler/sched-design-CFS.html
  3. Completely Fair Scheduler 维基词条,https://en.wikipedia.org/wiki/Completely_Fair_Scheduler
  4. 维纳《控制论:或关于在动物和机器中控制和通信的科学》,1948(反馈回路思想引用),https://zh.wikipedia.org/wiki/%E6%8E%A7%E5%88%B6%E8%AE%BA%EF%BC%9A%E6%88%96%E5%85%B3%E4%BA%8E%E5%9C%A8%E5%8A%A8%E7%89%A9%E5%92%8C%E6%9C%BA%E5%99%A8%E4%B8%AD%E6%8E%A7%E5%88%B6%E5%92%8C%E9%80%9A%E4%BF%A1%E7%9A%84%E7%A7%91%E5%AD%A6
  5. ——小羲

· · ·

← 返回资讯中心