c# - 在 CPU 中不能使用超过一半的总可用线程

标签 c# multithreading threadpool cpu parallel.foreach

我正在一台运行 64 位 Windows Server 2008 R2 Enterprise 的服务器上测试一个程序,它有 4 个 Intel E7-4870 处理器,总共 40 个内核和 80 个可用线程(我可以在Windows 任务管理器)。

程序代码如下:

numlist 是包含数百个数字的列表,每个数字都是一个参数,用于某些计算

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%。是否有任何与此相关的编译器设置?

最佳答案

根据工作类型,hyper threading并不总是有帮助。对于许多类型的纯数学运算,每个核心只能有效处理一个工作项,而不是处理器“线程数”建议的 2 个。

超线程实际上并不是独立的内核,因此在它们上面运行的指令并不总是会带来 yield 。这是 discussed here :

Depending on the cluster configuration and, most importantly, the nature of the application running on the cluster, performance gains can vary or even be negative. The next step is to use performance tools to understand what areas contribute to performance gains and what areas contribute to performance degradation.

在最好的情况下,超线程往往会使整体性能提高 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 .

关于c# - 在 CPU 中不能使用超过一半的总可用线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18473412/

相关文章:

c# - TFS2010 : Retrieve all changesets associated with a branch (full recursion)

c++ - 删除 std::thread 指针引发异常 "libc++abi.dylib: terminating"

java - 在 Eclipse 中使用 get Thread Alsigned Bytes() 获取编译错误

c# - 使用 ThreadPool 进行垃圾收集

c# - .NET TcpListener Stop 方法在有子进程时不会停止监听器

c# - update panel的asyncpostbacktrigger可以有两个控件ID吗?

c# - 与 Linq to SQL 和存储过程一起使用的通用类或方法?

c++ - 仅读取共享内存时的互斥锁定

objective-c - Objective-C 的 NSMutableArray 是线程安全的吗?

java - 关闭后如何重用ThreadPoolExecutor