以编程方式禁用 CPU 核心

Programmatically disable CPU core

已知在Linux中禁用逻辑CPU的方法,基本上是echo 0 > /sys/devices/system/cpu/cpu<number>/online。这样,您只是告诉 OS 忽略给定的 (<number>) CPU.

我的问题更进一步,是否可以不仅忽略它而且以编程方式物理关闭它?我希望 CPU 不接收任何电源,以使其能耗为零。

我知道可以从 BIOS 中禁用内核(并非总是如此),但我想知道是否可以在某个程序中执行此操作。

据我所知,目前还没有可用的系统调用或库函数。甚至 ioctl 实现。因此,除了创建新模块/系统调用之外,我还有两种方法可以想到:

  1. 使用 ASM asm(<assembly code>);,其中汇编代码是特定于体系结构的汇编代码,用于修改 cpu 标志。

  2. c 中的系统调用 (man 3 system)。假设你只想通过 c.

您可以使用像 cpufreq 这样的调控器来最接近这一点。使 Linux 排除 CPU 省电模式将确保内核以最低频率运行。

当您执行 echo 0 > /sys/devices/system/cpu/cpu<number>/online 时,接下来会发生什么取决于特定的 CPU。在 ARM 嵌入式系统上,内核通常会禁用驱动特定核心 PLL 的时钟,这样您就可以有效地得到想要的东西。

在 Intel X86 系统上,您只能禁用中断并调用 hlt 指令(Linux 内核执行)。这有效地将 CPU 置于省电状态,直到它在用户请求下被另一个 CPU 唤醒。如果您有一台笔记本电脑,您可以通过从 /sys/class/power_supply/BAT{0,1}/current_now(或 uevent 读取所有值,例如电压)或使用 [=42] 来验证禁用内核时功耗是否确实下降=]实用程序。

例如,这里是用于禁用 Linux Intel CPU 内核中的 CPU 内核的调用链。 https://github.com/torvalds/linux/blob/master/drivers/cpufreq/intel_pstate.c

arch/x86/kernel/smp.c: smp_ops.play_dead = native_play_dead,

arch/x86/kernel/smpboot.c : native_play_dead() -> play_dead_common() -> local_irq_disable()

在此之前,CPUFREQ 还会将 CPU 设置为最低功耗级别,然后再禁用它,尽管这似乎并不是绝对必要的。

intel_pstate_stop_cpu -> intel_cpufreq_stop_cpu -> intel_pstate_set_min_pstate -> intel_pstate_set_pstate -> wrmsrl_on_cpu(cpu->cpu, MSR_IA32_PERF_CTL, pstate_funcs.get_val(cpu, pstate));

在 Intel X86 上似乎没有禁用实际时钟和稳压器的官方方法。即使有,它也会特定于主板,因此您最接近的赌注可能是研究 BIOS,例如 coreboot。 嗯,我意识到除了查看内核源代码之外我对英特尔一无所知。

您还可以在内核启动时将 cpus 与调度程序隔离。

在内核引导参数中添加isolcpus=0,1,2

https://www.linuxtopia.org/online_books/linux_kernel/kernel_configuration/re46.html

在 Windows10 中,新的电源管理命令 CPMINCORES CPMAXCORES 成为可能。

Powercfg -setacvalueindex scheme_current sub_processor CPMAXCORES 50
Powercfg -setacvalueindex scheme_current sub_processor CPMINCORES 25
Powercfg -setactive scheme_current

这里50%的核心分配给想要的深度睡眠,25%的核心禁止停放。非常擅长需要更高时钟速率的数值模拟(Intel 提升 15%)

您无法选择停放哪些内核,但 Windows 10 内核会检查 Intel 的 Comet Lake 和更新的“首选”(更节能)内核,并开始停放那些不受欢迎的内核。 这不是严格的停放,因此在高负载下内核可以使用这些负载非常低的内核。

以防万一您正在寻找替代品

我知道这是一个老问题,但禁用 CPU 的一种方法是通过 grub 配置。

如果您在 /etc/default/grub 中添加到 GRUB_CMDLINE_LINUX 的末尾(假设您使用的是标准 Linux dist,如果您使用的是设备,则 grub 配置的位置可能是不同),例如:

GRUB_CMDLINE_LINUX=".......Current config here **maxcpus**=2"

然后通过 运行 重新制作 grub 配置 grub2-mkconfig -o /boot/grub2/grub.cfg(或 grub-mkconfig -o /boot/grub2/grub.cfg,具体取决于您的安装)。一些发行版可能需要 nr_cpus 而不是 maxcpus.

只是一些额外的信息:

  • 如果您是 运行 具有多个物理 CPU 的服务器,那么禁用一个 CPU 很可能会禁用链接到该 CPU 的内存集=39=],因此它可能会对服务器的性能产生影响

  • 以这种方式禁用 CPU,不会影响您的 1 类虚拟机管理程序访问 CPU(这是基于 xen 虚拟机管理程序,我相信它将适用于 vmware另外,如果有人能提供确认就太好了)。根据 virtualbox 设置,它可能会限制 CPU 您可以分配给 VM 的数量,除非您是 运行 准虚拟化。

  • 但是我不确定您是否会节省电量,如今大多数服务器甚至台式机都已经很好地控制了电源,使当前负载不需要的任何设备进入睡眠状态。我担心的是通过减少 CPU(核心)的数量,然后您只需将负载移动到剩余的 CPU 并且由于需要安排处理器时间,并且可能有指令排队,以及可用于中断的内核数量较少(例如:网络流量)的影响,可能会对功耗产生负面影响。