9

我有一些关于多线程编程和多核使用的问题。

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

这是我关于线程的问题:

  • 当产生一个新线程时,将线程分配给特定核心的算法是什么?
    1. 循环算法类型
    2. 随机的
    3. 目前使用最少的核心
  • 如果不是当前使用最少的核心,那么确定这种类型的代码是否会使线程的典型使用相形见绌,从而使事情变得更糟?
  • 线程在其生命周期内是否从一个核心移动到另一个核心?如果是这样,这是为了处理由于某种原因被“过度使用”的内核,因此操作系统会尝试将线程转移到使用较少的内核以帮助系统?如果不是,再次,为什么不呢?

我的最后一个问题,基本上是对上述内容的重用,是关于 .NET ThreadPool 类的,它处理诸如 .BeginInvoke 之类的事情。这门课做这些事情吗?如果不是,为什么不,或者应该这样做?

有什么办法可以调整这种处理方式,在操作系统中暗示这个特定线程,当你给它分配一个内核时请多加注意,因为我知道它会使用很多 cpu。这有意义吗?或者“很多cpu”只是相对的,因此还不够好?

4

2 回答 2

18

当产生一个新线程时,将线程分配给特定核心的算法是什么?

这完全取决于操作系统。答案通常是经过大量修改的循环方案。每 x 毫秒,一个核心被中断,并在其上放置一个新线程(因此没有“最少使用的核心”。只要有线程准备好运行,每个核心都会有事可做)。

在 Windows 中,我相信总是选择优先级最高的线程/进程来执行。(因此,如果您有一个进程在单核系统上以高优先级运行,该进程可能会在 100% 的时间内运行,从而使所有其他进程都处于饥饿状态。当然,这仅适用于该进程永不阻塞的情况,这在现实中。

当然,因为像 Windows 这样的现代操作系统很复杂,所以它还有很多其他功能。某些进程有时会得到优先处理,但根据经验,Windows 总是会选择高优先级进程(这就是为什么你可以通过在单核时代给予进程“实时”优先级来几乎冻结你的计算机)

在 Linux 下,优先级较低的进程也会定期调度,只是不那么频繁。

但是你能做的最好的通常是假设操作系统会制定一个公平的方案,然后尝试与系统的其余部分配合得很好。(当你无事可做时让/阻塞/睡眠,允许其他线程运行)。

线程在其生命周期内是否从一个核心移动到另一个核心?

当然。假设您在双核系统上运行三个线程。向我展示一个不涉及在内核之间定期移动线程的公平时间表。

我的最后一个问题,基本上是对上述内容的重用,是关于 .NET ThreadPool 类的,它处理诸如 .BeginInvoke 之类的事情。这门课做这些事情吗?如果不是,为什么不,或者应该这样做?什么东西?线程调度和选择要运行的内核?不,线程池只是一种将线程重用于多个任务的机制,而不是必须为每个任务创建一个新线程,然后再关闭它。

有什么方法可以调整这种处理方式,在操作系统中暗示这个特定线程

这就是线程/进程优先级的用途。如果您的线程必须获得大量 CPU 时间,即使有其他 CPU 密集型线程正在运行,请提高线程的优先级。但要小心处理。通常,运行的 CPU 密集型线程并不多,这意味着即使在正常优先级下,您也将获得 99.9% 的 CPU 时间。正如我所说,Windows 会非常积极地调度优先级更高的线程,所以只有在你真的认真时才提高优先级。

于 2008-12-28T13:14:01.227 回答
6

除了 jalf 出色而全面的答案,请记住,“并行扩展”(应该被纳入 .NET 4.0)有很多代码专门用于将工作(从队列)均匀地分配给核心,包括工作窃取,以及潜在的掘金喜欢关心哪个核心与工作所在的内存“最接近”。

因此,使用 .NET 4.0,使用诸如此类的东西Parallel.For,您应该可以免费获得很多。总的来说,操作系统足够聪明,只能从局外人的角度来看。jalf 给出了很多关于幕后发生的事情的细节,但大多数时候你不需要这个级别的细节,除非你正在用高线程代码解决一些性能问题。

于 2008-12-28T13:25:06.930 回答