Почему однопоточный процесс выполняется на нескольких процессорах / ядрах? - PullRequest
11 голосов
/ 13 декабря 2011

Допустим, я запускаю простой однопоточный процесс, подобный приведенному ниже:

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

(Это Java, потому что это то, с чем я знаком, но я подозреваю, что это на самом деле не имеет значения)

У меня есть процессор i7 (4 ядра или 8 с учетом гиперпоточности), и я использую 64-разрядную версию Windows 7, поэтому я запустил Sysinternals Process Explorer, чтобы посмотреть на загрузку процессора и, как ожидается, он использует около 20% всех доступных процессоров.

Graph showing 20% CPU usage across all cores

Но когда я переключаю опцию, чтобы показать 1 график на процессор, я вижу, что вместо 1 из 4 используемых «ядер» загрузка процессора распределяется по всем ядрам:

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 ядре - это более простой и эффективный способ?

* Я говорю, в основном, однопоточный, потому что здесь несколько тем, но только 2 из них что-то делают:

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

Ответы [ 2 ]

18 голосов
/ 13 декабря 2011

ОС отвечает за планирование. Можно свободно остановить поток и запустить его снова на другом процессоре. Это будет сделано, даже если машина больше ничего не делает.

Процесс перемещается вокруг процессоров, поскольку ОС не предполагает, что есть причина продолжать запускать поток на одном и том же процессоре каждый раз.

По этой причине я написал библиотеку для блокировки потоков на ЦП, чтобы она не перемещалась и не прерывалась другими потоками. Это уменьшает задержку и улучшает пропускную способность, но зато утомляет процессор для этого потока. Это работает для Linux, возможно, вы можете адаптировать его для Windows. https://github.com/peter-lawrey/Java-Thread-Affinity/wiki/Getting-started

1 голос
/ 02 апреля 2016

Я также ожидал бы, что это может быть сделано специально для ЦП и ОС, чтобы попытаться распределить тепловую нагрузку на матрицу ЦП ...

Таким образом, он будет вращать (уникальный / единственный) поток от ядра к ядру.

И это, по общему признанию, может быть аргументом против попыток бороться с этим слишком усердно (тем более что на практике вы часто увидите лучшие улучшения, просто все равно настроив / улучшив само приложение)

...