本文通过“关键任务和后台任务共用 CPU”的例子,浅谈 DSec 的 QoS-aware CPU Scheduling(面向服务质量的 CPU 调度)。

为便于理解,下面假设一个物理核有两个 SMT硬件线程,不展开参数配置和性能测试。

What

先把最容易混淆的一点说清楚:

1
2
3
降低后台任务的调度优先级
≠
消除它对关键任务的 CPU 干扰

DSec 将沙箱分成两类:

1
2
3
4
5
LS(Latency-Sensitive,时延敏感):
希望及时完成,例如每一步都有时间限制的游戏任务

BE(Best-Effort,尽力而为):
利用剩余的 CPU 运行机会

它组合了两个机制:

1
2
3
4
5
SCHED_IDLE:
调度时,让 BE 给 LS 让路

Core Scheduling:
避免 BE 在同一物理核的另一个 SMT 线程上干扰 LS

这里的 QoS,重点是保护 LS 的运行时延,同时让 BE 利用空闲算力。

Why

为什么只降低 BE 的优先级还不够?

因为 两个 SMT 硬件线程,不等于两个完全独立的物理核。它们仍然共享核内的部分硬件资源。

因此,即使 LS 已经获得 CPU、没有排队等待,BE 也可能在同一物理核的另一个硬件线程上运行,与它争用资源。

可以简单理解为:

让后台任务“不抢我的运行机会”,还不等于让它“不分走我正在使用的核内资源”。

基础 Example

假设只有一个 LS 任务 A 和一个 BE 任务 B,它们各有一个工作线程。

只使用 SCHED_IDLE

即使 B 的优先级很低,仍可能出现:

1
2
3
4
5
6
同一个物理核

SMT 线程 0:运行 A(LS)
SMT 线程 1:运行 B(BE)

两者仍然共享核内资源

A 已经被调度运行,但仍可能被 B 拖慢。

再配合 Core Scheduling

将 A、B 放入不允许同时共享物理核的不同组。假设 A 被选中运行,而另一个 SMT 线程没有同组的可运行任务:

1
2
3
4
同一个物理核

SMT 线程 0:运行 A(LS)
SMT 线程 1:保持空闲,不运行 B

宁可暂时空着,也不让 B 在旁边争用核内资源。

这叫作 Forced Idle(强制空闲):虽然有 B 可以执行,调度器仍选择让这个硬件线程空闲。

它不是永久把物理核留给 A。A 不再运行时,这个核仍可以重新用于执行 B。

How

只看两个配合的动作。

1. 用 SCHED_IDLE 降低 BE 的调度优先级

DSec 为 BE 使用 SCHED_IDLE,让 LS 优先获得运行机会。

BE 并不是被禁止执行,而是在有可用 CPU 机会时继续做事。

2. 用 Core Scheduling 控制谁能同时共享物理核

Linux Core Scheduling 使用 cookie 标记任务的分组。可以把它理解为“允许一起运行的组号”,而不是优先级数值。

1
2
3
4
5
相同 cookie:
允许同时共享一个物理核

不同 cookie:
不安排在同一个物理核上同时运行

选定一组任务后,另一个 SMT 线程可以运行同组的可运行任务;没有合适的任务时,才需要强制空闲。

所以,Core Scheduling 并不意味着另一个 SMT 线程必须一直闲着。

DSec 通过 prctl(PR_SCHED_CORE) 按 QoS 类别配置分组,将这些现有 Linux 能力接入沙箱管理流程,无需修改内核。

需要注意,这套方案针对的是调度竞争和同核 SMT 干扰,并不消除共享缓存、内存带宽以及整机负载引起的频率变化等影响。

记忆图

1
2
3
4
5
6
7
8
              保护 LS 运行时延
│
┌─────────────┴─────────────┐
▼ ▼
SCHED_IDLE Core Scheduling
│ │
BE 在调度时让路 BE 不在同核另一个线程上
与 LS 同时运行

一句话概括:

不仅让后台任务“先让关键任务跑”,还要避免它“在旁边一起跑、分走核内资源”。


参考资料:

  1. DeepSeek Elastic Compute (DSec): A Sandbox Infrastructure for Effective Agentic Training at Scale — §4.3、§5.2、§7、§8.5
  2. Linux Kernel Documentation: Core Scheduling