当 KVM 来宾需要时,主机 CPU 不会调整频率

Huy*_*ens 8 linux freebsd kvm cpu-frequency clock

观察:
我有一台配备 AMD 双核 CPU (Turion II Neo N40L) 的 HP 服务器,它可以将频率从 800 扩展到 1500 MHz。频率缩放适用于 FreeBSD 9 和带有 Linux 内核 3.5 的 Ubuntu 12.04。但是,当我将 FreeBSD 9 放在 Ubuntu 之上的 KVM 环境中时,频率缩放不起作用。来宾(因此是 FreeBSD)不会检测最小和最大频率,因此当 CPU 占用率更高时不会扩展任何内容。在主机(即 Ubuntu)上,KVM 进程使用了​​ 80% 到 140% 的 CPU 资源,但没有发生频率缩放,频率保持在 800 MHz,尽管当我在同一个 Ubuntu 机器上运行任何其他进程时,按需调节器很快将频率缩放到 1500 MHz!

关注和问题:
我不明白 CPU 是如何虚拟化的,以及是否由来宾执行适当的缩放。是否需要向来宾公开某些 CPU 功能才能使其工作?

Apendix:
下面的Red Hat发布说明倾向于认为,频率缩放出来工作,即使在虚拟化环境中(参见第6.2.2和6.2.3),认为注未能解决其虚拟化技术与(KVM,Xen的这项工作, 等等。?)

有关信息,cpufreq-infoUbuntu 上的输出为:

$ cpufreq-info
cpufrequtils 007: cpufreq-info (C) Dominik Brodowski 2004-2009
Report errors and bugs to cpufreq@vger.kernel.org, please.
analyzing CPU 0:
  driver: powernow-k8
  CPUs which run at the same hardware frequency: 0
  CPUs which need to have their frequency coordinated by software: 0
  maximum transition latency: 8.0 us.
  hardware limits: 800 MHz - 1.50 GHz
  available frequency steps: 1.50 GHz, 1.30 GHz, 1000 MHz, 800 MHz
  available cpufreq governors: conservative, ondemand, userspace, powersave, performance
  current policy: frequency should be within 800 MHz and 1.50 GHz.
                  The governor "ondemand" may decide which speed to use
                  within this range.
  current CPU frequency is 800 MHz.
  cpufreq stats: 1.50 GHz:14.79%, 1.30 GHz:1.07%, 1000 MHz:0.71%, 800 MHz:83.43%  (277433)
analyzing CPU 1:
  driver: powernow-k8
  CPUs which run at the same hardware frequency: 1
  CPUs which need to have their frequency coordinated by software: 1
  maximum transition latency: 8.0 us.
  hardware limits: 800 MHz - 1.50 GHz
  available frequency steps: 1.50 GHz, 1.30 GHz, 1000 MHz, 800 MHz
  available cpufreq governors: conservative, ondemand, userspace, powersave, performance
  current policy: frequency should be within 800 MHz and 1.50 GHz.
                  The governor "ondemand" may decide which speed to use
                  within this range.
  current CPU frequency is 800 MHz.
  cpufreq stats: 1.50 GHz:14.56%, 1.30 GHz:1.06%, 1000 MHz:0.79%, 800 MHz:83.59%  (384089)
Run Code Online (Sandbox Code Playgroud)

我希望此功能起作用的原因是:节省能源,运行更安静(不那么热)以及简单的好奇心以更好地了解为什么这不起作用以及如何使其起作用。

Huy*_*ens 10

由于Nils给出的提示和一篇不错的文章,我找到了解决方案。

调整按需CPU DVFS调控

按需调节器有一组参数来控制它何时启动动态频率缩放(或用于动态电压和频率缩放的 DVFS)。这些参数位于 sysfs 树下:/sys/devices/system/cpu/cpufreq/ondemand/

其中一个参数up_threshold就像名称所暗示的那样是一个阈值(单位是 CPU 的百分比,但我还没有确定这是每个核心还是合并的核心),高于该阈值时,按需调节器会启动并开始动态更改频率。

使用 sudo 将其更改为 50%(例如)很简单:
sudo bash -c "echo 50 > /sys/devices/system/cpu/cpufreq/ondemand/up_threshold"

如果您是 root,则可以使用更简单的命令:
echo 50 > /sys/devices/system/cpu/cpufreq/ondemand/up_threshold

注意:这些更改将在下次主机重新启动后丢失。您应该将它们添加到在启动期间读取的配置文件中,就像/etc/init.d/rc.local在 Ubuntu 上一样。

我发现我的来宾虚拟机虽然在主机上消耗了大量 CPU (80-140%) 却在两个内核上分配负载,因此没有一个内核超过 95%,因此令我恼火的是 CPU保持在 800 MHz。现在有了上面的补丁,CPU 可以更快地动态改变每个内核的频率,这更适合我的需求,50% 似乎是我来宾使用的更好阈值,您的里程可能会有所不同。

(可选)验证您是否使用 HPET

DVFS 可能会影响一些不正确实现计时器的适用对象。这可能是主机和/或来宾环境中的一个问题,尽管主机可以有一些复杂的算法来尝试最小化这个问题。但是,现代 CPU 具有更新的 TSC(时间戳计数器),它们独立于当前的 CPU/核心频率,它们是:常量(constant_tsc)、不变(invariant_tsc)或不间断(nonstop_tsc),请参阅有关TSC 重新同步的Chromium 文章有关每个的更多信息。因此,如果您的 CPU 配备了此 TSC 之一,则无需强制使用 HPET。要验证您的主机 CPU 是否支持它们,请使用类似的命令(将 grep 参数更改为相应的 CPU 功能,这里我们测试常量 TSC):

$ grep constant_tsc /proc/cpuinfo
Run Code Online (Sandbox Code Playgroud)

如果您没有这种现代 TSC,您应该:

  1. Active HPET,这在后面描述;
  2. 如果 VM 中有任何依赖于精确计时的应用程序,则不要使用 CPU DVFS,这是Red Hat 推荐的

一个安全的解决方案是启用 HPET 计时器(有关更多详细信息,请参见下文),它们的查询速度比 TSC 计时器慢(TSC 在 CPU 中,而 HPET 在主板中)并且可能没有精确度(HPET >10MHz;TSC通常是最大 CPU 时钟)但它们更可靠,尤其是在每个内核可能具有不同频率的 DVFS 配置中。Linux 足够聪明,可以使用最好的可用计时器,它会首先依赖 TSC,但如果发现太不可靠,它将使用 HPET 计时器。这在主机(裸机)系统上运行良好,但由于虚拟机管理程序并未正确导出所有信息,这对于来宾 VM 检测行为不良的 TSC 来说更具挑战性。诀窍是在来宾中强制使用 HPET,尽管您需要虚拟机管理程序来使该时钟源可供来宾使用!

您可以在下面找到如何在 Linux 和 FreeBSD 上配置和/或启用 HPET。

Linux HPET 配置

HPET,即高精度事件计时器,是自 2005 年以来您可以在大多数商品 PC 中找到的硬件计时器。现代操作系统可以有效地使用该计时器(Linux 内核从 2.6 开始支持它,从最新的 9.x 开始稳定支持 FreeBSD但在 6.3 中引入)以始终为 CPU 电源管理提供一致的时序。它允许构建更简单的无滴答调度程序实现

基本上,HPET 就像一个安全屏障,即使主机启用了 DVFS,主机和来宾计时事件也不会受到影响。

IBM一篇关于启用 HPET好文章,它解释了如何验证您的内核正在使用哪个硬件计时器以及哪些可用。我在这里提供一个简短的总结:

检查可用的硬件定时器:
cat /sys/devices/system/clocksource/clocksource0/available_clocksource

检查当前活动定时器:
cat /sys/devices/system/clocksource/clocksource0/current_clocksource

如果可用,强制使用 HPET 的更简单方法是修改引导加载程序以要求启用它(自内核 2.6.16 起)。此配置取决于发行版,因此请参阅您自己的发行版文档以正确设置。您应该在内核引导行启用hpet=enableclocksource=hpet(这又取决于内核版本或发行版,我没有找到任何相关信息)。
这确保来宾正在使用 HPET 计时器。

注意:在我的内核 3.5 上,Linux 似乎会自动启动 hpet 计时器。

FreeBSD 来宾 HPET 配置

在 FreeBSD 上,可以通过运行以下命令来检查哪些计时器可用:
sysctl kern.timecounter.choice

当前选择的计时器可以通过以下方式验证:
sysctl kern.timecounter.hardware

FreeBSD 9.1 似乎比其他计时器提供者更喜欢 HPET。

Todo:如何在 FreeBSD 上强制使用 HPET。

管理程序 HPET 导出

当主机支持时,KVM 似乎会自动导出 HPET。但是,对于 Linux 来宾,他们更喜欢另一个自动导出的时钟,即 kvm-clock(主机 TSC 的半虚拟化版本)。有些人报告首选时钟有问题,您的里程可能会有所不同。如果要在guest 中强制HPET,请参考上一节。

默认情况下,VirtualBox 不会将 HPET 时钟导出到客户机,并且在 GUI 中没有这样做的选项。您需要使用命令行并确保 VM 已关闭。命令是:

./VBoxManage modifyvm "VM NAME" --hpet on
Run Code Online (Sandbox Code Playgroud)

如果guest在上述更改后继续选择HPET以外的其他来源,请参阅上一节如何强制内核使用HPET时钟作为来源。