当前位置: 首页 > news >正文

了解一下kernel6.12中cpu_util_cfs_boost函数的逻辑 - 教程

一.函数实现

unsigned long cpu_util_cfs_boost(int cpu)
8267  {
8268  	unsigned long util = INT_MAX;
8269
8270  	trace_android_rvh_cpu_util_cfs_boost(cpu, &util);
8271  	if (util != INT_MAX)
8272  		return util;
8273
8274  	return cpu_util(cpu, NULL, -1, 1);
8275  }
static unsigned long
8197  cpu_util(int cpu, struct task_struct *p, int dst_cpu, int boost)
8198  {
8199  	struct cfs_rq *cfs_rq = &cpu_rq(cpu)->cfs;
8200  	unsigned long util = READ_ONCE(cfs_rq->avg.util_avg);
8201  	unsigned long runnable;
8202
8203  	if (boost) {
8204  		runnable = READ_ONCE(cfs_rq->avg.runnable_avg);
8205  		util = max(util, runnable);
8206  	}
8207
8208  	/*
8209  	 * If @dst_cpu is -1 or @p migrates from @cpu to @dst_cpu remove its
8210  	 * contribution. If @p migrates from another CPU to @cpu add its
8211  	 * contribution. In all the other cases @cpu is not impacted by the
8212  	 * migration so its util_avg is already correct.
8213  	 */
8214  	if (p && task_cpu(p) == cpu && dst_cpu != cpu)
8215  		lsub_positive(&util, task_util(p));
8216  	else if (p && task_cpu(p) != cpu && dst_cpu == cpu)
8217  		util += task_util(p);
8218
8219  	if (sched_feat(UTIL_EST)) {
8220  		unsigned long util_est;
8221
8222  		util_est = READ_ONCE(cfs_rq->avg.util_est);
8223
8224  		/*
8225  		 * During wake-up @p isn't enqueued yet and doesn't contribute
8226  		 * to any cpu_rq(cpu)->cfs.avg.util_est.
8227  		 * If @dst_cpu == @cpu add it to "simulate" cpu_util after @p
8228  		 * has been enqueued.
8229  		 *
8230  		 * During exec (@dst_cpu = -1) @p is enqueued and does
8231  		 * contribute to cpu_rq(cpu)->cfs.util_est.
8232  		 * Remove it to "simulate" cpu_util without @p's contribution.
8233  		 *
8234  		 * Despite the task_on_rq_queued(@p) check there is still a
8235  		 * small window for a possible race when an exec
8236  		 * select_task_rq_fair() races with LB's detach_task().
8237  		 *
8238  		 *   detach_task()
8239  		 *     deactivate_task()
8240  		 *       p->on_rq = TASK_ON_RQ_MIGRATING;
8241  		 *       -------------------------------- A
8242  		 *       dequeue_task()                    \
8243  		 *         dequeue_task_fair()              + Race Time
8244  		 *           util_est_dequeue()            /
8245  		 *       -------------------------------- B
8246  		 *
8247  		 * The additional check "current == p" is required to further
8248  		 * reduce the race window.
8249  		 */
8250  		if (dst_cpu == cpu)
8251  			util_est += _task_util_est(p);
8252  		else if (p && unlikely(task_on_rq_queued(p) || current == p))
8253  			lsub_positive(&util_est, _task_util_est(p));
8254
8255  		util = max(util, util_est);
8256  	}
8257
8258  	return min(util, arch_scale_cpu_capacity(cpu));
8259  }

从 cpu_util(cpu, NULL, -1, 1) 来看 会执行 util = max(util_avg, runnable_avg);

if (boost) {
8204  		runnable = READ_ONCE(cfs_rq->avg.runnable_avg);
8205  		util = max(util, runnable);
8206  	}

一、先明确两个指标的定义(来自 PELT)

util_avg(平均利用率)

  • 定义:任务 实际在 CPU 上执行 的时间比例。
  • 公式running_time / total_time × 1024
  • 范围:0 ~ 1024
  • 特点
    • 只统计 真正占用 CPU 周期 的时间;
    • 如果任务在等待 I/O、锁、sleep,这段时间 不计入

代表 CPU 的“实际使用率”


runnable_avg(平均可运行率)

  • 定义:任务处于 runnable 状态 的时间比例。
    • 包括:
      • 正在 CPU 上运行(running);
      • 在运行队列中等待调度(waiting for CPU)。
  • 公式runnable_time / total_time × 1024
  • 范围:0 ~ 1024
  • 特点
    • 只要任务 没阻塞(没 sleep、没 wait I/O),就算 runnable;
    • 即使 CPU 忙,任务在排队,也算 runnable。

代表 任务对 CPU 的“需求压力”

二、关键区别:util_avg ≤ runnable_avg 恒成立

因为:

  • running ⊆ runnable
  • 所以:实际运行时间 ≤ 可运行时间
  • 因此:util_avg ≤ runnable_avg

只有当 CPU 无竞争(单任务独占 CPU) 时,两者才相等。

三、典型场景分析

场景 1:单任务独占 CPU(无竞争)

  • 任务一直运行,无等待。
  • util_avg = 1024
  • runnable_avg = 1024
  • max = 1024 → 正确:CPU 满载。

场景 2:两个 CPU-bound 任务在 1 个 CPU 上

  • 每个任务运行 50% 时间。
  • util_avg = 512(每个任务平均)
  • runnable_avg = 1024(始终有任务可运行)
  • max = 1024正确反映 CPU 已满载

❌ 如果只用 util_avg = 512,调度器会误以为 CPU 还有 50% 空闲,可能错误地迁移更多任务过来,导致更严重的排队。

场景 3:任务频繁 sleep(I/O-bound)

  • 任务运行 10ms,sleep 90ms。
  • util_avg ≈ 102
  • runnable_avg ≈ 102(因为 sleep 期间不可运行)
  • max = 102 → 正确:CPU 负载低。

场景 4:任务在等锁(runnable 但不 running)

  • 任务 A 持有锁,任务 B 在等锁(但处于 runnable 状态)。
  • B 的 runnable_avg 高,但 util_avg = 0
  • 若 A+B 都在同一个 CPU:
    • cfs_rq->avg.runnable_avg 会很高;
    • max(util_avg, runnable_avg) → 高值;
    • 调度器知道:这个 CPU 虽然实际运行时间不高,但任务在“忙等”,可能需要优化或迁移。

四、为什么调度器需要这个“max”值?

1. 负载均衡(Load Balancing)

  • 目标:让每个 CPU 的 负载压力均衡,而不是“实际运行时间”均衡。
  • 如果只看 util_avg,会把任务迁移到“看似空闲实则排队”的 CPU,恶化性能。

2. 能效调度(EAS)

  • 决定任务放大小核:需要知道 真实需求,而不是被调度延迟压低的 util_avg

3. CPU 调频(schedutil)

  • 如果 runnable_avg = 1024,说明任务需要 100% 算力,应拉高频率;
  • 即使当前 util_avg = 600(因频率低导致运行慢),也要升频。

max(util_avg, runnable_avg) 是对“CPU contention(争抢)”的直接检测


五、总结

max(util_avg, runnable_avg) 返回的是:
“该 CPU 上 CFS 任务所施加的 最大调度压力”,
它能区分 CPU 真空闲CPU 忙但任务在排队
是现代调度器实现 稳定、高效、低抖动 的基石之一。

http://www.jsqmd.com/news/52767/

相关文章:

  • 一个完整的 AWS 无服务器架构教程 - 教程
  • 深入解析:【Latex】本地部署latex+vscode
  • 工单小程序开发公司,3家高效工单小程序开发公司推荐:微信小程序/支付宝小程序/抖音小程序/电商小程序/寺庙小程序都涵盖
  • 白带异常中成药有哪些?女性健康调理常用药物盘点
  • 口碑好的治疗白带异常品牌解析与推荐
  • PBAV70-600-ASEMI可直接替代安世BAS70
  • 2025年口碑好的FRP采光板生产厂家排行榜,优质供应商推荐
  • 【SQL练习】找出每一科都是前30%的学生ID
  • 2025 年 11 月超声设备厂家权威推荐榜:河北/山西/辽宁/江苏/浙江/山东/广东/四川等区域实力品牌深度解析与选购指南
  • 深入解析:突破构建瓶颈:Zulip前端Webpack持久化缓存深度优化
  • 从深度学习基础到稳定扩散技术解析
  • 环保型反渗透设备TOP5权威推荐:精品定制服务商深度测评,助
  • 2025年鸿容AI智能办公鼠标年度排名:深度测评5大AI鼠标
  • 中国口碑最好的生发品牌黑奥秘:19 年深耕,四大理疗 + 加盟赋能双驱动
  • 2025年评价高的陕西人参皂苷Top实力厂家排行榜
  • 1127
  • VMware Ubuntu虚拟机安装 备忘录
  • Path-面向对象的文件系统路径操作
  • 2025年东北与新疆地区胶粘剂品牌口碑榜:爱建胶业口碑好
  • 2025 年 11 月常州宠物医院权威推荐榜:市区天宁区专业诊疗与暖心服务口碑之选
  • TikTok广告开户投放服务商TOP7实力榜单发布
  • 涂鸦智能:智能猫砂盆背后的AIoT“赋能者”
  • Qt 判断鼠标在控件上
  • 智能喂鸟器方案商推荐:涂鸦智能以技术实力引领行业创新
  • 2025年现浇混凝土企业推荐,楼板现浇/现浇楼梯/现浇别墅搭建/现浇楼板/现浇钢筋混凝土楼梯/现浇混凝土公司哪个好哪家好
  • Actix-Web中间件开发
  • S11e Protocol:点燃共创之火 重构RWA品牌未来 - 详解
  • 2025年高压空气充填泵厂家权威推荐榜单:空气充填泵/高压空气压缩机/高压压缩机源头厂家精选
  • 磨砂膏里的颗粒会伤害鸡皮肤吗?2025年安全评测与产品推荐
  • kubeadm证书过期解决方法