如何配置我的多线程 .NET 5 应用程序以使用所有 Windows CPU 组?

发布于 2025-01-11 06:32:03 字数 2938 浏览 0 评论 0原文

我正在尝试将项目从 .NET Framework 4.7.2 迁移到 .NET 5,但我的程序的性能显着下降。该程序的部分内容利用并行性在具有 96 个内核和 192 个逻辑处理器(分布在 4 个 CPU 组)的服务器上进行批量操作。

我在安装了 .NET 5 Runtime(未安装 .NET 5 SDK)的 Windows Server 2016 上运行该程序。该项目是用 F# 5.0 编写的。

在 .NET Framework 4.7.2 中,我们使用了以下 app.config 文件,该文件成功地使程序在所有 192 个逻辑处理器上运行,实现了约 98% 的 CPU 利用率:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <runtime>
        <Thread_UseAllCpuGroups enabled="true" />
        <GCCpuGroup enabled="true" />
        <gcServer enabled="true" />
        <gcAllowVeryLargeObjects enabled="true" />
    </runtime>
</configuration>

迁移到 .NET 5 后(并且通过扩展.NET Core)CPU 利用率下降,并且我无法再次提高它。

根据 微软自己的文档 app.config 不用于配置 .NET Core 项目,而是由 [appname].runtimeconfig.json 代替。为了适应这一变化,我在我的项目中添加了一个 runtimeconfig.template.json

{
  "configProperties": {
    "System.GC.CpuGroup": true,
    "System.GC.Server": true,
    "COMPlus_gcAllowVeryLargeObjects": 1
  }
}

这会生成以下 [appname].runtimeconfig.json 文件:

{
  "runtimeOptions": {
    "tfm": "net5.0",
    "framework": {
      "name": "Microsoft.NETCore.App",
      "version": "5.0.0"
    },
    "configProperties": {
      "System.GC.CpuGroup": true,
      "System.GC.Server": true,
      "COMPlus_gcAllowVeryLargeObjects": 1
    }
  }
}

属性 System.GC.CpuGroup 似乎有效,通过将线程分布在单个 CPU 组上,CPU 利用率达到约 28% 的峰值:

Windows 任务管理器的屏幕截图,显示 192 个逻辑处理器中的 48 个逻辑处理器利用率为 100%,总体利用率为 28%< /a>

现在我需要在不同的 CPU 组之间分配线程。

由于本文档指出该变量在 runtimeconfig.json 中不适用,并且必须设置为环境变量

根据 尝试在 .Net Core 应用程序中使用 Thread_UseAllCpuGroups 这仅在命令行设置时有效,但我尝试了多种设置方法:

  1. CommandLine 使用 set COMPlus_Thread_UseAllCpuGroups=1在运行我的程序之前。
  2. 通过控制面板 -> 设置变量系统与安全->系统->环境变量
  3. 使用变量定义一个 launchSetting.json 文件并将其复制到输出目录。
  4. 使用 System.Environment.SetEnvironmentVariable("COMPlus_Thread_UseAllCpuGroups", "1") 在我的 program.fs 文件中手动设置变量。

上述方法都不起作用,我不确定我做错了什么,特别是考虑到我在网上找到的关于这个问题的帖子很少。

最后我的问题是:如何使我的 .NET 5 控制台应用程序利用我的所有逻辑处理器?

编辑:我已尝试将项目提升到 .NET 6 和 F# 6,但问题仍然存在。

I'm trying to migrate a project from .NET Framework 4.7.2 to .NET 5, but the performance of my program has dropped significantly. Parts of the program exploit parallelism for bulk operations on a server with 96 Cores and 192 Logical processors split across 4 CPU groups.

I'm running the program on a Windows Server 2016 with the .NET 5 Runtime installed (.NET 5 SDK not installed). The project is written in F# 5.0.

In .NET Framework 4.7.2 we used the following app.config-file which successfully made the program run across all 192 Logical processors, achieving ~98% CPU utilization:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <runtime>
        <Thread_UseAllCpuGroups enabled="true" />
        <GCCpuGroup enabled="true" />
        <gcServer enabled="true" />
        <gcAllowVeryLargeObjects enabled="true" />
    </runtime>
</configuration>

After migrating to .NET 5 (and by extension .NET Core) the CPU utilization dropped, and I am having trouble increasing it again.

According to Microsoft's own documentation app.config is not used to configure .NET Core projects, replaced by [appname].runtimeconfig.json. To accommodate this change i have added a runtimeconfig.template.json to my project:

{
  "configProperties": {
    "System.GC.CpuGroup": true,
    "System.GC.Server": true,
    "COMPlus_gcAllowVeryLargeObjects": 1
  }
}

This produces the following [appname].runtimeconfig.json-file:

{
  "runtimeOptions": {
    "tfm": "net5.0",
    "framework": {
      "name": "Microsoft.NETCore.App",
      "version": "5.0.0"
    },
    "configProperties": {
      "System.GC.CpuGroup": true,
      "System.GC.Server": true,
      "COMPlus_gcAllowVeryLargeObjects": 1
    }
  }
}

The property System.GC.CpuGroup seems to work, giving me a peak of ~28% CPU utilization by distributing threads across a single CPU Group:

Screenshot of Windows Task Manager showing 100% utilization of 48 of 192 logical processors for an overall utilization of 28%

Now I need to distribute threads across different CPU Groups.

Thread_UseAllCpuGroups was omitted due to this documentation saying the variable is N/A in runtimeconfig.json, and must be set as an environment variable.

According to Trying to use Thread_UseAllCpuGroups in a .Net Core app this only works when set at the command line, but i have tried multiple ways of setting it:

  1. CommandLine using set COMPlus_Thread_UseAllCpuGroups=1 before running my program.
  2. Setting the variable though Control Panel -> System and Security -> System -> Environment Variables.
  3. Defining a launchSetting.json-file with the variable and copying it to the output directory.
  4. Manually setting the variable in my program.fs-file using System.Environment.SetEnvironmentVariable("COMPlus_Thread_UseAllCpuGroups", "1").

None of the above methods have worked, and I am unsure what I am doing wrong, especially given how few posts I can find online on this issue.

Finally my question is: How do I make my .NET 5 console application utilize all my logical processors?

Edit: I've tried lifting the project to .NET 6 and F# 6, but the problem still remains.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

过期情话 2025-01-18 06:32:03

@Hobitten:虽然我更喜欢旧的 Thread_UseAllCpuGroups ,但我创建了一个入门批处理文件(我发现它真的很愚蠢!!!)。也许这有帮助。我使用不同大小写的原因只是因为我不(并且仍然不)知道环境变量是否区分大小写。

set complus_GCCpuGroup=1
set COMPlus_GCCpuGroup=1
set COMPlus_Thread_UseAllCpuGroups=1

set DOTNET_GCCpuGroup=1
set DOTNET_Thread_UseAllCpuGroups=1

call <yourexe>

@Hobitten: Although I would prefer the old Thread_UseAllCpuGroups , I created a starter batch file (which I find really stupid!!!). Maybe this helps. The reason why I use the difference cases is only because I didn't (and still don't) know if the enevironment vars a case sensitive.

set complus_GCCpuGroup=1
set COMPlus_GCCpuGroup=1
set COMPlus_Thread_UseAllCpuGroups=1

set DOTNET_GCCpuGroup=1
set DOTNET_Thread_UseAllCpuGroups=1

call <yourexe>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文