在计算cpu的util(函数sugov_get_util)期间需要使用margin来补偿util(在看schedutil governor的时候,不仅仅有cpu 的util margin,还有freq margin),得到最终的util+=margin
那么这个margin怎么计算的呢?
sugov_update_shared–>sugov_get_util–>boosted_cpu_util
下面就来看看这个函数怎么计算margin的吧

unsigned long
boosted_cpu_util(int cpu)
{  unsigned long util = cpu_util_freq(cpu);//获取当前cpu的util long margin = schedtune_cpu_margin(util, cpu);  trace_sched_boost_cpu(cpu, util, margin);  return util + margin;
}  

使用walt计算cpu util:

static inline unsigned long cpu_util_freq(int cpu)
{  unsigned long util = cpu_rq(cpu)->cfs.avg.util_avg;  unsigned long capacity = capacity_orig_of(cpu);  #ifdef CONFIG_SCHED_WALT  if (!walt_disabled && sysctl_sched_use_walt_cpu_util)  util = div64_u64(cpu_rq(cpu)->cumulative_runnable_avg,  walt_ravg_window >> SCHED_LOAD_SHIFT);
#endif  return (util >= capacity) ? capacity : util;
}  

可以知道util = cumulative_runnable_avg/(walt_avg_window>>10)。walt_avg_window是常量,在walt.c文件中定义了,而且在将walt负载怎么计算的文章中有详细的解释:https://blog.csdn.net/wuming_422103632/article/details/81633225

我们重点看schedtune_cpu_margin怎么计算得到margin的

static inline int
schedtune_cpu_margin(unsigned long util, int cpu)
{  int boost = schedtune_cpu_boost(cpu);  if (boost == 0)  return 0;  return schedtune_margin(util, boost);
}  

详细解释如下:
1.schedtune_cpu_boost函数

int schedtune_cpu_boost(int cpu)
{  struct boost_groups *bg;  bg = &per_cpu(cpu_boost_groups, cpu);  return bg->boost_max;
}  

上面函数是获取结构体struct boost_group 元素boost_max,结构体boost_group是存储cpu上面runnable task分不同的group,可能每个group有不同的boost参数设定。下面是这个结构体的解释:

/* SchedTune boost groups * Keep track of all the boost groups which impact on CPU, for example when a * CPU has two RUNNABLE tasks belonging to two different boost groups and thus * likely with different boost values. * Since on each system we expect only a limited number of boost groups, here * we use a simple array to keep track of the metrics required to compute the * maximum per-CPU boosting value. */
struct boost_groups {  /* Maximum boost value for all RUNNABLE tasks on a CPU */  bool idle;  int boost_max;  struct {  /* The boost for tasks on that boost group */  int boost;  /* Count of RUNNABLE tasks on that boost group */  unsigned tasks;  } group[BOOSTGROUPS_COUNT];  /* CPU's boost group locking */  raw_spinlock_t lock;
};
/* Boost groups affecting each CPU in the system */
DEFINE_PER_CPU(struct boost_groups, cpu_boost_groups);

2.schedtune_margin函数:

static long
schedtune_margin(unsigned long signal, long boost)
{  long long margin = 0;  /* * Signal proportional compensation (SPC) * * The Boost (B) value is used to compute a Margin (M) which is * proportional to the complement of the original Signal (S): *   M = B * (SCHED_CAPACITY_SCALE - S) * The obtained M could be used by the caller to "boost" S. */  if (boost >= 0)  margin = signal * boost;  else  margin = -signal * boost;  margin  = reciprocal_divide(margin, schedtune_spc_rdiv);  if (boost >= 0)  margin = clamp_t(long long, margin, 0,  SCHED_CAPACITY_SCALE - signal);  if (boost < 0)  margin *= -1;  return margin;
}  

主要是计算schedtune_spc_rdiv = reciprocal_value(100);reciprocal_value函数源码如下:

struct reciprocal_value reciprocal_value(u32 d)
{  struct reciprocal_value R;  u64 m;  int l;  l = fls(d - 1);  /*d=100,fls(99)=7*/m = ((1ULL << 32) * ((1ULL << l) - d));  do_div(m, d);  ++m;  R.m = (u32)m;  //R.m = 1202590843R.sh1 = min(l, 1);  //R.sh1 = 1R.sh2 = max(l - 1, 0); //R.sh2 = 6return R;
}  /** * fls - find last (most-significant) bit set * @x: the word to search * * This is defined the same way as ffs. * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. */  static __always_inline int fls(int x)
{  int r = 32;  if (!x)  return 0;  if (!(x & 0xffff0000u)) {  x <<= 16;  r -= 16;  }  if (!(x & 0xff000000u)) {  x <<= 8;  r -= 8;  }  if (!(x & 0xf0000000u)) {  x <<= 4;  r -= 4;  }  if (!(x & 0xc0000000u)) {  x <<= 2;  r -= 2;  }  if (!(x & 0x80000000u)) {  x <<= 1;  r -= 1;  }  return r;
}  

所以能够知道结构体schedtune_spc_rdiv是一个常量结构体,而函数

margin  = reciprocal_divide(margin, schedtune_spc_rdiv);  

是一个除法,reciprocal_divide是计算A/B的优化函数。由于乘法在计算机上快得多,所以内核使用所谓的 Newton-Raphson 方法,这只需要乘法和位移,虽然我们对数学细节并不关系,但我们需要知道,内核可以不计算C=A/B,而是使用C=reciprocal_divide(A, reciprocal_value(B))的方式,后者涉及的两个函数都是库程序。

static inline u32 reciprocal_divide(u32 a, struct reciprocal_value R)
{  u32 t = (u32)(((u64)a * R.m) >> 32);  return (t + ((a - t) >> R.sh1)) >> R.sh2;
}  

这个算法的思路简介如下:算法简介
这个算法的实现就是margin = signal*boost/100,从打印结果也证实了:

[ 52.191507] signal=49,margin=4 //执行reciprocal_divide之后打印的
[ 52.191519] boost=10,margin=4 //执行clamp_t之后打印的数值
[ 52.191532] signal=49,margin=4
[ 52.191543] boost=10,margin=4
[ 52.191931] signal=700,margin=70

而clamp_t函数定义如下:

#define clamp_t(type, val, lo, hi) min_t(type, max_t(type, val, lo), hi)

可以明显的知道margin就是signal/100的数值,这里的signal是经过boost转化的,具体看上面的code,经过这么负载的算法运算,目的是这个除法运算太频繁了,而在arm里面除法比较消耗cpu指令,所以乘法和位移来替代除法运算。最后归结一句话,上面的代码没必要看,执行boosted_cpu_util(cpu)之后,对此cpu的util修正,实际执行的是如下公式:

util += ±(util * boost)/100

最复杂的就是优化除法。遗留action:
上面处理的boost在schedtune中,涉及到cgroup(control group)这个子系统比较复杂,需要耗时间去理解。后续在学习

【cpufreq governor】cpu util 和 cpu margin怎么计算的相关推荐

  1. [cpufreq governor] schedutil governor解析

    1.schedutil governor相关的结构体说明 struct sugov_policy { struct cpufreq_policy *policy; /*cpu freq的policy* ...

  2. 设置CPU频率和CPU运行核心数

    1.查看当前的CPU信息 cat /proc/cpuinfo ums312_1h10:/ # cat /proc/cpuinfo processor : 0 BogoMIPS : 52.00 Feat ...

  3. 【Linux】CPU频率控制|Conflicting CPU frequency values detected

    目录 即看即用 背景 相关/原理: 使用cpupower设置CPU Performance模式 前言 更新历史 cpufreq的五种模式 cpupower设置performance 附录: cpupo ...

  4. [cpufreq governor]sched governor解析

    前有schedutil governor来调节cpu频率,现有sched(精确的讲应该称为schedfreq....) governor来调节cpu频率,现在来讲解它的来龙去脉. 源代码参考AOSP ...

  5. CPU load和CPU使用率飙高,系统性能问题如何排查?

    压测时或多或少都收到过CPU或者Load高的告警,如果是单机偶发性的,经常会认为是"宿主机抢占导致的",那事实是否真是如此呢?是什么引起了这些指标的飙高?网络.磁盘还是高并发?有什 ...

  6. 如何查看CPU信息、CPU占用率和内存占用

    查看CPU占用情况 第一种方法:通过top命令查看CPU的占用情况.如下例图,adb输入"top"后,可以看到: 上图中一些参数的意义: PID : progress identi ...

  7. 【Linux kernel/CPU idle】CPU Idle 初探

    cpuidle framework 每一个 CPU 核心都会有一个 idle 进程,idle 进程是当系统没有调度 CPU 资源的时候,会进入 idle 进程,而 idle 进程的作用就是不使用 CP ...

  8. c# 获取所有的进程的cpu使用率_Linux CPU使用率很高,但为啥却找不到高CPU的进程

    案例分析 你的准备 今天依旧探究系统CPU使⽤率⾼的情况,所以这次实验的准备⼯作,与上节课的准备⼯作基本相同,差别在于案例所⽤的Docker 镜像不同. 本次还是基于 Ubuntu 18.04,同样适 ...

  9. 【Android 逆向】函数拦截 ( CPU 高速缓存机制 | CPU 高速缓存机制 导致 函数拦截失败 )

    文章目录 一.CPU 高速缓存机制 二.CPU 高速缓存机制 导致 函数拦截失败 一.CPU 高速缓存机制 CPU 架构模型中 , 指令 在开始时 , 存放在内存中 , 如 : /proc/pid/m ...

最新文章

  1. 前端构建工具gulpjs的使用介绍及技巧 (转)
  2. SuperMap 房产政务协同管理平台
  3. GCC全过程详解+剖析生成的.o文件
  4. 面向对象--接口的实际应用--制定标准
  5. 记一次ZABBIX监控JMX故障
  6. matlab连通区边界_Matlab图像处理学习笔记(一):二值化、开操作、连通区域提取、重心、ROI...
  7. Android Studio设置,鼠标放上去有提示
  8. 新年新气象[xgluxv]
  9. C++ 常用术语(后续补充)
  10. java 坐标反算_Java实现坐标反算方位角
  11. 大学生免费查题公众号_大学生免费查题公众号?搜题免费公众号?
  12. 【经典算法】:银行金额大写转换
  13. 【周记】腾讯犀牛鸟「云开发」校园技术布道师养成计划
  14. 微软壁纸。我全部都要
  15. 2D图片转3D模型软件介绍
  16. PCL 基于对应点分类的对象识别
  17. 网页版数据库管理工具安装教程——phpAdmin
  18. 计算机网络安全的对策,计算机网络安全和对策.PDF
  19. Vue.config.silent = true
  20. 记录yolov5更改backbone为ShuffleBlock网络迁移训练出错问题以及解决方法

热门文章

  1. Java8 LocalDateTime常用方法
  2. 月薪3万 的一道面试题
  3. 数值计算方法计算机,数值计算方法
  4. 股东分红税高达20%,该怎么节税?
  5. 面试题总结(mybatis一级缓存及二级缓存、springboot自动装配原理等)
  6. 中国乳化机市场现状研究分析与发展前景预测报告
  7. rabbitmq 连接失败pika.exceptions.ProbableAccessDeniedError
  8. 解决 另一个程序正在使用此文件,进程无法访问
  9. 将表结构设计导出数据库设计文档
  10. Unity实现APK覆盖安装