使用 Linux cgroups 来平衡 CPU 性能

Gre*_*ith 13 linux performance cgroups

我安装了两个双核 Linux 系统,使用 Linux cgroups 和相对较新的内核;一个运行 Debian Squeeze,另一个运行 Ubuntu 11.04 Natty Narwhal。尽管内核较旧,但我已经通过 cgroup 在 Debian 系统上更好地工作来实现 CPU 负载平衡。但这并不适用于所有情况,我在这里询问的特定奇怪现象发生在两个系统上。

如果您阅读带有控制组的 Linux 中的资源管理,它提供了一个示例,说明如何重现该问题。这是 Ubuntu 版本(以 root 身份运行):

cd /sys/fs/cgroup/cpu
    [On Debian Squeeze start at /mnt/cgroups/cpu instead]
mkdir low high
echo 512 > low/cpu.shares
echo 2048 > high/cpu.shares
yes low > /dev/null &
echo $! > low/tasks
yes high > /dev/null &
echo $! > high/tasks
ps -C yes -opid,%cpu,psr,args
    [repeat that a few times]
killall -9 yes
Run Code Online (Sandbox Code Playgroud)

我期望“高”进程比“低”进程分配更多时间;这个测试用例的实际情况总是更像这样:

root@black:/sys/fs/cgroup/cpu# ps -C yes -opid,%cpu,psr,args
  PID %CPU PSR COMMAND
 3105 88.3   1 yes low
 3106 94.5   0 yes high
Run Code Online (Sandbox Code Playgroud)

时间几乎相等的地方。这是我的问题:为什么会这样?

在演示中,通过将每个进程固定到同一个 CPU,这个问题会消失;额外的行来测试:

taskset -c 1 yes high > /dev/null &
echo $! > high/tasks
taskset -c 1 yes low > /dev/null &
echo $! > low/tasks
ps -C yes -opid,%cpu,psr,args
[later, rinse, repeat]
killall -9 yes
Run Code Online (Sandbox Code Playgroud)

结果就是我一直期待看到的:“高”进程获得更高百分比的 CPU:

root@black:/sys/fs/cgroup/cpu# ps -C yes -opid,%cpu,psr,args
  PID %CPU PSR COMMAND
 3128 83.3   1 yes high
 3129 20.7   1 yes low
Run Code Online (Sandbox Code Playgroud)

解释为什么这行得通将是找出为什么前一个行不通的有用步骤。

Gre*_*ith 10

我从 Stefan Seyfried 那里得到了关于这个测试用例的初步解释,他写了这个例子的论文。这里的问题是 cgroups 的 CPU 调度程序部分总是旨在保持任何可用的 CPU 忙碌;如果一切都适合,它永远不会强制执行硬限制。

如果两个进程(这里是高和低)在 >=2 个内核上运行,它只会在一个内核上保持高电平,而在另一个内核上保持低电平。然后两者都会以接近 100% 的使用率一直运行,因为它们可以这样做而不会遇到调度程序没有给它们足够的 CPU 时间的情况。cpu.share 调度仅在出现短缺时发生。

在第二种情况下,两个进程都固定到同一个 CPU。然后 CPU 共享逻辑必须对相关的 cpu.shares 数字做一些有用的事情来平衡它们,它会按希望的那样做。

CPU 使用率的硬限制在CFS 带宽控制补丁出现之前不太可能出现。到那时,可能会得到更像我希望的东西。