返回

Linux下查找CPU最高睿频核心:turbostat/i7z 实用指南

Linux

Linux 系统下如何查找 CPU 最高睿频核心?

想知道 CPU 各个核心的睿频能到多少?这挺重要的,因为 CPU 的频率会根据当前负载动态变化。像现在的游戏大作,多线程优化都做得不错,用 6 个或 8 个核心很常见。在决定咱们自己写的程序用多少个核心的时候,就得考虑一下,多用了核心,是不是会牺牲掉一部分单核频率。

我们可以用 stress-ng 这个工具给 CPU 加上任意多线程的负载:

stress-ng --cpu 1

/proc/cpuinfo 文件里头有 CPU 频率的信息:

$ cat /proc/cpuinfo
processor   : 0
vendor_id   : AuthenticAMD
cpu family  : 23
model       : 1
model name  : AMD Ryzen Threadripper 1950X 16-Core Processor
stepping    : 1
microcode   : 0x8001137
cpu MHz     : 2200.000
cache size  : 512 KB
physical id : 0
siblings    : 16
core id     : 0
cpu cores   : 16
apicid      : 0
initial apicid  : 0
fpu     : yes
fpu_exception   : yes
cpuid level : 13
wp      : yes
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl nonstop_tsc cpuid extd_apicid amd_dcm aperfmperf rapl pni pclmulqdq monitor ssse3 fma cx16 sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw skinit wdt tce topoext perfctr_core perfctr_nb bpext perfctr_llc mwaitx cpb hw_pstate ssbd ibpb vmmcall fsgsbase bmi1 avx2 smep bmi2 rdseed adx smap clflushopt sha_ni xsaveopt xsavec xgetbv1 clzero irperf xsaveerptr arat npt lbrv svm_lock nrip_save tsc_scale vmcb_clean flushbyasid decodeassists pausefilter pfthreshold avic v_vmsave_vmload vgif overflow_recov succor smca sev
bugs        : sysret_ss_attrs null_seg spectre_v1 spectre_v2 spec_store_bypass retbleed smt_rsb srso div0
bogomips    : 6799.35
TLB size    : 2560 4K pages
clflush size    : 64
cache_alignment : 64
address sizes   : 43 bits physical, 48 bits virtual
power management: ts ttp tm hwpstate eff_freq_ro [13] [14]
[...]

但问题是,cpu MHz 显示的频率好像不太准,而且不能直接告诉我们哪个核心频率最高。接下来咱们就来解决这个问题。

问题分析:为什么/proc/cpuinfo不够用?

/proc/cpuinfo 里的 cpu MHz 字段显示的是内核启动时读取到的一个参考频率,或者是在系统空闲时的频率。在 CPU 负载变化的时候,这个值并不会实时更新。并且,它显示的是一个平均值,不能反映每个核心的具体频率。

我们需要一种能够实时、准确地反映每个 CPU 核心当前频率的方法。

解决方案:实时监控各核心频率

下面这几个方法可以帮我们找到频率最高的核心:

1. 使用 turbostat 工具

turbostat 是一个很强大的工具,可以用来监控 CPU 的频率、温度、功耗等各种信息。它可以非常详细地显示每个核心的状态。

原理和作用:

turbostat 通过读取 CPU 的 Model Specific Registers (MSRs) 来获取这些信息。MSRs 是一些特殊的寄存器,CPU 用它们来存储和控制各种硬件状态。

代码示例/命令行指令:

  1. 安装: 绝大多数 Linux 发行版可以通过包管理器直接安装 turbostat

    • Debian/Ubuntu 系:

      sudo apt update
      sudo apt install linux-tools-common linux-tools-generic
      
    • Red Hat/Fedora/CentOS 系:

      sudo yum install kernel-tools
      
    • Arch Linux 系:

      sudo pacman -S linux-tools
      
  2. 运行: 最简单的用法是直接运行 turbostat,它会每隔 5 秒显示一次 CPU 的状态。 可以配合 stress-ng 命令, 观察指定核心数下的各个核心频率:

    sudo turbostat --quiet --Summary --show PkgWatt,CorWatt,GFXWatt,RAMWatt,PKG%,Core%,CPU%,Busy%,Bzy%,IRQ,SMI,C1,C1E,C3,C6,C7,Temp,CPUFreq
    

    使用 --interval 参数调整显示频率。 示例: 每 1 秒钟显示一次。
    bash sudo turbostat --quiet --Summary --show PkgWatt,CorWatt,GFXWatt,RAMWatt,PKG%,Core%,CPU%,Busy%,Bzy%,IRQ,SMI,C1,C1E,C3,C6,C7,Temp,CPUFreq --interval 1
    如果要关注所有核心,在有负载的时候, 可以这样做:
    bash stress-ng --cpu $(nproc) & sudo turbostat --quiet --show PkgWatt,CorWatt,GFXWatt,RAMWatt,PKG%,Core%,CPU%,Busy%,Bzy%,IRQ,SMI,C1,C1E,C3,C6,C7,Temp,CPUFreq --interval 1

额外说明:

  • 需要 root 权限来运行 turbostat,因为它需要访问 MSRs。
  • --quiet: 输出不要那么啰嗦。
  • --Summary: 只显示总结信息。
  • --show:指定需要显示的列。上面命令会显示功耗(PkgWatt, CorWatt, GFXWatt, RAMWatt)、利用率(PKG%, Core%, CPU%, Busy%, Bzy%)、中断(IRQ, SMI)、C-states(C1, C1E, C3, C6, C7)、温度(Temp)和 CPU 频率(CPUFreq)。

运行以上指令,配合stress-ng指令调整核心数, turbostat 输出结果中,"CPUFreq" 列会显示每个核心的当前频率。找到数值最大的那一列,对应的就是当前频率最高的核心。

安全建议:
长期高负荷运行可能对CPU 寿命产生一定影响。

2. 使用 i7z 工具 (Intel CPU 专用)

如果你的 CPU 是 Intel 的,i7z 是一个很好用的工具。它可以实时显示每个核心的频率,以及 C-states 等信息。

原理和作用:

turbostat 类似,i7z 也是通过读取 CPU 的 MSRs 来获取信息。

代码示例/命令行指令:

  1. 安装:

    • Debian/Ubuntu 系:

      sudo apt update
      sudo apt install i7z
      
    • Red Hat/Fedora/CentOS 系:

      sudo yum install i7z
      
  2. 运行: 运行需要root权限。

    sudo i7z
    

进阶使用技巧
如果仅仅想要频率, 可以这样做。

sudo i7z -w | grep "cpu [0-9]*"

i7z 会打开一个图形界面,显示每个核心的频率。直接找到频率最高的那个核心就行了。

安全建议:
长期高负荷运行可能对CPU 寿命产生一定影响。

3. 通过 /sys/devices/system/cpu/ 目录查看

Linux 内核把 CPU 的各种信息都放在 /sys/devices/system/cpu/ 目录下。我们可以直接读取这些文件来获取频率信息。

原理和作用:

/sys 文件系统是一个虚拟文件系统,它提供了一个访问内核数据的接口。内核会把各种硬件的信息都放在这个目录下。

代码示例/命令行指令:

可以写一个简单的脚本来读取每个核心的频率,然后找出最高的那个:

#!/bin/bash

max_freq=0
max_cpu=""

for cpu_dir in /sys/devices/system/cpu/cpu[0-9]*; do
  cpu_num=$(basename "$cpu_dir" | cut -c4-)
  freq=$(cat "$cpu_dir/cpufreq/scaling_cur_freq")

  if [[ "$freq" -gt "$max_freq" ]]; then
    max_freq=$freq
    max_cpu="CPU$cpu_num"
  fi
done

echo "Highest frequency: $max_freq kHz on $max_cpu"

这段脚本做了下面这几件事。

  1. 遍历 CPU 核心目录: /sys/devices/system/cpu/cpu[0-9]* 会匹配所有 CPU 核心的目录,例如 cpu0cpu1cpu2 等。
  2. 获取核心编号: basename "$cpu_dir" | cut -c4- 从目录名中提取出 CPU 编号。
  3. 读取当前频率: cat "$cpu_dir/cpufreq/scaling_cur_freq" 读取当前核心的频率。这个频率是以 kHz 为单位的。
  4. 比较并记录最大值: 如果当前核心的频率比之前记录的最大值还大,就更新最大频率和对应的 CPU 编号。
  5. 输出结果: 最后输出最高的频率和对应的 CPU 核心。
    直接运行这个脚本,就可以得到当前频率最高的那个核心。

安全建议:
通常,以非特权用户身份浏览此目录就足够了。

进阶技巧

结合 watch 命令, 可以获得与turbostati7z 类似效果。 我们可以将上面代码结合 watch 指令来用:

watch -n 1 "bash ./find_max_freq.sh"

find_max_freq.sh 替换成脚本保存的路径. -n 1 表示每 1 秒更新一次。

这几种方法各有优劣,你可以根据你用起来是否顺手,你的 CPU 型号(Intel 还是 AMD)来选择最适合你的。 一般来说,turbostat 是首选, 适用范围广。