sched discussion
[PATCH] sched/fair: avoid creating misfits during cache-aware balancing
LLM 分析
sched/fair:缓存感知负载均衡过程中避免制造 misfit 任务
系列概况
- 标题:[PATCH] sched/fair: avoid creating misfits during cache-aware balancing
- 作者:Tim Chen tim.c.chen@linux.intel.com
- 版本:单 patch,v1(无 vN 编号,最终被 tip-bot 收录到 sched/urgent 分支)
- 规模:1 file changed, 50 ++++++++++++++++++++++++++++++++++++++++-----(45 insertions, 5 deletions)
- 修改文件:
kernel/sched/fair.c - 代码统计:45 行新增 / 5 行删除
- Message-ID:20260825174112.2580942-1-tim.c.chen@linux.intel.com
- 完整性:主线完整,最终通过 tip/sched/urgent 合入(commit f0d243a96f26),maintainer 为 Peter Zijlstra,tip-bot 自动收尾邮件为 178833371591.3717435.12313738810106701533.tip-bot2@tip-bot2,拿到 Ricardo Neri 和 Chen Yu 的 Reviewed/Tested-by
补丁目的
在 big.LITTLE 这类异构(asymmetric)CPU 容量域中,缓存感知的负载均衡原本会把任务拉向其 preferred LLC。但目标 LLC 内部可能混着大核和小核,如果只看 LLC 是否是首选就把任务拉过去,可能把本来能 fit 源 CPU 的任务塞到一个根本装不下它的小核上 —— 任务从此变成 misfit,性能损失远超 cache locality 带来的收益。
补丁目的是:
- 在
can_migrate_llc_task()中,如果任务 fit 源 CPU 但不 fit 目标 CPU,直接返回mig_forbid。 - 在
alb_break_llc()中,对同样的情况否决 active balance,避免把正在运行的 task 推到不合适的 CPU。 - 在
llc_balance()入口,若 sg 统计里已经有 misfit 任务(group_misfit_task_load),在异构域下让 misfit 迁移优先于 LLC 聚合。 - 全部 gate 在
SD_ASYM_CPUCAPACITY上,对对称多处理器零影响。
旧流程的问题
旧流程只看 LLC 偏好,忽略 CPU 容量差异:
+-----------+ pull to preferred LLC +-----------+
| src CPU | -------------------> | dst LLC |
| (big) | | contains |
| task fits | | small CPU |
+-----------+ | task NO fit
+-----------+
can_migrate_llc_task只看p->preferred_llc,不查目标 CPU 是否能装得下。alb_break_llc也只关心 LLC 命中。llc_balance一旦发现group_misfit_task_load,依然优先按 LLC 聚合,让 misfit 任务在小核之间挤来挤去。
结果:异构系统上 LLC locality 赢了,但 misfit 严重降频,整体吞吐反而下降。
新流程
新增 task_misfits_asym_cpu() 守门人:在异构域下,若任务 fit 源 CPU 但不 fit 目标 CPU,强行禁止这次迁移:
cache-aware migrate?
|
+------------+------------+
| |
misfit on dst? (other cases)
fits(src) && !fits(dst)
| |
return mig_forbid follow old LLC path
v
task_misfits_asym_cpu()
|
+---> alb_break_llc() also veto
+---> llc_balance() if group_misfit_task_load
on SD_ASYM_CPUCAPACITY -> return false
(let misfit path take over)
alb_break_llc 同样加这道闸,并且当 migration_type == migrate_misfit 时不再走 LLC break,直接放过,让 misfit 任务能找到更合适的 CPU。
Patch 概览
- 单 patch,标题
[PATCH] sched/fair: avoid creating misfits during cache-aware balancing - 修改文件:
kernel/sched/fair.c - 改动统计:+45 / -5
- 新增 helper:
task_misfits_asym_cpu() - 修改函数签名:
can_migrate_llc_task()改传lb_env - 修改调用点:
alb_break_llc()、llc_balance()、migrate_degrades_llc()
关键实现
新增 helper:
static inline bool task_misfits_asym_cpu(struct lb_env *env,
struct task_struct *p)
{
/*
* On asymmetric CPU capacity domains, do not let cache-aware
* balancing pull the task onto a destination CPU that cannot
* accommodate it. Doing so would turn the task into a misfit on
* the destination, trading a cache-locality gain for a capacity
* loss. If the task already does not fit its source CPU, the move
* cannot make things worse, so let the LLC preference decide.
*/
if ((env->sd->flags & SD_ASYM_CPUCAPACITY) && p &&
!task_fits_cpu(p, env->dst_cpu) &&
task_fits_cpu(p, env->src_cpu))
return true;
return false;
}
调用点 1:can_migrate_llc_task()
static enum llc_mig can_migrate_llc_task(struct lb_env *env,
struct task_struct *p)
{
int cpu, src_cpu, dst_cpu;
if (task_misfits_asym_cpu(env, p))
return mig_forbid;
src_cpu = env->src_cpu;
dst_cpu = env->dst_cpu;
...
}
注意签名变化:原先只传 src_cpu/dst_cpu,现在传 lb_env,并新增 src_cpu/dst_cpu 局部变量复用。
调用点 2:alb_break_llc()
/*
* Migrating misfit tasks from current CPU
* to CPU with a better fit.
* Prioritize that over LLC preference.
*/
if (env->migration_type == migrate_misfit)
return false;
if (task_misfits_asym_cpu(env, cur) ||
can_migrate_llc(env->src_cpu, env->dst_cpu, ...))
return true;
调用点 3:llc_balance()
/*
* On asymmetric domains, group_misfit_task_load
* should be prioritized to move tasks to CPU that fit them
* over aggregating tasks to their preferred LLC.
*/
if ((env->sd->flags & SD_ASYM_CPUCAPACITY) &&
sgs->group_misfit_task_load)
return false;
最后还有一个 cleanup:migrate_degrades_llc() 把 can_migrate_llc_task(env->src_cpu, env->dst_cpu, p) 改为 can_migrate_llc_task(env, p),与新签名对齐。
类比
把 LLC 想象成办公楼楼层:
- LLC = 楼层。同一楼层意味着能用同一台咖啡机、同一份共享文档(cache 复用)。
- 大核 = 工位宽裕的主管办公室;小核 = 拥挤的格子间。
- 任务 = 员工。
旧策略:"这个员工喜欢 7 楼(preferred LLC),只要 7 楼有空位就让他搬过去。"
问题:7 楼也可能有格子间(只有小核),把一个身材高大的员工硬塞进格子间,他根本施展不开(misfit),工作效率反而更低。
新策略:先把员工的工位大小需求(task util)跟楼层里的工位尺寸对一遍:
- 7 楼有主管办公室(big core):搬过去,皆大欢喜。
- 7 楼只有格子间(small core):禁止搬,哪怕他喜欢 7 楼。
- 员工本身在大格子间里已经嫌挤(已经在源 CPU 上 misfit):那就让楼层偏好继续生效,因为没有比这更差的结果 —— 这刚好保留 misfit 任务向上迁移到大核的常规路径。
alb_break_llc 那条 misfit 提前 return false,相当于:员工已经在喊"我挤得慌,要换工位",HR(active balancer)就别再拿你属意哪层楼来卡他了。
Highlight:风险与注意点
p为 NULL 的边界:注释里特意&& p,但旧函数本身就要求传入struct task_struct *p;can_migrate_llc_task现有的内部循环会传cur,需要确认cur非空。- gate 仅看
SD_ASYM_CPUCAPACITY:非异构系统行为完全不变;对 Intel Hybrid、Arm big.LITTLE 生效;如果未来出现"容量相同但 LLC 偏好不同"的拓扑不会误伤。 - active balance 否决可能放大 imbalance:否决
alb_break_llc会让 cache-aware 主动均衡机会减少,理论上可能让某些 cache-local 任务暂时停留在次优位置;这是 cache locality 与 capacity 之间的有意取舍。 - misfit 上行迁移保留:
task_misfits_asym_cpu故意只在task_fits_cpu(src)为真时拦,避免破坏小核上的 misfit 任务继续按 LLC 偏好上行到大核的既有路径。 migrate_misfit直接返回 false 让 active balance 不参与,意味着 LLC 抢占逻辑被旁路,需要确认后续detach_task不会因此把 misfit 任务错误地推到坏位置。- 未提供 patch 版本号,但最终被
tip: sched/urgent收,说明被维护者认定为 critical fix;社区可重点关注 v6.x stable backport 是否及时。
版本变化
只有 v1 + tip 收尾,无 v2/v4 重新发版:
- v1:45 insertions / 5 deletions,单 patch,标题为
sched/fair: avoid creating misfits during cache-aware balancing。 - tip 收尾:tip-bot2 在
tip: sched/urgent分支以 commitf0d243a96f26收录,标题首字母大写化为Avoid creating misfits during cache-aware balancing,无功能改动。
一句话总结
在异构 CPU 域里给 cache-aware 负载均衡加了一道目标 CPU 容量闸门,避免把任务搬到它装不下的 LLC,同时让 misfit 迁移优先于 LLC 聚合。