EAS(能量感知调度)绿色节能调度器

发布时间 2023-12-17 22:07:26作者: yooooooo

能量感知调度(EAS)使调度程序能够预测其决策对 CPU 消耗的电量的影响。 EAS 依赖于 CPU 的能量模型 (EM) 来为每个任务选择省电的 CPU,同时要求对执行任务的吞吐量的影响最小。

EAS 仅在异构 CPU 架构上(例如 Arm big.LITTLE)上运行,因为这是通过调度器节省电量的效果最大的地方。

术语

能量 = [焦耳](移动设备上的电池、电能)

功率 = 能量/时间 = [焦耳/秒] = [瓦特]

EAS的目标使用最小的能量完成所需要执行的动作,所以我们主要考量下面两个参数:

performance [ ints / s] / power [w] 最大值

energy [j] / instruction 最小值

在上述两个指标合适的同时仍然获得优异的性能表现,这种思路考虑了两个方面:能效和性能。

引入 EM 背后的想法是让调度程序能够评估其决策的影响,而不是盲目使用可能仅对某些平台有效果的低功耗手段。同时,EM 模型必须尽可能简单,以减小调度程序延迟的效果。

简而言之,EAS 改变了 CFS 任务分配给 CPU 的方式。当调度程序决定当前任务应该在哪里运行时(在唤醒期间),EM 用来打破了几个好的 CPU 候选者之间的平等关系,选择一个最佳的候选CPU运行当前任务:会产生最少的电量消耗而不牺牲系统的吞吐量的目标。 EAS 做出的预测依赖于有关平台架构的特性,其中包括 CPU 的“容量”及其各自的能源成本。

EAS调度器的软件框架如下图所示:

image

EAS调度算法有如下一些重要的概念。
1、量化的计算能力。 系统单个CPU最高计算能力设定为1024。
2、量化的能效模式。 每个cluster和CPU都有一套不同频率下量化的计算能力和功耗,EAS调度器根据此能效模型来实现节能调度。
3、复用Linux内核中的CPU调度域拓扑关系图。 增加了描述能效模型的数据结构struct sched_group_energy,MC等级的调度组描述单个CPU的能效模型,DIE等级的调度组描述的cluster的能效模型。
4、WALT Time。 这是WALT算法中一个重要的概念,是计算负载和计算能力的量化尺度。一个统计窗口时间默认是20ms,EAS调度器把一个统计窗口里的CPU使用率映射计算能力中。系统中的最强的CPU以最高频率运行一个统计窗口时间,那么他的CPU使用率是100%。量化后的最大计算能力是1024,量化后的最大WALT Time是20ms。EAS调度器把CPU使用率、CPU频率和CPU计算能力三者完美的量化到同一量化值中,这就是所谓的scale-invariant load tracking的精髓。
5、CPU使用率的计算, 详见cpu_until()函数。
6、CPU Over-Utilized,也称为Tipping point。 当一个CPU发生Over-Utilized,整个系统暂时退出EAS调度器。
7、新增的CPU frequency governor。

linux内核CFS调度器和SMP负载均衡主要是为了性能优先场景而考虑,而采用大小核设计的产品大部分采用电池供电,更应该优先考虑功耗优先。

 三种主要考虑场景:

 1 性能优先,有一些应用场景希望能得到更多更快地运行,例如服务器应用场景,benchmark场景。

 2 功耗优先,有一些应用场景希望在满足最基本的计算要求上还能尽可能地省电,例如手机。

 3 实时性优先, 例如现在热门的VR,AR,IOT等产品。

EAS设计目标:在保证满足系统性能的前提下,尽可能的降低功耗;通过合理的选择CPU来执行任务,合理的调整CPU频率。

量化计算能力

EAS提出两个概念:

FIE(Frequency Invariant Engine):计算CPU负载时考虑CPU频率的变化。

CIE(CPU Invariant Engine):考虑不同CPU架构的计算能力对负载的影响。

3.2 cpu_capacity_orig 和 cpu_capacity的区别:

就绪队列runqueue数据结构中新增两个成员

cpu_capacity_orig:指CPU在dts中定义的最高计算能力,这是量化值,系统中最强处理器的最高量化计算能力为1024。

cpu_capacity:当前cpu的CFS调度类量化计算能力,扣除DL和RT调度类之后剩余的CFS调度类的量化计算能力

3.3 在系统启动之初建立系统调度域拓扑时就会去计算每个CPU的计算能力;同时读取dts中的配置参数来获取cpu的计算能力。

能效模型

1 能效模型架构图

EAS调度器基础能效模型(Energy Model),能效模型需要考虑CPU的计算能力(capacity)和功耗(energy)两方面因素。

image

2 性能域

性能域: 哪些CPU是可以组成一个组,一起进行性能和功耗调整,比如频率调整等。通常在同一个性能域的CPU必须拥有同样的质地,比如相同的微处理器架构(micro-architecture)。

OPP(Operating Performance Point):指CPU某个domain的频率和电压的节点,用来描述CPU频率和功耗的关系。通常CPU的核心电压和CPU频率存在某种对应的关系,高频率必然需要比较高的CPU核心电压,也会带来高功耗。cpufreq模块驱动通常维护着一个频率和电压的对应表,每个表项就是OPP。在芯片设计时能单独设置频率和电压的称为一个电源域(power domain)。把这些频率和电压组成一个点,成为OPP;对于电源域来说,他可能有多个OPP组成,并形成一个表(OPP Table)。

OPP Table可以使用设备树表示 ,使用{hz,uV}的方式来表述它:

{300000000,1000000}
{800000000,1200000}
{1000000000,1300000}

能效模型接口API:

int em_register_perf_domain(cpumask_t*span,unsigned int nr_states,struct em_data_callback *cb)

2). 获取一个性能域

struct em_perf_domain *em_cpu_get(int cpu)

3). 预测能耗

unsigned long em_pd_energy(struct em_perf_domain *pd,unsigned long max_util,unsigned long sum_util)

计算能效比Cost:
image

该选那个CPU呢?(EAS核心)

如下图,进程该如何选择CPU呢?
image

计算大小核PD当中最大的剩余算力://安放进程后预算
image

寻找最合适的CPU,API接口:

static int find_energy_efficient_cpu(struct task_struct *p,int prev_cpu,int sync)

static void select_max_spare_cap_cpus(struct sched_domain *sd, cpumask_t *cpus, struct perf_domain *pd,struct task_struct *p)

计算pd的功耗值:

static long compute_energy(struct task_struct *p, int dst_cpu, struct perf_domain *pd)

static inline unsigned long em_pd_energy(struct em_perf_domain *pd, unsigned long max_util, unsigned long sum_util)

1). 一个系统中CPU的最高计算能力被量化为1024。(如海思芯片,大核CPU最高计算能力量化为1024,而小核的最高计算能力为592)。

2). 判断一个CPU当前的负载是否繁重或者计算能力,我们采用cfs_rq->avg.util_avg这个值。

3). 计算一个进程P的计算能力,我们采用p->se.avg.util_avg。

4). 这个时候需要在小核PD域以及大核PD域里面挨个CPU去计算,假如把P加入到CPU里面能否容的下呢? 安放条件是CPU的总计算能力不能超过最高计算能力的80%,CPU0~CPU4都可以安放这个进程P。接下来要看大小核这两个域里面那个CPU最合适安放,也就是说安放了进程P之后,它的剩余计算能力最多为优胜者。我们通过计算发现,小核域的CPU1和大核域的CPU3为候选者。

5). 接下来要去比较究竟选择进程运行在CPU1还是CPU3最为省电呢?

 通过计算比较,我们发现把进程P迁移到小核CPU1来运行最为省电。

2 假设现在大核CPU都休眠了,小核CPU上还在运行几个进程,那么把进程派发(spreading)到大核上呢,还是继续在小核上运行呢?

EAS的做法是:

1). 如果当前系统还没触发overutilized的"Tipping Point" 条件,那么EAS调度器就 不会做负载均衡;只有触发了这个条件,EAS调度器才会做负载均衡。

2). 判断当前的CPU的计算负载是否超过了该CPU最高计算能力的80%,如果是,说明触发overutilized条件了。