关于

本文主要涉及Linux CPUFreq子系统是什么,为什么需要,怎么用。

并解决在实际测试中遇到的三个问题:

  • scaling_governor没有userspace的问题。
  • /proc/cpuinfocpuinfo_cur_freq显示频率不同。
  • 无法针对单个核心调频并使一个CPU下的不同的核心运行在不同的频率下。

参考资料

  1. Linux 2.6 内核中的最新电源管理技术综述_CPUFreq
  2. Linux动态频率调节系统CPUFreq
  3. Fedora社区对于问题一的讨论地址
  4. Archlinux论坛对于问题一的讨论地址
  5. StackExchange 问题:Why do cpuinfo_cur_freq and /proc/cpuinfo report different numbers?
  6. Stackoverflow 问题:Understanding cpu frequency, thread selection and more
  7. Intel 论坛问题:How can I scale only one core’s frequency in a multi-core processor?

初探变频技术:在Linux中查看CPU相关信息

再问为什么之前,可以先看看到底Linux变频到底是什么,可以通过什么手段来看。

本部分使用的操作系统是Fedora27linux内核版本是4.13。本部分参考参考资料2的博客。

在Linux系统中查看与CPU相关的信息主要有两个方法:

  • 通过查看/proc/cpuinfo,比如当前运行频率可以通过|grep MHz查看。但是这个方法在413,414内核变动较大,不推荐通过此方法查看。具体的原因可以见后面的小节。
  • 另外一个方法是通过sysfs查看与修改,目录是/sys/devices/system/cpu/cpu*

先主要通过第二个方法进行查看:

与CPU相关的sysfs接口均在此目录下,可以通过查看这些文件内容查看CPU相关的信息,例如:

  • online offline 文件中保存着当前在线以及下线的核心的数量。
  • present 中记录着主板上安装的CPU的编号

进一步进入cpufreq目录下,该目录下的文件记录与频率相关的内容。

对于fedora系统,无需安装其它工具。如果使用ubuntu系统时,该目录可能为空,需要手动安装cpufrequtils

cpuN(N为具体的第几个CPU)下有关于该CPU的具体参数文件。与频率有关的文件在该目录下的cpufreq文件夹下。fedora系统该文件夹下有如下信息:

  • cpuinfo_xxx 开头文件代表着cpu硬件上支持的频率

    • cpuinfo_max_freq cpuinfo_min_freq 最大、最小频率
    • cpuinfo_cur_freq 是当前运行的频率(可能也有问题,具体见后面的小节)
  • scaling_xxx开头文件代表可以通过CPUFreq系统用软件进行调节时所支持的频率
    • scaling_available_governors 可供选择的频率调节策略
    • scaling_governors 当前选择的策略
    • scaling_max_freq scaling_min_freq 调节是最大、最小频率
    • scaling_cur_freq 是软件当前指定的频率
    • scaling_driver 调频驱动 (当前intel_pstate

特别注意:可能新版的处理器,新的Linux内核中只有部分接口,且调度也只有powersave和ondemand两种,这是由于使用了p-state driver导致。如何修改见后面小节。

CPUFreq 子系统

根据以上观察,可以有如下总结:

  • CPU的硬件特性决定了这个CPU的最高和最低工作频率,所有的频率调整数值都必须在这个范围内。
  • 可以在这个范围内再次定义出一个软件的调节范围,它们用scaling_xxx_freq来表示
  • CPUFreq系统把一些公共的逻辑和接口代码抽象出来,这些代码与平台无关,也与具体的调频策略无关
  • 另外一部分,与实际的调频策略相关的部分被称作cpufreq_policy
  • cpufreq_policy又是由频率信息和具体的governor组成,governor才是具体策略的实现者
  • governor的实现最好能做到平台无关,与平台相关的代码用cpufreq_driver表述

关于CPUFreq的具体理论,主要参考参考文献1,该参考文献使用的linux内核位2.6版本,该部分以2.6版本为主。

为什么会出现变频技术

简要来说,变频技术的主要目的是节约功耗。变频技术作为电源管理技术以节能为目的加入linux内核。与之前看的大小核类似,变频技术都是为了 energy efficient computing,为了提高performance per watt

变频与超频

变频与超频不同的是,超频是指通过提高核心电压等手段让处理器工作在非标准频率下的行为,这往往会造成 CPU 使用寿命缩短以及系统稳定性下降等严重后果。而变频技术是指CPU硬件本身支持在不同的频率下运行,系统在运行过程中可以根据随时可能发生变化的系统负载情况动态在这些不同的运行频率之间进行切换,从而达到对性能和功耗做到二者兼顾的目的。

为什么需要 CPUFreq子系统

由于每一个各家实现变频技术的使用方法都不同,故需要按照其实现方法向内核中添加代码,才能支持处理的变频使用。为了兼容各种类型的处理器并最大程度复用代码,故linux中开发了CPUFreq子系统用于实现变频的功能。

CPUFreq需要实现哪些部分

所以大思路是要兼容各种处理器,再根据工作负载动态调整处理器的运行的频率。所以可以将这个部分分为两个部分:

  • 根据系统负载的动态变化挑选出 CPU 合适的运行频率。
  • 按照选定的运行频率在选定的时间对 CPU 进行设置,使之真正工作在这一频率上。

从设计角度来说,应该保证二者是清晰的隔离开的并通过规范定义的接口进行通信

CPUFreq的设计

CPUFreq内核子系统的设计框架如下图所示:

cpufreq作为中间层,向上抽象了处理器变频的具体实现,向下分离了变频的策略。将具体的策略和变频的物理上实现进行分离。

这种设计带来的好处是使得 governor 和 CPU 相关的变频驱动程序的开发可以相互独立进行,并在最大限度上实现代码重用,内核开发人员在编写和试验新的 governor 时不会再陷入到某款特定 CPU 的变频技术的硬件实现细节中去,而 CPU 生产厂商在向 Linux 内核中添加支持其特定的 CPU 变频技术的代码时只需提供一个相对来说简单了很多的驱动程序,而不必考虑在各种不同的应用场景中如何选择合适的运行频率这些复杂的问题。

CPUFreq的使用

第一部分在实际机器上看的实际sysfs中的文件就是CPUFreq留的接口,可以通过cat对文件进行读取,同时可以用echo向文件写入。在2.6内核中,在选择使用userspace的策略时,向scaling_setspeed中写入指定的频率,可以修改CPU的运行频率。

除了可以使用sysfs中提供的接口,还可以用上文提到的cpufrequtils 工具包。

用户如何根据实际负载变频

所以,当选择userspace时,可以每固定时钟间隔根据任务负载对CPU频率进行调节。但是直接在用户态实现这些调节算法有以下两种问题:

  1. 当性能需求徒然提升时,需要等待下一次调节周期时才能更新实际运行频率,故有一段时间的慢速运行时间。

  2. 在用户空间对系统负载情况采样分析是否合理:

    由于一个用户态程序很难完整的收集到所有需要的信息,因为这些信息大部分都保存在内核空间,如果想要收集这些系统信息,必然需要进行用户态与内核态之间的数据交互,而频繁的用户态与内核态之间的数据交互又会给系统性能带来负面影响。

所以在2.6内核中提出了ondemand,其是一个在运行在内核态,细粒度时间间隔对系统负载情况采样分析的策略。那么这个表明系统负载的百分比数值是如何得到的呢?

在支持 Intel 最新的 Enhanced Speedstep 技术的 CPU 中,在处理器硬件中直接提供了两个 MSR 寄存器(Model Specific Register)供 ondemand governor 采样分析系统负载情况使用。这两个 MSR 寄存器的名字分别为 IA32_MPERF 和 IA32_APERF,

  • IA32_MPERF MSR 中的 MPERF 代表 Maximum Performance ,该寄存器是一个当 CPU 处在 ACPI C0 状态下时按照 CPU 硬件支持的最高运行频率每隔一个时钟周期加一的计数器

  • IA32_APERF MSR 中的 APERF 代表 Actual Performance ,该寄存器是一个当 CPU 处在 ACPI C0 状态下时按照 CPU 硬件当前的实际运行频率每隔一个时钟周期加一的计数器

    有了这两个寄存器的存在,再考虑上 CPU 处于 ACPI C0 和处于 ACPI C1、C2、C3 三种状态下的时间比例,也就是 CPU 处于工作状态和休眠状态的时间比例, ondemand governor 就可以准确的计算出 CPU 的负载情况了

具体CPU驱动相关部分

实际上支持 Intel Enhanced Speedstep 技术的处理器为用户提供了非常简单的编程接口,对 CPU 运行频率进行设置是通过一个名为 IA32_PERF_CTL 的 MSR 寄存器进行的,另外还有一个名为 IA32_PERF_STATUS 的 MSR 寄存器可供检查 CPU 当前所处的运行频率。当用户需要对 CPU 运行频率进行设置时只需按照 Intel 开发手册的说明向 IA32_PERF_CTL MSR 寄存器中写入规定的数值即可。

所以,来调频吧

这一部分,本来想就是测试一下修改不同核心的频率,然后使其运行在不同的频率下。最后书写测试程序,使线程绑定具体的核心,跑下测试。然而没想到又遇到了很多问题。

  • 首先,是governor没有userspace的问题。
  • 再,到底谁才真正显示了当前频率。
  • 最后,CPU的核心真的能运行在不同频率下吗????

问题一:解决intel_pstate driver

解决思路

在两台Macbook Pro和Macbook Air上安装Fedora后并没有看到上面所说的ondemand的调度方法,也没有发现可以通过用户态调整核心运行频率的接口,爬了各种帖子后发现其根本原因出在intel_pstate driver上。(在/sys/devices/system/cpu/cpuX/cpufreq下查看scaling_driver显示为intel_pstate。)

fedora社区讨论地址、archlinux论坛讨论地址,查看之后找到了archlinux里面的一个描述文档

  • 对于现代 Intel CPU,将使用 pstate 功率驱动程序,而非下列其他驱动程序。此驱动程序的优先级高于其他驱动程序,并编入内核(而非编译为模块)。此驱动程序将自动用于 Sandy Bridge(以及更新的 CPU)。如果在使用这个驱动的时候遇到问题,建议您在 Grub 的内核参数中将其禁用(即修改 /etc/default/grub 文件,在 GRUB_CMDLINE_LINUX_DEFAULT= 后添加 intel_pstate=disable)。您可以使用与此驱动程序配套的用户空间工具,但这些工具不受您的控制
  • 尽管上述 P State 行为会受到 /sys/devices/system/cpu/intel_pstate 影响,例如:可以通过 # echo 1 > /sys/devices/system/cpu/intel_pstate/no_turbo关闭 Intel 睿频加速,从而降低 CPU 的温度。
  • 对于现代 Intel CPU,Linux Thermal Daemon 也提供了一些其他的控制方法(例如 thermald),它们可以通过 P-state、T-state 或 Intel 节能驱动程序来主动控制系统温度。thermald 也适用于较老的 Intel CPU。如果最新版本的驱动程序不可用,那么守护进程会还原为 x86 MSR (Model Specific Register),由 Linux“cpufreq 子系统”来控制系统冷却。

Linux kernel中关于intel_pstate的描述文档:链接 。Intel官方关于此驱动给的Slide:链接。

简单来说,pstat又回去了,结合了变频策略和具体的硬件驱动,为了更好的性能和功耗……可能吧。有机会再详细学习一下pstat

在Fedora中将驱动改回acpi-cpufreq

  1. 按照官方说明,在/etc/default/grub 文件,在 GRUB_CMDLINE_LINUX_DEFAULT= 后添加 intel_pstate=disable

  2. 对于ubuntu系统,提供了update-grub的工具,而对于Fedora,需要利用grub2-mkconfig工具,输入以下命令:

    sudo grub2-mkconfig -o /boot/grub2/grub.cfg           #Traditional
    sudo grub2-mkconfig -o /boot/efi/EFI/fedora/grub.cfg #EFI
  3. 重新查看/sys/devices/system/cpu/cpuX/cpufreq/scaling_driver已经变为acpi-cpufreq

本以为大功告成,可以愉快的测试了。结果又出现了更多的问题:

问题二:谁到底正真显示了CPU的当前频率!!

问题现象

按照道理来说,第一部分介绍的两种方式查出来的当前频率应该相同。然而,事实并非如此:

/proc/cpuinfo 与 cpuinfo_cur_freq 居然不相符!!!!

发现问题时,我的内核已经更新到Linux4.14了。当然发现与内核版本有关时,已是后话了。

/proc/cpuinfocpuinfo_cur_freq中反应的当前的CPU的频率有比较大的出入,下面是在设置调度策略为ondemand时分别监视/proc/cpuinfo中的频率信息与sysfscpuinfo_cur_freq中的频率信息。可以发现其中的差异非常大。

当设置调频策略为userspace且设置四个核心为cpuinfo_cur_freq中所示频率时,/proc/cpuinfo中并没有相似的变动。

写了一个创建4个线程并平均分配到四个核心的相同计算任务的测试程序,并设置调频策略为ondemand。可以看到在计算任务重时,虽然两个地方都显示跑到了最高频率,但是最高频率并不相同。

解决思路

爬了很多帖子,最后在Stack Exchange的这个问题 Why do cpuinfo_cur_freq and /proc/cpuinfo report different numbers? 下找到了线索。其中的一个老哥的回复非常有用,回复内容如下:

Note: Since Kernel 4.13, cat /proc/cpuinfo | grep MHz no longer returns the current clock speed. At the Kernel Bugzilla, they say it’s intentional. See /proc/cpuinfo does not update frequency. It’s also mentioned here: Power Management Updates Touch Intel P-State & More For Linux 4.13

– Marc Ranolfi Oct 11 ‘17 at 3:14

在第一个链接描述的现象正是现在我面临的情况:

The 4.13 kernel with intel_pstate=passive (or active) does not appear to correctly update the CPU frequency in /proc/cpuinfo

在该问题的讨论中,提及到4.13之后不再以/proc/cpuinfo读取cpu频率信息,且cpuinfo_cur_freq才是正确的。这也导致一些依赖于/proc/cpuinfo 的软件出现一些问题。

在第二个链接里面提到了在Kernel 4.13的更新中有这样一条新的特性:

x86 systems will no longer try to export their current CPU frequency to /proc/cpuinfo. There’s also a way to rework how the CPU frequency is exported via sysfs too, using the registers for computing the current frequency rather than relying upon the CPUFreq driver

好吧,总的来说,就是和Linux内核版本相关,新的内核版本可能取消了向CPUinfo输出实时频率的feature。

实际测试

而实际测试发现情况并没有这么简单。测试平台CPU信号为Intel haswell架构i5-4258U。

由于Fedora更新比较勤快,我的Fedora系统有三个内核,两个是4.14的,一个是4.13的。

下面测试均开了四个watch窗口,分别监视:/proc/cpuinfocpuinfo_cur_freqscaling_cur_freqscaling_governor

4.14内核

首先测试在4.14内核中的情况:

当书写脚本将四个核心均调到性能模式(从按需模式调过来的),可以发现两个现象

  • 目前来说没有问题,均到了最大频率。
  • 但是和上面帖子不同的是,/proc/cpuinfo中展现的可能是正确的频率。

然后测试的是powersave模式,如下图所示,有以下发现

  • 依然没有问题,所有频率都降到了最低
  • 同样,/proc/cpuinfo中展现的可能是正确的频率

然后跑自己设置的实验环境,两个900000,两个2401000。这次结果就比较有趣了

  • 确实是用户设置的频率,但是只有设置的cpu0有用,其他的都按照cpu0的频率跑
  • cpuinfo_cur_freq倒是按照了设置来走的,可惜不是实际评论。

在测试一下设置不同的,可以断定所有的cpu均按照cpu0的频率来走了。

再设置回performance时,发现其并没有全部升到最高,可能performance策略不管用了……

总结一下414内核的特点:

  • /proc/cpuinfo是显示正确频率的地方
  • cpuinfo_cur_freq显示的是错误的,虽然是最接近设置目标的。
  • userspace只能设置统一频率
  • performance不管用

4.13内核

切换回4.13内核进行测试,配置测试环境依旧如上相同。这里不单一分析了,直接在最后进行总结。

用户配置模式,这里配置的是2300000, 2300000,1800000,1500000。依旧只按照cpu0进行设置。

powersaving模式:

performance模式:

特意为了检测governor是否也只能统一设置,做了如下实验,得出结论,governor也是统一设置的。

所以4.13内核的总结如下:

  • /proc/cpuinfo总是显示最高频率,cpuinfo_cur_freq中显示的亦不是正确频率
  • scaling_cur_freq中显示的是当前频率。
  • userspace可以统一设置频率,不能单独设置。
  • performance没有用。

总结

  • 412 413 414 内核关于CPU变频这块变动明显
  • 无论是413还是414内核,均以scaling_cur_freq为准。
  • 貌似核心频率只能全部修改,不能当个修改。

问题三:到底能不能单独配置每个核心运行频率?

上面的测试可以发现,核心频率可以全部修改,不能单独修改?所以到底能不能单独配置每个核心的运行频率呢?

第一条线索

为了找这个问题的答案,爬了很多帖子,在stackoverflow的这个问题下找到了线索:Understanding cpu frequency, thread selection and more,取答案中比较关键的部分翻译如下:

大体来说,cpufreq提供的很多功能并不被Hardware或者Kernel所支持,所以通过cpufreq设置的功能不一定会按照预期运行。例如,如果利用cpufreq为每个cpu设置单独的运行的频率,现实中在超线程的系统,两个CPUs可能会绑定在一起,所以必须有相同的频率。

Intel P-states实际上是提供了一个frequency-voltage对,通过降低cpu运行的电压来降低cpu的运行频率。这些frequency-voltage对是离散的,可能与cpufreq提供的可选频率有出入。

所以从这个答案可以知道第一个原因:

  • 可能由于超线程技术导致两个虚拟CPU其实是一个核心,所以两个绑定在一起。

第二条线索

转到Intel的论坛,发现类似的一个帖子:How can I scale only one core’s frequency in a multi-core processor? 在这个问题中,McCalpin, John给出了另一个比较详细的解释,原答案可以找原贴看。

首先要了解什么是uncore,其实uncore就是intel用来描述其微处理器上不是un处理器核心core的部分,包括例如L1 L2 cacheALU之类一堆。处理器运行的频率/电压与uncore有关。

回答的主要内容总结如下

  • 首先第一个问题是当前消费级别的uncore(如i系),只支持设置唯一一个时钟频率。

  • 然后是服务器级的uncore(如E系),虽然支持每个核心不同频率,但是你一旦指定他们运行在不同的频率,uncore中功耗控制单元(PCU)可能会再次改写你的请求,因为PCU可能认为你的设定不合理……

  • 所以讨论一下运行在不同的频率的可能性:

    1. 能否直接要求每个核心运行在不同频率:

      设置是可以的,通过修改MSR IA32_PERF_CTL寄存器,但是这并不意味着硬件会响应你的请求。

    2. 能否通过设置不同核的电压,间接改变核心的运行频率:

      • 首先很少系统是有与核数量相同的电源来提供运行在不同电压上。
      • 再则,在Haswell架构之前,频率和电压是绑定的,一起写入MSR IA32_PERF_CTL
      • Haswell 提供了 on-chip voltage regulators ,其允许给不同的核心不同的频率。
      • 这也不意味着硬件会响应你的请求(因为PCU的存在)
    3. 所以到底他们有可能会响应吗

      • 首先要清楚,PCU有最终的决定权
      • 该答案的作者也没能在Haswell之前的处理器中实现运行不同频率。
      • 这个部分详细可以去看 Uncore Performance Monitoring Manuals for the various Xeon E5 products

So… Conclusion

所以在我的当前的笔记本环境下跑出不同频率的CPU可能性不大了。本来想着p-state和具体uncore对于变频的处理细节可以暂时不管,可能现在需要继续填坑,详细了解了。

初探Linux CPU动态调频与实测相关推荐

  1. linux CPU动态调频【转】

    转自:https://www.xuebuyuan.com/2185926.html 针对sep4020的linux低功耗研究也有一段时间了,基本把低功耗的实现方式想清楚了(主要分成机制和策略),这段时 ...

  2. linux CPU动态调频

    针对 sep4020的 linux低功耗研究也有一段时间了,基本把低功耗的实现方式想清楚了(主要分成机制和策略),这段时间的工作主要在机制上.暂时想实现的主要的机制有: cpu级,设备驱动级,系统平台 ...

  3. linux动态调频响应时间,CPU动态调频(linux 3.14.0)一

    最近做了一个关于CPU动态调频的project,边工作边学习,在此记录一下. code版本:3.14.0(在linxu目录顶层Makefile中可看到版本号) 设备:基于安卓4.4原生系统的某厂商的手 ...

  4. CPU动态调频二:interactive governor

    Linux提供了多种governor供用户选择,这里以interactive为例,毕竟现在的android手机中都是采用该governor. 基于linux 3.14 以下代码若未指明位置则默认在dr ...

  5. rk3368 CPU动态调频与温度保护

    Platform: RK3368 OS: Android 6.0 Kernel: 3.10.0 rk3368采用cpufreq进行CPU频率调节,但同时又做了过温保护和温度限制频率. 1. 过温保护 ...

  6. 【interactive governor】CPU动态调频:

    #!/usr/bin/bash # interactive(互动)是目前最常用的调速器, CPU 频率是根据负载实现交互式反应, # ondemand(一经请求)  # conserative(保守) ...

  7. CPU动态调频三:interactive governor如何选频

    choose_freq函数用来选频,使选频后的系统workload小于或等于target load. 核心思想是:选择最小的频率来满足target load. 影响选频结果的因素有两个: 1.两次统计 ...

  8. 【Linux 内核】宏内核与微内核架构 ( 操作系统需要满足的要素 | 宏内核 | 微内核 | Linux 内核动态加载机制 )

    文章目录 一.操作系统需要满足的要素 二.宏内核 三.微内核 四.Linux 内核动态加载机制 一.操作系统需要满足的要素 电脑上运行的 操作系统 , 是一个 软件 ; 设备管理 : 操作系统需要 为 ...

  9. Linux部署动态网页,linux构建动态WEB服务器安装篇

    linux构建动态WEB服务器安装篇 发布时间:2008-09-18 08:50:01   作者:佚名   我要评论 基本配置 安装web服务器:httpd-2.X.X 先优化吧 根据CPU设置变量 ...

最新文章

  1. SCCM 2012系列之新特性概览一:SCCM 2012安装选项和控制台新界面预览
  2. (转)CSS样式表继承详解
  3. 衔接上一学期:排球积分规则
  4. 你的项目刚刚启动?是时候考虑Globalization了!
  5. 【转】回调函数,函数指针与函数对象
  6. 一个代码托管平台居然公开拒招中国人,谁给了你歧视中国程序员的勇气?
  7. 递归转手动管理栈的非递归
  8. Tabio – 轻松,高效的管理 Chrome 标签页
  9. .NET框架类在ASP.NET中的使用(1)——QA
  10. 关于PV、EV、AC、CV、SV、CPI、SPI、BAC、ETC、EAC的解析及计算
  11. 由四个坐标位置计算中心点和旋转角度
  12. 聚光灯效应:为什么没有人记得你做过什么
  13. 如何保护自己的颈椎?
  14. 版本控制管理工具Git/SVN
  15. 解决uniapp手机浏览器视频封面不显示问题
  16. 手机罗盘(指南针)校准方法
  17. DNS劫持 DNS污染 介绍 与 公共DNS 推荐
  18. python自动化 html 翻译转 pdf
  19. ConcurrentHashMap 的理解
  20. 5 款最好的免费 SSD 数据恢复软件

热门文章

  1. TRH15VL、TRH20VL、TRH20VE、TRH25VE、TRH30VE直线导轨型号替换
  2. C-Way:用乐高的方式做儿童智能手表
  3. Grafana + prometheus在Centos搭建服务器监控系统(一)---安装、配置
  4. Mybatis框架简介
  5. 用Python轻松创建一个交互式可视化大屏!
  6. java-php-python-ssm清空购物商城系统计算机毕业设计
  7. php盒子模型,HTML与CSS的盒子模型
  8. linux修改时间时区及语言
  9. 足球俱乐部介绍——多特蒙德
  10. 本松新材IPO被终止:曾拟募资近6亿 周永松控制57%表决权