1*4407cca0STang Yizhou.. SPDX-License-Identifier: GPL-2.0
2*4407cca0STang Yizhou.. include:: ../disclaimer-zh_CN.rst
3*4407cca0STang Yizhou
4*4407cca0STang Yizhou:Original: Documentation/scheduler/schedutil.rst
5*4407cca0STang Yizhou
6*4407cca0STang Yizhou:翻译:
7*4407cca0STang Yizhou
8*4407cca0STang Yizhou  唐艺舟 Tang Yizhou <tangyeechou@gmail.com>
9*4407cca0STang Yizhou
10*4407cca0STang Yizhou=========
11*4407cca0STang YizhouSchedutil
12*4407cca0STang Yizhou=========
13*4407cca0STang Yizhou
14*4407cca0STang Yizhou.. note::
15*4407cca0STang Yizhou
16*4407cca0STang Yizhou   本文所有内容都假设频率和工作算力之间存在线性关系。我们知道这是有瑕疵的,
17*4407cca0STang Yizhou   但这是最可行的近似处理。
18*4407cca0STang Yizhou
19*4407cca0STang YizhouPELT(实体负载跟踪,Per Entity Load Tracking)
20*4407cca0STang Yizhou==============================================
21*4407cca0STang Yizhou
22*4407cca0STang Yizhou通过PELT,我们跟踪了各种调度器实体的一些指标,从单个任务到任务组分片到CPU
23*4407cca0STang Yizhou运行队列。我们使用指数加权移动平均数(Exponentially Weighted Moving Average,
24*4407cca0STang YizhouEWMA)作为其基础,每个周期(1024us)都会衰减,衰减速率满足y^32 = 0.5。
25*4407cca0STang Yizhou也就是说,最近的32ms贡献负载的一半,而历史上的其它时间则贡献另一半。
26*4407cca0STang Yizhou
27*4407cca0STang Yizhou具体而言:
28*4407cca0STang Yizhou
29*4407cca0STang Yizhou  ewma_sum(u) := u_0 + u_1*y + u_2*y^2 + ...
30*4407cca0STang Yizhou
31*4407cca0STang Yizhou  ewma(u) = ewma_sum(u) / ewma_sum(1)
32*4407cca0STang Yizhou
33*4407cca0STang Yizhou由于这本质上是一个无限几何级数的累加,结果是可组合的,即ewma(A) + ewma(B) = ewma(A+B)。
34*4407cca0STang Yizhou这个属性是关键,因为它提供了在任务迁移时重新组合平均数的能力。
35*4407cca0STang Yizhou
36*4407cca0STang Yizhou请注意,阻塞态的任务仍然对累加值(任务组分片和CPU运行队列)有贡献,这反映了
37*4407cca0STang Yizhou它们在恢复运行后的预期贡献。
38*4407cca0STang Yizhou
39*4407cca0STang Yizhou利用这一点,我们跟踪2个关键指标:“运行”和“可运行”。“运行”反映了一个调度实体
40*4407cca0STang Yizhou在CPU上花费的时间,而“可运行”反映了一个调度实体在运行队列中花费的时间。当只有
41*4407cca0STang Yizhou一个任务时,这两个指标是相同的,但一旦出现对CPU的争用,“运行”将减少以反映每个
42*4407cca0STang Yizhou任务在CPU上花费的时间,而“可运行”将增加以反映争用的激烈程度。
43*4407cca0STang Yizhou
44*4407cca0STang Yizhou更多细节见:kernel/sched/pelt.c
45*4407cca0STang Yizhou
46*4407cca0STang Yizhou
47*4407cca0STang Yizhou频率 / CPU不变性
48*4407cca0STang Yizhou================
49*4407cca0STang Yizhou
50*4407cca0STang Yizhou因为CPU频率在1GHz时利用率为50%和CPU频率在2GHz时利用率为50%是不一样的,同样
51*4407cca0STang Yizhou在小核上运行时利用率为50%和在大核上运行时利用率为50%是不一样的,我们允许架构
52*4407cca0STang Yizhou以两个比率来伸缩时间差,其中一个是动态电压频率升降(Dynamic Voltage and
53*4407cca0STang YizhouFrequency Scaling,DVFS)比率,另一个是微架构比率。
54*4407cca0STang Yizhou
55*4407cca0STang Yizhou对于简单的DVFS架构(软件有完全控制能力),我们可以很容易地计算该比率为::
56*4407cca0STang Yizhou
57*4407cca0STang Yizhou            f_cur
58*4407cca0STang Yizhou  r_dvfs := -----
59*4407cca0STang Yizhou            f_max
60*4407cca0STang Yizhou
61*4407cca0STang Yizhou对于由硬件控制DVFS的更多动态系统,我们使用硬件计数器(Intel APERF/MPERF62*4407cca0STang YizhouARMv8.4-AMU)来计算这一比率。具体到Intel,我们使用::
63*4407cca0STang Yizhou
64*4407cca0STang Yizhou           APERF
65*4407cca0STang Yizhou  f_cur := ----- * P0
66*4407cca0STang Yizhou           MPERF
67*4407cca0STang Yizhou
68*4407cca0STang Yizhou             4C-turbo;  如果可用并且使能了turbo
69*4407cca0STang Yizhou  f_max := { 1C-turbo;  如果使能了turbo
70*4407cca0STang Yizhou             P0;        其它情况
71*4407cca0STang Yizhou
72*4407cca0STang Yizhou                    f_cur
73*4407cca0STang Yizhou  r_dvfs := min( 1, ----- )
74*4407cca0STang Yizhou                    f_max
75*4407cca0STang Yizhou
76*4407cca0STang Yizhou我们选择4C turbo而不是1C turbo,以使其更持久性略微更强。
77*4407cca0STang Yizhou
78*4407cca0STang Yizhour_cpu被定义为当前CPU的最高性能水平与系统中任何其它CPU的最高性能水平的比率。
79*4407cca0STang Yizhou
80*4407cca0STang Yizhou  r_tot = r_dvfs * r_cpu
81*4407cca0STang Yizhou
82*4407cca0STang Yizhou其结果是,上述“运行”和“可运行”的指标变成DVFS无关和CPU型号无关了。也就是说,
83*4407cca0STang Yizhou我们可以在CPU之间转移和比较它们。
84*4407cca0STang Yizhou
85*4407cca0STang Yizhou更多细节见:
86*4407cca0STang Yizhou
87*4407cca0STang Yizhou - kernel/sched/pelt.h:update_rq_clock_pelt()
88*4407cca0STang Yizhou - arch/x86/kernel/smpboot.c:"APERF/MPERF frequency ratio computation."
89*4407cca0STang Yizhou - Documentation/translations/zh_CN/scheduler/sched-capacity.rst:"1. CPU Capacity + 2. Task utilization"
90*4407cca0STang Yizhou
91*4407cca0STang Yizhou
92*4407cca0STang YizhouUTIL_EST / UTIL_EST_FASTUP
93*4407cca0STang Yizhou==========================
94*4407cca0STang Yizhou
95*4407cca0STang Yizhou由于周期性任务的平均数在睡眠时会衰减,而在运行时其预期利用率会和睡眠前相同,
96*4407cca0STang Yizhou因此它们在再次运行后会面临(DVFS)的上涨。
97*4407cca0STang Yizhou
98*4407cca0STang Yizhou为了缓解这个问题,(一个默认使能的编译选项)UTIL_EST驱动一个无限脉冲响应
99*4407cca0STang Yizhou(Infinite Impulse Response,IIR)的EWMA,“运行”值在出队时是最高的。
100*4407cca0STang Yizhou另一个默认使能的编译选项UTIL_EST_FASTUP修改了IIR滤波器,使其允许立即增加,
101*4407cca0STang Yizhou仅在利用率下降时衰减。
102*4407cca0STang Yizhou
103*4407cca0STang Yizhou进一步,运行队列的(可运行任务的)利用率之和由下式计算:
104*4407cca0STang Yizhou
105*4407cca0STang Yizhou  util_est := \Sum_t max( t_running, t_util_est_ewma )
106*4407cca0STang Yizhou
107*4407cca0STang Yizhou更多细节见: kernel/sched/fair.c:util_est_dequeue()
108*4407cca0STang Yizhou
109*4407cca0STang Yizhou
110*4407cca0STang YizhouUCLAMP
111*4407cca0STang Yizhou======
112*4407cca0STang Yizhou
113*4407cca0STang Yizhou可以在每个CFS或RT任务上设置有效的u_min和u_max clamp值(译注:clamp可以理解
114*4407cca0STang Yizhou为类似滤波器的能力,它定义了有效取值范围的最大值和最小值);运行队列为所有正在
115*4407cca0STang Yizhou运行的任务保持这些clamp的最大聚合值。
116*4407cca0STang Yizhou
117*4407cca0STang Yizhou更多细节见: include/uapi/linux/sched/types.h
118*4407cca0STang Yizhou
119*4407cca0STang Yizhou
120*4407cca0STang YizhouSchedutil / DVFS
121*4407cca0STang Yizhou================
122*4407cca0STang Yizhou
123*4407cca0STang Yizhou每当调度器的负载跟踪被更新时(任务唤醒、任务迁移、时间流逝),我们都会调用
124*4407cca0STang Yizhouschedutil来更新硬件DVFS状态。
125*4407cca0STang Yizhou
126*4407cca0STang Yizhou其基础是CPU运行队列的“运行”指标,根据上面的内容,它是CPU的频率不变的利用率
127*4407cca0STang Yizhou估计值。由此我们计算出一个期望的频率,如下::
128*4407cca0STang Yizhou
129*4407cca0STang Yizhou             max( running, util_est );  如果使能UTIL_EST
130*4407cca0STang Yizhou  u_cfs := { running;                   其它情况
131*4407cca0STang Yizhou
132*4407cca0STang Yizhou               clamp( u_cfs + u_rt, u_min, u_max );  如果使能UCLAMP_TASK
133*4407cca0STang Yizhou  u_clamp := { u_cfs + u_rt;                         其它情况
134*4407cca0STang Yizhou
135*4407cca0STang Yizhou  u := u_clamp + u_irq + u_dl;		[估计值。更多细节见源代码]
136*4407cca0STang Yizhou
137*4407cca0STang Yizhou  f_des := min( f_max, 1.25 u * f_max )
138*4407cca0STang Yizhou
139*4407cca0STang Yizhou关于IO-wait的说明:当发生更新是因为任务从IO完成中唤醒时,我们提升上面的“u”。
140*4407cca0STang Yizhou
141*4407cca0STang Yizhou然后,这个频率被用来选择一个P-state或OPP,或者直接混入一个发给硬件的CPPC式
142*4407cca0STang Yizhou请求。
143*4407cca0STang Yizhou
144*4407cca0STang Yizhou关于截止期限调度器的说明: 截止期限任务(偶发任务模型)使我们能够计算出满足
145*4407cca0STang Yizhou工作负荷所需的硬f_min值。
146*4407cca0STang Yizhou
147*4407cca0STang Yizhou因为这些回调函数是直接来自调度器的,所以DVFS的硬件交互应该是“快速”和非阻塞的。
148*4407cca0STang Yizhou在硬件交互缓慢和昂贵的时候,schedutil支持DVFS请求限速,不过会降低效率。
149*4407cca0STang Yizhou
150*4407cca0STang Yizhou更多信息见: kernel/sched/cpufreq_schedutil.c
151*4407cca0STang Yizhou
152*4407cca0STang Yizhou
153*4407cca0STang Yizhou注意
154*4407cca0STang Yizhou====
155*4407cca0STang Yizhou
156*4407cca0STang Yizhou - 在低负载场景下,DVFS是最相关的,“运行”的值将密切反映利用率。
157*4407cca0STang Yizhou
158*4407cca0STang Yizhou - 在负载饱和的场景下,任务迁移会导致一些瞬时性的使用率下降。假设我们有一个
159*4407cca0STang Yizhou   CPU,有4个任务占用导致其饱和,接下来我们将一个任务迁移到另一个空闲CPU上,
160*4407cca0STang Yizhou   旧的CPU的“运行”值将为0.75,而新的CPU将获得0.25。这是不可避免的,而且随着
161*4407cca0STang Yizhou   时间流逝将自动修正。另注,由于没有空闲时间,我们还能保证f_max值吗?
162*4407cca0STang Yizhou
163*4407cca0STang Yizhou - 上述大部分内容是关于避免DVFS下滑,以及独立的DVFS域发生负载迁移时不得不
164*4407cca0STang Yizhou   重新学习/提升频率。
165*4407cca0STang Yizhou
166