Почему однопоточный процесс выполняется на нескольких процессорах/ядрах?
Скажем, я запускаю простой однопоточный процесс, подобный приведенному ниже:
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 core maxed out, но это происходит только тогда, когда я устанавливаю сродство к процессу к одному ядру.
![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]()
Ответы
Ответ 1
ОС отвечает за планирование. Он может остановить поток и запустить его снова на другом CPU. Он будет делать это, даже если больше ничего не делает машина.
Процесс перемещается вокруг процессоров, потому что ОС не предполагает, что есть какая-либо причина продолжать выполнение потока на одном и том же ЦП каждый раз.
По этой причине я написал библиотеку для блокировки потоков в CPU, чтобы она не перемещалась и не прерывалась другими потоками. Это уменьшает время ожидания и повышает пропускную способность, но утомляет процессор для этого потока. Это работает для Linux, возможно, вы можете адаптировать его для Windows. https://github.com/peter-lawrey/Java-Thread-Affinity/wiki/Getting-started
Ответ 2
Я также ожидал, что это может быть сделано специально для процессора и ОС, чтобы попытаться распространить тепловую нагрузку на процессорную матрицу...
Таким образом, он будет вращать (уникальный/одиночный) поток от ядра к ядру.
И это может быть аргументом против попыток бороться с этим слишком сложно (особенно, поскольку на практике вы часто увидите улучшения, просто настроив/улучшив приложение в любом случае)