如何配置我的多线程 .NET 5 应用程序以使用所有 Windows CPU 组?
我正在尝试将项目从 .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% 的峰值:
现在我需要在不同的 CPU 组之间分配线程。
由于本文档指出该变量在 runtimeconfig.json
中不适用,并且必须设置为环境变量。
根据 尝试在 .Net Core 应用程序中使用 Thread_UseAllCpuGroups 这仅在命令行设置时有效,但我尝试了多种设置方法:
- CommandLine 使用
set COMPlus_Thread_UseAllCpuGroups=1
在运行我的程序之前。 - 通过
控制面板 -> 设置变量系统与安全->系统->环境变量
。 - 使用变量定义一个
launchSetting.json
文件并将其复制到输出目录。 - 使用
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:
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:
- CommandLine using
set COMPlus_Thread_UseAllCpuGroups=1
before running my program. - Setting the variable though
Control Panel -> System and Security -> System -> Environment Variables
. - Defining a
launchSetting.json
-file with the variable and copying it to the output directory. - Manually setting the variable in my
program.fs
-file usingSystem.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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
@Hobitten:虽然我更喜欢旧的 Thread_UseAllCpuGroups ,但我创建了一个入门批处理文件(我发现它真的很愚蠢!!!)。也许这有帮助。我使用不同大小写的原因只是因为我不(并且仍然不)知道环境变量是否区分大小写。
@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.