Допустим, у меня есть процессор с 4 ядрами и 4 потоками и приложение с 20 потоками, которые нужны мне для постоянных проверок (скажем, они являются событиями), как процессор запускает все потоки одновременно с его ограниченным количеством потоки? Я знаю, что процессор переключается с одного потока на другой, и, поскольку изменения происходят очень быстро, мы их не замечаем, но это все, что происходит, или компьютер делает что-то еще. Кроме того, как компьютер сохраняет информацию для каждого потока в определенный момент времени, только в оперативной памяти?
2 ответа
20 потоков не могут работать одновременно, кроме как в системе с 20 или более ядрами. Система может сделать так, чтобы она выглядела так, как будто они работают в одно и то же время.
Это то, для чего предназначен планировщик операционной системы.
До появления многоядерных процессоров операционная система должна была распределять процессорное время между несколькими процессами, каждый из которых мог иметь несколько отдельных потоков.
Операционная система должна управлять каждым потоком, выделять ему количество времени на ЦП, восстанавливать состояние, запускать поток, приостанавливать и сохранять состояние. Ничто из этого существенно не отличается между многоядерным, многопроцессорным или одноядерным.
Что изменилось, так это уровень сложности и количество вещей, которые можно запланировать на одновременное выполнение. Там, где мы могли запускать только один поток за раз, теперь мы можем запустить четыре. Происходит тот же процесс отслеживания состояния потока (счетчик программы и т.д.), И не имеет значения, сколько потоков имеет программа.
Операционная система будет пытаться правильно спланировать все потоки на ЦП некоторое время, основываясь на том, есть ли у них работа (может ли ожидаться аппаратное прерывание или какие-то данные с диска), каков приоритет процесса / потока и целый ряд других вещей. Потоки могут уведомлять операционную систему о том, что им нечем заняться, пока не произойдут различные события, которые могут быть устаревшими, аппаратными или программными событиями и так далее. В этом случае планировщик операционной системы может просто пропустить этот поток, пока не найдет поток, готовый выполнить некоторую работу.
В настоящий момент система, которую я использую, сообщает, что во всех запущенных процессах 2500 потоков, очевидно, что невозможно будет одновременно запустить их все на 4-ядерном процессоре.
Во-первых: ЦП не имеет "потоков", несмотря на то, что маркетинговая затея пытается претендовать. Процессор может работать до указанного количества потоков одновременно. В частности, процессор с n ядрами и не включенной гиперпоточностью может запускать n потоков. Процессор с n ядрами и включенной гиперпоточностью может запускать потоки 2_n_. В техническом контексте мы называем «вещь, которая может запустить поток» как логический процессор или LP. Машина без HT имеет один LP на ядро; HT дает это два.
Типичная система Windows содержит сотни или даже тысячи потоков, всего в ней одновременно. Это зависит от кода каждой отдельной программы. Когда вы создаете процесс, этот процесс всегда начинается с одного потока. Некоторые простые программы, особенно программы командной строки (символьный режим), могут использовать только один поток. Но код, выполняющийся в этом первом потоке, может создавать другие потоки, и эти потоки могут создавать другие потоки и т.д. Практически без практического ограничения. Есть веские причины не просто создавать огромное количество потоков, но нет ничего, что сделало бы невозможным создание гораздо большего количества потоков, чем можно было бы использовать.
(На платформе x86 со значениями по умолчанию для размера стека потоков существует ограничение в 2000 потоков на процесс, налагаемое лимитом адресного пространства.)
На вкладке «Сведения» диспетчера задач можно включить столбец «Потоки», в котором будет указано количество потоков в каждом процессе на данный момент. Вот команда PowerShell, которая подсчитает все потоки в вашей системе:
($threads = get-ciminstance win32_thread).count
3437
Это на машине с четырьмя гиперзаходными ядрами, всего восемь LP.
Это не проблема, потому что очень немногие из этих потоков действительно хотят работать в любой момент. Большинство потоков в большинстве процессов проводили большую часть своего времени в том, что Windows называет состоянием "ожидания", то есть они не хотят или не могут использовать процессорное время вообще. Они ожидают завершения ввода-вывода (может быть, сети, диска и т.д.), Ожидают ввода данных пользователем, ожидают, что какой-то другой поток освободит ресурс, к которому им нужен доступ и т.д. (* Производные от nix системы называют это "заблокированным".)
Если вы хотите количество ожидающих потоков, попробуйте это:
PS C:\Users\jeh> ($threads = get-ciminstance win32_thread | where-object -Property ThreadState -EQ 5).count
3427
Похоже, что сейчас только 10 потоков пытаются использовать LP. Но это даже лучше, чем это. При 8 LP 8 из этих потоков являются простоями системы. Есть свободная тема, посвященная каждому LP. Они всегда готовы к запуску, но они запускаются только в том случае, если ничего не хочет LP. Поэтому в тот момент, когда я выполнял приведенные выше команды, было только два "настоящих" потока, которые хотели работать. Действия незанятых потоков не включены в линейный график диспетчера задач, показывающий загрузку ЦП.
Примечание: эти цифры не совсем точны, потому что эти операции Powershell и WMI не синхронизированы с функциями операционной системы. Но они легко достаточно близки, чтобы проиллюстрировать это.
Если потоков (кроме незанятых потоков) больше "Готово", чем существующих LP, то планировщик, как правило, выбирает потоки nLP с наивысшим приоритетом - с некоторыми изменениями в зависимости от того, кто недавно работал на каких процессорах. Если есть несколько потоков с одинаковым приоритетом, они могут быть "разделены по времени", работать в "циклическом" режиме, каждый из которых может работать за 20 или 60 мсек, прежде чем планировщик переключит LP на другой.
Вот ответ, который я дал, в котором более подробно рассказывается о том, как работают приоритеты потоков в Windows.