编程实现在Linux系统中Intel CPU功耗的获取

编程实现在Linux系统中Intel CPU功耗的获取

资料的获取

Intel的CPU相关功能,Intel公司做了一个非常全面的帮助手册,开发人员想查找的所有功能,基本上在这个开发手册里面都有了。
传送门: https://software.intel.com/zh-cn/articles/intel-sdm (好像对国内网络不太好)
Intel 软件开发者帮助手册: 链接: https://pan.baidu.com/s/18c9hU8h-Cel7VqPmGqiGuQ 提取码: ztrg (下载了官网全卷的帮助文档pdf版,如果第一个链接能进,就用第一个链接吧!)
msr-tool 工具地址: https://01.org/zh/msr-tools?langredirect=1

X86 MSR寄存器介绍

MSR(Model Specific Register)是x86架构中的概念,指的是在x86架构处理器中,一系列用于控制CPU运行、功能开关、调试、跟踪程序执行、监测CPU性能等方面的寄存器。

MSR寄存器的雏形开始于Intel 80386和80486处理器,到Intel Pentium处理器的时候,Intel就正式引入RDMSR和WRMSR两个指令用于读和写MSR寄存器,这个时候MSR就算被正式引入。在引入RDMSR和WRMSR指令的同时,也引入了CPUID指令,该指令用于指明具体的CPU芯片中,哪些功能是可用的,或者这些功能对应的MSR寄存器是否存在,软件可以通过CPUID指令查询某些功能是否在当前CPU上是否支持。

每个MSR寄存器都会有一个相应的ID,即MSR Index,或者也叫作MSR寄存器地址,当执行RDMSR或者WRMSR指令的时候,只要提供MSR Index就能让CPU知道目标MSR寄存器。这些MSR寄存器的编号(MSR Index)、名字及其各个数据区域的定义可以在Intel x86架构手册”Intel 64 and IA-32 Architectures Software Developer’s Manual"的Volume 4中找到。
(以上内容摘自知乎作者河马的文章x86 CPU的MSR寄存器: https://zhuanlan.zhihu.com/p/50142793)

X86 CPUID介绍

CPUID操作码是一个面向x86架构的处理器补充指令,它的名称派生自CPU识别,作用是允许软件发现处理器的详细信息。它由英特尔在1993年引入奔腾和SL增强486处理器。
通过使用CPUID操作码,软件可以确定处理器的类型和特性支持(例如MMX/SSE)。
关于CPUID的详细操作,见维基百科英文版说明: https://en.wikipedia.org/wiki/CPUID
这里通过CPUID指令获取cpu的vendor ID字符串为例:
在调用cpuid汇编指令之前,通过给eax寄存器赋值,然后执行cpuid指令,cpu就会将想获取的数据放入eax,ebx,ecx,edx四个寄存器中。
通过阅读危机百科英文版中CPUID关于EAX=0的部分,得到如下信息:
首先在调用cpuid汇编命令之前,将eax寄存器的值赋值为0,然后调用cpuid完成之后,cpu会将返回的12个字节的字符串分别放入ebx,edx,ecx三个寄存器中,然后编写如下程序代码:

#include <stdio.h>
#include <string.h>
typedef unsigned int uint32_t;

struct cpuid_info{
    uint32_t eax;
    uint32_t ebx;
    uint32_t ecx;
    uint32_t edx;
};
void get_cpuinfo(uint32_t eax, uint32_t ecx, struct cpuid_info* cpuid) {
    asm(
            "cpuid":
            "=a"(cpuid->eax), "=b"(cpuid->ebx), "=c"(cpuid->ecx), "=d"(cpuid->edx):
            "a"(eax), "c"(ecx)
       );
}
char cpu_ID[13];
void get_vendor_ID(char* vendorID) {
    struct cpuid_info cpuinfo;
    get_cpuinfo(0, 0, &cpuinfo);
    strncpy(vendorID, (const char*)&cpuinfo.ebx, 4);
    strncpy(vendorID+4, (const char*)&cpuinfo.edx, 4);
    strncpy(vendorID+8, (const char*)&cpuinfo.ecx, 4);
    vendorID[13] = '\0';
}

int main(int argc, char** argv) {
    get_vendor_ID(cpu_ID);
    printf("vendor ID: %s\n", cpu_ID);
    return 0;
}

其中get_cpuid函数即为通过cpuid获取运行当前程序的cpu的vendor ID信息,get_vendor_ID函数即为获取将寄存器里面的值组合为一个完整的字符串。
通过阅读CPUID相关的信息,我们得知当设置eax=1时,cpu是否支持msr寄存器的标志位就在edx寄存器的5比特位上。
当然,这些信息在Linux里面已经有工具帮我们实现好了,使用lscpu命令就能查看了。
在这里插入图片描述

X86 RAPL介绍

RAPL全称为: running average power limit
RAPL是x86处理器用于限制功耗、获取功耗的一组工具,rapl提供了一系列的设置接口用于限制和获取cpu的功耗以及CPU的能量消耗,而我们调用这些功能的入口就是学会读写msr寄存器。关于RAPL的操作说明,参考Intel开发者帮助手册第3卷14.9章节。

Linux中挂载CPUID和MSR模块

一般Linux中,给了我们选择挂载CPUID和MSR模块的功能,一旦模块挂载之后,便不用使用汇编去在cpu中获取了,直接通过操作文件的形式操作/dev/cpu/[cpu]/cpuid和/dev/cpu/[cpu]/msr两个文件来读取和修改相关数值了。相关的操作可以查看资料里面的msr-tool源码:
/dev/cpu/[cpu]/cpuid中的信息,通过eax+(ecx<<32)作为文件的偏移来读取。
/dev/cpu/[cpu]/msr中的信息,通过msr寄存器的索引作为文件的偏移来读取和写入。
加载CPUID和MSR模块的命令:

sudo modprobe cpuid
sudo modprobe msr

加载之后的效果:
在这里插入图片描述

实现思路

在RAPL中获取功耗的思路是:

  1. 首先使用cpuid代码或者lscpu查看cpu是否支持msr (这个一般都支持)
  2. 读取MSR_RAPL_POWER_UNIT寄存器的内容,得到能量的基本计算单元。
  3. 读取MSR_PKG_ENERGY_STATUS寄存器的内容,用来乘以能量基本计算单元,得到具体的累积能量消耗(单位:焦耳)。
  4. 程序暂停一段时间。
  5. 再次读取MSR_PKG_ENERGY_STATUS寄存器的内容,乘以能量基本计算单元,得到累积能量消耗。
  6. 用第二次得到的累积能量消耗减去第一次的,除以时间,就得到了这段时间的平均功耗。

尝试过直接使用power相关的寄存器去获取功耗,但是发现失败了。如果有成功的同志,欢迎一起讨论。

Intel开发者帮助手册14.9中,关于MSR_RAPL_POWER_UNIT的介绍:
在这里插入图片描述
Intel开发者帮助手册14.9中,关于MSR_PKG_ENERGY_STATUS的介绍:
在这里插入图片描述
关于不同的cpu中MSR_RAPL_POWER_UNIT和MSR_PKG_ENERGY_STATUS寄存器的具体索引数值,可以在Intel开发者帮助手册第四卷里面找到。一般MSR_RAPL_POWER_UNIT的索引地址为:0x606,一般MSR_PKG_ENERGY_STATUS的索引地址为:0x611
实现代码这里就不贴上来了,具体代码实现见项目地址。
github地址: https://github.com/lixiaobai09/intel_power_consumption_get

PS: 感谢网友fengfengddu的指正,代码里面由于获取功耗是获取的一个package里面的功耗,一般意义上package就是一个插槽上完整的CPU。所以不用重复累加多个core的功耗。如果是多socket结构,可以考虑累加两个不同socket上的任一core的功耗就是两个CPU的总功耗了。

  • 8
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 在 Windows Subsystem for Linux (WSL) 读取 CPU 功耗数据的方法有多种。 一种方法是使用 "powerstat" 工具。可以在 Ubuntu WSL 环境使用 "apt-get" 命令安装它: ``` sudo apt-get install powerstat ``` 然后使用 "powerstat" 命令查看 CPU 功耗数据: ``` powerstat ``` 另一种方法是使用 "powertop" 工具。可以在 Ubuntu WSL 环境使用 "apt-get" 命令安装它: ``` sudo apt-get install powertop ``` 然后使用 "powertop" 命令查看 CPU 功耗数据: ``` sudo powertop ``` 还有其他工具如: - turbostat (intel-pstate) - cpupower-monitor (cpupower) 选择合适的工具,根据需要使用。 ### 回答2: 在Windows Subsystem for Linux (WSL) ,要读取 CPU功耗数据,可以按照以下步骤进行操作: 1. 安装 Powertop: 打开 WSL 终端,并确保已经安装了 apt 包管理器。然后使用以下命令安装 Powertop: ``` sudo apt update sudo apt install powertop ``` 2. 运行 Powertop: 输入以下命令以运行 Powertop: ``` sudo powertop ``` 3. 查看功耗数据: Powertop 将会显示各个进程及硬件设备的功耗数据。使用箭头键浏览不同的页面,如 "Overview"、"Device stats"、"Software activity" 和 "Tunables" 等,以查看相应的功耗信息。 4. 导出功耗数据: 如果需要将 Powertop 的功耗数据导出到文件,可以使用以下命令: ``` sudo powertop --html=power_report.html ``` 这将会生成一个名为 "power_report.html" 的文件,其包含了 Powertop 的功耗报告。 需要注意的是,Powertop 在 WSL 的使用可能会受到一些限制,因为它是基于虚拟化技术的。因此,你可能无法得到实际的硬件功耗数据,而只能获得虚拟化环境下的近似值。 ### 回答3: 在Windows Subsystem for Linux(WSL),要读取CPU功耗数据,你可以按照以下步骤进行操作。 1. 首先,确认你已经在Windows系统启用了WSL,并且已经安装了适当的Linux发行版,例如Ubuntu。 2. 打开WSL终端,并使用适当的命令安装所需的依赖库。例如,对于Ubuntu系统,你可以使用以下命令安装lm-sensors库: ``` sudo apt-get install lm-sensors ``` 3. 安装完成后,使用以下命令检测和配置传感器: ``` sudo sensors-detect ``` 在安装过程,你需要回答一系列关于硬件配置的问题。建议你选择默认选项,除非你对自己的硬件配置有精确的了解。 4. 配置完成后,你可以使用以下命令来查看CPU功耗数据: ``` sensors ``` 这将显示各个传感器的输出信息,包括CPU功耗数据。 注意事项: - 值得注意的是,WSL是一个虚拟化环境,它无法直接访问硬件。所以,以上方法只能提供来自操作系统的传感器数据,而不能提供直接从硬件读取功耗数据。 - 同样重要的是要选择合适的传感器库和命令,以适应你所使用的硬件和Linux发行版。 - 如果想要更详细和准确的CPU功耗数据,你可能需要考虑使用Windows操作系统的原生工具或第三方软件来完成。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值