Лабораторные работы по предмету "Параллельное программирование" для 1 курса магистратуры СППО Университета ИТМО
Вариант A = 280; map=[4,6]; merge=4; sort=4
-
На компьютере с многоядерным процессором установить ОС Linux и компилятор GCC версии не ниже 4.7.2. При невозможности установить Linux или отсутствии компьютера с многоядерным процессором можно выполнять лабораторную работу на виртуальной машине. Минимальное количество ядер при использовании виртуальной машины - 2.
-
На языке Cи написать консольную программу lab1.c, решающую задачу, указанную в п.IV (см. ниже). В программе нельзя исполь- зовать библиотечные функции сортировки, выполнения матричных операций и расчёта статистических величин. В программе нельзя использовать библиотечные функции, отсутствующие в стандарт- ных заголовочных файлах stdio.h, stdlib.h, math.h, sys/time.h. Задача должна решаться 100 раз с разными начальными значениями ге- нератора случайных чисел (ГСЧ). Структура программы примерно следующая:
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
int main(int argc, char* argv[])
{
int i, N;
struct timeval T1, T2;
long delta_ms;
N = atoi(argv[1]); /* N равен первому параметру командной строки */
gettimeofday(&T1, NULL); /* запомнить текущее время T1 */
for (i=0; i<100; i++) /* 100 экспериментов */
{
srand(i); /* инициализировать начальное значение ГСЧ */
/* Заполнить массив исходных данных размером N */
/* Решить поставленную задачу, заполнить массив с результатами
/* Отсортировать массив с результатами указанным методом */
}
gettimeofday(&T2, NULL); /* запомнить текущее время T2 */
delta_ms = 1000*(T2.tv_sec - T1.tv_sec) + (T2.tv_usec - T1.tv_usec) / 1000;
printf("\nN=%d. Milliseconds passed: %ld\n", N, delta_ms); /* T2 - T1 */
return 0;
}
-
Скомпилировать написанную программу без использования авто- матического распараллеливания с помощью следующей команды:
/home/user/gcc -O3 -Wall -Werror -o lab1-seq lab1.c
-
Скомпилировать написанную программу, используя встроенное в gcc средство автоматического распараллеливания Graphite с помо- щью следующей команды
/home/user/gcc -O3 -Wall -Werror -floop- parallelize-all -ftree-parallelize-loops=K lab1.c -o lab1-par-K
(пере- менной K поочерёдно присвоить хотя бы 4 значения: 1, меньше количества ядер, равное количеству физических ядер и больше ко- личества физических ядер). -
В результате получится одна нераспараллеленная программа и че- тыре или более распараллеленных.
-
Закрыть все работающие в операционной системе прикладные про- граммы (включая Winamp, uTorrent, браузеры и Skype), чтобы они не влияли на результаты последующих экспериментов. При ис- пользовании ноутбука необходимо иметь постоянное подключение к сети питания, на время проведения эксперимента.
-
Запускать файл lab1-seq из командной строки, увеличивая значения N до значения N1, при котором время выполнения превысит 0.01 с. Подобным образом найти значение N=N2, при котором время выполнения превысит 5 с.
-
Используя найденные значения N1 и N2, выполнить следующие эксперименты (для автоматизации проведения экспериментов рекомендуется написать скрипт):
- запускать lab1-seq для значений
N = N1, N1+∆, N1+2∆, N1+3∆,..., N2
и записывать получающиеся значения времениdelta_ms(N)
в функциюseq(N)
; - запускать lab1-par-K для значений
N = N1, N1+∆, N1+2∆, N1+3∆,..., N2
и записывать получающиеся значения времениdelta_ms(N)
в функциюpar − K(N)
; - значение ∆ выбрать так:
∆ = (N2 − N1)/10
.
- запускать lab1-seq для значений
-
Провести верификацию значения X. Добавить в конец цикла вывод значения X и изменить количество экспериментов на 5. Сравнить значения X для распараллеленной программы и не распараллеленной.
-
Написать отчёт о проделанной работе.
-
Подготовиться к устным вопросам на защите.
-
Найти вычислительную сложность алгоритма до и после распарал- леливания, сравнить полученные результаты.
-
Необязательное задание No1 (для получения оценки «четыре» и «пять»). Провести аналогичные описанным экс- перименты, используя вместо gcc компилятор Solaris Studio (или любой другой на своё усмотрение). При компиля- ции следует использовать следующие опции для автома- тического распараллеливания:
solarisstudio -cc -O3 - xautopar -xloopinfo lab1.c
. -
Необязательное задание No2 (для получения оценки «пять»). Это задание выполняется только после выполнения предыдущего пункта. Провести аналогичные описанным эксперименты, исполь- зуя вместо gcc компилятор Intel ICC (или любой другой на своё усмотрение). В ICC следует при компиляции использовать следу- ющие опции для автоматического распараллеливания:
icc -parallel -par-threashold0 -par-num-threads=K -o lab1-icc-par-K lab1.c
.
-
В исходном коде программы, полученной в результате выполнения лабораторной работы №1, нужно на этапах Map и Merge все циклы с вызовами математических функций заменить их векторными ана- логами из библиотеки «AMD Framewave» (http://framewave. sourceforge.net). При выборе конкретной Framewave-функции необходимо убедиться, что она помечена как
MT
(Multi-Threaded), т.е. распараллеленная. Полный перечень доступных функций на- ходится по ссылке: http://framewave.sourceforge.net/Manual/fw_section_060.html#fw_section_060. Например, Framewave-функцияmin
в списке поддерживаемых технологий имеет толькоSSE2
, но неMT
.Примечание: выбор библиотеки Framewave не является обязатель- ным, можно использовать любую другую параллельную библиоте- ку, если в ней нужные функции распараллелены, так, например, можно использовать ATLAS (для этой библиотеки необходимо вы- ключить троттлинг и энергосбережение, а также разобраться с ме- ханизмом изменения числа потоков) или Intel Integrated Performance Primitives.
-
Добавить в начало программы вызов Framewave-функции
SetNumThreads(M)
для установки количества создаваемых парал- лельной библиотекой потоков, задействуемых при выполнении рас- параллеленных Framewave-функций. Нужное число M следует уста- навливать из параметра командной строки(argv)
для удобства ав- томатизации экспериментов.Примечание: При использовании Intel IPP функцию SetNumThreads(M) не нужно использовать. Необходимо компилировать программу под разное количество потоков.
-
Скомпилировать программу, не применяя опции автоматического распараллеливания, использованные в лабораторной работе №1. Провести эксперименты с полученной программой для тех же значений N1 и N2, которые использовались в лабораторной работе No1, при M = 1, 2, . . . , K, где K – количество процессоров (ядер) на экспериментальном стенде.
-
Сравнить полученные результаты с результатами лабораторной ра- боты No1: на графиках показать, как изменилось время выполне- ния программы, параллельное ускорение и параллельная эффективность.
-
Написать отчёт о проделанной работе.
-
Подготовиться к устным вопросам на защите.
-
Необязательное задание №1 (для получения оценки «четыре» и «пять»). Исследовать параллельное ускорение для различных зна- чений M > K, т.е. оценить накладные расходы при создании чрез- мерного большого количества потоков. Для иллюстрации того, что программа действительно распараллелилась, привести график за- грузки процессора (ядер) во время выполнения программы при N = N2 для всех использованных M. Для получения графика можно как написать скрипт, так и просто сделать скриншот дис- петчера задач, указав на скриншоте моменты начала и окончания эксперимента (в отчёте нужно привести текст скрипта или назва- ние использованного диспетчера).
-
Необязательное задание №2 (для получения оценки «пять»). Это задание выполняется только после выполнения предыдущего пунк- та. Используя закон Амдала, рассчитать коэффициент распаралле- ливания для всех экспериментов и привести его на графиках. Про- комментировать полученные результаты.
-
Добавить во все for-циклы (кроме цикла в функции main, указывающего количество экспериментов) в программе из ЛР №1 следующую директиву OpenMP:
#pragma omp parallel for default(none) private(...) shared(...)
Наличие параметра default(none) является обязательным. -
Проверить все for-циклы на внутренние зависимости по данным между итерациями. Если зависимости обнаружились, использовать для защиты критических секций директиву ”#pragma omp critical” или ”#pragma omp atomic” (если операция атомарна), или параметр reduction (предпочтительнее) или вообще отказаться от распарал- леливания цикла (свой выбор необходимо обосновать).
-
Убедиться, что получившаяся программа обладает свойством прямой совместимости с компиляторами, не поддерживающими OpenMP (для проверки этого можно скомпилировать программу без опции
–fopenmp
, в результате не должно быть сообщений об ошибках, а программа должна корректно работать). -
Использовать функцию SetNumThreads для изменения числа потоков. В отчете указать максимальное количество потоков.
-
Провести эксперименты, замеряя параллельное ускорение. Привести сравнение графиков параллельного ускорения с ЛР №1 и ЛР №2.
-
Провести эксперименты, добавив параметр ”schedule” и варьируя в экспериментах тип расписания. Исследование нужно провести для всех возможных расписаний: static, dynamic, guided. С 4 вариантами chunck_size равными: единице, меньше чем число потоков, равному числу потоков и больше чем число потоков. Привести сравнение параллельного ускорения при различных расписаниях с результатами п.4.
-
Определить какой тип расписания на машине при использовании
schedule
default
. -
Выбрать из рассмотренных в п.4 и п.5 наилучший вариант при различных N. Сформулировать условия, при которых наилучшие результаты получились бы при использовании других типов рас- писания.
-
Найти вычислительную сложность алгоритма до и после распарал- леливания, сравнить полученные результаты.
-
Для иллюстрации того, что программа действительно распаралле- лилась, привести график загрузки процессора (ядер) от времени при выполнении программы при N = N1 для лучшего варианта распараллеливания. Для получения графика можно как написать скрипт так и просто сделать скриншот диспетчера задач, указав на скриншоте моменты начала и окончания эксперимента (в от- чёте нужно привести текст скрипта или название использованно- го диспетчера). Недостаточно привести однократное моментальное измерение загрузки утилитой htop, т.к. требуется привести график изменения загрузки за всё время выполнения программы.
-
Написать отчёт о проделанной работе.
-
Подготовиться к устным вопросам на защите.
-
Необязательное задание №1 (для получения оценки «четыре» и «пять»). Построить график параллельного ускорения для точек N < N1 и найти значения N, при которых накладные расходы на распараллеливание превышают выигрыш от распараллеливания (независимо для различных типов расписания).
-
Необязательное задание №2 (для получения оценки «пять») Для лучшего результата по итогам всех экспериментов сделать еще минимум 3 эксперимента, заменив флаг -O3 на другие флаги оптимизации. Построить график времени выполнения от N.
-
Взять в качестве исходной OpenMP-программу из ЛР-4, в которой распараллелены все этапы вычисления. Убедиться, что в этой программе корректно реализован одновременный доступ к общей переменной, используемой для вывода в консоль процента завершения программы.
-
Изменить исходную программу так, чтобы вместо OpenMP-директив применялся стандарт «POSIX Threads»:
- для получения оценки «3» достаточно изменить только один этап (Generate, Map, Merge, Sort), который является узким местом (bottle neck), а также функцию вывода в консоль процента завершения программы;
- для получения оценки «4» и «5» необходимо изменить всю программу, но допускается в качестве расписания циклов использовать «schedule static»;
- для получения оценки «5» необходимо хотя бы один цикл распараллелить, реализовав вручную расписание «schedule dynamic» или «schedule guided».
- Провести эксперименты и по результатам выполнить сравнение работы двух параллельных программ («OpenMP» и «POSIX Threads»), которое должно описывать следующие аспекты работы обеих программ (для различных N):
- полное время решения задачи;
- параллельное ускорение;
- доля времени, проводимого на каждом этапе вычисления («нормированная диаграмма с областями и накоплением»);
- количество строк кода, добавленных при распараллеливании, а также грубая оценка времени, потраченного на распараллеливание (накладные расходы программиста);
- остальные аспекты, которые вы выяснили самостоятельно
- Вам необходимо реализовать один (для оценки 3) или два (для оценки 4) этапа вашей программы из предыдущих лабораторных работ. При этом вычисления можно проводить как на CPU, так и на GPU (на своё усмотрение, но GPU предпочтительнее).
- Дополнительной задание (оценка 5).
- Выполнение заданий для оценки 3 и 4.
- Расчёт доверительного интервала.
- Посчитать время 2 способами: с помощью profiling и с помощью обычного замера (как в предыдущих заданиях).
- Оценить накладные расходы, такие как доля времени, проводимого на каждом этапе вычисления («нормированная диаграмма с областями и накоплением»), число строк кода, добавленных при распараллеливании, а также грубая оценка времени, потраченного на распараллеливание (накладные расходы программиста), и т.п.
- Необязательное задание для магистрантов с большим количеством свободного времени: проводить вычисления совместно на GPU и CPU (т.е. итерации в некоторой обоснованной пропорции делятся между GPU и CPU, и параллельно на них выполняются).
- При желании данную лабораторную работу можно написать на CUDA.