不能使用 CPU 中总可用线程的一半以上
Posted
技术标签:
【中文标题】不能使用 CPU 中总可用线程的一半以上【英文标题】:Cannot use more than half of total available thread in CPU 【发布时间】:2013-08-30 16:06:49 【问题描述】:我正在运行 64 位 Windows Server 2008 R2 Enterprise 的服务器上测试一个程序,它有 4 个 Intel E7-4870 处理器,总共 40 个内核和 80 个可用线程(我可以在Windows 任务管理器)。
程序代码如下:
numlist is List 包含数百个数字,每个数字都是用于某些计算的参数
Parallel.ForEach(numlist, num =>
// do some calculation using parameter = num
);
问题是当我在服务器上运行这个程序时,只有一半的可用线程显示在 windows 任务管理器中使用(当然 CPU 使用率显示为 50%),其余 40 个完全未使用和闲置。
我还在另一台只有 2 个处理器和总共 24 个可用线程的服务器上测试了相同的程序,所有 24 个线程都将被完全使用,并且 CPU 使用率显示为 100%。
有什么方法可以让 40 核 CPU 服务器运行这个程序并充分利用其所有可用的 80 个线程(或接近 80 个线程)?仅使用 50% 的 CPU 资源时性能不够好。
这是我正在测试的完整程序代码:
namespace Test
internal class Program
private static void Main(string[] args)
Console.WriteLine("Press any key to start");
Console.ReadLine();
List<int> numlist = new List<int>();
for (int i = 0; i < 100; i++)
numlist.Add(i);
Parallel.ForEach(numlist, num =>
while (true)
num++;
);
在有 2 个 Intel X5690 处理器(总共 24 个线程可用)的服务器上运行时,所有 24 个线程都被使用,并且 CPU 使用率显示为 100%;
但是当我在有 80 个可用线程的 4 处理器服务器上运行它时,只使用了 40 个线程,CPU 使用率只有 50%。有没有与此相关的编译器设置?
【问题讨论】:
你确定你有超过 40 个号码吗?这里确实没有太多信息,很难找出问题所在。 是的,为了组成numlist,我把这段代码放在并行循环之前: ListParalellOptions
中使用MaxDegreeOfParallelism
我试过了,MaxDegreeOfParallelism 没有帮助。我什至创建了两个Task对象,每个都包含一个parallel.foreach循环,并在程序内部同时启动两个任务。 CPU 使用率仍然是 50%,并且只使用了一半的线程。
澄清一下,我发现这个问题的原因是,我正在写一个大型的windows服务系统,并行循环内部有复杂的业务逻辑。我在不同的服务器上测试了该服务并发现了这个问题。于是就写了上面的小测试。从测试结果来看,这个问题似乎与并行循环内部的内容无关,只是c#编译器自己确定“40核80线程对于单个exe进程来说太多了”。
【参考方案1】:
根据工作类型,hyper threading 并不总是有帮助。对于许多类型的纯数学运算,每个内核只能有效处理一个工作项,而不是处理器“线程数”建议的 2 个。
超线程实际上并不是独立的内核,因此在它们上运行的指令并不总能带来收益。这是discussed here:
根据集群配置,最重要的是,根据集群上运行的应用程序的性质,性能提升可能会有所不同,甚至是负面的。下一步是使用性能工具来了解哪些领域有助于提高性能,哪些领域会导致性能下降。
超线程往往会使整体性能提高 30% 左右在最佳情况下。为此,您通常需要通过内核上的每个线程推送不同的 CPU 指令,以便内核可以正常执行工作。当跨多个超线程“CPU 线程”并行运行相同的计算时,您通常会发现与每个内核运行一个进程相比没有任何优势。
这也可能是因为您使用的是托管代码,该代码将仅限于处理器组 0,因为 CLR 不使用 Windows 2008 R2 中的新 NUMA 指令。因此,如果您的系统设置为处理器组 0 为 40 个处理器,而其他 40 个处理器被拆分为处理器组 1,则您可能会用此进程使整个第一个处理器组饱和。详情请见How to Get Started with Multi-Core: Parallel Processing You Can Use。
【讨论】:
是的,我理解这种情况下的性能差异,但我主要关心的是,为什么在 2 处理器 24 线程服务器上,所有线程都被充分利用;但在 4 处理器 80 线程服务器上,只有一半被利用? .Net 编译器“认为”80 个线程对我的程序来说太多了吗? @CMinusGuy 不看你的作品很难判断,但可能是“24线程服务器”是2、12核处理器,而你的“80线程服务器”是4、10核超线程处理器。 @CMinusGuy 刚刚编辑以链接到另一篇文章。在使用托管代码时,您的系统可能将处理器组设置为仅使用 40 个 proc,而不是潜在的 64 个。 如何检查我的系统设置是否与托管代码应使用多少处理器组相关?谢谢! @CMinusGuy 我不认为你可以在托管代码中 - 你需要降到本机,并使用 NUMA 的 API 来查看它是如何设置的。我怀疑这就是问题所在(C# 永远不能使用超过 64 个处理器,但这取决于系统将它们放在一个处理器组中)以上是关于不能使用 CPU 中总可用线程的一半以上的主要内容,如果未能解决你的问题,请参考以下文章