Skip to content

添加了linaro官方的big.LITTLE-mp(HMP负载调度器), 并增加了完全的注释信息

Latest
Compare
Choose a tag to compare
@gatieme gatieme released this 01 Dec 07:42
· 45 commits to master since this release

内核配置参数, 参见3.10/linaro/configs/big-LITTLE-MP.conf

CONFIG_CGROUPS=y
CONFIG_CGROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
CONFIG_NO_HZ=y
CONFIG_SCHED_MC=y
CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE=y  #禁止内核自带的SMP负载均衡
CONFIG_SCHED_HMP=y
CONFIG_HMP_FAST_CPU_MASK=""
CONFIG_HMP_SLOW_CPU_MASK=""
CONFIG_HMP_VARIABLE_SCALE=y   # 运行动态修改负载计算的比率
CONFIG_HMP_FREQUENCY_INVARIANT_SCALE=y  # 设置cpufreq频率
CONFIG_SCHED_HMP_LITTLE_PACKING=y  # 小任务封包服务

HMP 调度器的实现可以简单概况为:

  • 把小核调度域上“大活”迁移到大核调度域的空闲 CPU 上(向上迁移 up migration)
  • 把每个大核 CPU 上“小活”迁移到小核调度域的空闲 CPU 上(向下迁移 down migration)
    大活就是负载比较重的进程,小活就是负载比较轻的进程

如何判断进程是大活还是小活呢?

HMP 采用 load_avg_ratio 来比较,load_avg_ratio 的计算公式之前已经描述过,它并没有像内核中采用的 load_avg_contrib 一样考虑进程的可运行时间比重(runnable_sum/unable_period)和实际权重,在 HMP 调度器眼里只考虑进程的可运行时间比重

那么 CPU 密集型的进程以及长时间运行的进程容易理解为大活,那些间隙性运行的进程就变成小活了,即便它优先级很高。比如一个优先级很高的进程,它只是间歇性的运行,那么它是没机会在大核上遛弯的

另外 HMP 调度器还定义了 hmp_up_threshold(700)和 hmp_down_threshold(512),
那么也就是说可运行时间比重(runnable_sum/unable_period)小于 50%就认为是小活,大于68.3%就认为是大活

HMP 调度器的实现比内核中自带的 CPU 负载均衡要简单的多,首先 HMP 调度器只定义了两个调度域,没有调度组和调度能力的概念,而且调度域没有层次. 内核自带的负载均衡调度器可以根据 CPU 的物理属性来定义调度域的层次关系

另外 HMP 调度器没有考虑调度域内以及调度域之间的负载均衡. HMP 调度器寄托在调度域中有空闲 CPU。假设小核上有进程突然持续的在使用 CPU,那么 load_avg_ratio 变大表示这个是大活,可是大核上暂时没有空闲 CPU 啊,那怎么办?

假设大小核调度域都没有空闲 CPU,那么谁来保证他们之间的负载均衡呢?有人说用系统默认的 CPU 负载均衡调度器啊. Linaro 上实现的 HMP 调度器是默认关闭了系统自带的SMP 负载均衡的,即关闭 CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE 这个宏. 如果开启的话会出现什么情况,那么 SMP 调度器就会考虑大小核调度域之间的负载均衡了,他们要负载大致相等喔(假设不考虑大小核之间的能力系数 capacity),那相当于小核调度域也要和大核调度域干一样的活,那这样的话 big.LITTLE 模型就失去意义。另外两套调度器一起运行是否会冲突,即 HMP 迁移了进程,又被 SMP 调度器给迁移回来,