深入详解CFS任务放置代码

一、前言

本文出现的内核代码来自Linux5.10.61,为了减少篇幅,我们对引用的代码进行了删减(例如去掉了NUMA的代码,毕竟手机平台上我们暂时不关注这个特性),如果有兴趣,读者可以配合完整的源代码代码阅读本文。

二、能量模型框架及其相关数据结构

1. 概述

在嵌入式平台上,为了控制功耗,很多硬件模块被设计成可以运行在多种频率下工作(配合对应的电压,形成不同的performance level),这种硬件的驱动模块可以感知到在不同performancelevel下的能耗。系统中的某些模块可能会希望能感知到硬件能耗从而做出不同的判决。能量模型框架(EnergyModel (EM) framework)是一个通用的接口模块,该接口连接了支持不同perf level的驱动模块和系统中的其他想要感知能量消耗的模块。

一个典型的例子就是CPU调度器和CPU驱动模块,调度器希望能够感知底层CPU能量的消耗,从而做出更优的选核策略。对于CPU设备,各个cluster有各自独立的调频机制,cluster内的CPU统一工作在一个频率下。因此每个cluster就会形成一个性能域(performance domain)。调度器通过EM framework接口可以获取CPU在各个performance level的能量消耗。在了解了能量模型的基本概念之后,我们一起来看看和调度器相关的EM数据结构。

2. struct root_domain

最初引入root domain的概念是因为rt调度的问题。对于cfs task,我们只要保证每一个cpu runqueue上的公平就OK了(load balancer也会尽量cpu之间的公平),不需要严格保证全局公平。但是对于rt task就不行了,我们必须保证从全局范围看,优先级最高的任务最优先得到调度。然而这样会引入扩展性问题:随着cpu core数据增大,维持全局的rt调度策略有些困难,这样的情况下,我们把CPU分成一个个的区域,每一个区域对应一个root domain。对于rt调度,我们不需要维持全局,只要保证一个root domain中,最高优先级的rt任务最优先得到调度即可。

当然,后来更多的成员增加到这个数据结构中(例如本文要描述的performancedomain),丰富了它的含义。在手机平台上,我们只有一个root domain,有点类似整个系统的味道了。本文只描述和负载均衡相关的成员,具体如下:

这里需要澄清一下overload和overutilized这两个概念,对于一个CPU而言,其处于overload状态则说明其runqueue上有大于等于2个任务,或者虽然只有一个任务,但是是misfit task。对于一个CPU而言,其处于overutilized状态说明:该cpu的utility超过其capacity(缺省预留20%的算力,另外,这里的capacity是用于cfs任务的算力)。在单个cpu overload/overutilized基础上,我们定义root domain(即整个系统)的overload和overutilized。对于root domain,overload表示至少有一个cpu处于overload状态。overutilized表示至少有一个cpu处于overutilized状态。overutilized状态非常重要,它决定了调度器是否启用EAS,只有在系统没有overutilized的情况下,EAS才会生效。Overload和newidlebalance的频次控制相关,当系统在overload的情况下,newidle balance才会启动进行均衡。

在CPU拓扑初始化的时候,通过build_perf_domains函数创建各个perf domain,形成root domain的perf domain链表。

3. struct perf_domain

Struct perf_comain表示一个CPU性能域,perf_comain和cpufreq policy是一一对应的,对于一个4+3+1结构的平台,每一个性能域都是由perf_domain抽象,因此系统共计3个perf domain,形成链表,链表头在root domain。Perf_domain的各个成员如下:

4. struct em_perf_domain

在EM framework中,我们使用em_perf_domain来抽象一个performance domain:

5. struct em_perf_state

每个性能域都有若干个perf level,每一个perf level对应能耗是不同的,我们用struct em_perf_state来表示一个perf level下的能耗信息:

三、能量计算概述

我们都知道一个基本的能量计算公式,如下:

对于CPU而言,我们要计算其能量需要进一步细化公式(省略了CPU处于idle状态的能耗):

在内核中,EM中记录了CPU各个频点的功率,而运行时间是通过cpu utility来呈现的。有一个不太方便的地方就是CPU utility是归一化到1024的一个值,失去了在某个频点的运行时间长度的信息,不过没有关系,我们可以转换:CPU在该频点运行时间 = cpu utility / cpu currentcapacityCPU在某个perf state的算力如下:

不考虑idle state的功耗,Cpu在某个perfstate的能量估计如下:

把公式(1)带入公式(2)可以得到:

上面公式的第一项是一个常量,保存在em_perf_state的cost成员中。由于每个perf domain中的微架构都是一样的,因此scale_cpu是一样的,那么cost也是一样的,通过提取公因式我们可以得到整个per

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值