SMP核心、进程和线程是如何精确协同工作的?

56

在单核CPU上,每个进程都在操作系统中运行,CPU会在不同的进程间跳转以最大程度地利用自身。一个进程可以有多个线程,在这种情况下,当CPU运行在相应的进程上时,它会依次运行这些线程。

现在,在多核CPU上:

  • 多个核心是否会同时运行每个进程,或者在某一特定时间点,多个核心是否可以分别在不同的进程中运行?例如,您运行了一个包含两个线程的程序A。双核CPU能否同时运行该程序的两个线程?如果我们使用类似 OpenMP 之类的东西,我认为答案应该是肯定的。但是,在运行此OpenMP嵌入式进程时,其中一个核心是否可以简单地切换到其他进程?

  • 对于为单核设计的程序,在运行到100%时,为什么每个核心的CPU利用率分布不均?(例如80%和20%的双核CPU。在这种情况下,所有核心的利用率百分比总和始终为100%。)是不是每个核心都试图通过以某种方式运行每个进程的每个线程来互相帮助?


3
硬件工作的最简示例:https://dev59.com/jXNA5IYBdhLWcg3wZ81R#33651438 - Ciro Santilli OurBigBook.com
5个回答

53

核心(或 CPU)是计算机的物理元素,用于执行代码。通常,每个核心都具有执行计算、寄存器文件、中断线等必要元素。

大多数操作系统将应用程序表示为进程。这意味着应用程序具有自己的地址空间(即内存视图),其中操作系统确保该视图及其内容与其他应用程序隔离。

一个进程由一个或多个线程组成,通过在 CPU 上执行机器代码来执行应用程序的实际工作。操作系统确定哪个线程在哪个 CPU 上执行(通过使用聪明的启发式算法以提高负载平衡、能源消耗等)。如果您的应用程序仅包含单个线程,则整个多 CPU 系统对您的应用程序帮助不大,因为它仍然只使用一个 CPU 来运行您的应用程序。(但是,总体性能仍可能提高,因为操作系统会在其他 CPU 上运行其他应用程序,以使它们不会与第一个应用程序混在一起)。

现在回答您的具体问题:

1)操作系统通常至少允许您提示要在哪个核心上执行某些线程。OpenMP 所做的就是生成代码,生成一定数量的线程以将程序循环的共享计算工作分配给多个线程。它可以使用操作系统的提示机制(请参阅:线程亲和力)来实现此目的。 然而,OpenMP 应用程序仍将与其他应用程序同时运行,因此操作系统可以自由地中断其中一个线程并计划在 CPU 上执行其他(可能不相关的)工作。 实际上,您可能想要应用许多不同的调度方案,具体取决于您的情况,但这是高度特定的,并且大多数时候您应该能够信任您的操作系统为您做正确的事情。

2)即使在多核 CPU 上运行单线程应用程序,您也会注意到其他 CPU 也在执行工作。这是因为 a)操作系统在此期间执行其工作,以及 b)事实是您的应用程序永远不会单独运行 - 每个运行的系统都由一整组并发执行的任务组成。检查 Windows 的任务管理器(或 Linux 上的 ps/top)以查看正在运行的内容。


13

注意,操作系统并不在意线程来自哪个进程。它通常会将线程调度到处理器/核心上,而不考虑线程来自哪个进程。这可能会导致来自一个进程的四个线程同时运行,就像来自四个进程的一个线程同时运行一样。


这实际上取决于调度方案。某些方案,例如团队调度(http://en.wikipedia.org/wiki/Gang_scheduling),确实包含哪些线程应该在一起的信息。 - BjoernD
得到了我想要的答案..非常简洁 - FatherMathew

10

@BjoernD,您提到…

.. 如果您的应用程序仅由单个线程组成,那么整个多CPU系统对您的帮助不大,因为它仍然只会为您的应用程序使用一个CPU...

我认为即使是单线程应用程序,在其生命周期内该应用程序线程也可能在不同的核上执行。每次抢占和稍后分配到CPU时,都可能将不同的核分配给该线程。


2
挑剔但正确 :) 但很遗憾,系统仍然无法分离您的进程工作... - Tomáš Zato
是的,这比单核系统更糟糕,因为新核心上的缓存在虚假迁移后会变得冷。 (当然,如果有其他后台任务,它们可以安排在其他核心上,而不是从单线程程序中窃取周期)。 无论如何,这是一个无意义的争论; BjoernD显然是指“一次只能使用一个CPU”。 - Peter Cordes

7
是的,线程和进程可以在多核CPU上并发运行,因此它按照您描述的方式工作(无论如何创建这些线程和进程,包括OpenMP或其他方式)。单个进程或线程一次只能在一个核心上运行。如果有更多的线程请求CPU时间而可用核心不足(通常情况),操作系统调度程序将根据需要将线程移动到核心上。
单线程进程在多个CPU或核心上运行的原因与您的操作系统有关,而不是硬件的特定功能。某些操作系统没有“线程亲和性”的概念-它们不关心线程正在哪个处理器上运行-因此当重新评估正在使用的资源时(至少每秒数次),它们将从一个核心/CPU移动线程/进程到另一个核心/CPU。除了导致缓存未命中外,这通常不会影响您的进程性能。

0
如果有一个只有一个线程应用程序,它有10个线程,最初它将在同一CPU/核心上启动。随着时间的推移,由于Linux中的负载平衡器,多个线程将分布到其他核心/ CPU上。如果有多个这样的线程应用程序,我认为所有应用程序线程大多在同一个核心/ CPU上运行,因为线程的本地/全局变量在它们运行的核心的L1 / L2缓存中很容易获得。将它们移出核心比执行时间更耗时。如果需要在不同的核心上运行线程,我认为必须向线程提供亲和力信息。

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