以节能的方式动态禁用内核?

Mic*_*yer 5 linux multi-core power-management

我正在寻找一种在 Linux 中动态禁用内核的机制,以最大限度地减少功耗。

不幸的是,根据Watts Up?的读数,使用以下简单方法禁用内核实际上会增加功率。Pro测量系统总功率:

echo 0 > /sys/devices/system/cpu/cpu7/online
Run Code Online (Sandbox Code Playgroud)

我的经验似乎得到了其他人的证实(尽管这个错误已被标记为“CLOSED PATCH_ALREADY_AVAILABLE”): https://bugzilla.kernel.org/show_bug.cgi ?id=5471

由于机器已卸载,我希望除了一个核心之外的所有核心(或者可能是两个“核心”,因为 CPU 是超线程的)都处于尽可能深度的睡眠状态。根据 acpitool 的输出,这似乎不会单独发生:

Processor ID           : 7
Bus mastering control  : no
Power management       : yes
Throttling control     : no
Limit interface        : no
Active C-state         : C0
C-states (incl. C0)    : 3
Usage of state C1      : 899 (99.3 %)
Usage of state C2      : 6 (0.7 %)
Run Code Online (Sandbox Code Playgroud)

顺便说一句,令我困惑的一点是 acpitool 和 /proc/acpi 似乎对可用的 C 状态不一致,或者它们可能使用不同的命名方案。

$ cat /proc/acpi/processor/CPU7/power 
active state:            C0
max_cstate:              C8
maximum allowed latency: 2000000000 usec
states:
    C1:                  type[C1] promotion[--] demotion[--] latency[001] usage[00000000] duration[00000000000000000000]
    C2:                  type[C2] promotion[--] demotion[--] latency[017] usage[00001248] duration[00000000001877531423]
    C3:                  type[C3] promotion[--] demotion[--] latency[017] usage[00000006] duration[00000000000012580727]
Run Code Online (Sandbox Code Playgroud)

这似乎表明有 4 个 C 状态 (C0-C3),但 acpitool 仅报告 3 个 C 状态。


其实这可以归结为两个问题:

  1. 是否有一种(安全)方法可以强制各个核心进入特定的睡眠状态(C 状态),并强制它们保持在那里,直到我明确唤醒它们?
  2. 或者,如何提高操作系统更一致地自动将内核置于更深睡眠状态的能力?

请注意,从深度睡眠状态醒来的延迟不是一个问题。FWIW,我在 Intel i7 920 上运行 Ubuntu 10.04.3(内核 2.6.32-38)。

小智 -1

上述限制 C 状态的方法都是永久性的(直到系统重新启动)。如果您希望系统在特定时间内具有极低的延迟,但希望在其他时间节省更多电量,可以使用一种方法来动态控制使用哪些 C 状态。

\n\n

要动态控制 C 状态,请打开文件 /dev/cpu_dma_latency 并将最大允许延迟写入其中。只要文件 /dev/cpu_dma_latency 保持打开状态,这将阻止使用转换延迟高于指定值的 C 状态。写入最大允许延迟 0 将使处理器保持在 C0 状态(如使用内核参数 \xe2\x80\x9cidle=poll\xe2\x80\x9d),写入较低值(通常为 5 或更低)应强制处理器空闲时C1。将处理器限制为 C1 状态所需的确切值取决于各种因素,例如您正在使用的空闲驱动程序、您正在使用的 CPU,以及系统中可能的 ACPI 表。还可以写入更高的值来限制使用延迟大于写入值的 C 状态。使用的值应对应于 /sys/devices/system/cpu/cpuX/cpuidle/stateY/latency 中的延迟值(其中 X 是 CPU 编号,Y 是空闲状态)\xe2\x80\x94CPU 空闲状态具有不应使用比写入 /dev/cpu_dma_latency 更大的延迟。

\n\n

执行此操作的一种简单方法是编译一个简单的程序,该程序将写入该文件,并保持打开状态直到该文件被终止。下面是此类程序的一个示例,可以通过将代码剪切并粘贴到名为 setcpulatency.c 的文件中,然后运行 ​​\xe2\x80\x9cmake setcpulatency\xe2\x80\x9d 来进行编译。因此,为了最大限度地减少某些时段(例如上午 8 点到下午 5 点)的延迟,可以将 cron 作业设置为在上午 8 点运行。这个 cron 作业可以在后台运行 setcpulatency,参数为 0,并且 cron 表条目如下:

\n\n
00 08 * * * /path/to/setcpulatency 0 &\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后,在下午 5 点,另一个 cron 作业可能会杀死任何保持 /dev/cpu_dma_latency 打开的程序:

\n\n
00 17 * * * kill -9 `lsof \xe2\x80\x93t /dev/cpu_dma_latency`\n
Run Code Online (Sandbox Code Playgroud)\n\n

当然,这只是一个示例,用于展示如何动态控制 C 状态... crond 服务通常在低延迟环境中被禁用,但这些步骤可以手动执行或通过其他方式运行。

\n\n
#include <stdio.h>\n#include <fcntl.h>\n\nint main(int argc, char **argv) {\n   int32_t l;\n   int fd;\n\n   if (argc != 2) {\n      fprintf(stderr, "Usage: %s <latency in us>\\n", argv[0]);\n      return 2;\n   }\n\n   l = atoi(argv[1]);\n   printf("setting latency to %d us\\n", l);\n\n   fd = open("/dev/cpu_dma_latency", O_WRONLY);\n\n   if (fd < 0) {\n      perror("open /dev/cpu_dma_latency");\n      return 1;\n   }\n\n   if (write(fd, &l, sizeof(l)) != sizeof(l)) {\n      perror("write to /dev/cpu_dma_latency");\n      return 1;\n   }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

  • 这是来自戴尔 PDF 的未经编辑的粘贴,内容涉及如何执行与 OP 要求相反的操作(暂时防止核心闲置以获得最大性能)。在大多数情况下,空闲是默认行为。 (2认同)