CPU 亲和性如何与 Linux 中的 cgroup 交互?

Edd*_*ett 13 linux kernel multi-core cgroup

我正在尝试在一组独立的 CPU 上运行多线程基准测试。长话短说,我最初尝试使用isolcpustaskset,但遇到了问题。现在我在玩 cgroups/csets。

我认为“简单”cset shield用例应该可以很好地工作。我有 4 个内核,所以我想使用内核 1-3 进行基准测试(我还将这些内核配置为处于自适应滴答模式),然后内核 0 可用于其他所有内容。

按照这里的教程,它应该很简单:

$ sudo cset shield -c 1-3
cset: --> shielding modified with:
cset: "system" cpuset of CPUSPEC(0) with 105 tasks running
cset: "user" cpuset of CPUSPEC(1-3) with 0 tasks running
Run Code Online (Sandbox Code Playgroud)

所以现在我们有一个隔离的“盾牌”(用户 cset),核心 0 用于其他一切(系统 cset)。

好的,目前看起来不错。现在让我们来看看htop。这些进程应该都已迁移到 CPU 0 上:

csets

嗯?一些进程显示为在屏蔽内核上运行。为了排除 htop 存在错误的情况,我还尝试使用taskset检查显示为在屏蔽中的进程的亲和掩码。

也许那些任务是不可移动的?让我们选择一个显示为在 CPU3 上运行的任意进程(应该在屏蔽中)htop,看看它是否出现在系统 cgroup 中,根据cset

$ cset shield -u -v | grep 864
   root       864     1 Soth [gmain]
   vext01    2412  2274 Soth grep 864 
Run Code Online (Sandbox Code Playgroud)

是的,根据cset. 所以htopcset不同意。

那么这里发生了什么?我该信任谁:cpu 亲和力 ( htop/ taskset) 还是cset?

我怀疑你不应该cset和亲和力一起使用。也许防护罩工作正常,我应该忽略亲和力掩码和htop输出。无论哪种方式,我都觉得这很令人困惑。有人可以透露一些信息吗?

Edd*_*ett 7

来自cpusets 文档

对 sched_setaffinity 的调用被过滤为仅在该任务的 cpuset 中允许的那些 CPU。

这意味着 CPU 关联掩码与进程所属的 cgroup 中的 cpu 相交。

例如,如果进程的关联掩码包括内核 {0, 1, 3} 并且该进程正在系统 cgroup 上运行,而系统 cgroup 仅限于内核 {1, 2},那么该进程将被迫在内核 1 上运行。

我 99% 肯定htop输出是“错误的”,因为自 cgroup 被创建以来进程没有被唤醒,并且显示显示进程运行的最后一个核心。

如果我在制作我的盾牌之前启动 vim,vim 分叉两次(出于某种原因),并且最深的孩子在核心 2 上运行。如果我然后制作盾牌,然后睡眠 vim (ctrl+z) 并唤醒它,两个进程都有移至核心 0。我认为这证实了htop显示陈旧信息的假设。

您还可以检查/proc/<pid>/status和查看cpus_allowed_*字段。

例如,我有一个console-kit-daemon进程(pid 857)在 htop 中显示为在核心 3 上运行,但在/proc/857/status

Cpus_allowed:   1
Cpus_allowed_list:      0
Run Code Online (Sandbox Code Playgroud)

我认为这是说关联掩码是 0x1,由于 cgroup,它只允许在核心 1 上运行:即 intersect({0,1,2,3}, {0}) = {0}。

如果可以的话,我会留出这个问题一段时间,看看是否有更好的答案出现。

感谢@davmac 对此的帮助(在 irc 上)。