土法炼钢兴趣小组的算法知识备份

【操作系统百科】多核负载均衡:调度域与迁移

文章导航

分类入口
os
标签入口
#load-balance#sched-domain#numa-balancing#wake-affine#imbalance

目录

Linux 不搞”一个全局 runqueue”——每 CPU 独立 runqueue,锁本地,不争不抢。代价是需要主动搬任务才不会出现”3 个 CPU 空转,1 个 CPU 排队”。负载均衡机制从 2003 年 SMP 以来演化至今,层次繁多。本文系统讲解。

一、先看图:调度域层级

flowchart TB
    NODE[NUMA Node · DIE]
    NODE --> MC0[MC (socket) 0]
    NODE --> MC1[MC (socket) 1]
    MC0 --> CORE00[Core 0]
    MC0 --> CORE01[Core 1]
    CORE00 --> SMT0[HT 0]
    CORE00 --> SMT1[HT 1]
    CORE01 --> SMT2[HT 2]
    CORE01 --> SMT3[HT 3]
    classDef l0 fill:#388bfd22,stroke:#388bfd,color:#adbac7;
    classDef l1 fill:#3fb95022,stroke:#3fb950,color:#adbac7;
    classDef l2 fill:#f0883e22,stroke:#f0883e,color:#adbac7;
    classDef l3 fill:#a371f722,stroke:#a371f7,color:#adbac7;
    class NODE l0
    class MC0,MC1 l1
    class CORE00,CORE01 l2
    class SMT0,SMT1,SMT2,SMT3 l3

每层对应一个 sched_domain:SMT、MC (Multi-Core, cluster/socket)、DIE(整颗芯片)、NUMA (跨 socket)。每层有自己的 migration cost(小 → 大)和 均衡频率

二、均衡的四个触发时机

2.1 wake-up 时

新任务或唤醒任务要放哪个 CPU?

关键启发式 WAKE_AFFINESD_BALANCE_WAKE flag 在 sched domain 里。

2.2 新任务 fork/exec 时

select_task_rq_fair 决定落在哪。倾向”父 CPU 的同 LLC 组里的空核”——新进程往往和父共享 data。

2.3 周期性 balance

每 CPU tick 检查 rq->next_balance,到期扫描 sched_domain 看是否要 migration。频率随域变化(SMT 1ms、MC 4ms、NUMA 100ms+ 不等,都是经验值)。

2.4 idle balance (pull)

CPU 空转前的最后一刻:去其他 CPU “拉” 任务过来。newidle_balance 函数。这是最激进的均衡,空闲 CPU 宁可迁移一个任务也不闲置。

三、imbalance 判定

不是”有差就迁”——迁移有代价(cache 冷、TLB 失效)。判定大致:

imbalance = busiest.load_avg - local.load_avg
if (imbalance > threshold) migrate

threshold 随域增大(高层迁移更贵)。6.x 后 SD_ASYM_CPUCAPACITY 加入 capacity 差异(大小核),不只看 load。

四、NUMA Balancing

多 NUMA node 场景:任务 A 的内存在 node 0,任务跑到 node 1 → 远程访问慢 3-5x。

方案 1:把任务挪回(task migration) 方案 2:把页迁过来(page migration) 方案 3:都不动,接受性能损失

Linux 的 NUMA Balancing 周期性:

  1. 扫描任务 VMA,把一些页标记 “PROT_NONE”
  2. 触碰即 fault,记录”是哪个 node 访问的”
  3. 统计积累后决定:迁页 或 迁任务

/proc/sys/kernel/numa_balancing 开关;/sys/kernel/mm/mempolicy/... 调。

坏处:fault 本身有成本。HPC 场景往往关 NUMA balancing 用手动 numactl。

五、prefer_sibling 与 SMT

超线程(SMT)两线程共享 core 资源。优先填满不同 core 的 HT 才填同 core:SD_PREFER_SIBLING

场景:2 CPU-bound 任务应分到 2 个物理核而不是挤在一个核的两 HT。

现代 Intel + AMD + ARM 都有 SMT(ARM big 核部分型号)。调度器自动识别 topology。

六、Energy-Aware Scheduling (EAS)

移动 / 客户端用的扩展:给每 CPU 一个 “能量模型”(频率 → 功耗曲线)。选 CPU 时不只看 load,还估计”哪放更省电”。

要开 CONFIG_ENERGY_MODEL + 厂商提供 energy-costs.dtsi。Android / Chromebook 默认开。

详见 C-25(big.LITTLE)。

七、诊断负载均衡

7.1 看 topology

lscpu --extended
# CPU NODE SOCKET CORE L1d L1i L2 L3

7.2 看域

cat /proc/schedstat            # 老接口,较粗
ls /sys/kernel/debug/sched/domains/   # 每 CPU 每域统计
cat /sys/kernel/debug/sched/domains/cpu0/domain0/name
# → "MC"

7.3 事件

bpftrace -e 'tracepoint:sched:sched_migrate_task {
    @migrations[cpu] = count();
}'

短时间看谁被迁去哪。

7.4 NUMA

numastat -p <pid>
cat /proc/<pid>/numa_maps

perf c2c 能抓跨 node cache line 争用。

八、常见问题

问题 A:两个 CPU 忙,另两个长期空 原因:cache-hot 标志让任务不愿迁走;或 imbalance 阈值高 解决taskset 强绑;或调 kernel.sched_migration_cost_ns

问题 B:容器里 latency 飙 原因:cgroup 限额 + CPU 迁移 → cache 失效后 throttle;或调度域太大频繁迁 解决cpu.cfs_period_us / quota 调小;或 isolate 专用 CPU

问题 C:NUMA Balancing 反而让性能下降 原因:应用内存分布固定但被来回迁 解决numactl --membind --cpunodebind;关 autonuma

问题 D:HT 独占性不够 原因:prefer_sibling 没生效或 topology 报告错 诊断cat /sys/devices/system/cpu/cpu0/topology/thread_siblings_list

问题 E:多租户云上 noisy neighbor 原因:VM 间共享 LLC / HT 解决:Intel RDT (CAT) + cpuset + L3 隔离

九、工作负载与策略对照

负载 推荐策略
数据库(PostgreSQL、MySQL) 绑 CPU(cpuset) + numactl 本 node + 关 NUMA bal
高并发 HTTP 默认即可,watch wake_affine
HPC MPI numactl + rank pinning
AI 训练 GPU 绑卡 + NUMA bal 关
实时 isolcpus + nohz_full
桌面 默认(EAS + autogroup)

十、小结

下一篇 C-25 讲 big.LITTLE / Intel P+E 的异构多核调度——capacity-aware、misfit migration、Intel Thread Director。


参考文献

工具


上一篇SCHED_DEADLINE 下一篇big.LITTLE / Intel P+E:异构多核调度

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-04-27 · os

【操作系统百科】内存回收

Linux 内存回收是 VM 最复杂的子系统之一。本文讲 active/inactive LRU、kswapd 与 direct reclaim、watermark 三线、swappiness 的真实含义、MGLRU 改造、memcg 回收与 PSI。

2026-04-28 · os

【操作系统百科】交换

swap 还值得开吗?本文讲 swap area 基础、swap cache、zram 压缩内存、zswap 前端压缩池、swappiness 的真实含义、容器里的 swap 策略,以及为什么现代 Android 全靠 zram 不靠磁盘。

2026-05-03 · os

【操作系统百科】Slab/SLUB 分配器

buddy 只管页粒度(4K+),内核大多数对象只有几十到几百字节。slab/SLUB 在 buddy 之上做对象级缓存。本文讲 slab 历史、SLUB 接手、SLOB 退场、kmem_cache、per-CPU cache、KASAN 集成。

2026-05-07 · os

【操作系统百科】用户态分配器

glibc malloc、tcmalloc、jemalloc、mimalloc 各有哲学。本文讲 arena、thread cache、size class、madvise 返还策略、碎片与 RSS 膨胀、如何根据负载选分配器。


By .