3. 调度域与调度组:数据结构详解

在组调度场景下,CPU 域迁移的决策依赖于两个核心数据结构:调度域(sched_domain)和调度组(sched_group)。调度域定义了 CPU 之间的拓扑层次和负载均衡范围,而调度组则代表了该域内可进行任务迁移的实体单元。理解这两个结构体的字段含义和相互关系,是进行域迁移参数调优的基础。

3.1 调度域(sched_domain)

调度域是一个树形层次结构,每个层级对应不同的 CPU 拓扑(如 SMT、MC、NUMA)。内核通过 sched_domain 结构体描述每个 CPU 所属的域层级。其核心字段如下:

字段名 类型 说明
span cpumask_var_t 该域覆盖的 CPU 位图,用于判断 CPU 是否属于本域。
level int 域层级编号,数值越小越接近物理 CPU(如 SMT 层为 0)。
flags int 控制域行为的标志位,如 SD_BALANCE_NEWIDLE、SD_BALANCE_EXEC、SD_BALANCE_FORK、SD_BALANCE_WAKE、SD_LOAD_BALANCE 等。
min_interval unsigned int 负载均衡的最小触发间隔(单位:ms)。
max_interval unsigned int 负载均衡的最大触发间隔(单位:ms)。
busy_factor unsigned int 繁忙状态下间隔放大倍数。
imbalance_pct unsigned int 触发迁移的不平衡百分比阈值(如 117 表示负载差超过 17% 时触发)。
cache_nice_tries unsigned int 缓存亲和性尝试次数。
groups struct sched_group * 指向本域内第一个调度组的指针,形成环形链表。
调优提示: imbalance_pct 是组调度场景下最常调整的参数之一。在 NUMA 系统中,适当增大该值(如从 117 调整为 125)可以减少跨域迁移,降低内存访问延迟。

3.2 调度组(sched_group)

每个调度域由多个调度组组成,调度组是负载均衡的基本单元。组内可以包含一个或多个 CPU,组与组之间通过环形链表连接。其核心字段如下:

字段名 类型 说明
cpumask cpumask_var_t 该组包含的 CPU 位图。
group_weight unsigned int 组内 CPU 数量,用于计算组容量。
sgc struct sched_group_capacity * 指向组容量信息的指针,包含计算能力、负载等统计。
next struct sched_group * 指向下一个调度组,形成环形链表。
asym_prefer_cpu int 非对称拓扑中优先使用的 CPU 编号。

3.3 域与组的关系:层次与环形结构

调度域与调度组的关系可以用以下 SVG 图表示。图中展示了一个 4 核 2 线程的 NUMA 系统,包含 SMT、MC、NUMA 三个域层级,每个域内包含多个调度组。

调度域与调度组层次关系图 NUMA 域 (Domain 2) — span: CPU0-7 调度组 0 (Node 0) cpumask: CPU0-3 group_weight: 4 调度组 1 (Node 1) cpumask: CPU4-7 group_weight: 4 MC 域 (Domain 1) — Node 0 组 0-0 CPU0-1 weight: 2 组 0-1 CPU2-3 weight: 2 MC 域 (Domain 1) — Node 1 组 1-0 CPU4-5 weight: 2 组 1-1 CPU6-7 weight: 2 SMT 域 (Domain 0) CPU0 组 0-0 CPU0 (线程0) 关键说明 • 每个域内组形成环形链表 • 负载均衡在组间进行 • 迁移决策逐层向上 • 组权重影响容量计算

3.4 数据结构在组调度中的协作流程

当内核触发负载均衡时,调度域与调度组按以下步骤协作:

  1. 选择域层级:从当前 CPU 所在的最低层域(如 SMT)开始,逐层向上检查是否需要均衡。
  2. 遍历调度组:在当前域内,通过 groups 指针遍历环形链表中的每个调度组。
  3. 计算组负载:读取每个组的 sgc 中的负载统计,计算组平均负载。
  4. 判断不平衡:比较最忙组与最闲组的负载差,若超过 imbalance_pct 阈值,则触发迁移。
  5. 执行迁移:从最忙组中选择任务,迁移到最闲组中的目标 CPU。
性能优化要点:在组调度场景下,sched_domain 的 flags 字段控制着哪些事件会触发均衡。例如,SD_BALANCE_WAKE 标志控制唤醒时是否进行负载均衡。对于延迟敏感型应用,建议关闭高层域的 SD_BALANCE_WAKE,避免频繁的跨 NUMA 迁移。

3.5 关键参数与数据结构字段映射

以下表格列出了常见的调度参数与其对应的数据结构字段,帮助你在调优时快速定位:

调度参数 对应数据结构字段 所属结构体 典型值
kernel.sched_domain.imbalance_pct imbalance_pct sched_domain 117 (NUMA), 125 (MC)
kernel.sched_domain.busy_factor busy_factor sched_domain 32 (NUMA), 64 (MC)
kernel.sched_domain.cache_nice_tries cache_nice_tries sched_domain 2 (NUMA), 4 (MC)
kernel.sched_group.group_weight group_weight sched_group CPU 数量 (如 2, 4, 8)
注意:直接修改 sched_domain 或 sched_group 的内核字段需要重新编译内核。在运行时,建议通过 /proc/sys/kernel/sched_domain/ 下的 sysctl 接口进行调整,这些接口会间接更新对应数据结构的字段值。