Выбор текущего потока из нескольких активных потоков, пытающихся получить
Выбранный для выполнения поток работает в течение некоего периода, называемого квантом, по истечении которого поток вытесняется, то есть процессор передается другому потоку. Предполагается, что поток не знает, в какой момент он будет вытеснен. Поток также может быть вытеснен даже, если его квант еще не истек. Это происходит, когда к выполнению готов поток с более высоким приоритетом.
Процедура планирования обычно связана с весьма затратной процедурой диспетчеризации - переключением процессора на новый поток, поэтому планировщик должен заботиться об эффективном использовании процессора. Принадлежность потоков к процессу при планировании не учитывается, то есть единицей планирования в ОС Windows является именно поток. Запуск процедуры планирования удобно проиллюстрировать на упрощенной (по сравнению с диаграммой, изображенной на рис 5.3) диаграмме состояний потока, см. рис 6.1.
(рис 6.1) Упрощенная диаграмма состояний потоков в ОС WindowsНаиболее важным вопросом планирования является выбор момента для принятия решения. В ОС Windows запуск процедуры планирования вызывается одним из следующих событий.
Это, во-первых, события, связанные с освобождением процессора.
(1) Завершение потока
(2) Переход потока в состояние готовности в связи с тем, что его квант времени истек
(3) Переход потока в состояние ожидания
Во-вторых, это события, в результате которых пополняется или может пополниться очередь потоков в состоянии готовности.
(4) Поток вышел из состояния ожидания
(5) Поток только что создан
(6) Деятельность текущего потока может иметь следствием вывод другого потока из состояния ожидания.
В последнем случае выведенный из состояния ожидания поток может сразу же начать выполняться, если имеет высокий приоритет.
Наконец, процедура планирования может быть запущена, если изменяется
Заметим, что переключение из пользовательского режима в режим ядра (и обратно) не влияет на планирование потока, так как контекст в этом случае не меняется.
В результате операции планирования система может определить, какой поток выполнять следующим, и переключить контексты старого и нового потоков. В системе нет центрального потока планировщика. Программный код, отвечающий за планирование и диспетчеризацию, рассредоточен по ядру. В случаях 1-3 процедуры планирования работают в контексте текущего потока, который запускает программу планировщика для выбора преемника и потенциальной загрузки его контекста.
Перевод потока из состояния ожидания в состояние готовности (вариант 4) может быть следствием прерывания, свидетельствующим об окончании операции ввода-вывода. В этом случае процедура планирования может быть отложена (deffered procedure call) до окончания выполнения высокоприоритетного системного кода.
Иногда подобный переход происходит в результате деятельности другого потока, который, например, выполнил операцию up на семафоре (пример 6-го варианта). Хотя этот другой поток и может продолжить работу, он должен запустить процедуру планирования, поскольку в очереди готовности могут оказаться потоки с более высоким приоритетом. По тем же причинам планирование осуществляется в случае запуска нового потока.
В ОС Windows реализовано вытесняющее
В системе предусмотрено 32 уровня приоритетов. Шестнадцать значений приоритетов (16-31) соответствуют группе приоритетов реального времени, пятнадцать значений (1-15) предназначены для обычных потоков, и значение 0 зарезервировано для системного потока обнуления страниц (см. рис 6.2).
(рис 6.2) Приоритеты потоковЧтобы избавить пользователя от необходимости запоминать числовые значения приоритетов и иметь возможность модифицировать планировщик, разработчики ввели в систему слой абстрагирования приоритетов. Например, класс приоритета для всех потоков конкретного процесса можно задать с помощью набора констант-параметров функции SetPriorityClass, которые могут иметь следующие значения:
REALTIME_PRIORITY_CLASS ),HIGH_PRIORITY_CLASS ),ABOVE_NORMAL_PRIORITY_CLASS ),NORMAL_PRIORITY_CLASS ),BELOW_NORMAL_PRIORITY_CLASS )IDLE_PRIORITY_CLASS ).Относительный SetThreadPriority:
Совокупность из шести классов
| Классы |
Критичный ко времени | Самый высокий | Выше нормы | Нормальный | Ниже нормы | Самый низкий | Неработающий |
|---|---|---|---|---|---|---|---|
| Неработающий | 15 | 6 | 5 | 4 | 3 | 2 | 1 |
| Ниже нормы | 15 | 8 | 7 | 6 | 5 | 4 | 1 |
| Нормальный | 15 | 10 | 9 | 8 | 7 | 6 | 1 |
| Выше нормы | 15 | 12 | 11 | 10 | 9 | 8 | 1 |
| Высокий | 15 | 15 | 14 | 13 | 12 | 11 | 1 |
| Реального времени | 31 | 26 | 25 | 24 | 23 | 22 | 16 |
Базовый приоритет процесса и первичного потока по умолчанию равен значению из середины диапазонов
Приоритеты с 16 по 31 в действительности приоритетами реального времени не являются, поскольку в рамках поддержки мягкого реального времени, которая реализована в ОС Windows, никаких гарантий относительно сроков выполнения потоков не дается. Это просто более высокие приоритеты, которые зарезервированы для системных потоков и тех потоков, которым такой приоритет дает пользователь с административными правами. Тем не менее, наличие приоритетов реального времени, а также вытесняемость кода ядра, локализация страниц памяти (см. лекцию 10) и ряд дополнительных возможностей - все это позволяет выполнять в среде ОС Windows приложения мягкого реального времени, например, мультимедийные. Системный поток с нулевым приоритетом занимается обнулением страниц памяти. Обычные пользовательские потоки могут иметь приоритеты от 1 до 15.
Планировщик принимает решения на основе текущего
Например, после завершения операции ввода-вывода увеличивают
Другими примерами подобных ситуаций могут служить: пробуждение потока после состояния ожидания семафора или иного события; получение потоком доступа к оконному вводу.
Динамическое повышение приоритета решает также проблему голодания потоков, долго не получающих
Динамическое повышение приоритетов призвано оптимизировать SetProcessPriorityBoost и SetThreadPriorityBoost.
#include <windows.h>
#include <stdio.h>
#include <math.h>
void Calculations()
{
int i,N=50000000;
double a,b;
for ( i = 0; i<N; i++) {
b=(double)i / (double)N;
a=sin(b);
}
}
DWORD WINAPI SecondThread( LPVOID lpParam )
{
printf("Begin of Second Thread\n");
Calculations();
printf("End of Second Thread\n");
return 0;
}
VOID main( VOID )
{
DWORD dwThreadId, dwThrdParam;
HANDLE hThread;
hThread = CreateThread(
NULL,
0,
SecondThread,
dwThrdParam,
0,
dwThreadId);
if (hThread == NULL)
{
printf("CreateThread failed\n" );
return;
}
SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL);
SuspendThread(hThread);
getchar();
ResumeThread(hThread);
printf("Begin of First Thread\n");
Calculations();
printf("End of First Thread\n");
}
В приведенной программе два параллельных потока выполняют длительный счетный цикл (подпрограмма Calculations). Второй поток в силу более высокого приоритета выполняется раньше. (приостановка и возобновление потока) используется для фиксации начала соревнования. Если закомментировать SetThreadPriority, то можно будет увидеть, что оба потока заканчивают работу одновременно.
В качестве самостоятельного упражнения рекомендуется реализовать более гибкие сценарии планирования, например, с добавлением функций SwitchToThread (передача управления потоку), или Sleep (приостановка потока в течение заданного промежутка времени). В MSDN имеется описание множества полезных функций, связанных с планированием потоков.
Величина кванта времени имеет критическое значение для эффективной работы системы в целом. Необходимо сохранить интерактивные качества системы и при этом избежать слишком частого
По умолчанию начальная величина кванта в Windows Professional равна двум интервалам таймера, а в Windows Server эта величина увеличена до 12, чтобы свести к минимуму переключение контекста. Длительность интервала таймера определяется
Выбор между короткими и длинными значениями можно сделать с помощью панели "свойства" "Моего компьютера". Величина кванта задается в параметре HKLM\SYSTEM\CurrentControlSet\Control\PriorityControl\Win32PrioritySeparation реестра.
Реентерабельность кода ядра позволяет ОС Windows поддерживать симметричные мультипроцессорные системы (процессоры идентичны). Необходимость загрузки нескольких процессоров усложняет задачу планирования. Количество процессоров система определяет при загрузке, и эта информация становится доступной приложениям через функцию GetSystemInfo. Число процессоров, используемых системой, может быть ограничено с помощью параметра NumPcs из файла Boot.ini.
Ведение отдельных очередей готовых к выполнению потоков для каждого из процессоров может иметь следствием неравномерную загрузку процессоров, поэтому используется общая очередь потоков в состоянии готовности. Любой поток становится в очередь и планируется на любой доступный процессор.
Поскольку в системе нет главного процессора, каждый процессор занимается самопланированием и выбирает поток из очереди готовности. Чтобы гарантировать, что два процессора не выберут один и тот же поток, для каждого процессора организовывается эксклюзивный доступ к данной очереди за счет использования
У каждого потока имеется маска привязки к процессорам (SetProcessAffinityMask и SetThreadAfftnityMask или с помощью инструментальных средств Windows (например, это может сделать диспетчер задач). Есть также возможность сформировать априорную маску привязки в файле образе запускаемого процесса.
Помимо номера последнего процессора в блоке ядра потока KTHREAD хранится номер идеального процессора (ideal processor) - предпочтительного для выполнения данного потока. Идеальный процессор выбирается случайным образом при создании потока. Это значение увеличивается на 1 всякий раз, когда создается новый поток, поэтому создаваемые потоки равномерно распределяются по набору доступных процессоров. Поток может поменять это значение с помощью функции SetThreadIdealProcessor.
Готовый к выполнению поток система пытается подключить к простаивающему процессору. Если таких несколько, то предпочтение отдается идеальному процессору данного потока, а затем последнему из процессоров, на котором поток выполнялся. Если все процессоры заняты, то делается проверка на возможность вытеснить какой-либо выполняющийся или ждущий поток (в первую очередь на идеальном процессоре, затем - на последнем для данного потока). Если вытеснение невозможно, новый поток помещается в очередь готовых потоков с соответствующим уровнем приоритета и ждет выделения процессорного времени.
Таким образом, в ОС Windows реализовано двухуровневое планирование. На верхнем уровне алгоритма потоки приписываются конкретным (идеальным, последним, наименее загруженным) центральным процессорам, в результате чего у каждого процессора создается своя очередь потоков. На нижнем уровне каждым процессором осуществляется реальное планирование при помощи приоритетов и других средств.
Например, если какой-либо процессор начинает простаивать, у загруженного работой процессора отбирается поток и отдается ему. Двухуровневое планирование равномерно распределяет нагрузку среди процессоров и использует преимущество родственности кэша.
Жесткая привязка (hard SetProcessAffinityMask и SetThreadAfftnityMask, целесообразна в архитектурах с неунифицируемым (NUMA) доступом, где
скорость доступа к памяти зависит от взаимного расположения процессоров и банков памяти на системных платах.
Процессорное время - ограниченный ресурс, поэтому планирование - важная и критичная для производительности операция. Один из ключевых вопросов - выбор момента для запуска процедуры планирования. В системе реализовано приоритетное
Выбор текущего потока из нескольких активных потоков, пытающихся получить
Выбранный для выполнения поток работает в течение некоего периода, называемого квантом, по истечении которого поток вытесняется, то есть процессор передается другому потоку. Предполагается, что поток не знает, в какой момент он будет вытеснен. Поток также может быть вытеснен даже, если его квант еще не истек. Это происходит, когда к выполнению готов поток с более высоким приоритетом.
Процедура планирования обычно связана с весьма затратной процедурой диспетчеризации - переключением процессора на новый поток, поэтому планировщик должен заботиться об эффективном использовании процессора. Принадлежность потоков к процессу при планировании не учитывается, то есть единицей планирования в ОС Windows является именно поток. Запуск процедуры планирования удобно проиллюстрировать на упрощенной (по сравнению с диаграммой, изображенной на рис 5.3) диаграмме состояний потока, см. рис 6.1.
(рис 6.1) Упрощенная диаграмма состояний потоков в ОС WindowsНаиболее важным вопросом планирования является выбор момента для принятия решения. В ОС Windows запуск процедуры планирования вызывается одним из следующих событий.
Это, во-первых, события, связанные с освобождением процессора.
(1) Завершение потока
(2) Переход потока в состояние готовности в связи с тем, что его квант времени истек
(3) Переход потока в состояние ожидания
Во-вторых, это события, в результате которых пополняется или может пополниться очередь потоков в состоянии готовности.
(4) Поток вышел из состояния ожидания
(5) Поток только что создан
(6) Деятельность текущего потока может иметь следствием вывод другого потока из состояния ожидания.
В последнем случае выведенный из состояния ожидания поток может сразу же начать выполняться, если имеет высокий приоритет.
Наконец, процедура планирования может быть запущена, если изменяется
Заметим, что переключение из пользовательского режима в режим ядра (и обратно) не влияет на планирование потока, так как контекст в этом случае не меняется.
В результате операции планирования система может определить, какой поток выполнять следующим, и переключить контексты старого и нового потоков. В системе нет центрального потока планировщика. Программный код, отвечающий за планирование и диспетчеризацию, рассредоточен по ядру. В случаях 1-3 процедуры планирования работают в контексте текущего потока, который запускает программу планировщика для выбора преемника и потенциальной загрузки его контекста.
Перевод потока из состояния ожидания в состояние готовности (вариант 4) может быть следствием прерывания, свидетельствующим об окончании операции ввода-вывода. В этом случае процедура планирования может быть отложена (deffered procedure call) до окончания выполнения высокоприоритетного системного кода.
Иногда подобный переход происходит в результате деятельности другого потока, который, например, выполнил операцию up на семафоре (пример 6-го варианта). Хотя этот другой поток и может продолжить работу, он должен запустить процедуру планирования, поскольку в очереди готовности могут оказаться потоки с более высоким приоритетом. По тем же причинам планирование осуществляется в случае запуска нового потока.
В ОС Windows реализовано вытесняющее
В системе предусмотрено 32 уровня приоритетов. Шестнадцать значений приоритетов (16-31) соответствуют группе приоритетов реального времени, пятнадцать значений (1-15) предназначены для обычных потоков, и значение 0 зарезервировано для системного потока обнуления страниц (см. рис 6.2).
(рис 6.2) Приоритеты потоковЧтобы избавить пользователя от необходимости запоминать числовые значения приоритетов и иметь возможность модифицировать планировщик, разработчики ввели в систему слой абстрагирования приоритетов. Например, класс приоритета для всех потоков конкретного процесса можно задать с помощью набора констант-параметров функции SetPriorityClass, которые могут иметь следующие значения:
REALTIME_PRIORITY_CLASS ),HIGH_PRIORITY_CLASS ),ABOVE_NORMAL_PRIORITY_CLASS ),NORMAL_PRIORITY_CLASS ),BELOW_NORMAL_PRIORITY_CLASS )IDLE_PRIORITY_CLASS ).Относительный SetThreadPriority:
Совокупность из шести классов
| Классы |
Критичный ко времени | Самый высокий | Выше нормы | Нормальный | Ниже нормы | Самый низкий | Неработающий |
|---|---|---|---|---|---|---|---|
| Неработающий | 15 | 6 | 5 | 4 | 3 | 2 | 1 |
| Ниже нормы | 15 | 8 | 7 | 6 | 5 | 4 | 1 |
| Нормальный | 15 | 10 | 9 | 8 | 7 | 6 | 1 |
| Выше нормы | 15 | 12 | 11 | 10 | 9 | 8 | 1 |
| Высокий | 15 | 15 | 14 | 13 | 12 | 11 | 1 |
| Реального времени | 31 | 26 | 25 | 24 | 23 | 22 | 16 |
Базовый приоритет процесса и первичного потока по умолчанию равен значению из середины диапазонов
Приоритеты с 16 по 31 в действительности приоритетами реального времени не являются, поскольку в рамках поддержки мягкого реального времени, которая реализована в ОС Windows, никаких гарантий относительно сроков выполнения потоков не дается. Это просто более высокие приоритеты, которые зарезервированы для системных потоков и тех потоков, которым такой приоритет дает пользователь с административными правами. Тем не менее, наличие приоритетов реального времени, а также вытесняемость кода ядра, локализация страниц памяти (см. лекцию 10) и ряд дополнительных возможностей - все это позволяет выполнять в среде ОС Windows приложения мягкого реального времени, например, мультимедийные. Системный поток с нулевым приоритетом занимается обнулением страниц памяти. Обычные пользовательские потоки могут иметь приоритеты от 1 до 15.
Планировщик принимает решения на основе текущего
Например, после завершения операции ввода-вывода увеличивают
Другими примерами подобных ситуаций могут служить: пробуждение потока после состояния ожидания семафора или иного события; получение потоком доступа к оконному вводу.
Динамическое повышение приоритета решает также проблему голодания потоков, долго не получающих
Динамическое повышение приоритетов призвано оптимизировать SetProcessPriorityBoost и SetThreadPriorityBoost.
#include <windows.h>
#include <stdio.h>
#include <math.h>
void Calculations()
{
int i,N=50000000;
double a,b;
for ( i = 0; i<N; i++) {
b=(double)i / (double)N;
a=sin(b);
}
}
DWORD WINAPI SecondThread( LPVOID lpParam )
{
printf("Begin of Second Thread\n");
Calculations();
printf("End of Second Thread\n");
return 0;
}
VOID main( VOID )
{
DWORD dwThreadId, dwThrdParam;
HANDLE hThread;
hThread = CreateThread(
NULL,
0,
SecondThread,
dwThrdParam,
0,
dwThreadId);
if (hThread == NULL)
{
printf("CreateThread failed\n" );
return;
}
SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL);
SuspendThread(hThread);
getchar();
ResumeThread(hThread);
printf("Begin of First Thread\n");
Calculations();
printf("End of First Thread\n");
}
В приведенной программе два параллельных потока выполняют длительный счетный цикл (подпрограмма Calculations). Второй поток в силу более высокого приоритета выполняется раньше. (приостановка и возобновление потока) используется для фиксации начала соревнования. Если закомментировать SetThreadPriority, то можно будет увидеть, что оба потока заканчивают работу одновременно.
В качестве самостоятельного упражнения рекомендуется реализовать более гибкие сценарии планирования, например, с добавлением функций SwitchToThread (передача управления потоку), или Sleep (приостановка потока в течение заданного промежутка времени). В MSDN имеется описание множества полезных функций, связанных с планированием потоков.
Величина кванта времени имеет критическое значение для эффективной работы системы в целом. Необходимо сохранить интерактивные качества системы и при этом избежать слишком частого
По умолчанию начальная величина кванта в Windows Professional равна двум интервалам таймера, а в Windows Server эта величина увеличена до 12, чтобы свести к минимуму переключение контекста. Длительность интервала таймера определяется
Выбор между короткими и длинными значениями можно сделать с помощью панели "свойства" "Моего компьютера". Величина кванта задается в параметре HKLM\SYSTEM\CurrentControlSet\Control\PriorityControl\Win32PrioritySeparation реестра.
Реентерабельность кода ядра позволяет ОС Windows поддерживать симметричные мультипроцессорные системы (процессоры идентичны). Необходимость загрузки нескольких процессоров усложняет задачу планирования. Количество процессоров система определяет при загрузке, и эта информация становится доступной приложениям через функцию GetSystemInfo. Число процессоров, используемых системой, может быть ограничено с помощью параметра NumPcs из файла Boot.ini.
Ведение отдельных очередей готовых к выполнению потоков для каждого из процессоров может иметь следствием неравномерную загрузку процессоров, поэтому используется общая очередь потоков в состоянии готовности. Любой поток становится в очередь и планируется на любой доступный процессор.
Поскольку в системе нет главного процессора, каждый процессор занимается самопланированием и выбирает поток из очереди готовности. Чтобы гарантировать, что два процессора не выберут один и тот же поток, для каждого процессора организовывается эксклюзивный доступ к данной очереди за счет использования
У каждого потока имеется маска привязки к процессорам (SetProcessAffinityMask и SetThreadAfftnityMask или с помощью инструментальных средств Windows (например, это может сделать диспетчер задач). Есть также возможность сформировать априорную маску привязки в файле образе запускаемого процесса.
Помимо номера последнего процессора в блоке ядра потока KTHREAD хранится номер идеального процессора (ideal processor) - предпочтительного для выполнения данного потока. Идеальный процессор выбирается случайным образом при создании потока. Это значение увеличивается на 1 всякий раз, когда создается новый поток, поэтому создаваемые потоки равномерно распределяются по набору доступных процессоров. Поток может поменять это значение с помощью функции SetThreadIdealProcessor.
Готовый к выполнению поток система пытается подключить к простаивающему процессору. Если таких несколько, то предпочтение отдается идеальному процессору данного потока, а затем последнему из процессоров, на котором поток выполнялся. Если все процессоры заняты, то делается проверка на возможность вытеснить какой-либо выполняющийся или ждущий поток (в первую очередь на идеальном процессоре, затем - на последнем для данного потока). Если вытеснение невозможно, новый поток помещается в очередь готовых потоков с соответствующим уровнем приоритета и ждет выделения процессорного времени.
Таким образом, в ОС Windows реализовано двухуровневое планирование. На верхнем уровне алгоритма потоки приписываются конкретным (идеальным, последним, наименее загруженным) центральным процессорам, в результате чего у каждого процессора создается своя очередь потоков. На нижнем уровне каждым процессором осуществляется реальное планирование при помощи приоритетов и других средств.
Например, если какой-либо процессор начинает простаивать, у загруженного работой процессора отбирается поток и отдается ему. Двухуровневое планирование равномерно распределяет нагрузку среди процессоров и использует преимущество родственности кэша.
Жесткая привязка (hard SetProcessAffinityMask и SetThreadAfftnityMask, целесообразна в архитектурах с неунифицируемым (NUMA) доступом, где
скорость доступа к памяти зависит от взаимного расположения процессоров и банков памяти на системных платах.
Процессорное время - ограниченный ресурс, поэтому планирование - важная и критичная для производительности операция. Один из ключевых вопросов - выбор момента для запуска процедуры планирования. В системе реализовано приоритетное
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.