Linux内核调度子系统之负载跟踪

1.概述
Linux 内核的 多核CPU 调度程序有一项具有挑战性的任务:它必须以公平的方式分配各个任务对多个CPU的访问实现最大化系统吞吐量并最小化功耗 。用户期望最好的效果,而不理睬他们系统中实际的工作负载的特征如何,实际上 这些目标经常相互冲突 。所以调度程序必须清晰地知道每个任务的负载究竟有多大,从而在正确的时间在正确的CPU核心上运行正确的任务 。
CFS 调度程序(在 3.7 和之前的内核中)在每个运行队列的基础上跟踪负载,调度程序为每个CPU建立了一个运行队列,调度程序会考虑每个运行队列对整个系统负载的贡献 。该级别的负载跟踪足以帮助组调度程序在控制组之间分配 CPU 时间,但是在工作负载相对稳定时,在运行队列级别跟踪负载也往往会产生差异很大的估计 。
2.PELT算法
PELT负载跟踪通过跟踪粒度下推到单个“调度实体”的级别来精细化调度程序的控制 。为此讲一个跟踪周期划分成,记录任务处于可运行状态下的时间为x us 该任务在第i个周期对当前的CPU利用率为x / 1024,而对应的负载为
L =* x /1024
是CPU的容量,用于归一化系统中每个CPU运行的处理能力
收集到任务每个周期内的负载后,PELT需要计算一段时间内所有周期的累加负载L

Linux内核调度子系统之负载跟踪

文章插图
L = L0 + L1*y + L2 * y2 + L3 * y3 + …
其中y为衰减因子,用来衰减当前时间之前的CPU负载,认为之前的负载对当前负载的贡献是依此减弱的 。
在当前代码中,y 已被选择,因此 y32 等于 0.5 。因此,实体在过去 32 个周期的负载贡献的权重是其当前贡献的一半 。
该公式为最近的负载赋予最大权重,但允许过去的负载以递减的方式影响计算 。这个公式的好处是实际上没有必要保留一系列过去的负载贡献;简单地将前一时期的总负载贡献乘以 y 并添加新的 L0 就足够了 。
3.WALT算法
【Linux内核调度子系统之负载跟踪】PELT算法体现的是CPU负载连续的一段时间内变化的趋势,所以PELT有以下局限性:
WALT算法该进了PELT的缺点:
Linux内核调度子系统之负载跟踪

文章插图
WALT 保留了 PELT 的基础设施:实体跟踪;
改善策略 - 将任务的运行时间和可运行时间划分为N个窗口,这两个参数对任务负载的贡献在 N 个滑动窗口上平均 。这个指标可以粗略地认为是没有阻塞的任务的未加权负载 。N个窗口比PELT允许更快、更准确的任务迁移决策 。
WALT 忽略阻塞或睡眠的时间,即滑动窗口只存在当任务在运行队列或正在运行时 。这允许快速重新甄别短暂的睡眠后负载同样很重的任务 。因此一个任务不需要
重新执行获得它的负载,可以立刻迁移到其他 CPU上立即地执行 。
CPU busy time: 衡量CPU负载大小通过累加最近几个窗口所有任务的执行时间总和,所以使用CPU busy time所以更贴近瞬时的负载情况
一旦任务从 WALT 运行队列取出,WALT 就会忽略这个任务对 CPU 的贡献
因此调控器可以选择在刚刚结束后的一个窗口去降低频率,可能会更节省电量
根据更准确的使用数据,根据需要进行滞后设置 。