0/2 已展开

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-ID20260825174112.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 带来的收益。

补丁目的是:

  1. can_migrate_llc_task() 中,如果任务 fit 源 CPU 但不 fit 目标 CPU,直接返回 mig_forbid
  2. alb_break_llc() 中,对同样的情况否决 active balance,避免把正在运行的 task 推到不合适的 CPU。
  3. llc_balance() 入口,若 sg 统计里已经有 misfit 任务(group_misfit_task_load),在异构域下让 misfit 迁移优先于 LLC 聚合。
  4. 全部 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:风险与注意点

  1. p 为 NULL 的边界:注释里特意 && p,但旧函数本身就要求传入 struct task_struct *pcan_migrate_llc_task 现有的内部循环会传 cur,需要确认 cur 非空。
  2. gate 仅看 SD_ASYM_CPUCAPACITY:非异构系统行为完全不变;对 Intel Hybrid、Arm big.LITTLE 生效;如果未来出现"容量相同但 LLC 偏好不同"的拓扑不会误伤。
  3. active balance 否决可能放大 imbalance:否决 alb_break_llc 会让 cache-aware 主动均衡机会减少,理论上可能让某些 cache-local 任务暂时停留在次优位置;这是 cache locality 与 capacity 之间的有意取舍。
  4. misfit 上行迁移保留task_misfits_asym_cpu 故意只在 task_fits_cpu(src) 为真时拦,避免破坏小核上的 misfit 任务继续按 LLC 偏好上行到大核的既有路径。
  5. migrate_misfit 直接返回 false 让 active balance 不参与,意味着 LLC 抢占逻辑被旁路,需要确认后续 detach_task 不会因此把 misfit 任务错误地推到坏位置。
  6. 未提供 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 分支以 commit f0d243a96f26 收录,标题首字母大写化为 Avoid creating misfits during cache-aware balancing,无功能改动。

一句话总结

在异构 CPU 域里给 cache-aware 负载均衡加了一道目标 CPU 容量闸门,避免把任务搬到它装不下的 LLC,同时让 misfit 迁移优先于 LLC 聚合。