3

在具有 2 个物理 x86/amd64 处理器 (P0 + P1) 的 Windows 操作系统中,运行 2 个进程 (A + B),每个进程有两个线程 (T0 + T1),是否可能(甚至常见)看到以下内容:

P0:A:T0同时运行P1:B:T0

然后,在 1(或者是 2?)上下文切换之后(es?)

P0:B:T1同时运行P1:A:T1

简而言之,我想知道 - 在多处理器机器上 - 操作系统是否可以随时从任何进程中调度任何线程,而不管来自其他进程的其他线程已经在运行。

编辑: 为了澄清这个愚蠢的例子,假设进程 A 的线程 A:T0 与处理器 P0(和 A:T1 到 P1)具有亲和力,而进程 B 的线程 B:T0 与处理器 P1 具有亲和力(和 B:T1 到 P0 )。这些处理器是核心还是插槽可能并不重要。

进程上下文切换是否有一流的概念?Perfmon 在 Thread 对象下显示上下文切换,但在 Process 对象下不显示任何内容。

4

2 回答 2

6

是的,这是可能的,而且经常发生。
操作系统尝试不在 CPU 之间切换一个线程(您可以使其更加努力地设置线程首选处理器,或者您甚至可以通过关联将其锁定到单个处理器)。
Windows 的进程本身并不是一个执行单元——从这个角度来看,它基本上只是其线程的上下文。

编辑(进一步说明)

没有什么能比得上“进程上下文切换”。基本上,操作系统调度程序通过(非常自适应的)循环算法将线程分配给任何空闲的处理器/内核(在亲和力允许的情况下),如果“前一个”处理器不能立即可用,无论进程如何(这意味着多线程进程可以窃取更多的 CPU 能力)。

这种“跳跃”可能看起来很昂贵,至少考虑到 L1(有时是 L2)缓存是每个内核的(除了不同的插槽/封装处理器),但它仍然比等待“正确”处理器和无能造成的延迟便宜进行精细的负载平衡(“跳跃”方案使之成为可能)。
可能不适用于 NUMA 体系结构,但涉及更多考虑因素(例如,将所有内存分配调整为线程处理器绑定,并尽可能避免状态/内存共享)。

至于关联性:您可以为每个线程或每个进程设置关联掩码(它取代所有进程的线程设置),但操作系统强制每个线程至少关联一个逻辑处理器(您永远不会以零掩码结束)。

进程的默认关联掩码继承自其父进程(允许您为有问题的遗留可执行文件创建单核加载程序),线程从它们所属的进程继承掩码。

您可能无法将线程关联设置到进程关联之外的处理器,但您可以进一步限制它。

默认情况下,任何线程都会在可用的逻辑处理器之间跳转(特别是如果它产生、调用内核等),即使它有其首选处理器集也可能会跳转,但前提是它必须跳转,但它不会跳转到其关联掩码之外的处理器(这可能会导致相当大的延迟)。

我不确定调度程序是否看到物理处理器和超线程处理器之间的任何差异,但即使没有(我假设),在大多数情况下后果也不值得关注,即应该没有太大区别如果线程数相同,则共享物理或逻辑处理器的多个线程之间。无论如何,在这种情况下,有一些关于缓存抖动的报告,主要是在高性能的多线程应用程序中,例如 SQL Server 或 .NET 和 Java VM,这些应用程序可能会或可能不会从关闭超线程中受益。

于 2010-06-04T11:26:58.890 回答
2

我一般同意前面的答案,但是事情要复杂得多。

尽管进程不是执行单元,但属于同一进程的线程区别对待。这有两个原因:

  1. 相同的地址空间。意味着 - 在此类线程之间切换上下文时,无需设置地址转换寄存器。
  2. 同一进程的线程更有可能访问相同的内存。

(2)对缓存状态影响很大。如果线程读取相同的内存位置 - 它们会重用 L2 缓存,因此整个过程会加快速度。但是也有缺点:一旦线程更改了内存位置 - 该地址在两个处理器的 L2 缓存和 L2 缓存中都无效,因此另一个处理器也使其缓存无效。

因此,同时运行同一进程的线程(在不同的处理器上)有利有弊。BTW 这种情况有个名字:“排班”。

于 2010-06-04T23:34:33.703 回答