arthur-zhang / morning-up-up

78 stars 6 forks source link

1130 分享:实时进程调度算法 FIFO RR、nice 值对 CFS 的影响 #25

Open arthur-zhang opened 3 years ago

arthur-zhang commented 3 years ago

1、实时进程调度算法的一些问题探究 sched_rt_period_us sched_rt_runtime_us 参数的理解 2、nice 值对 CFS 调度算法的影响实例演示 3、chrt 和 renice 命令的使用

sudo renice -n -5 -g 14822 sudo chrt -f -a -p 60 12615

image

作业: 1、通过 chrt 验证 RR 调度算法 CPU 占用的变化 2、通过 renice 验证不同 nice 值对 CPU 占用的影响

IKNOWLJT commented 3 years ago

[TOC]

进程调度再探究 (FIFO、RR、CFS)

1. 实时进程和普通进程的区别:

如果系统中有一个实时进程且可运行,那么调度器总是会选择它,除非另有一个优先级更高的实时进程

2. CPU密集型 和 IO密集型

吞吐 vs 响应:

​ 响应:最小化某个任务的响应时间,哪怕牺牲其他的任务为代价。

​ 吞吐:全局视野,整个系统的workload被最大化处理。

任何操作系统的调度设计都需要最大化的追求2个目标:吞吐率大和延迟低。但是这两个目标却是有些冲突,是相对的,整个系统的吞吐率大,意味着CPU必须尽量的最大限度的工作,不要让cpu空闲下来,但是要求响应低,则必须在优先级高的进程在需要的情况下随时可以抢占进来,打断别人,强行插队,但是,抢占会引起上下文切换,上下文切换的时间本身对吞吐率来讲,是一个消耗(上下文切换更大的消耗不是切换本身,而是切换会引起大量的cache miss。你明明微博跑的很爽,现在切过去微信,那么CPU的cache是不太容易命中微信的)

操作系统中估算"上下文切换"对吞吐能力影响时,不是计算上下文切换本身,而是在CPU 高速cache中的miss。一旦从一个进程切到另一个进程,会造成比较多的cache miss,从而影响吞吐能力。

CPU密集型 vs IO密集型

3. 调度策略

3.1 调度策略:
3.2 FIFO 调度策略命令实操:
3.2.1 测试代码:进程的调度和资源的封装一节中的 fake_make.c
3.2.2 开启两个终端,分别执行 ./fake_make -j2 , 查看cpu占用率和进程调度策略

新创建的线程,如果不知道调度策略,则默认都是SCHED_OTHER(SCHED_NORMAL),基于CFS的完全公平调度策略,可以跑满整个CPU

image-20201130164420653

3.2.3 修改其中一个线程的调度策略为FIFO:sudo chrt -f -a -p 30266

可以看到被修改成FIFO的进程的CPU占用率, 达到接近 190%

另一个处于NORMAL的进程的CPU占用率,接近10%

image-20201130164910316

3.2.4 将两个进程同时修改成FIFO,并且不同的优先级

sudo chrt -f -a -p 30 6525

sudo chrt -f -a -p 20 6548

可以看到只有一个 6525 的进程执行,CPU的使用率接近190%,符合优先级越高,优先执行的情况,并且因为进程是死循环,先执行的永远不会结束,优先级低的永远不会执行

image-20201130165512386

3.2.5 将两个进程同时修改成FIFO,并且相同的优先级

sudo chrt -f -a -p 30 6525

sudo chrt -f -a -p 30 6548

可以看到只有一个 6525 的进程执行,CPU的使用率接近190%,符合优先级相同,先进先出的策略

image-20201130174358127

3.2.6 最后我们再来探讨下,为什么无论我们如何设置CPU的占用率都最高是190%左右呢?(我的虚拟机是两个核的)

这是因为操作系统设置实时进程在一个运行周期(sched_rt_period_us)内,最多占用CPU运行时间为 sched_rt_runtime_us

在linux中,这两个参数默认为

​ sched_rt_period_us = 1s

​ sched_rt_runtime_us = 0.95s

所以对于单核的机器,设置了实时调度策略后,最多可以占用到95%的CPU,双核的机器最多占用190%的CPU

image-20201130174959970

3.3 RR 调度策略实操:
3.3.1 和FIFO实操代码相同,同样的开启两个终端,分别执行 ./fake_make -j2
3.3.2 修改其中一个进程的调度策略为RR:sudo chrt -r -a -p 30 13225

现象和上面的FIFO的同样的操作一样

可以看到被修改成RR的进程的CPU占用率, 达到接近 190%

另一个处于NORMAL的进程的CPU占用率,接近10%

image-20201130175734954

3.3.3 修改两个进程的调度策略为均为RR,且不同优先级

sudo chrt -r -a -p 30 13225

sudo chrt -r -a -p 40 13211

和FIFO的相同步骤一样,符合不同优先级,高优先级的先执行

image-20201130180119386

3.3.4 修改两个进程的调度策略为均为RR,且相同优先级

sudo chrt -r -a -p 30 13225

sudo chrt -r -a -p 30 13211

和FIFO的相同步骤不一样,符合对于RR策略,相同优先级的轮训执行

image-20201130180219833

3.4 CFS调度实验
3.4.1 和FIFO实操代码相同,同样的开启两个终端,分别执行 ./fake_make -j2
3.4.2 设置其中一个进程的nice值为-5 sudo renice -n -5 -g 29962 查看CPU使用率变化情况

修改为-5 的renice值的进程的CPU使用率变为 150%,没有修改的进程的CPU使用率为50%

image-20201130193451916

3.4.3 CFS调度实验总结:

CFS的调度原理是根据vruntime 构建一个红黑树,通过这个红黑树每次都会调度vruntime最小的进程,同时vruntime又是不断变化的,所以也会不停的调整红黑树,保证每次获取到的都是vruntime最小的进程

image-20201130194326278

vruntime的计算规则

虚拟运行时间 vruntime += 实际运行时间 delta_exec * NICE_0_LOAD / 权重

image-20201130194513005

根据vruntime的计算规则,我们可以知道,vruntime的变化是基于实际运行的时间* NICE_0_LOAD(1024) /prio_to_weight[NICE] 值

比如在上面CFS的实操中:
    1. 对于上面设置的NICE值为 -5 的进程:29926
        vruntime(NICE:-5) += delta_exec * 1024 / 3121
    2. 对于普通线程来说(NICE值为0):29992
        vruntime(NICE:0) += delta_exec * 1024 / 1024
    可见在相同的 delta_exec 情况下,(NICE:-5) 的进程执行三次的vruntime 才会和(NICE:0)的进程一样,所以  29926 的CPU占用率和 29992 的CPU占用率呈现3:1的比例也就可以理解了

CFS的思想就是让每个调度实体(没有组调度的情形下就是进程,以后就说进程了)的vruntime互相追赶,而每个调度实体的vruntime增加速度不同,权重越大的增加的越慢,这样就能获得更多的cpu执行时间。

4. chrt命令和renice命令

4.1 chrt 命令:修改进程的调度策略和优先级的 (针对实时进程,比如RR和FIFO)

​ 需要注意点的这个里面设置的进程优先级的值是值越大,进程优先级越高

​ 比如:

sudo chrt -r -a -p 40 13211 的优先级大于 sudo chrt -r -a -p 30 13225

4.2 renice 命令设置进程的 NICE值,从而达到控制进程CPU使用率的效果 (针对普通进程 CFS调度算法)

需要注意 renice的设置需要在 sudo sysctl -w kernel.sched_autogroup_enabled=0 (修改完需要重新登录)的情况下设置

eg. sudo renice -n -5 -g 29962

Wolf-ZR commented 3 years ago

image image

wefun94 commented 3 years ago

### (1)实时进程调度 linux下进程是分优先级的,0级到99级是分给实时进程的,100级到139级是分给非实时进程的

在实时进行调度下,有两个参数特别重要啊:

sysctl -n kernel.sched_rt_period_us   # 实时进程调度的单位CPU时间 1 秒
1000000
sysctl -n kernel.sched_rt_runtime_us  # 实时进程在 1 秒中实际占用的CPU时间, 0.95秒
950000

我们可以使用命令来修改进程的调度策略和优先级

sudo chrt -r -a -p 20 13421  # 使用rr调度策略,并调整13421的优先级为20

当我们启动两个实时进程时

avatar

我们可以看到其中一个实时进程占用了95%的CPU,这里的计算就是根据上面参数的,另外一个实时进程需要等前面的执行完才会执行。

### (2)nice值对进程调度的影响 对于非实时进程的调度,是通过CFS调度器来实现的,CFS调度器的核心是虚拟运行时间vruntime。虚拟运行时间跟进程运行时间和优先级有关,进程占用CPU时间越长,进程优先级越低,其vruntime就越大

vruntime=delta *(NICE_0_LOAD/ weight)

我们可以通过renice设置进程的 NICE值

sudo renice -n -5 -p 14797 

我们启动两个非实时进程,两个进程的CPU占用比较均衡

avatar

接下来我们修改 14798进程的nice值 sudo renice -n -5 -p 14797

avatar

修改完后,14798进程的 weight 会变大,相关的vruntime就变小,线程优先级就越大 avatar

通过上表,可以看到nice=0和nice=-5的权重基本就是1 :3,下图展示了修改后的情况,相应的CPU占用也是 3:1