
# 内核cpu cgroup的多级混部调度
#### 需求背景
在业务混部场景中，Linux内核调度器需要为高优先级任务赋予更多的调度机会，并需要把低优先级任务对内核调度带来的影响降到最低。原有的在线、离线两级混部调度无法满足业务需求。
为解决此问题，HCE 2.0和HCE 3.0内核cpu cgroup支持多级混部调度，提供cgroup接口/sys/fs/cgroup/cpu/cpu.qos_level将任务调度级别扩展到5个级别，支持用户对每个cgroup组单独设置优先级。
#### 约束与限制
当前cpu.qos_level仅支持cgroup-v1， 不支持cgroup-v2。
#### 多级混部调度接口说明
cpu.qos_level的生效规则：
- CFS调度器自上而下逐层选择task_group，同一个父节点内的子节点之间cpu.qos_level生效。
- 子cgroup创建时默认继承父cgroup的cpu.qos_level，支持重新配置cpu.qos_level值。
- 同优先级的qos_level之间的资源竞争服从CFS调度器的策略。
- 同一个cpu上，qos_level \< 0 的任务始终会被qos_level \>= 0的任务无条件抢占，不受层级约束。
在调度高优先级任务时：
- 在线任务可无条件抢占离线任务，在多核调度时，在线任务可优先抢占其他核上的离线任务。超线程（Hyper Thread）场景，优先级为2的在线任务可驱逐SMT上的离线任务。
- 高优先级的任务被唤醒时获得一定的时间片加速，可立刻抢占低优先级的任务（忽略CFS的最小运行时间片），获得更低的时延响应。
表1cpu.qos_level接口说明 
| 接口            | 说明                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
|:---|:---|
| cpu.qos_level | 配置cgroup的cpu优先级。取值类型为整数形式，取值范围 为\[-2, 2 \] ，默认值为0。 - cpu.qos_level \>= 0 标识cgroup组内任务为在线任务，在线任务可无条件抢占离线任务。 优先级 0 \< 1 \< 2，同为在线业务的任务，高优先级的在线相比低优先级的在线可获取更多的CPU资源抢占机会。   - cpu.qos_level \< 0 标识cgroup组内的任务为离线任务，-1优先级高于-2。 -1级别的任务比-2级别的任务可获得更多的CPU资源抢占机会。 父节点运行离线任务时，子节点只能继承父节点的优先级，不支持修改为其他优先级。    |
   
#### 接口示例
按如下所示创建3个cgroup节点A、B、C，配置并查看qos_level接口。
图1cgroup节点A、B、C   
![](https://support.huaweicloud.com/usermanual-hce/zh-cn_image_0000002512128963.png "点击放大")
表2数据规划 
| cgroup组 | cpu.qos_level |
|:---|:---|
| A       | 1             |
| B       | -2            |
| C       | 2             |
   
1. 创建cgroup A及子节点B、C，依次设置A、B、C的cpu调度优先级为1、-2、2。
   cgroup A和cgroup C中的任务可无条件抢占cgroup B任务的CPU资源，cgroup C优先级大于cgroup A。
   ```
   mkdir -p /sys/fs/cgroup/cpu/A
   echo 1 > /sys/fs/cgroup/cpu/A/cpu.qos_level
   mkdir -p /sys/fs/cgroup/cpu/A/B
   echo -2 > /sys/fs/cgroup/cpu/A/B/cpu.qos_level
   mkdir -p /sys/fs/cgroup/cpu/A/C
   echo 2 > /sys/fs/cgroup/cpu/A/C/cpu.qos_level
   ```
   
2. 将task1、task2、task3进程加入cgroup B。
   task1、task2、task3进程加入cgroup B后，task1、task2、task3进程的cpu调度优先级为-2。
   ```
   echo $PID1 > /sys/fs/cgroup/cpu/A/B/tasks
   echo $PID2 > /sys/fs/cgroup/cpu/A/B/tasks
   echo $PID3 > /sys/fs/cgroup/cpu/A/B/tasks
   ```
   
3. 将task4、task5进程加入cgroup C。
   task4、task5进程加入cgroup C后，task4、task5进程的cpu调度优先级为2。
   ```
   echo $PID4 > /sys/fs/cgroup/cpu/A/C/tasks
   echo $PID5 > /sys/fs/cgroup/cpu/A/C/tasks
   ```
   
4. 查看cgroup B的cpu调度优先级及进程。
   ```
   [root@localhost cpu_qos]# cat /sys/fs/cgroup/cpu/A/B/cpu.qos_level
   -2
   [root@localhost boot]# cat /sys/fs/cgroup/cpu/A/B/tasks
   1879
   1880
   1881
   ```
   
5. 查看cgroup C的cpu调度优先级及进程。
   ```
   [root@localhost cpu_qos]# cat /sys/fs/cgroup/cpu/A/C/cpu.qos_level
   2
   [root@localhost boot]# cat /sys/fs/cgroup/cpu/A/C/tasks
   1882
   1883
   ```
   
 
