获取当前CPU的运行速度

1.实时获取下面的这个频率
在这里插入图片描述

2.获取的方法,使用性能计数器PDH来实现对性能数据的高级访问。PDH是Windows提供的库。相关文档可以自行查看。
实时频率 = 处理器性能*基准频率

下面就是代码:
获取的单位是MHz,可以进行转换。另外,和当前资源管理器显示的不是完全一致的,因为这个值是在实时更新的。

#include <Pdh.h>
#include <PdhMsg.h>
#include <iostream>
#pragma comment(lib,"pdh.lib") 

double getCurrentCpuSpeed();
void main()
{
	while (true)
	{
		std::cout << getCurrentCpuSpeed() << std::endl;
	}
}

//获取当前CPU的频率 失败返回-1,成功返回一个大于0的数
double getCurrentCpuSpeed()
{
	HQUERY query;
	//打开PDH
	PDH_STATUS status = PdhOpenQuery(NULL, NULL, &query);
	if (status != ERROR_SUCCESS)
		return -1;

	HCOUNTER cpuPerformance;
	HCOUNTER cpuBasicSpeed;

	//添加CPU当前性能的计数器
	status = PdhAddCounter(query, TEXT("\\Processor Information(_Total)\\% Processor Performance"), NULL, &cpuPerformance);
	if (status != ERROR_SUCCESS)
		return -1;

	//添加CPU基准频率的计数器
	status = PdhAddCounter(query, TEXT("\\Processor Information(_Total)\\Processor Frequency"), NULL, &cpuBasicSpeed);
	if (status != ERROR_SUCCESS)
		return -1;

	//收集计数 因很多计数需要区间值 所以需要调用两次Query(间隔至少1s) 然后再获取计数值
	PdhCollectQueryData(query);
	Sleep(1000);
	PdhCollectQueryData(query);

	PDH_FMT_COUNTERVALUE pdhValue;
	DWORD dwValue;

	status = PdhGetFormattedCounterValue(cpuPerformance, PDH_FMT_DOUBLE, &dwValue, &pdhValue);
	if (status != ERROR_SUCCESS)
		return -1;
	double cpu_performance = pdhValue.doubleValue / 100.0;

	status = PdhGetFormattedCounterValue(cpuBasicSpeed, PDH_FMT_DOUBLE, &dwValue, &pdhValue);
	if (status != ERROR_SUCCESS)
		return -1;
	double basic_speed = pdhValue.doubleValue;

	//关闭PDH
	PdhCloseQuery(query);

	return (double)(cpu_performance * basic_speed);
}
<think> 我们之前讨论了使用psutil获取CPU当前速度的方法,现在用户遇到了获取速度不准确的问题。根据用户提供的引用,我们之前使用了`psutil.cpu_freq()`来获取频率。然而,在某些情况下,这个值可能不准确或者不可用。我们需要探讨可能的原因和解决方案。 可能的原因: 1. **系统兼容性问题**:psutil的cpu_freq在不同操作系统上的支持程度不同。例如,在Linux上,它通过读取`/proc/cpuinfo`或`/sys/devices`来获取信息,而Windows则使用WMI。某些系统可能没有提供这些信息。 2. **权限问题**:在某些系统上(如Linux),读取CPU频率可能需要root权限。 3. **硬件或驱动问题**:硬件本身可能没有提供频率信息,或者驱动不支持。 4. **动态频率调整**:现代CPU频率是动态变化的,获取的瞬间值可能不能代表当前状态,尤其是当interval设置不当时。 解决方案: 1. **检查权限**:确保程序以足够的权限运行(例如,在Linux上使用sudo)。 2. **使用更稳定的接口**:如果psutil返回不准确,可以尝试直接读取系统文件(仅限Linux)或使用其他系统工具。 3. **多次采样取平均**:由于频率动态变化,可以多次获取然后取平均值。 4. **使用其他库或工具**:如果psutil不可靠,可以考虑使用其他方法,如使用`lscpu`(Linux)或`WMIC`(Windows)命令,然后解析输出。 具体步骤: ### 方案1:提升权限(Linux) 在Linux系统上,尝试使用root权限运行脚本。 ### 方案2:直接读取系统文件(Linux) 在Linux中,CPU当前频率信息通常可以在`/sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq`中找到。我们可以读取这些文件。 ```python import os def get_cpu_current_speed_linux(): """在Linux上直接读取CPU当前频率(单位:kHz,需要转换为MHz)""" speeds = [] cpu_dirs = [d for d in os.listdir('/sys/devices/system/cpu') if d.startswith('cpu') and d[3:].isdigit()] for cpu_dir in cpu_dirs: try: with open(f'/sys/devices/system/cpu/{cpu_dir}/cpufreq/scaling_cur_freq', 'r') as f: speed_khz = int(f.read().strip()) speeds.append(speed_khz / 1000) # 转换为MHz except FileNotFoundError: continue return speeds # 返回每个核心的频率列表 if __name__ == "__main__": if os.name == 'posix': speeds = get_cpu_current_speed_linux() for i, speed in enumerate(speeds): print(f"核心{i}: {speed:.2f} MHz") ``` ### 方案3:使用系统命令(跨平台) #### Windows 使用WMIC命令: ```python import subprocess def get_cpu_current_speed_windows(): cmd = 'wmic cpu get CurrentClockSpeed' output = subprocess.check_output(cmd, shell=True).decode() # 解析输出 lines = output.strip().split('\n') speeds = [] for line in lines[1:]: if line.strip().isdigit(): speeds.append(float(line.strip())) # 单位已经是MHz return speeds if __name__ == "__main__": if os.name == 'nt': speeds = get_cpu_current_speed_windows() for i, speed in enumerate(speeds): print(f"核心{i}: {speed} MHz") ``` #### Linux 使用`lscpu`命令: ```python def get_cpu_current_speed_linux_cmd(): cmd = 'lscpu' output = subprocess.check_output(cmd, shell=True).decode() # 解析输出,注意:lscpu没有直接提供当前频率,但有些版本有CPU MHz # 如果输出中有CPU MHz,则提取 for line in output.split('\n'): if 'CPU MHz' in line: mhz = line.split(':')[1].strip() return float(mhz) return None ``` ### 方案4:多次采样(适用于psutil) 如果仍然想用psutil,但希望减少动态变化的影响,可以多次采样取平均。 ```python import psutil def get_avg_cpu_speed(sample_count=5, delay=0.1): total = 0.0 for _ in range(sample_count): freq = psutil.cpu_freq() total += freq.current time.sleep(delay) return total / sample_count ``` ### 注意事项 - 上述直接读取系统文件或使用命令的方法可能因系统而异,请根据实际情况调整。 - 在Windows上,WMIC命令返回的是每个核心的当前速度,但注意它可能返回的是基本速度(BaseSpeed)而不是当前速度,具体取决于硬件和驱动。 ### 总结 用户可以根据操作系统选择合适的方法。如果psutil不准确,可以尝试直接读取系统文件(Linux)或使用系统命令(Windows)。同时,考虑到频率的动态性,多次采样取平均可以提高稳定性。 §§相关问题§§ 1. 如何解决psutil在Windows获取CPU频率为0的问题? 2. 除了psutil,还有哪些Python库可以准确获取CPU频率? 3. 如何实时监控CPU频率的波动? 4. 为什么在虚拟机上获取CPU频率不准确? </think> # 解决 psutil 获取 CPU 当前速度不准确的问题 在使用 psutil 获取 CPU 当前速度时,确实可能遇到不准确的情况,这通常由以下原因引起: ## 常见原因及解决方案 ### 1. 系统权限不足(Linux/MacOS) **问题**:在 Linux 或 MacOS 上,获取 CPU 频率需要 root 权限 **解决方案**: ```python import psutil def get_accurate_cpu_freq(): try: freq = psutil.cpu_freq() return freq.current except PermissionError: print("需要 root/管理员权限获取精确频率") # 尝试使用系统命令作为备选方案 if psutil.LINUX: return get_cpu_freq_from_proc() # 见下方备选方案 return None ``` ### 2. 操作系统兼容性问题 **问题**:Windows 系统下 `cpu_freq()` 可能返回基础频率而非当前速度 **解决方案**:使用 WMI 作为备选方案(Windows) ```python import wmi def get_windows_cpu_speed(): c = wmi.WMI() for processor in c.Win32_Processor(): return processor.CurrentClockSpeed ``` ### 3. 动态频率变化太快 **问题**:现代 CPU 频率在纳秒级变化,单次采样不准确 **解决方案**:多次采样取平均值 ```python import psutil import time def get_avg_cpu_speed(samples=5, interval=0.1): """获取CPU平均频率""" total = 0 for _ in range(samples): freq = psutil.cpu_freq() total += freq.current time.sleep(interval) return total / samples ``` ### 4. 虚拟化环境限制 **问题**:虚拟机中可能无法获取准确的物理 CPU 频率 **解决方案**:检测虚拟环境并调整预期 ```python def get_cpu_speed_with_vm_check(): if psutil.virtualization(): print("警告:在虚拟环境中,CPU频率可能不准确") return psutil.cpu_freq().current ``` ### 5. 备选方案:直接读取系统文件(Linux) ```python def get_cpu_freq_from_proc(): """从/proc文件系统直接读取CPU频率(Linux)""" try: with open('/proc/cpuinfo', 'r') as f: for line in f: if 'cpu MHz' in line: return float(line.split(':')[1].strip()) except FileNotFoundError: return None ``` ### 6. 使用更高精度工具 ```python def get_cpu_speed_with_turbo(): """结合使用psutil和第三方库获取更精确数据""" freq = psutil.cpu_freq().current # 使用py-cpuinfo作为补充 try: import cpuinfo info = cpuinfo.get_cpu_info() if 'hz_advertised' in info: turbo = info['hz_advertised'][0] / 1e6 print(f"最大睿频: {turbo} MHz") return max(freq, turbo) if turbo else freq except ImportError: return freq ``` ## 最佳实践:综合解决方案 ```python import psutil import time import os def get_accurate_cpu_speed(): """获取最准确的CPU当前频率""" try: # 尝试使用psutil的标准方法 freq = psutil.cpu_freq() # Linux系统:直接读取系统文件作为验证 if psutil.LINUX: proc_freq = get_cpu_freq_from_proc() if proc_freq and abs(freq.current - proc_freq) > 100: # 差异大于100MHz return proc_freq # 优先使用/proc数据 # 多次采样减少波动影响 speeds = [freq.current] for _ in range(4): time.sleep(0.05) speeds.append(psutil.cpu_freq().current) return sum(speeds) / len(speeds) # 返回平均值 except Exception as e: print(f"获取CPU频率出错: {str(e)}") # 备选方案 if psutil.WINDOWS: return get_windows_cpu_speed() elif psutil.LINUX: return get_cpu_freq_from_proc() return None # 无法获取 ``` ## 验证数据准确性 ```python def verify_cpu_speed(): """验证CPU速度数据准确性""" print("验证CPU速度数据:") print(f"psutil: {psutil.cpu_freq().current} MHz") if psutil.LINUX: print(f"/proc/cpuinfo: {get_cpu_freq_from_proc()} MHz") if psutil.WINDOWS: print(f"WMI: {get_windows_cpu_speed()} MHz") print(f"5次采样平均值: {get_avg_cpu_speed()} MHz") ``` ## 专业建议 1. **结合负载分析**: ```python def get_cpu_performance(): """获取CPU性能状态""" speed = get_accurate_cpu_speed() usage = psutil.cpu_percent(interval=0.5) max_freq = psutil.cpu_freq().max performance = (speed / max_freq) * (usage / 100) print(f"性能指数: {performance:.2f} (速度:{speed}MHz, 使用率:{usage}%)") return performance ``` 2. **监控频率变化**: ```python def monitor_frequency(duration=10, interval=0.5): """监控CPU频率变化""" end_time = time.time() + duration while time.time() < end_time: speed = get_accurate_cpu_speed() load = psutil.cpu_percent(interval=0.1) print(f"速度: {speed:.0f} MHz | 负载: {load}% | {'█' * int(load//10)}") time.sleep(max(0, interval - 0.1)) ``` 3. **跨平台解决方案**: ```python def get_universal_cpu_speed(): """跨平台获取CPU速度""" if hasattr(psutil, "cpu_freq"): return psutil.cpu_freq().current try: # macOS系统 if psutil.MACOS: import subprocess result = subprocess.run(["sysctl", "-n", "hw.cpufrequency"], capture_output=True, text=True) return float(result.stdout.strip()) / 1e6 # Hz转MHz except: pass return None ``` > **重要提示**:CPU频率的准确性取决于硬件和操作系统支持程度。现代CPU的动态频率调整技术(如Intel的SpeedStep、AMD的Cool'n'Quiet)会导致频率在纳秒级变化,因此任何"当前速度"本质上都是近似值[^1]。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值