View
324
Download
1
Embed Size (px)
DESCRIPTION
2 встреча Smolensk Computer Science Club Анатолий Свириденков про параллельное программирование ВКонтакте: http://vk.com/scsc1
Citation preview
Smolensk Computer Science Club
Введение в параллелизм
Свириденков Анатолий
План
Введение в параллелизм
Примитивы синхронизации (теория)
Проблемы многопоточности (практика)
Алгоритмы и структуры данных
Введение в параллелизм(си\с++ и windows)
Классификация Флина
SISD (Single Instruction Single Data) – классический процессор старой школы
SIMD (Single Instruction Multiple Data) – MMX, SSE
MISD (Multiple Instruction Single Data) – до конца не определено
MIMD (Multiple Instruction Multiple Data) – многоядерные процессоры
SIMT (Single Instruction Multiple Threads) – кастыли от NVIDIA
Закон Амдала
a – доля последовательных вычислений N – количество потоков
Выгоды от многопоточности
Неочевидный параллелизм
Много потоков на одном ядре (квазимногопоточность)
Аппаратное ускорение: сопроцессоры, DMA, аппаратные прерывания.
Кластеры
Интернет
Примитивы синхронизации
Синхронизация, события
Мьютекс
Событие
Приветсвие TCP\IP
Мьютекс Mutex (mutual execution) – примитив
исключающий совместный доступ к разделяемому ресурсу.
Семафор Дейкстры (1965):
P: while (s==0) sleep; // вход s = s — 1;
V: s = s + 1; // выход
Алгоритм Петерсона (1981)shared int[2] = {0, 0};
shared int turn;
// вход в cs
ready[i] = 1; // i — номер потока
turn = 1 — i;
while(ready[1 — i] && turn == 1-i);
// cs
ready[i] = 0; // выход из cs
Событие
События служат для информирования потоко о событии.
Типичное применение событий: Производитель – Потребитель (Producer – Consumer)
События нельзя применять для синхронизации доступа.
Приветсвие TCP\IP
Трехтактное рукопожатие при установлении TCP\IP соединение это обмен событиями, с учетом возможности потери последнего.
Ошибки многопоточности
Гонки
Взаимные блокировки
Пересинхронизация
Возможно ли r1 = r2 = 0 ?
Поток 1:
x = 1r1 = y;
Поток 2:
y = 1;r2 = x;
int x = 0;int y = 0;
int r1 = -1;int r2 = -1;
volatile
volatile – ключевое слово для работы с signals. Запрещает перемещение переменной в регистр.
volatile – модификатор доступа, как и const. Могут быть volatile классы и функции. Снимается через const_cast<>;
MS specific – к volatile атомарный доступ
Что тут в r1 и r2?
Поток 1:
x = -1r1 = y;
Поток 2:
y = -1;r2 = x;
volatile int x = 0;volatile int y = 0;
int r1 = 0;int r2 = 0;
Гонки и атомарный доступ
char * buffer[3] = {0}
Поток 1: strcpy(buffer, ”11”); Поток 2: strcpy(buffer, ”22”);
Итог: 11, 12, 21, 22
Атомарность в x86
BYTE;
WORD, DWORD выровненые на границу кеш линии;
WORD, DWORD с сигналом LOCK на шине. В С\С++ функции InterlockedXXXX.
Если все атомарно (r1 = r2 = 0)?
Поток 1:
x = 1r1 = y;
Поток 2:
y = 1;r2 = x;
volatile int x = 0;volatile int y = 0;
int r1 = -1;int r2 = -1;
Типы процессоров
Векторные;
Скалярные;
Суперскаляные;
VLIW.
Суперскалярные процессоры
Стадии обработки команды:
Выборка;
Декодирование;
Исполнение;
Установка результата;
Без конвеера
Такт Выборка Декод. Выполнение Запись
1 К1
2 К1
3 К1
4 К1
С конвеером
Такт Выборка Декод. Выполнение Запись
1 К1
2 К2 К1
3 К3 К2 К1
4 К4 К3 К2 К1
Конфликты в конвеере
Конфликты по данным – ввод одной инструкции зависит от вывода другой;
Конфликты по управлению – переходы;
Структурный конфликт – нехватка вычислительных модулей (ALU).
Модели памяти
Строгая модель памяти – out-of-order выполнение запрещено;
Слабая модель позволяет переупорядычивание операций;
Intel® 64 Architecture Memory Ordering White Paper
Foundations of the C++ Concurrency Memory Model
Барьеры памяти
lfence — все операции загрузки должны быть заверены пока команда выполняется;
sfence — все операции выгрузки должны быть заверешны пока команда выполняется;
mfence — sfence + lfence; cpuid; interlocked операции.
Memory Ordering in Modern Microprocessors
Type Alpha ARMv7 POWER x86 x86 oostore
AMD64 IA64
Loads reordered after Loads
y y y y y
Loads reordered after Stores
y y y y y
Stores reordered after Stores
y y y y y
Stores reordered after Loads
y y y y y y y
Atomic reordered with Loads
y y y y
Atomic reordered with Stores
y y y y
Dependent Loads reordered
y
Incoherent Instruction cache pipeline
y y y y y y
Как должно быть
Поток 1:x = 1mfence;r1 = y;
Поток 2:y = 1;mfence;r2 = x;
volatile int x = 0;volatile int y = 0;
int r1 = -1;int r2 = -1;
Взаимоблокировка
EnterCriticalSectio(&r1);EnterCriticalSectio(&r2);….LeaveCriticalSection(&r2);LeaveCriticalSection(&r1);
EnterCriticalSectio(&r2);EnterCriticalSectio(&r1);….LeaveCriticalSection(&r1);LeaveCriticalSection(&r2);
CRITICAL_SECTION r1, r2;
Взаимоблокировка
Deadlock detection
struct RTL_CRITICAL_SECTION
{
PRTL_CRITICAL_SECTION_DEBUG DebugInfo; LONG LockCount; LONG RecursionCount;
HANDLE OwningThread; HANDLE LockSemaphore; ULONG_PTR SpinCount;};
Deadlock detection
struct _RTL_CRITICAL_SECTION_DEBUG{
WORD Type; WORD CreatorBackTraceIndex; RTL_CRITICAL_SECTION *CriticalSection;
LIST_ENTRY ProcessLocksList; DWORD EntryCount; DWORD ContentionCount;
DWORD Spare[ 2 ];}
Пересинхронизация
Ошибка в проектировании, когда работающие потоки мешают друг другу. Обычно связано с: Общими ресурсами
NUMA
Кеш
Пересинхронизация на общем ресурсе
for(int i = 0; i < SIZE/2; i++){ EnterCriticalSectio(&cs); sum += array[i]; LeaveCriticalSection(&cs);
}
for(int i = 0; i < SIZE/2; i++){ EnterCriticalSectio(&cs); sum += array[i + SIZE/2]; LeaveCriticalSection(&cs);
}
int sum = 0; int array[SIZE];
CRITICAL_SECTION cs;
Пересинхронизация и кеш
for(int i = 0; i < SIZE/2; i++){ array[2*i] = i;}
for(int i = 0; i < SIZE/2; i++){ array[2*i + 1] = i;
}
int array[SIZE] = {0};
Принципы на примере циклов
Не распараллеленый:C[i] = A[i] + B[i];
РаспараллеленыйC[N*i + k] = A[N*i + k] + B[N*i + k]
N – количество потоков k – номер потока
Зависимость назад
Не распараллеленый:A[i - 1] = A[i] + B[i];
РаспараллеленыйAN = AA[N*i + k - 1] = AN[N*i + k] + B[N*i + k]
N – количество потоков k – номер потока
Зависимость вперед
Не распараллеленый:A[i + 1] = A[i] + B[i];
РаспараллеленыйВ общем случае не параллелится.
Некоторые приемы Пул потоков
Асинхронное программирования
Двойная проверка
Map reduce
Счетчик доступа
Данные и алгоритмы
Блокировки – с явной синхронизацией;
Obstruction-free (без препятствий) – поток завершит исполнение за детерменированное количество шагов;
Lock-free (без блокировок) – на каждом шаге происходит прогресс в системе;
Wait-free (без ожиданий) – нет ожиданий.
Приемы
Read-only
Атомарные операции
Барьеры памяти
Вопросы ?