今天我和一位客户进行了一次有趣的通话。我们有一个应用程序可以调度其他应用程序,通常情况下,使用 NUMA 配置的服务器(2 到 4 个节点)完全没有问题。
在通话中,我们启动了两个非常耗 CPU 的应用程序,并且都分配给了节点 0,因此整个机器的使用率只有 50%。一旦我们将第二个应用程序实例更改为另一个节点,我们就会使用所有核心(一半在一个应用程序上,一半在另一个应用程序上)。似乎不可能将应用程序分配给所有核心。
现在,这台机器和我习惯使用的机器之间的唯一区别是,Windows 的任务管理器在下拉列表中列出了节点,而不是一长串单独的核心,因此微软知道这个限制是什么,但这是一个很难在线研究的问题。
很明显,我们必须开发 NUMA 节点亲和性,但现在我正在尝试理解这个问题。什么会导致一种类型的 NUMA 机器允许应用程序透明地使用两个节点,现在又是什么导致了这种行为?
我可以看到这种架构对于许多小型应用程序来说运行良好,但我们通常运行具有许多线程的单片应用程序。
我正在使用的服务器是带有两个 Intel Xeon E5-2690V3 CPU 的 HP Proliant DL388Gen9。
思考一下这是什么原因造成的?
答案1
一个进程只能分配给一个 NUMA 节点。这是简短的回答。您不能强制单个实例在多个 NUMA 节点上运行。考虑到 NUMA 的用途,以及在使用 64 位 CPU 亲和性位掩码的操作系统上允许超过 64 个 CPU 核心的次要用途,这是有道理的。
答案2
我不是这个问题的专家,但我会发表我的意见。
很明显,我们必须开发 NUMA 节点亲和性,但现在我正在尝试理解这个问题。什么会导致一种类型的 NUMA 机器允许应用程序透明地使用两个节点,现在又是什么导致了这种行为?
我知道 Windows 会计算“节点距离”,估算各个 NUMA 节点相互通信所需的时间。我不知道它是基于延迟还是带宽(或者两者兼而有之),但了解这一点很重要。
现代机器(例如 Skylake-Server)可以具有“SubNuma Clustering”,其中同一芯片的不同部分被报告为不同的 NUMA 节点。但是,同一芯片内的节点之间的差异约为 10 纳秒。而不同插槽的差异可能约为 200 纳秒。
例如:两个 Xeon Gold(每个 CPU 20 个内核)开启 sub-NUMA 集群后,在 Windows 看来就像 4x NUMA 节点。每个芯片有 2 个 NUMA 节点,分别代表芯片两半上的“左”10 个内核和“右”10 个内核。左侧有 3 个内存控制器,右侧有 3 个内存控制器。但所有 20 个内核都可以在约 80 纳秒内与任一内存控制器通信。它们只需 70 纳秒即可与“较近”的内存控制器通信。几乎察觉不到差异,因此 Windows 可能更喜欢在这两个 NUMA 节点之间浮动线程。
我的假设是,在您的设置的默认设置下,Windows 已确定一个“节点距离”足够短以使线程浮动,而另一个设置的内存距离足够长,以至于 Windows 的默认设置倾向于将线程保持在 NUMA 节点内。
这不是我唯一的理论。我的第二个理论是“处理器组”出了点问题。处理器组是 Win32 API 的一个肮脏的兼容性黑客,因为出于性能原因,CPU 亲和性掩码已被限制为 64 位。因此,64 个逻辑核心是 Windows 的最大默认值。
您可以通过处理器组 API 访问超过 64 个逻辑核心。 https://msdn.microsoft.com/en-us/library/windows/desktop/dd405503(v=vs.85).aspx
简而言之:如果您的进程位于单独的“处理器组”上,您将需要程序员更改程序以支持处理器组。
我个人还没有对这个东西做过太多测试。但希望这些信息对你有用。