
# CPU软绑定
#### 背景说明
做NUMA亲和性绑定后，假如两个VM负载很高，但其他VM空闲，空闲的CPU无法被利用。如果不做绑定，则无法有效利用NUMA亲和性，尤其整机繁忙情况下，性能严重下降。无论哪种方式都有缺陷，所以提供了软绑定方案：
- 优先使用preferred CPU：当preferred CPU利用率低于阈值时，优先使用preferred CPU。
- 允许使用allowed CPU：当preferred CPU利用率超过阈值时，在所有allowed CPU内选核。
- 该软绑定方案同样适用于容器场景。
![](https://support.huaweicloud.com/usermanual-hce/public_sys-resources/note_3.0-zh-cn.png)
- preferred CPU为软绑定的优先调度CPU。

- allowed CPU为通过sched_setaffinity或cgroup等设置的绑定的CPU列表。
 
为了能更直观地观测到软绑定的执行，增加了软绑定调度计数值；为了在不关机的情况下实现开启/关闭软绑定功能，增加了软绑定调度开关。
#### 接口说明
- 软绑定功能开启时，cgroup组增加/sys/fs/cgroup/cpuacct/子cgroup/cpuacct.nr_select_allowed_cpus计数值，统计cgroup组内的任务在唤醒选核时，选择共享核的次数。
- 软绑定功能开启时，cgroup组增加/sys/fs/cgroup/cpuacct/子cgroup/cpuacct.nr_select_prefer_cpus计数值，统计cgroup组内的任务在唤醒选核时，选择优先核的次数。
- 软绑定功能开启时，cgroup组增加/sys/fs/cgroup/cpuacct/子cgroup/cpuacct.nr_smoothed_prefer_cpus计数值，统计cgroup组内的任务在唤醒选核时，由于平滑算法没有从优先核切换到共享核的次数。
- 提供/proc/sys/kernel/sched_dynamic_affinity_disable接口，用于禁用软绑定功能。参数值为0时表示软绑定开启，参数值为1时表示禁用软绑定。
 
#### 使用说明
软绑定的使用设置：
- 使用步骤
  1. 使用/proc/$PID/task/$TID/preferred_cpuset或者/sys/fs/cgroup/cpuset/下的cpuset.preferred_cpus为进程或cgroup组配置软绑定CPU列表。
  
  2. 通过/proc/sys/kernel/sched_util_low_pct设置preferred CPU利用率阈值，当preferred CPU利用率低于该阈值时，限制业务在preferred CPU中选核，否则在allowed CPU中选核。其中preferred CPU利用率有两种计算方式可选，详见步骤3。
  
  3. 通过/sys/kernel/debug/sched_features中开启或关闭DA_UTIL_TASKGROUP控制是基于taskgroup的preferred CPU利用率还是基于preferred CPU总利用率进行选核范围决策。
   
- 线程preferred_cpuset设置接口，用于配置软绑定CPUlist。cpulist是cpu逻辑编号的一个列表，以逗号隔开。比如CPU{1,3,5,6,7}的cpulist为"1,3,5,6,7"，其中连续的编号支持以范围的形式简写，比如"5,6,7"可简写为"5-7"。
  1. preferred_cpuset必须为allowed cpuset子集。
  
  2. 当preferred_cpuset未配置、配置为空或配置与allowed cpuset相同时，软绑定不生效。
     ```
     查看接口：
     cat /proc/$PID/task/$TID/preferred_cpuset
     给接口赋值示例：
     echo 5-7 > /proc/$PID/task/$TID/preferred_cpuset
     ```
     
   
- cgroup cpuset控制器下的每个目录，都会有cpuset.preferred_cpus设置接口，用于cgroup场景下软绑定设置。接口参数形式和线程preferred_cpuset设置一致。
  1. 当前cgroup cpuset.preferred_cpus 必须为 allowed cpu（即cpuset.cpus）子集。
  
  2. 当cpuset.preferred_cpus未配置、配置为空或配置与cpuset.cpus相同时，软绑定不生效。
  
  3. cpuset.preferred_cpus与父子cpuset.preferred_cpus都无约束关系。
     ```
     查看接口：
     cat /sys/fs/cgroup/cpuset/cpuset.preferred_cpus
     给接口赋值示例：
     echo 5-7 > /sys/fs/cgroup/cpuset/子cgroup/cpuset.preferred_cpus
     ```
     
   
- sched_util_low_pct设置接口，取值范围0-100（单位%），默认为85。参数0表示，不再受阈值限制，但选核时依然会优先考虑空闲的preferred CPU。参数100表示利用率超过preferred_cpus capacity时才会从cpuset.cpus中选核。
  ```
  查看接口：
  cat /proc/sys/kernel/sched_util_low_pct
  给接口赋值示例：
  echo 90 > /proc/sys/kernel/sched_util_low_pct
  ```
  
- DA_UTIL_TASKGROUP开关， /sys/kernel/debug/sched_features中新增DA_UTIL_TASKGROUP开关，默认开启。开启时，通过检测taskgroup在preferred_cpus中的利用率进行选核范围决策。关闭时，则通过检测preferred_cpus的总利用率（即包括非taskgroup进程在preferred_cpus的使用量）进行选核范围决策。
  ```
  开启：echo DA_UTIL_TASKGROUP > /sys/kernel/debug/sched_features
  关闭：echo NO_DA_UTIL_TASKGROUP > /sys/kernel/debug/sched_features
  ```
  
软绑定调度可视化和禁用开关的使用设置：
- 软绑定功能开启时，查看和清零接口：
  ```
  查看接口：
  cat /sys/fs/cgroup/cpuacct/子cgroup/cpuacct.nr_select_allowed_cpus //选择共享核的次数
  cat /sys/fs/cgroup/cpuacct/子cgroup/cpuacct.nr_select_prefer_cpus //选择优先核的次数
  cat /sys/fs/cgroup/cpuacct/子cgroup/cpuacct.nr_smoothed_prefer_cpus //在平滑功能下，没有从优先核切换到共享核的次数
  清零接口：
  echo 0 > /sys/fs/cgroup/cpuacct/子cgroup/cpuacct.nr_smoothed_prefer_cpus
  ```
  
- 对/proc/sys/kernel/sched_dynamic_affinity_disable接口，可以用cat的方式进行查看，也可以通过echo的方式修改其值。
  ```
  查看接口：cat /proc/sys/kernel/sched_dynamic_affinity_disable  // 接口值为0或1，为0时表示软绑定开启，为1时表示禁用软绑定
  接口赋值：echo 0 > /proc/sys/kernel/sched_dynamic_affinity_disable
  ```
  
- 在每个进程下新增了/proc/$pid/task/$tid/selected_cpuset接口，可以查看进程选定要运行的CPU范围。
![](https://support.huaweicloud.com/usermanual-hce/public_sys-resources/note_3.0-zh-cn.png)
如果cgroup v1未配置cpu子组或目标进程不存在于cpu子组中，则无论开关是否开启，都通过检测preferred_cpus总利用率进行选核范围决策。
#### 约束限制
1. 需要通过root用户权限使用，root用户具有系统最高权限，在使用root用户进行操作时，请严格按照操作指导进行操作，避免其他操作造成系统管理及安全风险。
2. 设置preferred_cpuset后，只有进程在唤醒或周期负载均衡时才会重新选核。
3. 软绑定在选择preferred CPU或allowed CPU时依赖pelt负载计算，1ms更新一次，所以如果负载频繁变化，会导致频繁选preferred CPU或allowed CPU。
 
