为什么单个线程进程在多个处理器/内核上执行?

Cas*_*par 11 java multithreading operating-system multicore multiprocessing

假设我运行一个简单的单线程进程,如下所示:

public class SirCountALot {
    public static void main(String[] args) {
        int count = 0;
        while (true) {
            count++;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

(这是Java,因为这是我所熟悉的,但我怀疑它并不重要)

我有一个i7处理器(4核,或8计数超线程),我正在运行Windows 7 64位,所以我启动了Sysinternals Process Explorer来查看CPU使用率,正如预期的那样,我看到它使用了大约20%所有可用的CPU.

图表显示所有核心的CPU使用率为20%

但是,当我切换每个CPU显示1个图形的选项时,我看到使用的是4个"核心"中的1个,CPU使用率遍布整个核心:

图表显示每个核心的CPU使用率不稳定,总使用率约为20%

相反,我期望的是1核心最大化,但这只发生在我将流程的亲和力设置为单个核心时.

图表显示最近的CPU使用量大部分仅限于第一个核心

为什么工作负载分散在不同的核心上?不会将工作负载分散到多个核心,因为缓存还是会导致其他性能损失?

这是为了防止一个核心过热的简单原因吗?还是有更深层次的原因?

编辑:我知道操作系统负责调度,但我想知道为什么它"烦恼".当然,从一个天真的角度来看,将(主要是*)单线程进程坚持到1核心是更简单,更有效的方法吗?

*我说主要是单线程,因为这里有多个theads,但只有2个在做任何事情:

显示Eclipse中线程数的屏幕截图 屏幕截图显示Process Explorer流程属性中的线程数

Pet*_*rey 19

操作系统负责安排.它可以自由地停止一个线程并在另一个CPU上再次启动它.即使机器没有其他功能,它也会这样做.

该过程在CPU周围移动,因为操作系统不会假设每次都有任何理由继续在同一CPU上运行该线程.

出于这个原因,我已经为CPU锁定了一个锁定线程的库,因此它不会移动,也不会被其他线程中断.这样可以减少延迟并提高吞吐量,但会为该线程浪费CPU.这适用于Linux,也许你可以适应Windows.https://github.com/peter-lawrey/Java-Thread-Affinity/wiki/Getting-started

  • 尽可能在同一个核心上保持一个连续准备运行的线程是有充分理由的——该线程所需的一切都在运行该线程的核心上很热。其中包括 L1 和 L2 缓存、分支预测缓冲区、TLB 等。更改核心意味着必须重新填充所有这些缓存。(这实际上仅适用于线程始终准备好运行的情况。如果核心因该线程无法继续运行而执行其他操作,则即使您将线程分配回同一核心,缓存也会变冷。) (2认同)