16

Я открыл диспетчер задач и заглянул в область "Система" и увидел:

Темы: 1337

Поскольку у меня есть двухъядерный процессор с гиперпоточностью (то есть четыре потока), как можно иметь более 1000 потоков, если в моем процессоре всего четыре?

3 ответа3

49

Ответ прост: не все потоки выполняются одновременно. Для более полного объяснения читайте дальше.

Планировщик задач операционной системы обычно предназначен для планирования приложений, и это позволяет вам выполнять одну задачу, пока компьютер работает над другой. В старые времена лакмусовой бумажкой многозадачности было форматирование дискеты, когда делали что-то еще. Если вы действительно хотите протестировать ОС, отформатируйте дискету, загружая файл через модем, подключенный к последовательному порту. Поскольку аппаратное обеспечение стало достаточно мощным, чтобы реально делать это осмысленно, воспроизведение видео иногда показывалось и в таких тестах. Если планировщик задач ОС мог бы беспрепятственно выполнять эти задачи, он мог бы обрабатывать что угодно.

Тем не менее, планировщик задач на самом деле не планирует приложения (процессы), он планирует потоки. Каждое приложение имеет по крайней мере один поток, но потенциально может использовать большое количество потоков для разделения работы, которую оно выполняет, на связанные или независимые части. Например, для приложения характерно иметь один поток, который обрабатывает пользовательский интерфейс, и создавать другой поток, когда пользователь запускает потенциально длительную операцию (это могут быть такие вещи, как печать, пересчет электронной таблицы, выполнение среды разработки). поиск символа и т. д. и т. д.). Некоторые среды программирования вводят некоторое количество потоков, незаметно для программиста; например, Java и .NET могут выполнять сборку мусора в отдельном потоке, который находится вне непосредственного контроля программиста. Некоторые программы создают несколько потоков на ранних этапах и объединяют их в пул, потому что создание новых потоков является сравнительно дорогой операцией (поэтому вам не обязательно создавать поток каждый раз, когда он вам нужен). Все, что делает предварительный просмотр, обычно выполняется в отдельном потоке, поэтому остальная часть пользовательского интерфейса остается отзывчивой, пока создается предварительный просмотр. И так далее. В совокупности все это означает, что количество потоков в системе в любое время может легко во много раз превышать количество процессов.

Каждый поток может находиться в одном из нескольких возможных состояний, но самое важное различие между состояниями выполнения, запуска и ожидания ; терминология может немного отличаться, но это общая идея. В любой момент времени может быть запущено только один поток на виртуальное (из-за гиперпоточности и схожих технологий) ядро ЦП (то есть выполнение инструкций машинного кода), но любое количество потоков может быть запущено (это означает, что он является кандидатом на получение). ЦП в следующий раз, когда планировщику необходимо принять решение о том, какой поток должен быть запущен). Ожидание (также называемое заблокированными) потоков - это всего лишь ожидание чего-либо - наиболее распространенные случаи, вероятно, состоят в том, что он ожидает пользовательского, дискового или сетевого ввода-вывода (в частности, пользовательский ввод исключительно медленный).

Количество потоков, которое вы видите в диспетчере задач, - это общее количество потоков в любом из этих состояний. Например, в системе Windows 7, на которой я сейчас набираю, запущено около 70 процессов, но почти 900 потоков. Со всеми фоновыми процессами для обработки различных задач и того, как они, вероятно, подразделяются на множество потоков каждый, это не возмутительное число.

Если углубиться в технические аспекты реализации, в основе планировщика задач многозадачной операционной системы обычно лежит какая-то аппаратная перехват прерываний. Это означает , что ядро может остановить CPU , когда он не имеет никакой полезной работы для выполнения (это почти наверняка одна из причин, если не причина, почему Linux проверяет инструкции HLT при загрузке на IA-32 совместимыми с RIHD процессоров, и , вероятно , выполняет аналогичные проверки на других архитектурах), будучи уверенным в том, что при некотором разумном определении будущего времени сработает прерывание и будет вызван планировщик задач. Поскольку прерывание срабатывает независимо от того, какую другую работу выполняет ЦП (такова идея прерываний), планировщик регулярно выполняется и получает возможность определить, какой поток должен быть выполнен в течение следующего отрезка времени. Поскольку переключение контекста относительно дорого, обычно возможно (по крайней мере, через исходный код) настроить агрессивность переключения планировщика между потоками; переключение потоков чаще приводит к тому, что система становится более отзывчивой, но накладные расходы на переключение означают, что общее время выполнения заданного набора задач больше. Самая быстрая система будет такой, которая будет переключаться между потоками только тогда, когда работающий поток больше не может работать (что означает, что он заблокирован в ожидании чего-либо или завершил свою работу), потому что это минимизирует издержки, тогда как наиболее отзывчивая система переключится между потоками каждый раз, когда вызывается планировщик, потому что это минимизирует среднее время ожидания, прежде чем конкретный поток получит процессорное время. Идеальная настройка обычно находится где-то посередине между этими двумя, и компромисс между этими вариантами, вероятно, является одной из основных причин, почему Linux предлагает выбор из нескольких планировщиков, а также некоторые параметры настройки через конфигурацию ядра.

С другой стороны, совместные многозадачные ОС и среды (например, Windows 3.x ) полагаются на каждое приложение, чтобы регулярно передавать управление планировщику. Обычно есть функция API, специально предназначенная для этого, и часто многие функции API делают это как часть своего внутреннего потока выполнения, потому что это помогает сделать взаимодействие с пользователем более плавным. Этот подход к проектированию работает хорошо до тех пор, пока все приложения хорошо себя ведут и уступают управление с короткими интервалами во время любых длительных операций (длительное выполнение означает более небольшой доли секунды), но приложение, которое не может засоряться вся система. Это одна из основных причин, почему Windows 3.x так плохо работала в тесте многозадачности, о котором я упоминал выше, в то время как OS/2 весело прогуливался, выполняя те же задачи на том же оборудовании: приложение могло сказать дисководу гибких дисков записать определенное сектор, и время, которое потребовалось для того, чтобы ответить на звонок, можно было измерить (от десятков до сотен миллисекунд и более); система многозадачности с вытеснением может прервать работу своего планировщика при следующем запланированном вызове, заметить, что поток, который в данный момент "работает", фактически заблокирован вызовом write, и просто переключиться на другой поток, который работает. (На практике это немного сложнее, но это общая идея.)

Как в многозадачной, так и в кооперативной средах также существует вероятность того, что разные потоки имеют разные приоритеты. Например, вероятно, более важно своевременно выполнить поток, который получает данные по каналу связи, а не тот, который обновляет отображение системного времени, поэтому принимающий поток имеет высокий приоритет, а поток средства обновления отображения времени имеет низкий приоритет , Приоритеты потоков играют роль в решении планировщика о том, какой поток разрешить выполнять (например, очень упрощенные потоки с высоким приоритетом должны всегда выполняться перед потоками с низким приоритетом, поэтому даже если потоку с низким приоритетом осталось выполнить работу, если высокий приоритетный поток становится работоспособным (он имеет приоритет), но такие конкретные решения по планированию не влияют на конструкцию базового механизма.

19

Подумайте о четырехполосном шоссе с 1037 автомобилями.

Ваша ОС нуждается в большом количестве запущенных процессов для работы с большим количеством сервисов. Даже самые простые графические программы потребуют многопоточного программирования. Когда вы думаете о множестве открытых программ, вы обнаруживаете необходимость совместного использования ресурсов вычислительной мощности.

Ваш менеджер задач показывает текущую загрузку системы. Спецификации вашего компа показывают, сколько потоков (во внешнем интерфейсе) принято для параллельного выполнения. Без особой разницы между гиперпоточностью и многоядерными функциями, с более логичным принятием потоков внешнего интерфейса, система в целом будет работать лучше.

5

Мы должны сделать шаг назад и спросить себя: как компьютер с одним процессором может иметь два потока?

Потоки - это программные объекты, а не аппаратные. Чтобы иметь другой поток, вам просто нужна память для объектов, составляющих поток, таких как структура дескриптора и стек.

Операционная система переключается между потоками в разное время, например, внутри определенных прерываний (таких как прерывание по таймеру) или когда потоки совершают вызовы в операционную систему.

Из всех потоков, существующих в системе, только подмножество обычно находится в состоянии, которое обычно называется "работоспособным". Выполняемые потоки стремятся к запуску: они либо выполняются, либо находятся в "очереди выполнения", ожидая отправки планировщиком. Потоки, которые не могут быть запущены, "блокируются", ожидают получения какого-либо ресурса или получения ввода, или "спят", что похоже на блокировку на входе, где "ввод" - это ход времени. "Переключение контекста" происходит, когда функция планировщика в операционной системе просматривает очередь выполнения процессора и выбирает другой поток для выполнения.

Не смущайтесь "гиперпоточностью", которая является названием Intel для конкретной аппаратной функции.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .