为什么我的.Net应用程序只使用单个NUMA节点

本文关键字:单个 NUMA 节点 我的 Net 应用程序 为什么 | 更新日期: 2023-09-27 18:29:49

我有一个服务器,它有2个NUMA节点,每个节点有16个CPU。我可以看到任务管理器中的所有32个CPU,前2行中的前16个(NUMA节点1)和最后2行中接下来的16个(NUMA节点2)。

在我的应用程序中,我使用Thread.Start()启动了64个线程。当我运行该应用程序时,它占用了大量的CPU,只有前16个CPU繁忙,其他16个CPU空闲。

为什么?我经常使用Interlocked.Increment()。这可能是一个原因吗?有没有一种方法可以在特定的NUMA节点上启动线程?

为什么我的.Net应用程序只使用单个NUMA节点

除了gcserver,我们还应该启用GCCpuGroupThread_UseAllCpuGroups,因此配置应该更像:

<configuration
   <runtime>
      <gcServer enabled="true"/>
      <GCCpuGroup  enabled="true"/>
      <Thread_UseAllCpuGroups  enabled="true"/>
   </runtime>
</configuration>

GcCpuGroup为多个CPU组启用垃圾回收,Thread_UseAllCpuGroups为运行时管理跨所有CPU组的线程分布。

首先要检查的是app.config,确保设置了必要的选项:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <runtime>
        <gcServer enabled="true" />
        <Thread_UseAllCpuGroups enabled="true" />
        <GCCpuGroup enabled="true" />
    </runtime>
    <startup> 
        <!-- 4.5 and later should work, use the one targeted -->
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>       
    </startup>
</configuration>

如果app.config-Wizadry没有帮助,很可能您的机器在不应该使用多个内核组(Kgroup)的时候使用了多个内核。如果您有Gen9 HP,则可以检查BIOS中的NUMA Group Size Optimization。如果处于Clustered模式,则当前CLR(2017,.net 4.6.2)仅使用第一个CLR。如果该机器中的核心不超过64个,则应该可以选择将所有核心放在同一组中的Flat布局。如果找不到,则可能需要BIOS更新。

有关更多详细信息,请参阅StackOverflow上的"无法在C#应用程序中为线程使用多个处理器组"。它甚至自带诊断工具。

是否已将垃圾收集器设置为服务器版本?

在app.config中,尝试:

<configuration
   <runtime>
      <gcServer enabled="true"/>
   </runtime>
</configuration>

由于堆的分配方式,服务器GC在具有多个核心的机器中的多个线程上搅拌大量对象/数据时会产生巨大的差异。