第69期 | 十六年的公平,被重写了
第六章第四期。上一期看完 CFS 的一本账:vruntime 拉平,永远取最欠。但这本账有个十六年没治好的病——时延敏感的任务,唤醒后只算零点几毫秒,却要和同 nice 的批量任务排同一条队,等 vruntime 收敛。时延,在 CFS 的账本里没有名字。2023 年,这本用了十六年的账,连账本带算盘一起被换了。
一、十六年的公平,被重写了
1995 年,EEVDF(Earliest Eligible Virtual Deadline First,最早合格虚拟截止期优先)第一次出现在科学出版物里¹;近三十年后,2023 年 3 月,Peter Zijlstra 把它的 Linux 实现贴上 LKML,同年 10 月随 Linux 6.6 合入,取代了自 2007 年起当班十六年的 CFS²。Zijlstra 在邮件里写:"It completely reworks the base scheduler, placement, preemption, picking — everything. The only thing they have in common is that they're both a virtual time-based scheduler."²——放置、抢占、挑选,全重写;和 CFS 唯一的共同点,是都按虚拟时间记账。
账本变了。CFS 只记一笔 vruntime;EEVDF 记两笔:多了一个 lag——"应得"与"实得"的差¹。lag 为正,是系统欠你的;为负,是你超支了。只有 lag≥0 的任务才有"资格"(eligible)参选;有资格的里面,各自算出虚拟截止期,最早的先跑¹。公平第一次长出了时间的形状:从"最欠的先跑",变成"有资格且最急的先跑"。
还有一处防老赖的心机:任务睡觉时,负的 lag 不会立刻清零,而是留在队列上"延迟出队",随虚拟时间慢慢衰减¹。睡一小觉就想把超支的账赖掉?没门。CFS 用 min_vruntime 防"睡了一万年醒来霸占 CPU";EEVDF 把"何者当忘"也写进了机制。
它要治的,正是 CFS 的老病:时延敏感的任务没有显式要低时延的通道³。EEVDF 允许任务带着更短的时间片入场——片越短,虚拟截止期越早,醒来插队越快¹。
Brooks 的尺子可以量一下⁴(思想化用):CFS 到 EEVDF,消灭的是偶然困难——时延抖动、调参玄学;而"公平到底用什么货币结算",纹丝未动。那是本质困难,留给下一节。
二、截止期,是意图的形状
如果 AI 的操作系统先出现,调度器根本不会从"时间片"起步。Agent 的任务天然带着意图:"这条推理 200ms 内必须回","这批向量检索可以等"。意图自带截止期——调度器要做的不是切时间,而是排意图。
EEVDF 是向那个方向迈出的第一步:它第一次允许任务开口说"我要多久",而不只是被记"你欠多少"。6.12 起,普通进程经 sched_setattr 可申请 0.1–100ms 的自定义时间片⁵——时延敏感,从此有了显式的表达通道。
原生的样子可以再往前推一格:意图拍卖行。每个 agent 进场声明三样东西——截止期、价值密度、要占的算力阵列;调度器按"最早虚拟截止期 × 边际价值"排序,lag 变成一本"智能欠条"。排的不是时间,是意图的优先级。
范式之眼再看一层:EEVDF 量的仍是 CPU 时间。向量阵列时代真正的稀缺物——Tensor Core 的占用、attention 吃掉的内存带宽、KV cache 占着的显存——一概不在账上。"按时间片切指令流"的旧抽象,借着 EEVDF 又续了一程。货币不换,公平的定义就还是 2007 年的。这是 EEVDF 留给 AI-native OS 的那道没答完的题。
三、给你的任务,定一个截止期
先看你活在哪个时代:uname -r,6.6 及以上,你已经活在 EEVDF 里。root 下 cat /sys/kernel/debug/sched/base_slice_ns,会看到 750000——0.75ms,全系统普通任务的默认"出价"⁵。
- 12 以上的内核,普通进程可以自己改出价,不用 root。今天在本机(7.0.0)上亲手验证过,返回 0:
attr.sched_policy = 0; /* SCHED_NORMAL */
attr.sched_nice = 0;
attr.sched_runtime = 100000; /* 0.1ms:我要更短的片 */
syscall(314, 0, &attr, 0); /* sched_setattr,返回 0 即生效 */
片越短,虚拟截止期越早——时延敏感的任务,第一次有了合法的插队姿势。
落到她手里的四样东西:跑本地模型的 Linux 机器上(3090),推理服务就是那个"音频 daemon"——给它 0.1–0.3ms 的自定义 slice,评测与批量任务保持默认;RK3588 边缘盒上算力更金贵,给关键 agent 更短的片,等于把"谁更急"写进内核。但记住:EEVDF 只给 CPU 排期,GPU 的显存与算力依然没有 OS 级的账本。CPU 的公平 2007 年解决了,异构算力的公平,是九羲可以补的那本账。
觉 然 小 注
「过去心不可得,现在心不可得,未来心不可得。」⁶(思想化用)
EEVDF 的 lag 衰减,是把这句写进了内核:睡过去的账,系统替你慢慢忘掉。执着于记住一切是病,知道何者当忘,才是智慧。
引 用 与 出 处
- [1] Linux 内核文档. EEVDF Scheduler(Documentation/scheduler/sched-eevdf.rst):EEVDF 1995 年首次见于科学出版物;Linux 6.6 起由 Peter Zijlstra 2023 年的版本替代 CFS;lag、虚拟截止期、有资格(eligible)参选机制;睡眠任务 lag 经 deferred dequeue 随虚拟时间衰减. https://www.kernel.org/doc/html/next//scheduler/sched-eevdf.html
- [2] SdxCentral. Linux 6.6 brings new scheduler, file sharing and security. 2023-10(CFS 自 2007 年起为默认调度器;引 Zijlstra 邮件原话 "It completely reworks the base scheduler, placement, preemption, picking — everything. The only thing they have in common is that they're both a virtual time-based scheduler."). https://www.sdxcentral.com/articles/news/linux-6-6-brings-new-scheduler-file-sharing-and-security/2023/10/
- [3] CodingPancake. Linux Kernel Process Scheduling Under the Hood: Architecture, Red-Black Trees, EEVDF, and sched_ext(CFS 无显式低时延调度通道:时延敏感的小计算量任务被迫与同 nice 批量任务排队等 vruntime 收敛). https://www.codingpancake.com/2026/08/linux-kernel-process-scheduling-under.html
- [4] F. P. Brooks. No Silver Bullet: Essence and Accidents of Software Engineering. IEEE Computer, 1987. DOI: 10.1109/MC.1987.1663532(思想化用:本质困难 vs 偶然困难)
- [5] Boardor. Understanding the EEVDF Scheduler in Linux Kernel(se.slice 默认 sysctl_sched_base_slice=0.75ms,可经 /sys/kernel/debug/sched/base_slice_ns 修改;Linux 6.12 起 sched_setattr 的 sched_attr.sched_runtime 可为普通进程设 0.1–100ms 自定义时间片;引 kernel/sched/syscalls.c __setscheduler_params). https://boardor.com/blog/understanding-the-eevdf-scheduler-in-linux-kernel
- [6] 「过去心不可得,现在心不可得,未来心不可得。」《金刚般若波罗蜜经》,鸠摩罗什译(思想化用)
· · ·