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

时间:2011-12-13 07:58:39

标签: java multithreading operating-system multiprocessing multicore

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

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

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

我有一个i7处理器(4个核心,或8个计数超线程),我正在运行Windows 7 64位,因此我启动了Sysinternals Process Explorer来查看CPU使用情况,并且正如我所料,我看到它正在使用占所有可用CPU的20%左右。

Graph showing 20% CPU usage across all cores

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

Graph showing erratic CPU usage on each core totaling around 20% usage

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

Graph showing most of recent CPU usage to be confined to first core

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

是否出于防止一个核心过热的简单原因?还是有更深层次的原因?

编辑:我知道操作系统负责调度,但我想知道它为何“烦恼”。当然,从一个天真的角度来看,将(主要是*)单线程进程固定在1核心上就更简单了。更有效的方式去?

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

Screenshot showing number of threads from Eclipse Screenshot showing number of threads in Process Explorer process properties

2 个答案:

答案 0 :(得分:18)

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

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

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

答案 1 :(得分:1)

我还希望CPU和操作系统可以有目的地完成这项工作,以便尝试在CPU芯片上散布热负载......

因此它会将(唯一/单个)线程从核心旋转到核心。

这无疑可能是反对尝试与之抗争的一个论点(特别是在实践中,你通常会通过简单地调整/改进应用程序本身来看到更好的改进)