【问题标题】:The relationship between cores and the number of threads I can spawn核心与我可以生成的线程数之间的关系
【发布时间】:2009-08-03 22:50:49
【问题描述】:

我有一个 Intel 四核 CPU。

如果我要开发一个只能在我的机器上使用的 Winforms 应用程序(我使用 C# 顺便说一句),我可以生成多少个线程?

内核与我可以在任何时候运行的最大线程数之间是否存在某种关联?我是否需要找出任何时候有多少线程正在运行,如果是这样,这可能吗? (我知道有最小和最大线程之类的属性)?这是否取决于线程池(此池中的最大线程数是否改变?)。这是这篇文章/线程的 C# 部分。

【问题讨论】:

  • 您希望生成多少线程?如果您完全关心任何类型的限制,那么您可能有太多了。
  • 我没有生成任何。这是假设的,而且是为了未来(我很好奇和好奇,我问的很多问题都与我正在做的任何当前开发无关)。我想知道理论。

标签: c# multithreading concurrency hardware


【解决方案1】:

这一切取决于,如果您的线程在 100% 的时间内都处于活动状态(而不是等待 IO),那么每个 CPU 拥有 1 个以上的线程就没有意义了。但是,除非您执行复杂的数值计算,否则这种情况很少发生。

.Nets 线程池有:http://msdn.microsoft.com/en-us/library/system.threading.threadpool.aspx

线程池的默认大小为 每个可用 250 个工作线程 处理器和 1000 I/O 完成 线程。

所以,我想说,除了:

  • 测量测量测量。

由于上下文切换和同步,当您添加更多线程时,事情会变慢

【讨论】:

  • +1 找到线程的最佳位置必须是有史以来最简单的分析任务之一。您只需在大多数消费者机器上尝试大约 20 个数据点即可看到非常明显的趋势,通常 10 个就足够了。因为这个数字将完全取决于线程正在做什么以及系统所有组件的规格,它确实是唯一的方法。
【解决方案2】:

必须衡量。也就是说,对于 N 个内核,我通常通过在 N+12N 个线程之间产生最好的结果。但你必须衡量。

【讨论】:

    【解决方案3】:

    虽然线程和内核之间存在松散的相关性(线程真正并发执行的唯一方法是让它们在单独的内核上运行,但这些知识的价值比您想象的要低),真正的工作是由操作系统调度程序完成,在本例中为 Windows 中的线程调度程序。

    至于您可以创建多少线程,这将因系统而异。 ThreadPool 类对生成自己的线程没有任何限制;它有一个内部管理的线程池。这些是您在检查 ThreadPool 类的属性时可以看到的值。然而,这并不是说你应该产生无限的线程。最终,操作系统将花费更多的时间在线程之间切换,而不是实际允许线程运行。通过基准测试找出适合您的应用程序的线程数。

    你到底想做什么?

    【讨论】:

      【解决方案4】:

      我可以生成多少个线程?

      哇,比您想要产生的最佳吞吐量要多(数百或数千倍)。

      我知道的每个线程的限制(在 Windows 上)是:

      • 16 位线程 ID
      • 为用户空间堆栈分配 4-8KB(通常更多)
      • 不可分页的内核空间上下文和堆栈,大约 16KB

      Dotnet 可能会为它自己的东西增加一堆每个线程的开销。 GC之类的。

      我喜欢用于 WAG 的一个公式是:

      threads = 2 * (cpu cores + active disk spindles)
      

      最佳数量通常在其两倍的范围内。其中。理论是所需的线程与 cpu 核心成比例(出于显而易见的原因),但也有一些线程会阻塞磁盘 I/O。当其他线程被阻塞时,乘以 2 可以让 CPU 做一些事情。

      无论如何,从它开始并衡量它。工作线程的数量是整个问题中最容易调整的部分,所以现在不用太担心。

      【讨论】:

        【解决方案5】:

        只是想知道启动多个线程会首先达到什么限制。我编写了以下简单的测试程序并尝试了它。现在我假设内存是限制因素。我能够运行 1000 个线程,但没有 Thread.Sleep() 系统变得“有点反应迟钝”。使用 2000 个线程后,我在启动大约 1800 个线程后出现内存不足异常。 (配备 Intel Core 2 Duo T5800 2.0 GHz、3.0 GiB RAM 和“少数”应用程序的笔记本电脑在带有 .NET Framework 3.5 SP1 的 WIndows XP SP3 上运行)

        更新

        内存不足异常是由线程堆栈引起的。在线程构造函数上指定堆栈大小后(我使用了 64 kB,但可能是我目前不知道的最小大小)我能够启动 3500 个线程(使用Thread.Sleep())。

        using System;
        using System.Linq;
        using System.Threading;
        
        namespace GeneralTestApplication
        {
            class Program
            {
                private static void Main()
                {
                    Console.WriteLine("Enter the number of threads to start.");
        
                    while (!Int32.TryParse(Console.ReadLine(), out Program.numberThreads)) { }
        
                    Program.counters = new Int64[Program.numberThreads];
        
                    Console.WriteLine("Starting {0} threads.", Program.numberThreads);
        
                    for (Int32 threadNumber = 0; threadNumber < Program.numberThreads; threadNumber++)
                    {
                        new Thread(Program.ThreadMethod).Start(threadNumber);
                    }
        
                    Console.WriteLine("Press enter to perform work on all threads.");
                    Console.ReadLine();
        
                    Program.manualResetEvent.Set();
        
                    Console.WriteLine("Press enter to stop all threads.");
                    Console.ReadLine();
        
                    Program.stop = true;
        
                    Console.WriteLine("At least {0} threads ran.", Program.counters.Count(c => c > 0));
        
                    Console.ReadLine();
                }
        
                private static Int32 numberThreads = 0;
                private static Int64[] counters = null;
                private static readonly ManualResetEvent manualResetEvent = new ManualResetEvent(false);
                private static volatile Boolean stop = false;
        
                public static void ThreadMethod(Object argument)
                {
                    Int32 threadNumber = (Int32)argument;
        
                    Program.manualResetEvent.WaitOne();
        
                    while (!Program.stop)
                    {
                        Program.counters[threadNumber]++;
        
                        // Uncomment to simulate heavy work.
                        Thread.Sleep(10);
                    }
                }
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-12-11
          • 2021-05-10
          • 1970-01-01
          • 2014-01-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多