Multi-core使用、线程、线程池

9

我对多线程编程和多核使用有一些疑问。

特别是我想知道操作系统和/或框架(这是.NET)如何处理被大量使用的核心。

以下是关于线程的问题:

  • 当新线程生成时,将该线程分配到特定核心的算法是什么?
    1. 轮换算法
    2. 随机算法
    3. 目前最少使用的核心
  • 如果不是目前最少使用的核心,那么决定这个核心的代码是否会使线程的典型使用变得更糟,从而使情况变得更糟?
  • 线程在其生命周期内是否移动到另一个核心?如果是,这是为了处理某些原因超负荷使用的核心,因此操作系统尝试将线程转移到使用较少的核心以帮助系统吗?如果没有,为什么?

我的最后一个问题,基本上是上面的重复利用,是关于.NET ThreadPool类的,它处理像.BeginInvoke之类的东西。这个类做这些事情吗?如果不是,为什么不应该这样做,或者应该吗?

有没有办法调整这种处理方式,就像提示操作系统,这个特定的线程,请在分配核心时多加注意,因为我知道它将使用大量CPU。这是有意义的吗?或者“很多的CPU”只是相对的,因此不太好?

2个回答

18
当一个新线程被创建时,将其分配给特定核心的算法完全取决于操作系统。通常采用的是一种经过大量修改的轮询方案。每隔x毫秒,一个核心会被中断,然后放置一个新线程在上面(所以没有“最少使用的核心”。只要有准备好运行的线程,每个核心都会有任务执行)。在Windows中,我认为选择执行最高优先级的线程/进程是始终如一的。因此,在单核系统上运行高优先级的一个进程将潜在地占用100%的时间,使得所有其他进程处于饥饿状态。当然,这仅适用于该进程从不阻塞,而这在现实世界中是不太可能的。当然,因为像Windows这样的现代操作系统非常复杂,其中还有很多内容。某些进程会不时获得优先处理,但作为一个经验法则,Windows始终会选择高优先级的进程(这就是为什么您可以通过为进程提供“实时”优先级来几乎冻结计算机的原因)。在Linux下,低优先级的进程也会定期进行调度,只是不会像高优先级的进程那么频繁。但你能做的最好的事情通常就是假设操作系统会解决公平的方案,然后尝试与系统的其他部分友好相处(当你没有任务可执行时,让出/阻塞/休眠,允许其他线程运行)。
当线程在其生命周期内从一个核心移动到另一个核心是很常见的。例如,在双核系统上运行三个线程,展示一个不涉及定期在核心之间移动线程的公平调度计划是很困难的。
至于.NET ThreadPool类,它处理像.BeginInvoke这样的事情。这个类是否会做这些事情?如果不是,为什么不这样做,或者应该这样做吗?什么东西?线程调度和选择核心运行?不是的,线程池只是一种机制,可以重复使用线程来执行多个任务,而不必为每个单独的任务创建一个新线程,然后在完成后关闭它。

是否有任何方法可以调整这个处理方式,就像向操作系统提示特定的线程一样?

这就是线程/进程优先级的作用。如果您有一个必须获得大量CPU时间的线程,即使有其他耗费CPU的线程正在运行,也可以提高该线程的优先级。但要小心处理。通常情况下,没有很多耗费CPU的线程在运行,这意味着即使以正常优先级运行,您也将获得99.9%的CPU时间。正如我所说,Windows会非常积极地调度更高优先级的线程,因此只有在确实需要时才提高优先级。


2
据我所了解,Windows 使用一种退化抢占式优先级调度程序;高优先级线程会暂时下降优先级,以防止它们完全饿死低优先级线程。 - Lawrence Dol
此外,Windows的调度程序似乎在防止相同优先级线程被同一优先级的其他线程饿死方面做得更好。 - Lawrence Dol
1
@Software Monkey - 我认为情况恰恰相反。Windows会增强被饥饿的线程,而Linux采取了你所描述的方法。 - Mick

6
除了jalf的出色和全面的答案之外,还要注意“Parallel Extensions”(应该合并到.NET 4.0中)有很多代码专门用于将工作(从队列中)均匀地分配给核心,包括工作窃取,并且可能会关心哪个核心“最接近”工作所在的内存等方面。
因此,在使用像Parallel.For等东西时,您应该免费获得很多内容。而且一般来说,操作系统足够聪明,从外部视图上看它就能正常工作。jalf已经提供了许多底层细节,但大多数情况下,您不需要这种详细级别,除非您正在解决高度线程化代码的性能问题。

我知道,但是4.0在未来几年内不在我们的计划之内,转换客户、规划升级等需要时间,所以我们不能在发布时立即跳跃。PFX也会为3.5发布吗? - Lasse V. Karlsen
1
CTP已经发布,表明它可以针对CLR 2.0工作。但是我并不确定。 - Marc Gravell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接