来自多个进程的线程是否实际同时运行

Jon*_*ono 3 windows multithreading process context-switch

在具有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对象下没有任何内容.

Vik*_*vub 6

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

编辑(进一步澄清)

没有什么比"进程上下文切换"更像了.基本上,OS调度程序通过(非常自适应的)循环算法将线程分配给任何空闲处理器/核心(如亲和允许),如果"先前"处理器不能立即可用,则无论进程如何(这意味着)多线程进程可以窃取更多的CPU能力).

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

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

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

您可能无法在进程的亲缘关系之外为处理器设置线程关联,但您可以进一步限制它.

默认情况下,任何线程都将在可用的逻辑处理器之间跳转(特别是如果它产生,调用内核等),即使它有其首选的处理器也可能会跳转,但只有当它必须时,但它不会跳转到处理器在其亲和力掩模之外(这可能导致相当大的延迟).

我不知道如果调度看到物理和超线程处理器之间的任何差别,但即使它没有(我假设),其后果是在大多数情况下不是问题的,也就是说,不应该太大的区别如果线程数相同,则在多个线程之间共享物理或逻辑处理器.无论如何,在这种情况下一些缓存抖动的报告,主要是高性能的多线程应用程序,如SQL服务器或.NET和Java VM,它们可能会或可能不会从关闭的HyperThreading中受益.