Содержание лекции

Download Report

Transcript Содержание лекции

Содержание
Время
Тема
20.07.09
18-00 – 19-00
Часть 1. Введение в параллелизм (коротко). Знакомство с WHPC.
Знакомство с примером. Запуск первой программы на кластере.
Распараллеливание задачи. Многопоточное программирование.
21.07.09
15-00 – 16-00
Часть 2. Первая программа на MPI. Распараллеливание задачи на
MPI.
23.07.09
15-00 – 16-00
Часть 3. Отладка параллельных программ. Оптимизация
параллельных приложений. Параллелизм в управляемом коде,
MPI.NET.
Инфраструктура
• Туалеты
• Перерывы
• Эвакуация != 
Тренеры
Денис Котляров, Microsoft
Василий Маланин, Microsoft
Андрей Паринов, Независимый эксперт
Группа поддержки
Часть 1. Введение в параллелизм.
Многопоточное программирование.
Введение
-
Зачем?
Типы параллелизма.
Ускорение -> Эффективность vs Переносимость
Распараллеливание = Инструменты &&
(Предметные области || Задачи)
Описание предметной области
Описание предметной области
800
600
Описание предметной области
Закон Амдала
P
Tпаралл. = {(1-P) + P/n} Tпослед
(1-P)
P/2
(1-P)
TПослед.
• Описывает верхний предел ускорения от
параллельного выполнения
n = количество проц.
P/∞
Ускорение = Tпослед / Tпаралл.
Последовательный код ограничивает ускорение
Постановка задач для кластера в HPCS
Адрес MSU кластера \ IKI кластера HN.PRACTICUM.CS.MSU.SU \ 193.232.2.150
Имя головного узла (head node)
hn.practicum\hn.cluster.local
Имя вычислительных узлов
cn1,cn2…\ cn1.cluster.local,cn2.cluster.local…
Сетевая папка доступная всем
hn.practicum\apps \ hn.cluster.local\apps
вычислительным узлам
Сетевая папка на каждом
\\cn1\Apps, \\cn2\Apps... \ cn1.cluster.local\apps
вычилительном узле
(физический расположенная в C:\Apps)
Для доступа к IKI кластеру необходимо включить VPN соединение, указав
User name: <user_ name>
Password: < password>
Domain: Cluster
WHPCS
Последовательно о
многопоточном.
Процессы и потоки
Stack
thread
main()
Stack
Stack
thread
…
thread
Сегмент кода
Сегмент данных
Преимущества потоков:
• Быстрое переключение между потоками
(переключение между процессами очень
ресурсоемкая операция)
• Простая организация взаимодействия –
общая память
Недостатки потоков:
• Некорректное использование данных
одним потоком отражается на всех других
• Необходимость в синхронизации при
доступе к общим данным
• Используемые библиотеки должны
поддерживать многопоточность
Средства создания многопоточных
программ
• Ручные: Библиотеки потоков
– Posix Threads
– Windows Threads
–…
• Полуавтоматические: OpenMP
• Автоматические: Распараллеливающие
компиляторы
• Неявный параллелизм (F#)
Синхронизация потоков
Необходима при:
• Совместном использовании
Критические секции
ресурса (атомарные
Мьютексы
операции)
• Уведомлении потоков о
События
некотором событии
Interlocked-функции
Семафоры
Закон Амдала
P
Tпаралл. = {(1-P) + P/n} Tпослед
(1-P)
P/2
(1-P)
TПослед.
• Описывает верхний предел ускорения от
параллельного выполнения
n = количество проц.
P/∞
Ускорение = Tпослед / Tпаралл.
Последовательный код ограничивает ускорение
Просто OpenMP
Параллелизм Fork-join:
•
Главный поток (Master thread) порождает группу потоков по
необходимости
•
Параллелизм добавляется постепенно
–
Последовательная программа “трансформируется в параллельную”
Главный
поток
Параллельные регионы
Параллельные циклы
• Определите циклы на вычисление которых уходит
наибольшее количество времени.
• Распределите их о выполнение между потоками.
Распределить цикл между потоками
void main()
{
double Res[1000];
for(int i=0;i<1000;i++){
do_huge_comp(Res[i]);
}
}
Последовательная программа
#include “omp.h”
void main()
{
double Res[1000];
#pragma omp parallel for
for(int i=0;i<1000;i++){
do_huge_comp(Res[i]);
}
}
Параллельная программа
Просто OpenMP
• Примитивы OpenMP подразделяются на
категории:
– Функции времени выполнения/переменные среды
окружения
– Параллельные регионы
– Распределение работ
– Синхронизация
• Принципиально OpenMP не зависит от
компилятора или языка, например Fortran и
C/C++
Функции
• Примитивы среды окружения:
• Изменить/проверить количество потоков
–
–
–
–
omp_set_num_threads()
omp_get_num_threads()
omp_get_thread_num()
omp_get_max_threads()
• Мы в параллельном регионе?
– omp_in_parallel()
• Сколько процессоров в системе?
– omp_num_procs()
Функции
• Чтобы установить количество потоков
Установить количество потоков
равное количеству процессоров
#include <omp.h>
void main()
Глоб. Переменная.
{
int num_threads;
Операция выполняется в
omp_set_num_threads(omp_num_procs());
одном потоке.
#pragma omp parallel
{
int id=omp_get_thread_num();
#pragma omp single
num_threads = omp_get_num_threads();
do_lots_of_stuff(id);
}
}
Переменные среды коружения
• Установить количество потоков, порождаемых по
умолчанию
– OMP_NUM_THREADS int_literal
• Установить способ распределения нагрузки по
умолчанию
– OMP_SCHEDULE “schedule[, chunk_size]”
Правила разделения переменных
• Неявное правило 1: Все переменные, определенные вне omp
parallel, являются глобальными для всех потоков
• Неявное правило 2: Все переменные, определенные внутри
omp parallel, являются локальными для каждого потока
• Неявное исключение: В прагме omp for, счетчик цикла
всегда локален для каждого потока
• Явное правило 1: Переменные, приведенные в shared(),
являются глобальными для всех потоков
• Явное правило 2: Переменные, приведенные в private(),
являются локальными для каждого потока
Какие переменные локальные, а какие
глобальные?
void func()
{
int a, i;
#pragma omp parallel for \
shared(c) private(d, e)
for (i = 0; i < N; i++)
{
int b, c, d, e;
a = a + b;
c = c + d * e;
}
}
Прагмы синхронизации
•
•
•
•
#pragma omp single – исполняет следующую команду только с
помощью одного (случайного) потока
#pragma omp barrier – удерживает потоки в этом месте, пока
все потоки не дойдут дотуда
#pragma omp atomic – атомарно исполняет следующую
операцию доступа к памяти (т.е. без прерывания от других ветвей)
#pragma omp critical [имя потока] – позволяет только
одному потоку перейти к исполнению следующей команды
int a[N], sum = 0;
#pragma omp parallel for
for (int i = 0; i < N; i++)
{
#pragma omp critical
sum += a[i]; // one thread at a time
}
Реализация параллельного алгоритма с
использованием OpenMP
Применяется OpenMP с помощью указания директив. Например :
#pragma omp parallel for
for (int i = 0; i < N; i++)
PerformSomeComputation(i);
Реализация параллельного алгоритма с
использованием OpenMP
Важно помнить про ситуацию (race conditions), которая возникает при
одновременном доступе к общим переменным.
#pragma omp parallel for schedule(static)
for (int i = 0; i < N; i++)
PerformSomeComputation(i);
Пусть функция PerformSomeComputation изменяет значение глобальной
переменной
int global = 0;
void PerformSomeComputation(int i)
{
global += i;
}
.
Реализация параллельного алгоритма с
использованием OpenMP
Избежать ситуацию возникновения гонки за ресурсами. Позволяет
использование критических секций:
void PerformSomeComputation(int i)
{
#pragma omp critical
{
global += i;
}
}
Выполнение упражнения
#pragma omp parallel for schedule(static) reduction(+:diffs)
for (int row = 1; row < rows-1; row++)