本文基于Linux 5.15.133版本讨论。
要计算一颗CPU的功耗,其主要实现在include/linux/energy_model.h头文件中定义的em_cpu_energy函数中。下面主要通过分析该函数的计算逻辑,回答标题中的问题。
先说下大体思路。em_cpu_energy函数会传入一个pd参数,该pd参数实质是一个em_perf_domain结构体类型的指针,代表了计算目标的性能域。
em_perf_domain结构体的table字段会指向一个静态数组,数组元素类型是em_perf_state结构体,该结构体的三个字段分别表示一个CPU频率(frequency),功耗(power)和功耗计算因数(cost)。数组元素按照频率从低到高依次排列。
我们需要根据CPU的占用率参数找到CPU对应的频率,然后根据cost参数计算出对应的功耗。
下面看代码。
首先取出CPU的算力值。
之后取出该CPU最高频率的em_perf_state数据。
计算占用率最大值(max_util)。
计算方式分两步:
a.max_util = max_util × 125%
b.如果新计算的max_util值超过了该CPU的算力值,则将最大值对齐到CPU算力。注意,这里用的是传入的allowed_cpu_cap参数。
接下来将占用率指标转换为能提供对应算力的频率。
计算方式为:
这里出现一个问题,就是根据以上计算逻辑,计算出的频率值不一定是该CPU支持的,或者说em_perf_domain的table数组所能提供的。所以我们需要找到在table中最接近预期频率的频率值并得到它的em_perf_state结构体指针。方法很简单,就是依次在table数组中遍历,直到找到合适的频率为止。
现在,我们可以获得cost的数值了。要利用cost数值来进行计算,我们还要先了解cost是如何计算出来的。
在em_perf_state结构体的定义处,注释标明了其计算方式。
也就是:
power对应的是freq,也就是这样按照比例计算后,cost就是max_freq对应的功耗(power)。
我们接下来看em_cpu_energy如何利用cost来计算CPU功耗。
用公式描述就是:
计算后的结果直接返回。