我维护一个 C# 多进程应用程序,它有一个调度程序进程来分配操作,并有其他 N 个工作进程来执行它们。操作是相互独立的,因此每个工作进程不会与其他进程进行通信。数量 N 是可配置的,我将其设置为等于机器 CPU 核心的数量。
问题是:
1 - 如果我通过 ProcessorAffinity 属性将每个进程分配给核心,程序会运行得更快吗?
2 - 如果我有 2 个 NUMA 节点,我需要如何配置工作进程以减少 NUMA 核心组相互访问内存?
我知道操作系统强制进程始终在一个区域中执行,并始终从同一区域分配内存,但我不确定明确添加限制是否会更好。
我不是专家,所以很多其他有更深入知识的人可以补充更多,但我确实有一些经验,所以我会尝试与你分享。
NUMA 灵敏度
首先,我想问一下您是否真的确定您的进程对 NUMA 敏感?
在绝大多数情况下,进程对 NUMA 不敏感,因此任何优化都是毫无意义的。
每个应用程序的运行可能会略有不同,并且始终会受到计算机上运行的其他进程的影响。 因此,您确实需要进行广泛的测试,以表明您的应用程序对 NUMA 敏感,更重要的是,它将产生足够显着的差异,以证明努力适应这一点是合理的。
O/S 调度程序
第二件事是你真的想尝试在程序和代码中控制它吗? 操作系统调度程序做它自己的事情,这通常可能会覆盖您尝试做的事情,或者在它分配或已经分配其他进程到您希望使用的核心时导致其他问题。 不同的 O/S 的行为方式也不同。 因此,如果您的目标是多个操作系统(或不同版本),那么它的行为可能会有所不同。
如果您使用 Kubernetes,这可能会更加复杂,因为实际上有各种版本在野外使用。 例如每个云供应商都有自己的略有更改的版本,其行为可能会或可能不会有所不同。
K8s 甚至可以使用替代调度程序,这也可能会影响这一点,尽管这为您提供了创建自己的调度程序来尝试和控制它的机会。
CPU架构
第三件事是,所有这些都受到您所运行的架构的影响。 Intel Sapphire-rapids 处理器与 Emerald Rapids 不同,AMD Epyc Genoa 与 Turin 不同,任何 AMD 肯定与 Intel 不同。 它们具有不同数量的 NUMA 和子 NUMA,并且工作方式也不同。 并且 O/S 在不同的架构上也有不同的行为。
因此,如果您计划在不同的架构上运行,那么大范围优化就变得非常困难。
我们的经验
我想说的是,我们的系统由超过 200 个单独的 POD 组成,其中只有大约 2 或 3 个对 NUMA 敏感。
每个单独的 POD 的单独资源需求相对较小,这有助于部署并减少 NUMA 问题的可能性。 具有大量资源需求的单个 POD 更有可能出现问题。
因此,我们不会尝试在代码中操作它,而是使用 Scheduler 和 HELM 文件配置来控制 POD 部署。 我们尝试只关注 Kubernetes 的一个版本,并尝试限制 CPU 架构。 通过确保 K8s 以正确的(对我们来说)方式部署 POD,我们可以避免 NUMA 问题,并且我们可以更好地了解应用程序的性能。
我希望这在某种程度上有所帮助。