Приоритет потока в windows

Обновлено: 03.07.2024

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

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

Процедура планирования обычно связана с весьма затратной процедурой диспетчеризации - переключением процессора на новый поток , поэтому планировщик должен заботиться об эффективном использовании процессора. Принадлежность потоков к процессу при планировании не учитывается, то есть единицей планирования в ОС Windows является именно поток . Запуск процедуры планирования удобно проиллюстрировать на упрощенной ( по сравнению с диаграммой, изображенной на рис. 5.3) диаграмме состояний потока, см. рис. 6.1.

Упрощенная диаграмма состояний потоков в ОС Windows


Рис. 6.1. Упрощенная диаграмма состояний потоков в ОС Windows

Наиболее важным вопросом планирования является выбор момента для принятия решения. В ОС Windows запуск процедуры планирования вызывается одним из следующих событий.

Это, во-первых, события, связанные с освобождением процессора.

(1) Завершение потока

(2) Переход потока в состояние готовности в связи с тем, что его квант времени истек

(3) Переход потока в состояние ожидания

Во-вторых, это события, в результате которых пополняется или может пополниться очередь потоков в состоянии готовности.

(4) Поток вышел из состояния ожидания

(5) Поток только что создан

(6) Деятельность текущего потока может иметь следствием вывод другого потока из состояния ожидания.

В последнем случае выведенный из состояния ожидания поток может сразу же начать выполняться, если имеет высокий приоритет.

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

Заметим, что переключение из пользовательского режима в режим ядра (и обратно) не влияет на планирование потока, так как контекст в этом случае не меняется.

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

Перевод потока из состояния ожидания в состояние готовности (вариант 4) может быть следствием прерывания, свидетельствующим об окончании операции ввода-вывода. В этом случае процедура планирования может быть отложена (deffered procedure call ) до окончания выполнения высокоприоритетного системного кода.

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

Алгоритмы планирования

Приоритеты

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

В системе предусмотрено 32 уровня приоритетов. Шестнадцать значений приоритетов (16-31) соответствуют группе приоритетов реального времени, пятнадцать значений (1-15) предназначены для обычных потоков, и значение 0 зарезервировано для системного потока обнуления страниц (см. рис. 6.2).

Приоритеты потоков

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

  • реального времени ( REALTIME_PRIORITY_CLASS ),
  • высокий ( HIGH_PRIORITY_CLASS ),
  • выше нормы ( ABOVE_NORMAL_PRIORITY_CLASS ),
  • нормальный ( NORMAL_PRIORITY_CLASS ),
  • ниже нормы ( BELOW_NORMAL_PRIORITY_CLASS )
  • и неработающий ( IDLE_PRIORITY_CLASS ).

Относительный приоритет потока устанавливается аналогичными параметрами функции SetThreadPriority :

Совокупность из шести классов приоритетов процессов и семи классов приоритетов потоков образует 42 возможные комбинации и позволяет сформировать так называемый базовый приоритет потока (см. таб. 6.1).

Базовый приоритет процесса и первичного потока по умолчанию равен значению из середины диапазонов приоритетов процессов (24, 13, 10, 8, 6 или 4). Смена приоритета процесса влечет за собой смену приоритетов всех его потоков, при этом их относительные приоритеты остаются без изменений.

Приоритеты с 16 по 31 в действительности приоритетами реального времени не являются, поскольку в рамках поддержки мягкого реального времени, которая реализована в ОС Windows, никаких гарантий относительно сроков выполнения потоков не дается. Это просто более высокие приоритеты, которые зарезервированы для системных потоков и тех потоков, которым такой приоритет дает пользователь с административными правами. Тем не менее, наличие приоритетов реального времени, а также вытесняемость кода ядра, локализация страниц памяти (см. "Функционирование менеджера памяти" ) и ряд дополнительных возможностей - все это позволяет выполнять в среде ОС Windows приложения мягкого реального времени, например, мультимедийные. Системный поток с нулевым приоритетом занимается обнулением страниц памяти. Обычные пользовательские потоки могут иметь приоритеты от 1 до 15.

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

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

Приоритет каждого потока определяется следующими критериями.

  • Класс приоритета его процесса
  • Уровень приоритета потока в классе приоритета его процесса

Класс приоритета и уровень приоритета объединяются для формирования базового приоритета потока. Сведения о динамическом приоритете потока см. в разделе повышение приоритета.

Класс Priority

Каждый процесс принадлежит одному из следующих классов приоритета: _класс приоритета простоя _
НИЖЕ _ обычного _ класса приоритета _
_класс обычного приоритета _
ВЫШЕ _ класса с нормальным _ приоритетом _
класс с высоким _ приоритетом _
_класс приоритета в режиме реального времени _

По умолчанию класс приоритета процесса — это класс с НОРМАЛЬным _ приоритетом _ . Используйте функцию CreateProcess , чтобы указать класс приоритета дочернего процесса при его создании. Если вызывающий процесс является _ классом приоритета простоя _ или ниже _ обычного _ класса приоритета _ , новый процесс будет наследовать этот класс. Используйте функцию жетприоритикласс для определения текущего класса приоритета процесса и функции сетприоритикласс , чтобы изменить класс приоритета процесса.

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

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

Почти никогда не следует использовать _ класс приоритета реального времени _ , так как это прерывает системные потоки, управляющие вводом мыши, вводом с клавиатуры и фоновым сбросом дисков. Этот класс может быть пригоден для приложений, которые «говорите» непосредственно на оборудование или выполняют короткие задачи, которые должны иметь ограниченные перерывы.

Уровень приоритета

Ниже приведены уровни приоритета в каждом классе приоритета. приоритет потока — _ _ бездействие
_ _ самый низкий приоритет потока
_приоритет потока _ ниже _ обычного
приоритет потока — _ _ нормальный
_приоритет потока _ выше _ обычного
приоритет потока — _ _ самый высокий
_ _ критическое время ПРИОРИТЕТа потока _

Все потоки создаются с использованием _ обычного приоритета потока _ . Это означает, что приоритет потока аналогичен классу приоритета процесса. После создания потока используйте функцию сетсреадприорити , чтобы изменить ее приоритет относительно других потоков в процессе.

Типичной стратегией является использование _ приоритета потока _ выше _ обычного или _ приоритета потока _ для входного потока процесса, чтобы обеспечить реагирование приложения на запросы пользователя. Фоновым потокам, в частности, которые являются ресурсоемкими, можно задать _ приоритет потока _ ниже _ обычного или _ приоритета потока _ , чтобы гарантировать, что при необходимости они могут быть вытеснены. Однако при наличии потока, ожидающего другого потока с более низким приоритетом для выполнения некоторой задачи, не забудьте заблокировать выполнение ожидающего потока с высоким приоритетом. Для этого используйте функцию Wait, критическую секциюили функцию Sleep , слипексили свитчтосреад . Это предпочтительнее, чтобы поток выполнял цикл. В противном случае процесс может привести к взаимоблокировке, так как не запланировано выполнение потока с более низким приоритетом.

Чтобы определить текущий уровень приоритета потока, используйте функцию жетсреадприорити .

Базовый приоритет

Класс приоритета процесса и уровень приоритета потока объединяются для формирования базового приоритета каждого потока.

В следующей таблице показан базовый приоритет для сочетания класса приоритета процесса и значения приоритета потока.

Потоки и планирование потоков

Что такое поток? Давайте дадим краткое определение. По своей сути поток это:

  • Средство параллельного относительно других потоков исполнения кода;
  • Имеющего общий доступ ко всем ресурсам процесса.

Давайте посмотрим из чего они состоят и как они рождаются. По сути поток — это средство эмуляции параллельного исполнения относительно других потоков. Почему эмуляция? Потому, что поток как бы странно и смело это ни звучало — это чисто программная вещь, которая идёт из операционной системы. А операционная система создаёт этот слой эмуляции для нас. Процессор при этом о потоках ничего не знает вообще.

Задача процессора — просто исполнять код. Поэтому с точки зрения процессора есть только один поток: последовательное исполнение команд. А задача операционной системы каким-либо образом менять поток т.о. чтобы эмулировать несколько потоков.

"Но как же так?", — скажите вы, — "во многих магазинах и на различных сайтах я вижу запись "Intel Xeon 8 ядер 16 потоков". Говоря по-правде это — либо скудность в терминологии либо — чисто маркетинговый ход. На самом деле внутри одного большого процессора есть в данном случае 8 ядер и каждое ядро состоит из двух логических процессоров. Такое доступно при наличии в процессоре технологии Hyper-Threading, когда каждое ядро эмулирует поведение двух процессоров (но не потоков). Делается это для повышения производительности, да. Но по большому счёту если нет понимания, на каких потоках идут расчёты, можно получить очень не приятный сценарий, когда код выполняется со скоростью, ниже чем если бы расчёты шли на одном ядре. Именно поэтому раздача ядер идёт +=2 в случае Hyper-Threading. Т.е. пропуская парные ядра.

Технология эта — достаточно спорная: если вы работаете на двух таких псевдо-ядрах (логических процессорах, которые эмулируются технологией Hyper-Threading), которые при этом находятся на одном физическом ядре и работают с одной и той-же памятью, то вы будете постоянно попадать в ситуацию, когда второй логический процессор так же пытается обратиться к данной памяти, создавая блокировку либо попадая в блокировку, т.к. поток, находящийся на первом ядре работает с той же памятью.

Возникает блокировка совместного доступа: хоть и идёт эмуляция двух ядер, на самом-то деле оно одно. Поэтому в наихудшем сценарии эти потоки исполняются по очереди, а не параллельно.

Так если процессор ничего не знает о потоках, как же достигается параллельное исполнение потоков на каждом из его ядер? Как было сказано, поток — средство операционной системы выполнять на одном процессоре несколько задач одновременно. Достигается параллелизм очень быстрым переключением между потоками в течение очень короткого промежутка времени. Последовательно запуская на выполнение код каждого из потоков и делая это достаточно часто, операционная система достигает цели: делает их исполнение псевдопараллельным, но параллельным с точки зрения восприятия человека. Второе обоснование существования потоков — это утверждение, что программа не так часто срывается в математические расчёты. Чаще всего она взаимодействует с окружающим её миром: различным оборудованием. Это и работа с жёстким диском и вывод на экран и работа с клавиатурой и мышью. Поэтому чтобы процессор не простаивал, пока оборудование сделает то, чего хочет от него программа, поток можно на это время установить в состояние блокировки: ожидания сигнала от операционной системы, что оборудование сделало то, что от него просили. Простейший пример этого — вызов метода Console.ReadKey() .

Если заглянуть в диспетчер задач Windows 10, то можно заметить, что в данный момент в вашей системе существует около 1,5 тысячи потоков. И если учесть, что квант на десктопе равен 20 мс, а ядер, например, 4, то можно сделать вывод, что каждый поток получает 20 мс работы 1 раз в 7,5 сек… Ну конечно же, нет. Просто почти все потоки чего-то ждут. То ввода пользователя, то изменения ключей реестра… В операционной системе существует очень много причин, чтобы что-либо ждать.

Так что пока одни потоки в блокировке, другие — что-то делают.

В эту функцию передаются следующие атрибуты:

1) Необязательная структура с атрибутами безопасности:

    Дескриптор безопасности (SECURITY_ATTRIBUTES) + признак наследуемости дескриптора.

2) Необязательный размер стека:

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

3) Указатель на функцию — точка входа нового потоками
4) Необязательный аргумент для передачи данных функции потока.

Планирование потоков

Для того чтобы понимать, в каком порядке исполнять код различных потоков, необходима организация планирования тих потоков. Ведь система может иметь как одно ядро, так и несколько. Как иметь эмуляцию двух ядер на одном так и не иметь такой эмуляции. На каждом из ядер: железных или же эмулированных необходимо исполнять как один поток, так и несколько. В конце концов система может работать в режиме виртуализации: в облаке, в виртуальной машине, песочнице в рамках другой операционной системы. Поэтому мы в обязательном порядке рассмотрим планирование потоков Windows. Это — настолько важная часть материала по многопоточке, что без его понимания многопоточка не встанет на своё место в нашей голове никоим образом.

Итак, начнём. Организация планирования в операционной системе Windows является: гибридной. С одной стороны моделируются условия вытесняющей многозадачности, когда операционная система сама решает, когда и на основе каких условия вытеснить потоки. С другой стороны — кооперативной многозадачности, когда потоки сами решают, когда они всё сделали и можно переключаться на следующий (UMS планировщик). Режим вытесняющей многозадачности является приоритетным, т.к. решает, что будет исполняться на основе приоритетов. Почему так? Потому что у каждого потока есть свой приоритет и операционная система планирует к исполнению более приоритетные потоки. А вытесняющей потому, что если возникает более приоритетный поток, он вытесняет тот, который сейчас исполнялся. Однако во многих случаях это бы означало, что часть потоков никогда не доберется до исполнения. Поэтому в операционной системе есть много механик, позволяющих потокам, которым необходимо время на исполнение его получить несмотря на свой более низкий по сравнению с остальными, приоритет.

Уровни приоритета

Windows имеет 32 уровня приоритета (0-31)

  • 1 уровень (00 — 00) — это Zero Page Thread;
  • 15 уровней (01 — 15) — обычные динамические приоритеты;
  • 16 уровней (16 — 31) — реального времени.

Продолжая говорить о том, что к нам не относится, стоит отметить приоритеты реального времени, которые когда-то давным-давно таковыми являлись, но быстро потеряли свой статус приоритетов реального времени и от этого статуса осталось лишь название. Другими словами, Real Time приоритеты на самом деле не являются таковыми. Они являются приоритетами с исключительно высоким значением приоритета. Т.е. если операционная система будет по какой-то причине повышать приоритет потока с приоритетом из динамической группы (об этом — позже, но, например, потому, что потоку освободили блокировку) и при этом значение до повышения было равно 15 , то повысить приоритет операционная система не сможет: следующее значение равно 16 , а оно — из диапазона реального времени. Туда повышать такими вот "твиками" нельзя.

Уровень приоритетов процессов с позиции Windows API.

Приоритеты — штука относительная. И чтобы нам всем было проще в них ориентироваться, были введены некие правила относительности расчетов: во-первых все потоки вообще (от всех приложений) равны для планировщика: планировщик не различает потоки это различных приложений или же одного и того же приложения. Далее, когда программист пишет свою программу, он задаёт приоритет для различных потоков, создавая тем самым модель многопоточности внутри своего приложения. Он прекрасно знает, почему там был выбран пониженный приоритет, а тут — обычный. Внутри приложения всё настроено. Далее, поскольку есть пользователь системы, он также может выстраивать приоритеты для приложений, которые запускаются на этой системе. Например, он может выбрать повышенный приоритет для какого-то расчетного сервиса, отдавая ему тем самым максимум ресурсов. Т.е. уровень приоритета можно задать и у процесса.

Однако, изменение уровня приоритета процесса не меняет относительных приоритетов внутри приложения: их значения сдвигаются, но не меняется внутренняя модель приоритетов: внутри по-прежнему будет поток с пониженным приоритетом и поток — с обычным. Так, как этого хотел разработчик приложения. Как же это работает?

Существует 6 классов приоритетов процессов. Класс приоритетов процессов — это то, относительно чего будут создаваться приоритеты потоков. Все эти классы приоритетов можно увидеть в "Диспетчере задач", при изменении приоритета какого-либо процесса.

Название Класс Базовый приоритет
1. Real Time 4 24
2. High 3 13
3. Above Normal 6 10
4. Normal 2 8
5. Below Normal 5 6
6. Idle 1 4

Другими словами класс приоритета — это то, относительно чего будут задаваться приоритеты потоков внутри приложения. Чтобы задать точку отсчёта, было введено понятие базового приоритета. Базовый приоритет — это то значение, чем будет являться приоритет потока с типом приоритета Normal:

  • Если процесс создаётся с классом Normal и внутри этого процесса создаётся поток с приоритетом Normal, то его реальный приоритет Normal будет равен 8 (строка №4 в таблице);
  • Если Вы создаёте процесс и у него класс приоритета Above Normal, то базовый приоритет будет равен 10. Это значит, что потоки внутри этого процесса будут создаваться с более повышенным приоритетом: Normal будет равен 10.

Для чего это необходимо? Вы как программисты знаете модель многопоточности, которая у вас присутствует.
Потоков может быть много и вы решаете, что один поток должен быть фоновым, так как он производит вычисления и вам
не столь важно, когда данные станут доступны: важно чтобы поток завершил вычисления (например поток обхода и анализа дерева). Поэтому, вы устанавливаете пониженный приоритет данного потока. Аналогично может сложится ситуация когда необходимо запустить поток с повышенным приоритетом.

Представим, что ваше приложение запускает пользователь и он решает, что ваше приложение потребляет слишком много процессорных ресурсов. Пользователь считает, что ваше приложение не столь важное в системе, как какие-нибудь другие приложения и понижает приоритет вашего приложения до Below Normal. Это означает, что он задаёт базовый приоритет 6 относительно которого будут рассчитываться приоритеты потоков внутри вашего приложения. Но в системе общий приоритет упадёт. Как при этом меняются приоритеты потоков внутри приложения?

Уровни насыщения
1. Time Critical (+15)
2. Higest (+2)
3. Above normal (+1)
4. Normal (+0)
5. Below normal (-1)
6. Lowest (-2)
7. Idle (-15)

Normal остаётся на уровне +0 относительно уровня базового приоритета процесса. Below normal — это (-1) относительно уровня базового. Т.е. в нашем примере с понижением уровня приоритета процесса до класса Below Normal приоритет потока 'Below Normal' пересчитается и будет не 8 - 1 = 7 (каким он был при классе Normal ), а 6 - 1 = 5 . Lowest (-2) станет равным 4 .

Тоже самое и с приоритетами. У нас есть Normal. Дальше, относительно Normal у нас есть чуть повыше
Normal (Normal above), чуть пониже Normal (Normal below). Также есть шаг на два вверх
или на два вниз (Higest и Lowest). Нам, поверьте, нет никакой необходимости в более подробной градации. Единственное, очень редко, может раз в жизни, нам понадобится сказать: выше чем любой приоритет в системе. Тогда мы выставляем уровень Time Critical . Либо наоборот: это надо делать, когда во всей системе делать нечего. Тогда мы выставляем уровень Idle . Это значения — так называемые уровни насыщения.

Как рассчитываются уровни приоритета?


У нас бал класс приоритета процесса Normal (Таблица 3) и приоритет потоков Normal — это 8. Если процесс Above Normal то поток Normal получается равен 9. Если же процесс выставлен в Higest, то поток Normal получается равен 10.

Поскольку для планировщика потоков Windows все потоки процессов равнозначны, то:

  • Для процесса класса Normal и потока Above-Normal
  • Для процесса класса Higest и потока Normal
    конечные приоритеты будут одинаковыми и равны 10.

Если мы имеем два процесса: один с приоритетом Normal, а второй — с приоритетом Higest, но при этом
первый имел поток Higest а второй Normal, то система их приоритеты будет рассматривать как одинаковые.

Но так как поток повышенным приоритетом исполняется только один на группе ядер, то получается,
что если у вас даже Real-Time потоки, не факт, что им будет выделено время.

Класс приоритета / относительный приоритет Real-Time High Above-Normal Normal Below-Normal Idle
Time Critical (+насыщение) 31 15 15 15 15 15
Highest (+2) 26 15 12 10 8 6
Above Normal (+1) 25 14 11 9 7 5
Normal (0) 24 13 10 8 6 4
Below Normal (-1) 23 12 9 7 5 3
Lowest (-2) 22 11 8 6 4 2
Idle (-насыщение) 16 1 1 1 1 1

Если перевести в графический вид, то можно заметить, что классы приоритетов пересекаются. Например, существует пересечение Above-Normal Normal Below-Normal (столбик с квадратиками):


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

Поэтому, когда процессу выдаётся более высокий класс приоритета, это повышает приоритет потоков процесса относительно обычных – с классом Normal.

Класс приоритета / относительный приоритет Real-Time High Above-Normal Normal Below-Normal Idle
Time Critical (+насыщение) 31 15 15 15 15 15
Highest (+2) 26 15 12 10 8 6
Above Normal (+1) 25 14 11 9 7 5
Normal (0) 24 13 10 8 6 4
Below Normal (-1) 23 12 9 7 5 3
Lowest (-2) 22 11 8 6 4 2
Idle (-насыщение) 16 1 1 1 1 1

Загляните к нам на сайт: мы сильно постарались, чтобы его было интересно изучить.

Рассмотрим, как в системе Windows осуществляется планирование потоков для их выполнения на центральном процессоре. Также посмотрим на приоритеты процессов и потоков.

Планирование потоков в системе

В Windows всегда выполняется хотя бы один поток с самым высоким приоритетом. Если в системе много ядер, то Windows делит все ядра на группы по 64 ядра. Каждому процессу даётся доступ к определённой группе ядер. Следовательно потоки этих процессов могут видеть только свою группу ядер.

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

Поток может не отработать весь свой квант, так как если другой поток готов к выполнению и имеет более высокий приоритет, то он вытеснит первый поток.

В системе существует планировщик, который и занимается управлением потоками. Именно он решает какой поток будет выполняться на процессоре следующим. Причем планировщик работает в режиме ядра.

Так как процессор постоянно обрабатывает разные, несвязанные между собой потоки, то он должен запоминать на каком результате он остановился выполняя определённый поток. Такое запоминание предыдущего потока и переключение на новый называют – переключением контекста.

Планирование осуществляется на уровне потоков, а не процессов. Например, Процесс_А имеет 10 потоков, а Процесс_Б – 2 потока. Тогда процессорное время распределился между этими 12 потоками равномерно.

Приоритеты потоков

Планирование потоков полагается на их приоритеты. Windows использует 32 уровня приоритета для потоков от 0 до 31:

  • 16 — 31 — уровни реального времени;
  • 1 — 15 — обычные динамические приоритеты;
  • 0 — зарезервирован для потока обнуления страниц.

Вначале поток получает свой Базовый приоритет, который наследуется от приоритета процесса:

Дальше назначается относительный приоритет который увеличивает или уменьшает приоритет потока:

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

Изменить базовый приоритет процесса можно из “Диспетчера задач” на вкладке “Подробности“, или в “Process Explorer“. Однако, это не поменяет относительный приоритет потока.

Диспетчер задач. Проверка приоритета процесса, запущенного командой «start /low notepad.exe»

Приоритеты отдельных потоков можно посмотреть в программе “Process Explorer“. Но изменять их нет смысла, так как только разработчик данной программы понимает как лучше расставить приоритеты потокам.


Получается что относительный приоритет у потока Notepad.exe равен 2, так как динамический приоритет больше базового на 2.

Состояния потоков

Поток может находиться в следующих состояниях:

  • Готов (Ready) — поток готов к выполнению и ожидает процессор.
  • Готов с отложенным выполнением (Deferred ready) — поток выбран для выполнения на конкретном ядре и ожидает именно это ядро.
  • В повышенной готовности (Standby) — поток выбран следующим для выполнения на конкретном ядре. Как только сможет процессор выполнит переключение контекста на этот поток.
  • Выполнение (Running) — выполняется на процессоре пока не истечет его квант времени, или пока его не вытеснит поток с большем приоритетом.
  • Ожидание (Waiting) — поток ждет каких-то ресурсов.
  • Переходное состояние (Transition) — готов к выполнению, но стек ядра выгружен из памяти, как только стек загрузится в память поток перейдет в состояние Готов.
  • Завершение (Terminated) — поток выполнил свою работу и завершился сам, или его завершили принудительно.
  • Инициализация (Initializated) — состояние при создании потока.

Кванты времени

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

Итак, теперь я вам покажу как переключить систему на работу с длинным или коротким квантом. Длительность кванта времени настраивается тут: “Свойства системы” / “Дополнительные параметры системы” / “Дополнительно” / “Быстродействие” / “Параметры” / “Дополнительно”:

На серверной системе можно выбрать “программ” если это сервер терминалов или просто настольный компьютер с установленной серверной системой.

На десктопной системе можно выбрать “служб” если вы запускаете какую-то длительную компиляцию или рендерите видео, а потом вернуть обратно в состояние “программ“.

Изменение приоритета планировщиком

Планировщик Windows периодически меняет текущий приоритет потоков. Делается это например для:

  • повышения приоритета, если поток слишком долго ожидает выполнение (предотвращает зависание программы);
  • повышения приоритета, если происходит ввод из пользовательского интерфейса (сокращение времени отклика);
  • повышения приоритета, после завершения операции ввода/вывода (чтобы потоки ждущие ввод/вывод быстрее выполнялись). При ждать могут:
    • диск, cd-rom, параллельный порт, видео — повышение на 1 пункт;
    • сеть, почтовый слот, именованный канал, последовательный порт — повышение на 2 пункта;
    • клавиатура или мышь — повышение на 6 пунктов;
    • звуковая карта — повышение на 8 пунктов.

    Эксперимент

    Позвольте продемонстрировать следующий эксперимент, который покажет как посмотреть за повышением и понижением динамического приоритета:

    1. Запустите программу «Блокнот».
    2. Запустите «Системный монитор».
    3. Щелкните на кнопке панели инструментов «Добавить» (Add Counter).
    4. Выберите объект «Поток» (Thread), а затем выберите счетчик «Текущий приоритет» (Priority Current).
    5. В поле со списком введите «Notepad», а затем щелкните на кнопке «Поиск» (Search).
    6. Найдите строку «Notepad/0». Выберите ее, щелкните на кнопке «Добавить» (Add), а затем щелкните на кнопке «ОК».
    7. Как только вы щелкните мышкой по блокноту, то заметите в Системном мониторе, что приоритет у потока «Блокнот» поднялся до 12, если свернуть блокнот то приоритет вновь упадет до 10.

    Поток простоя — idle

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

    Групповое планирование

    Планирование потоков на базе потоков отлично работает, но не способно решить задачу равномерного распределения процессорного времени между несколькими пользователями на терминальном сервере. Потому в Windows Server 2012 появился механизм группового планирования.

    Термины группового планирования:

    • поколение — период времени, в течении которого отслеживается использование процессора;
    • квота — процессорное время, разрешенное группе на поколение (исчерпание квоты означает, что группа израсходовала весь свой бюджет);
    • вес — относительная важность группы от 1 до 9 (по умолчанию 5);
    • справедливое долевое планирование — вид планирования, при котором потокам исчерпавшим квоту могут выделяться циклы простоя;
    • ранг — приоритет групповой политики, 0 — наивысший, чем больше процессорного времени истратила группа, тем больше будет ранг, и с меньшей вероятностью получит процессорное время (ранг всегда превосходит приоритет) (0 ранг у потоков которые: не входят ни в одну группу, не израсходовали квоту, потоки с приоритетами реального времени).

    Где же применяется групповое планирование? Например его использует механизм DFSS для справедливого распределения процессорного времени между сеансами на машине. Этот механизм включается по умолчанию при установке роли служб терминалов.

    Помимо DFSS групповое планирование применяется в объектах Jobs (Задания), так мы можем ограничить Задание по % потребления CPU, например задание будет потреблять не больше 20% процессорного времени.

    Доброго времени!

    Т.е. тема достаточно интересна, и может быть очень полезна как для любителей игр, так и для работы с видео, фото и пр. ресурсоемкими задачами.

    Теперь ближе к сути.

    ускорение ПК

    Работа с приоритетами

    Какие они бывают (основы)

    У каждой запускаемой программы или процесса в Windows есть приоритет. Обычно, ОС Windows "сама знает" кому и что выделять, и делает это автоматически (без участия пользователя). Вообще разнообразие приоритетов не такое уж и большое:

    1. Idle (низкий) — программы, выполнение которых может и подождать (при выставлении данного приоритета некоторый софт может тормозить);
    2. Below Normal (ниже среднего);
    3. Normal (средний) — большинство программ запускаются со средним приоритетом;
    4. Above Normal (выше среднего);
    5. High (высокий);
    6. Real Time (реального времени) — самый высокий приоритет. При его выставлении — в первую очередь будет выполняться именно эта программа.

    Изменение приоритета

    Итак, чтобы поменять приоритет работающей программы (процесса) в Windows — необходимо воспользоваться диспетчером задач. Для того, чтобы его вызвать — нажмите сочетание кнопок Ctrl+Shift+Esc (либо Ctrl+Alt+Del).

    Для вызова диспетчера задач — нажмите Ctrl+Shift+Esc

    Для вызова диспетчера задач — нажмите Ctrl+Shift+Esc

    Далее откройте вкладку "Подробности" (это для Windows 11/10, для Windows 7 — "Процессы" ) и найдите в списке нужный процесс ( прим. : название программы совпадает с названием процесса).

    Задание приоритета для запущенного процесса

    Задание приоритета для запущенного процесса

    Сохранение приоритета с помощью настроек реестра

    После перезагрузки компьютера (или при перезапуске программы) — установленный вами приоритет сбрасывается (т.е. Windows снова задает его автоматически). И это не очень удобно.

    Но с помощью настроек реестра можно "сохранить" указанный вами приоритет (т.е. Windows будет "знать", что эту программу нужно запустить с таким-то приоритетом).

    Как это сделать:

    regedit — открыть редактор реестра

    regedit — открыть редактор реестра

    Какую ветку в реестре нужно открыть

    Какую ветку в реестре нужно открыть

    Узнаем название исполняемого файла игры

    Узнаем название исполняемого файла игры / Кликабельно

    Создание раздела / Реестр

    Создание раздела / Реестр

    Разделы

    Создать параметр DWORD32

    Создать параметр DWORD32

    Что получилось в итоге!

    Что получилось в итоге!

    Запуск приложения с нужным приоритетом (через командную строку)

    Есть еще один вариант задания приоритета приложению — речь идет о командной строке (разумеется, если создать "BAT" файл — то запуская его, можно всегда иметь программу с нужным приоритетом).

    Как это сделать:

      создать на рабочем столе (например) обычный текстовый файл;

    Читайте также: