我在运行64位Windows Server 2008 R2 Enterprise的服务器上测试一个程序,它有4个Intel E7-4870处理器,总共40个内核和80个可用线程(我可以看到80个CPU使用率图表) 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%。是否有与此相关的编译器设置?
答案 0 :(得分:9)
根据工作类型,hyper threading并不总是有帮助。对于许多类型的纯数学运算,每个核心只能有效地处理一个工作项,而不是处理器“线程计数”所建议的2个。
超线程实际上不是单独的内核,因此在它们上运行的指令并不总能带来收益。这是discussed here:
根据群集配置,最重要的是,群集上运行的应用程序的性质,性能提升可能会有所不同甚至是负面的。下一步是使用性能工具来了解哪些方面有助于提高性能以及哪些方面会导致性能下降。
在最佳情况中,超线程往往会导致整体性能提升约30%。为此,您通常需要不同的CPU指令来推动核心上的每个线程,因此核心可以正常执行工作。在许多超线程“CPU线程”中并行运行相同的计算时,您通常会发现每个核心运行一个进程没有优势。
这也可能是因为您使用托管代码,因为CLR不使用Windows 2008 R2中的新NUMA指令,因此将限制为处理器组0。因此,如果您的系统已设置为处理器组0为40个处理器,而另外40个处理器组分为处理器组1,则可能会使此过程使整个第一个处理器组饱和。有关详细信息,请参阅How to Get Started with Multi-Core: Parallel Processing You Can Use。