- •Методичні вказівки до лабораторних робіт по курсу "інтерфейси паралельного програмування "
- •Методичні вказівки до лабораторних робіт по курсу "інтерфейси паралельного програмування "
- •7091502 “Системне програмування”;
- •Общие положения
- •1. Управление процессами и потоками
- •1.3.2. Создание и завершение процесса
- •1.3.3. Создание и завершение потока Поток создается вызовом функции
- •1.3.4. Приостановка и возобновление потоков
- •1.3.5. Переключение потоков
- •1.3.6. Определение периодов выполнения потоков
- •1.3.7. Приоритеты потоков
- •1.4. Задание на лабораторную работу
- •1.5. Контрольные вопросы и задания
- •2. Объекты синхронизации потоков и процессов
- •2.3.2. Мьютексы
- •2.3.3. Семафоры
- •Программа завершает работу с семафором вызовом функции
- •2.3.4.События
- •2.3.5. Wait -функции
- •2.4. Задание на лабораторную работу
- •2.5. Контрольные вопросы и задания
- •3. Обмен данными между программами на основе объекта winsock
- •3.1. Цель работы
- •3.2. Указания по подготовке к выполнению лабораторной работы
- •3.3. Сущность работы
- •3.3.1. Сторона клиента.
- •3.3.2 Сторона сервера
- •3.4. Задание на лабораторную работу
- •4.5. Контрольные вопросы и задания
- •4. Интерфейс параллельного программирования
- •4.1. Цель работы
- •4.2. Указания по подготовке к выполнению лабораторной работы
- •4.3. Обзор темы работы
- •4.3.1. Mpi. Терминология и обозначения
- •4.3.2. Общие процедуры mpi
- •4.3.3. Прием/передача сообщений между отдельными процессами
- •4.3.4. Прием/передача сообщений без блокировки
- •4.3.5. Объединение запросов на взаимодействие
- •4.3.6. Совмещенные прием/передача сообщений
- •4.3.7. Коллективные взаимодействия процессов
- •4.3.8. Синхронизация процессов
- •4.3.9. Работа с группами процессов
- •4.4. Задание на лабораторную работу
- •Вариант 2
- •4.5. Контрольные вопросы и задания
- •5.4. Задание на лабораторную работу
- •5.5. Контрольные вопросы и задания
- •Список литературы
- •Содержание
1.3.5. Переключение потоков
Следующая функция позволяет подключить к процессору следующий планируемый поток (конечно, если он есть):
BOOL SwitchToThread();
Когда вызывается данная функция, система проверяет, есть ли поток, которому не хватает процессорного времени. Если нет, SwitchToThread немедленно возвращает управление (результат функции в этом случае - FALSE), а если да, планировщик отдает ему дополнительный квант времени. По истечению этого кванта времени планировщик возвращается в нормальный режим.
1.3.6. Определение периодов выполнения потоков
Для определения времени, которое затрачивает поток на выполнение какого-либо сложного алгоритма, нельзя использовать метод, основанный на определении разницы между временем перед началом работы потока и временем завершения алгоритма. Например,
int Start = GetTickCount();
// Алгоритм
int Res = GetTickCount() – Start;
Данный метод основан на допущении, что выполняемый поток не будет прерван. В реальности, это условие невыполнимо. Поэтому, существует специальная функция, определяющая временные характеристики потока:
BOOL GetThreadTimes(
HANDLE hThread,
LPFILETIME lpCreationTime ,
LPFILETIME lpExitTime ,
LPFILETIME lpKernelTime ,
LPFILETIME lpUserTime
);
lpCreationTime - абсолютная величина, выраженная в интервалах по 100нс. Отсчитывается с полуночи 1 января 1601 года по Гринвичу до момента создания потока.
LpExitTime - абсолютная величина , выраженная в интервалах по 100нс. Отсчитывается с полуночи 1 января 1601 года по Гринвичу до момента завершения потока. Если поток все еще выполняется, этот показатель имеет неопределенное значение (либо устанавливается в 0).
LpKernelTime - абсолютная величина , выраженная в интервалах по 100нс. Сообщает время, затраченное потоком на выполнение кода операционной системы.
LpUserTime - абсолютная величина , выраженная в интервалах по 100нс. Сообщает время, затраченное потоком на выполнение кода приложения.
С помощью этой функции можно определить время, необходимое для выполнения сложного алгоритма:
FILETIME KernelStart, KernerEnd;
FILETIME UserStart, UserEnd;
FILETIME t;
GetThreadTimes(GetCurrentThread(), &t, &t, &KernelStart,&UserStart);
// ввыполняем алгоритм
GetThreadTimes(GetCurrentThread(), &t, &t, &KernelEnd,&UserEnd);
int TimeKernel = KernelEnd.dwLowDateTime-KernelEnd.dwLowDateTime;
int UserKernel = UserEnd.dwLowDateTime-UserEnd.dwLowDateTime;
// при условии, что время помещается в 32 бита!
Существует аналогичная функции GetThreadTimes для определения суммарного времени, затрачиваемого на выполнения всех потоков процесса.
Существуют две специальные функции для высокоточного измерения интервалов, применение которых основано на допущении, что они применяются для быстро выполняемых участков кода, которые не вытесняются:
BOOL QueryPerformanceFrequency( LARGE_INTEGER *lpFrequency );
BOOL QueryPerformanceCounter( LARGE_INTEGER *lpPerformanceCount);
Вот пример применения этих функций:
LARGE_INTEGER Fraq;
LARGE_INTEGER St, En;
QueryPerformanceFrequency(&Fraq);
QueryPerformanceCounter(&St);
// ввыполняем алгоритм
QueryPerformanceCounter(&En);
int Rez = ( (En.QuadPart – St.QuadPart) * 1000 ) / Fraq.QuadPart;
//результат в миллисекундах