在具有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
简而言之,我想知道 - 在多处理器机器上 - 操作系统是否可以随时从任何进程调度任何线程,无论其他进程的其他线程是否已在运行。< / p>
修改: 为了澄清愚蠢的例子,假设进程A的线程A:T0与处理器P0(和A:T1到P1)具有亲和性,而进程B的线程B:T0与处理器P1(和B:T1到P0)具有亲和性。这些处理器是核心还是插座可能无关紧要。
是否存在流程上下文切换的一流概念? Perfmon在Thread对象下显示上下文切换,但在Process对象下没有任何内容。
答案 0 :(得分:6)
是的,它是可能的并且经常发生。
操作系统尝试不在CPU之间切换一个线程(你可以更努力地设置线程首选处理器,或者您甚至可以通过亲和力将其锁定到单个处理器。)Windows的进程本身不是执行单元 - 从这个角度来看,它基本上只是其线程的上下文。
编辑(进一步澄清)
没有什么比“进程上下文切换”更像了。基本上,OS调度程序通过(非常自适应的)循环算法将线程分配给任何空闲处理器/核心(如亲和允许),如果“先前”处理器不能立即可用,则无论进程如何(这意味着)多线程进程可以窃取更多的CPU能力。)
这种“跳跃”可能看起来很昂贵,考虑到至少L1(有时是L2)缓存是每个核心(除了不同的插槽/封装处理器),但它仍然比等待“正确”的延迟更便宜处理器和无法进行复杂的负载均衡(“跳跃”方案使其成为可能)。这可能不适用于NUMA架构,但有更多的考虑因素(例如,适应)所有内存分配都是thread- 和处理器绑定的,并避免尽可能多的状态/内存共享。
至于亲和力:您可以为每个线程或每个进程设置关联掩码(它取代所有进程'线程'设置),但操作系统强制执行每个线程附属的至少一个逻辑处理器(您 从不 以零掩码结束。
进程的默认关联掩码从其父进程继承(允许您为有问题的遗留可执行文件创建单核加载器),并且线程从它们所属的进程继承掩码。
您可以不为进程的亲缘关系之外的处理器设置线程关联,但您可以进一步限制它。
默认情况下,任何线程, 将 在可用的逻辑处理器之间跳转(特别是如果它产生,调用内核等),< strong> 可能 即使设置了首选处理器也会跳转,但仅当必须时, 但是 不会 跳转到其亲和力掩码之外的处理器(这可能会导致相当大的延迟)。
我不确定调度程序是否看到物理和超线程处理器之间存在任何差异,但即使它没有(我假设),后果在大多数情况下都不是问题,即如果线程数相同,则不应在共享物理或逻辑处理器的多个线程之间存在很多差异。无论如何, 在这种情况下有一些缓存抖动的报告,主要是高性能的多线程应用程序,如SQL服务器或.NET和Java VM,可能或关闭HyperThreading可能无法受益。
答案 1 :(得分:2)
我普遍同意之前的回答,但事情要复杂得多。
虽然进程不是执行单元,但属于同一进程的线程应区别对待。这有两个原因:
(2)对缓存状态有很大影响。如果线程读取相同的内存位置 - 它们重用L2缓存,因此整个过程加速。但是也存在缺点:一旦线程改变了内存位置 - 该地址在两个处理器的L2缓存和L2缓存中都无效,因此另一个处理器也使其缓存无效。
因此,同时运行同一进程的线程(在不同的处理器上)有利有弊。 BTW这种情况有一个名字:“帮派调度”。