文章目录
1. 引子
近期遇到一个问题,某项目IC支持主频为2G,但是在分析问题过程中发现存在部分机器,即使负载已经超过300%的情况下频率仍没有在最大运行,而是1.5G左右;
这个现象引发了customer的重视,当然此问题很快就找到了原因,存在部分机器温度过高,触发了高温降频的策略,从而出现的这个现象;
对于这个现象来讲,问题分析过程比较明确:
- 确认HW最大支持多少?必要条件下可以做AB实验分析;
- 在HW支持的条件下,系统是否在哪里设置了软件最高速率限制?
- SW中可以影响到CPU频率的增减的策略有哪些:
- 动态负载均衡策略
- 高温降频甚至重启的策略
针对于此问题:
- HW支持最高频率为2G;
- 同一版软件,部分机器可以达到2G,有些只能达到1.5G,则怀疑点为HW影响或者上述策略影响;
- 通过CPU FREQ功能进行调试,配置为performance模式(即去除负载均衡策略),表现仍与之前情况相同,则怀疑点为HW影响或者温度策略;
- 将温度策略移除进行测试,所有机器均可以正常启动到2G的频率,则可以确认此问题为温度策略影响;
- 细化温度策略中的具体处理,分别针对于主控、connectivity等温度策略查看,最终确认与主AP相关;
至此,此问题原因已经确认,存在部分机器散热情况较差,导致出现降频处理,解决措施为HW增加散热处理,然后SW去除温度降频的策略(保留超过结温重启的策略)
对于这个问题已经处理完成了,但是在处理过程中其实对于整个CPU freq的处理逻辑梳理的不是特别清晰:
- CPU频率降低依赖于哪些功能?
- 系统中的cpufreq驱动支持哪些功能?
- 负载、温度调节freq的机制是哪里实现的?支持多少不同的方式?是否还有其他的策略调节频率?
小朋友,你的头上为什么这么多问号???
2. CPU 频率相关调节
2.1 CPU 频率
2.1.1 频率概念理解
CPU频率:
即CPU的时钟频率,CPU运算时的工作的频率(1秒内发生的同步脉冲数)的简称;
可以简单理解为1S内CPU可以运行指令的数量,当然与CPU的流水线结构以及其他设计也相关,不过可以说明一个概念,CPU的主频高比主频低要性能好;
单位为:HZ,现在一般为GHz;
2.1.2 HW支持
目前的主流IC,基本都支持如下几个功能
2.1.2.1 DVFS
DVFS(Dynamic voltage and frequency scaling):即动态调节电压和频率,用于平衡性能和节能,根据功率计算公式,在电压实际降低的情况下才有节能功效;
CMOS电路中分为动态功耗和静态功耗,公式为 power=Σ(CV²αf + VI)。
C 代表负载电容的容值,V 是工作电压,α 是当前频率下的翻转率,f为工作频率,I代表静态电流。
公式中加号前面部分代表动态功耗,后半部分代表静态功耗。要想降低动态功耗的话,需要从C/α/V/f几个参数入手,而对于软件而言,通常可以调节的只有V和f。所以对于只能调节F的只能降低动态功耗,而且有限,如果V和F都可以降低,就会好很多;
2.1.2.2 CPU hotplug
即CPU热插拔,可以在系统不重启的情况下,关闭或者打开CPU core;
linux文档:https://elixir.bootlin.com/linux/v4.9/source/Documentation/cpu-hotplug.txt
> maxcpus
这是由 cmdline 传递给 Kernel,表示启动时 Kernel power on 的 cpu 数量,会赋值给 setup_max_cpus
> nr_cpus
这是由 cmdline 传递给 Kernel,表示 cpu 数量
> possible cpu
表示可能可用的 cpu mask。初始化时通过 dts 中 cpus 相关域来配置 possible cpu 数量
> present cpu
表示已准备好的 cpu mask,下一步,就可以真正的执行 online 操作。
hotplug_cb_init 会把 possible cpu 配置成 present cpu
hotplug_cpu_init 会把 setup_max_cpus 开始到 possible cpu 配置成 present cpu
> cpu on
smp_init 会把 present cpu 且小于 maxcpus 数量的 cpu 给 power on
_hps_task_main 会把 possible cpu 给 power on
kernel中的配置:
CONFIG_SMP
CONFIG_HOTPLUG
2.1.2.3 thermal 采集
IC 上存在几个测量点,可以读取寄存器获取该测量点的温度;
则通过软件的实现即可,根据温度或者其他条件来动态调节频率、电压、core status;
2.2 如何查看当前系统的Frequence
2.2.1 cpuinfo driver
linux以及android中有提供一个cpufreq driver来动态调节frequence;
- 查看makefile:/kernel/drivers/cpufreq/Makefile
- 查看系统config:/kernel/arch/arm64/config/defconfig
- 感兴趣可以查看具体driver实现:/kernel/drivers/cpufreq/cpufreq
在机器上,可以查看对应节点:/sys/devices/system/cpu/cpu0
- 查看某一个cpu的freq:cat scaling_cur_freq
- 查看当前该cpu的策略:cat scaling_governor
- 查看该CPU是否online:cat online
如果是MTK的平台,会将该节点的数据添加到systrace上去,可以直接可视化界面查看,更加直观;
另外,这里是软件配置的值,需要注意有可能是软件中写的,但是实际没有设置到HW中去,这种情况下需要写一个运算程序,人为计算;
2.2.2 如何人为加大负载
linux文档:https://elixir.bootlin.com/linux/v4.9/source/Documentation/cpu-load.txt
- adb 操作:
cat /dev/urandom | gzip -9 | gzip -d | gzip -9 | gzip -d > /dev/null
这种方式,负载大约可以提高到200%左右,对于4 core; - 进行memtester:
memtester - 写一个while循环的程序(几个核就执行几次),这种可以达到399%左右:
#! /system/bin/sh
while :
do
done
2.2.3 如何查看负载
- cat /proc/loadavg
- top (一般看这个)
- dumpsys cpuinfo
- uptime
2.3 系统提供的调节CPU Frequence方案
- 基于CPU负载的调节方案
- 基于温度的频率调节方案
2.3.1 负载计算方案
根据负载情况降低或者升高CPU频率
2.3.1.1 governors
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors
支持如下几种方案:
策略 | 含义 |
---|---|
performance | 性能模式,默认最高频率运行 |
powersave | 节能模式,默认最低频率运行 |
ondemand | 根据负载调节,Linux初期使用,现在使用较少 |
userspace | 将选择权交给用户空间,可以通过setspeed方式设置CPU运行频率 |
conservative | 较为平滑的根据负载设置频率 |
这部分的默认配置在kernel config中:
2.3.2 温度计算方案
这部分主要是获取采集到的温度数据,然后根据温度策略做降频处理
3. 后记
上述只是简单的使用记录,后序需要具体查看CPU load计算方式,涉及到CPU调度相关信息:
- CPU 调度概念
- CPU 调度方案
- CPU 负载计算