'

Терафлопные вычисления

Понравилась презентация – покажи это...





Слайд 0

Параллельное программирование с использованием технологии OpenMP. Бахтин Владимир Александрович Ассистент кафедры системного программированния факультета ВМК, МГУ им. М. В. Ломоносова К.ф.-м.н., зав. сектором Института прикладной математики им М.В.Келдыша РАН Терафлопные вычисления


Слайд 1

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 2 из 137 Содержание Современные направления развития параллельных вычислительных систем OpenMP – модель параллелизма по управлению Конструкции распределения работы Конструкции для синхронизации нитей Система поддержки выполнения OpenMP-программ. Переменные окружения, управляющие выполнением OpenMP-программы Наиболее часто встречаемые ошибки в OpenMP-программах. Функциональная отладка OpenMP-программ Отладка эффективности OpenMP-программ Использование OpenMP на кластере


Слайд 2

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 3 из 137 Современные направления развития параллельных вычислительных систем Тенденции развития современных процессоров Существующие подходы для создания параллельных программ Что такое OpenMP?


Слайд 3

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 4 из 137 Тенденции развития современных процессоров В течение нескольких десятилетий развитие ЭВМ сопровождалось удвоением их быстродействия каждые 1.5-2 года. Это обеспечивалось и повышением тактовой частоты и совершенствованием архитектуры (параллельное и конвейерное выполнение команд). Узким местом стала оперативная память. Знаменитый закон Мура, так хорошо работающий для процессоров, совершенно не применим для памяти, где скорости доступа удваиваются в лучшем случае каждые 6 лет. Совершенствовались системы кэш-памяти, увеличивался объем, усложнялись алгоритмы ее использования. Для процессора Intel Itanium: Latency to L1: 1-2 cycles Latency to L2: 5 - 7 cycles Latency to L3: 12 - 21 cycles Latency to memory: 180 – 225 cycles Важным параметром становится - GUPS (Giga Updates Per Second)


Слайд 4

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 5 из 137 Время Тенденции развития современных процессоров В П В П В П В П В П В П Поток Поток Время В П В П В П Поток 1 В П В П В П В П В П В П В П В П В П Поток 2 Поток 3 Поток 4 В - вычисления П - доступ к памяти Chip MultiThreading увеличили производительность процессора в 2 раза Поток или нить (по-английски “thread”) – это легковесный процесс, имеющий с другими потоками общие ресурсы, включая общую оперативную память.


Слайд 5

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 6 из 137 Тенденции развития современных процессоров Суперкомпьютер Jaguar Cray XT5-HE Opteron Six Core 2.6 GHz Пиковая производительность - 2331 TFlop/s Число ядер в системе — 224 162 Производительность на Linpack - 1759 TFlop/s (75.4% от пиковой) Энергопотребление комплекса - 6950.60 кВт Важным параметром становится – Power Efficency (Megaflops/watt) Как добиться максимальной производительности на Ватт => Chip MultiProcessing, многоядерность.


Слайд 6

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 7 из 137 AMD Opteron серии 6100 (Magny-Cours) 6176 SE 12 ядер @ 2,3 ГГц, 12 МБ L3 Cache 6136 8 ядер @ 2,4 ГГц, 12 МБ L3 Cache встроенный контроллер памяти (4 канала памяти DDR3) 4 канала «точка-точка» с использованием HyperTransort 3.0 AMD Opteron серии 6200 (Interlagos) 16 ядер Тенденции развития современных процессоров


Слайд 7

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 8 из 137 Intel Xeon серии 5600 (Nehalem) X5680 6 ядер @ 3,33 ГГц, 12 нитей, 12 МБ L3 Cache X5677 4 ядра @ 3,46 ГГц, 8 нитей, 12 МБ L3 Cache Intel® Turbo Boost Intel® Hyper-Threading Intel® QuickPath Intel® Intelligent Power Тенденции развития современных процессоров


Слайд 8

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 9 из 137 Intel Core i7 980X (Gulftown) 3,33 ГГц 6 ядeр 12 потоков с технологией Intel Hyper-Threading 12 МБ кэш-памяти Intel Smart Cache встроенный контроллер памяти (3 канала памяти DDR3 1066 МГц ) технология Intel QuickPath Interconnect Тенденции развития современных процессоров


Слайд 9

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 10 из 137 Тенденции развития современных процессоров Intel Itanium 9350 (Tukwila) 1,73 ГГц 4 ядeр 8 потоков с технологией Intel Hyper-Threading 24 МБ L3 кэш-памяти технология Intel QuickPath Interconnect технология Intel Turbo Boost


Слайд 10

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 11 из 137 Тенденции развития современных процессоров IBM Power7 3,5 - 4,0 ГГц 8 ядер x 4 нити Simultaneuos MultiThreading L1 64КБ L2 256 КБ L3 32 МБ встроенный контроллер памяти


Слайд 11

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 12 из 137 Тенденции развития современных процессоров Темпы уменьшения латентности памяти гораздо ниже темпов ускорения процессоров + прогресс в технологии изготовления кристаллов => CMT (Chip MultiThreading) Опережающий рост потребления энергии при росте тактовой частоты + прогресс в технологии изготовления кристаллов => CMP (Chip MultiProcessing, многоядерность) И то и другое требует более глубокого распараллеливания для эффективного использования аппаратуры


Слайд 12

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 13 из 137 Автоматическое / автоматизированное распараллеливание Библиотеки нитей Win32 API POSIX Библиотеки передачи сообщений MPI OpenMP Существующие подходы для создания параллельных программ


Слайд 13

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 14 из 137 Вычисление числа ?


Слайд 14

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 15 из 137 Вычисление числа ?. Последовательная программа #include <stdio.h> int main () { int n =100000, i; double pi, h, sum, x; h = 1.0 / (double) n; sum = 0.0; for (i = 1; i <= n; i ++) { x = h * ((double)i - 0.5); sum += (4.0 / (1.0 + x*x)); } pi = h * sum; printf("pi is approximately %.16f”, pi); return 0; }


Слайд 15

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 16 из 137 Автоматическое распараллеливание Polaris, CAPO, WPP, SUIF, VAST/Parallel, OSCAR, Intel/OpenMP, UTL icc -parallel pi.c pi.c(8): (col. 5) remark: LOOP WAS AUTO-PARALLELIZED. pi.c(8): (col. 5) remark: LOOP WAS VECTORIZED. pi.c(8): (col. 5) remark: LOOP WAS VECTORIZED. В общем случае, автоматическое распараллеливание затруднено: косвенная индексация (A[B[i]]); указатели (ассоциация по памяти); сложный межпроцедурный анализ.


Слайд 16

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 17 из 137 Автоматизированное распараллеливание Intel/GAP (Guided Auto-Parallel), CAPTools/ParaWise, BERT77, FORGE Magic/DM, ДВОР (Диалоговый Высокоуровневый Оптимизирующий Распараллеливатель), САПФОР (Система Автоматизации Параллелизации ФОРтран программ) for (i=0; i<n; i++) { if (A[i] > 0) {b=A[i]; A[i] = 1 / A[i]; } if (A[i] > 1) {A[i] += b;} } icc -guide -parallel test.cpp


Слайд 17

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 18 из 137 Автоматизированное распараллеливание test.cpp(49): remark #30521: (PAR) Loop at line 49 cannot be parallelized due to conditional assignment(s) into the following variable(s): b. This loop will be parallelized if the variable(s) become unconditionally initialized at the top of every iteration. [VERIFY] Make sure that the value(s) of the variable(s) read in any iteration of the loop must have been written earlier in the same iteration. test.cpp(49): remark #30525: (PAR) If the trip count of the loop at line 49 is greater than 188, then use "#pragma loop count min(188)" to parallelize this loop. [VERIFY] Make sure that the loop has a minimum of 188 iterations. #pragma loop count min (188) for (i=0; i<n; i++) { b = A[i]; if (A[i] > 0) {A[i] = 1 / A[i];} if (A[i] > 1) {A[i] += b;} }


Слайд 18

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 19 из 137 Вычисление числа ? с использованием Win32 API #include <stdio.h> #include <windows.h> #define NUM_THREADS 2 CRITICAL_SECTION hCriticalSection; double pi = 0.0; int n =100000; void main () { int i, threadArg[NUM_THREADS]; DWORD threadID; HANDLE threadHandles[NUM_THREADS]; for(i=0; i<NUM_THREADS; i++) threadArg[i] = i+1; InitializeCriticalSection(&hCriticalSection); for (i=0; i<NUM_THREADS; i++) threadHandles[i] = CreateThread(0,0,(LPTHREAD_START_ROUTINE) Pi,&threadArg[i], 0, &threadID); WaitForMultipleObjects(NUM_THREADS, threadHandles, TRUE,INFINITE); printf("pi is approximately %.16f”, pi); }


Слайд 19

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 20 из 137 Вычисление числа ? с использованием Win32 API void Pi (void *arg) { int i, start; double h, sum, x; h = 1.0 / (double) n; sum = 0.0; start = *(int *) arg; for (i=start; i<= n; i=i+NUM_THREADS) { x = h * ((double)i - 0.5); sum += (4.0 / (1.0 + x*x)); } EnterCriticalSection(&hCriticalSection); pi += h * sum; LeaveCriticalSection(&hCriticalSection); }


Слайд 20

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 21 из 137 Конфликт доступа к данным При взаимодействии через общую память нити должны синхронизовать свое выполнение. Thread0: pi = pi + val; && Thread1: pi = pi + val; Результат зависит от порядка выполнения команд. Требуется взаимное исключение критических интервалов.


Слайд 21

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 22 из 137 Вычисление числа ? с использованием MPI #include "mpi.h" #include <stdio.h> int main (int argc, char *argv[]) { int n =100000, myid, numprocs, i; double mypi, pi, h, sum, x; MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD,&numprocs); MPI_Comm_rank(MPI_COMM_WORLD,&myid); MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); h = 1.0 / (double) n; sum = 0.0;


Слайд 22

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 23 из 137 Вычисление числа ? с использованием MPI for (i = myid + 1; i <= n; i += numprocs) { x = h * ((double)i - 0.5); sum += (4.0 / (1.0 + x*x)); } mypi = h * sum; MPI_Reduce(&mypi, &pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); if (myid == 0) printf("pi is approximately %.16f”, pi); MPI_Finalize(); return 0; }


Слайд 23

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 24 из 137 Вычисление числа ? с использованием OpenMP #include <stdio.h> int main () { int n =100000, i; double pi, h, sum, x; h = 1.0 / (double) n; sum = 0.0; #pragma omp parallel for reduction(+:sum) private(x) for (i = 1; i <= n; i ++) { x = h * ((double)i - 0.5); sum += (4.0 / (1.0 + x*x)); } pi = h * sum; printf("pi is approximately %.16f”, pi); return 0; }


Слайд 24

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 25 из 137 История OpenMP OpenMP Fortran 1.1 OpenMP C/C++ 1.0 OpenMP Fortran 2.0 OpenMP C/C++ 2.0 1998 2000 1999 2002 OpenMP Fortran 1.0 1997 OpenMP F/C/C++ 2.5 2005 OpenMP F/C/C++ 3.0 2008 OpenMP F/C/C++ 3.1 2011


Слайд 25

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 26 из 137 OpenMP Architecture Review Board AMD Cray Fujitsu HP IBM Intel NEC The Portland Group, Inc. Oracle Corporation Microsoft Texas Instrument CAPS-Enterprise NVIDIA ANL ASC/LLNL cOMPunity EPCC LANL NASA RWTH Aachen University Texas Advanced Computing Center


Слайд 26

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 27 из 137 Компиляторы, поддеживающие OpenMP OpenMP 3.0: Intel 11.0: Linux, Windows and MacOS Oracle Studio Express 11/08: Linux and Solaris PGI 8.0: Linux and Windows IBM 10.1: Linux and AIX GNU gcc (4.4.0) Предыдущие версии OpenMP: Absoft Pro FortranMP Lahey/Fujitsu Fortran 95 PathScale HP Microsoft Visual Studio 2008 C++


Слайд 27

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 28 из 137 Cимметричные мультипроцессорные системы (SMP) Все процессоры имеют доступ к любой точке памяти с одинаковой скоростью. Процессоры подключены к памяти либо с помощью общей шины, либо с помощью crossbar-коммутатора. Аппаратно поддерживается когерентность кэшей.


Слайд 28

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 29 из 137 Cимметричные мультипроцессорные системы (SMP) Fujitsu SPARC Enterprise M9000 SPARC64 VII 2,88 / 2,52 GHz 64 процессоров, 256 ядер, 512 нитей (Simultaneous Multi Threading) 4TB памяти OS Solaris 10 http://www.fujitsu.com/sparcenterprise/


Слайд 29

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 30 из 137 Системы с неоднородным доступом к памяти (NUMA) Система состоит из однородных базовых модулей (плат), состоящих из небольшого числа процессоров и блока памяти. Модули объединены с помощью высокоскоростного коммутатора. Поддерживается единое адресное пространство. Доступ к локальной памяти в несколько раз быстрее, чем к удаленной.


Слайд 30

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 31 из 137 Системы с неоднородным доступом к памяти (NUMA) SGI Altix UV (UltraVioloet) 1000 256 Intel® Xeon® quad-, six- or eight-core 7500 series (2048 cores) 16 TB памяти Interconnect Speed 15 ГБ/с, 1мкс http://www.sgi.com/products/servers/altix/uv/


Слайд 31

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 32 из 137 Содержание Современные направления развития параллельных вычислительных систем OpenMP – модель параллелизма по управлению Конструкции распределения работы Конструкции для синхронизации нитей Система поддержки выполнения OpenMP-программ. Переменные окружения, управляющие выполнением OpenMP-программы Наиболее часто встречаемые ошибки в OpenMP-программах. Функциональная отладка OpenMP-программ Отладка эффективности OpenMP-программ Использование OpenMP на кластере


Слайд 32

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 33 из 137 OpenMP– модель параллелизма по управлению Основные понятия Выполнение OpenMP-программы Модель памяти в OpenMP Классы переменных Параллельная область


Слайд 33

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 34 из 137 Обзор основных возможностей OpenMP omp_set_lock(lck) #pragma omp parallel for private(a, b) #pragma omp critical C$OMP PARALLEL DO SHARED(A,B,C) C$OMP PARALLEL REDUCTION (+: A, B) CALL OMP_INIT_LOCK (LCK) CALL OMP_TEST_LOCK(LCK) SETENV OMP_SCHEDULE “STATIC,4” CALL CALL OMP_SET_NUM_THREADS(10) C$OMP ORDERED C$OMP SINGLE PRIVATE(X) C$OMP SECTIONS C$OMP MASTER C$OMP ATOMIC C$OMP FLUSH C$OMP PARALLEL DO ORDERED PRIVATE (A, B, C) C$OMP THREADPRIVATE(/ABC/) C$OMP PARALLEL COPYIN(/blk/) nthrds = OMP_GET_NUM_PROCS() C$OMP BARRIER OpenMP: API для написания многонитевых приложений Множество директив компилятора, набор функции библиотеки системы поддержки, переменные окружения Облегчает создание многонитиевых программ на Фортране, C и C++ Обобщение опыта создания параллельных программ для SMP и DSM систем за последние 20 лет


Слайд 34

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 35 из 137 Директивы и клаузы Спецификации параллелизма в OpenMP представляют собой директивы вида: #pragma omp название-директивы[ клауза[ [,]клауза]...] Например: #pragma omp parallel default (none) shared (i,j) Исполняемые директивы: barrier taskwait taskyield flush Описательная директива: threadprivate


Слайд 35

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 36 из 137 Структурный блок Действие остальных директив распространяется на структурный блок: #pragma omp название-директивы[ клауза[ [,]клауза]...] { структурный блок } Структурный блок: блок кода с одной точкой входа и одной точкой выхода. #pragma omp parallel { … mainloop: res[id] = f (id); if (res[id] != 0) goto mainloop; … exit (0); } Структурный блок #pragma omp parallel { … mainloop: res[id] = f (id); … } if (res[id] != 0) goto mainloop; Не структурный блок


Слайд 36

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 37 из 137 Компиляция OpenMP-программы


Слайд 37

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 38 из 137 Условная компиляция OpenMP-программы #include <stdio.h> int main() { #ifdef _OPENMP printf("Compiled by an OpenMP-compliant implementation.\n"); #endif return 0; } В значении переменной _OPENMP зашифрован год и месяц (yyyymm) версии стандарта OpenMP, которую поддерживает компилятор.


Слайд 38

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 39 из 137 Использование функций поддержи выполнения OpenMP-программ (OpenMP API runtime library) #include <stdio.h> #include <omp.h> // Описаны прототипы всех функций и типов int main() { #pragma omp parallel { int id = omp_get_thread_num (); int numt = omp_get_num_threads (); printf(“Thread (%d) of (%d) threads alive\n”, id, numt); } return 0; }


Слайд 39

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 40 из 137 Параллельная область (директива PARALLEL) #pragma omp parallel [ клауза[ [, ] клауза] ...] структурный блок где клауза одна из : default(shared | none) private(list) firstprivate(list) shared(list) reduction(operator: list) if(scalar-expression) num_threads(integer-expression) copyin(list)


Слайд 40

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 41 из 137 001 Модель памяти в OpenMP Нить Кэш общих переменных Общая память Private-переменные Threadprivate-переменные 001 Нить Кэш общих переменных Private-переменные Threadprivate-переменные 001 Нить Кэш общих переменных Private-переменные Threadprivate-переменные


Слайд 41

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 42 из 137 Когерентность и консистентность памяти


Слайд 42

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 43 из 137 Сеть передачи данных http://www.sgi.com/products/servers/altix/numalink.html


Слайд 43

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 44 из 137 001 Нить 0 Общая память 001 Нить 1 static int i = 0; … = i + 1; i = i + 1; i = 0 i = 1 … = i + 2; // ? #pragma omp flush (i) #pragma omp flush (i) i = 1 i = 1 Модель памяти в OpenMP


Слайд 44

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 45 из 137 Консистентность памяти в OpenMP Корректная последовательность работы нитей с переменной: Нить0 записывает значение переменной - write(var) Нить0 выполняет операцию синхронизации – flush (var) Нить1 выполняет операцию синхронизации – flush (var) Нить1 читает значение переменной – read (var) Директива flush: #pragma omp flush [(list)] - для Си !$omp flush [(list)] - для Фортран


Слайд 45

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 46 из 137 Консистентность памяти в OpenMP Если пересечение множеств переменных, указанных в операциях flush, выполняемых различными нитями не пустое, то результат выполнения операций flush будет таким, как если бы эти операции выполнялись в некоторой последовательности (единой для всех нитей). Если пересечение множеств переменных, указанных в операциях flush, выполняемых одной нитью не пустое, то результат выполнения операций flush, будет таким, как если бы эти операции выполнялись в порядке, определяемом программой. Если пересечение множеств переменных, указанных в операциях flush, пустое, то операции flush могут выполняться независимо (в любом порядке).


Слайд 46

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 47 из 137 Классы переменных В модели программирования с разделяемой памятью: Большинство переменных по умолчанию считаются SHARED Глобальные переменные совместно используются всеми нитями (shared) : Фортран: COMMON блоки, SAVE переменные, MODULE переменные Си: file scope, static Динамически выделяемая память (ALLOCATE, malloc, new) Но не все переменные являются разделяемыми ... Стековые переменные в подпрограммах (функциях), вызываемых из параллельного региона, являются PRIVATE. Переменные, объявленные внутри блока операторов параллельного региона, являются приватными. Счетчики циклов, витки которых распределяются между нитями при помощи конструкций FOR и PARALLEL FOR.


Слайд 47

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 48 из 137 double Array1[100]; int main() { int Array2[100]; #pragma omp parallel work(Array2); printf(“%d\n”, Array2[0]); } extern double Array1[10]; void work(int *Array) { double TempArray[10]; static int count; ... } END PARALLEL PARALLEL TempArray TempArray TempArray Array1, Array2, count Array1, Array2, count Модель памяти в OpenMP


Слайд 48

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 49 из 137 Можно изменить класс переменной при помощи конструкций: SHARED (список переменных) PRIVATE (список переменных) FIRSTPRIVATE (список переменных) LASTPRIVATE (список переменных) THREADPRIVATE (список переменных) DEFAULT (PRIVATE | SHARED | NONE) Классы переменных


Слайд 49

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 50 из 137 Конструкция PRIVATE Конструкция «private(var)» создает локальную копию переменной «var» в каждой из нитей. Значение переменной не инициализировано Приватная копия не связана с оригинальной переменной В OpenMP 2.5 значение переменной «var» не определено после завершения параллельной конструкции #pragma omp parallel for private (i,j,sum) for (i=0; i< m; i++) { sum = 0.0; for (j=0; j< n; j++) sum +=b[i][j]*c[j]; a[i] = sum; }


Слайд 50

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 51 из 137 Конструкция FIRSTPRIVATE «firstprivate» является специальным случаем «private». Инициализирует каждую приватную копию соответствующим значением из главной (master) нити. BOOL FirstTime=TRUE; #pragma omp parallel for firstprivate(FirstTime) for (row=0; row<maxrow; row++) { if (FirstTime == TRUE) { FirstTime = FALSE; FirstWork (row); } AnotherWork (row); }


Слайд 51

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 52 из 137 Конструкция LASTPRIVATE Lastprivate передает значение приватной переменной, посчитанной на последней итерации в глобальную переменную. int i; #pragma omp parallel { #pragma omp for lastprivate(i) for (i=0; i<n-1; i++) a[i] = b[i] + b[i+1]; } a[i]=b[i]; /*i == n-1*/


Слайд 52

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 53 из 137 Директива THREADPRIVATE Отличается от применения конструкции PRIVATE: PRIVATE скрывает глобальные переменные THREADPRIVATE – переменные сохраняют глобальную область видимости внутри каждой нити #pragma omp threadprivate (Var) END PARALLEL PARALLEL END PARALLEL PARALLEL Var = 1 Var = 2 … = Var … = Var Если количество нитей не изменилось, то каждая нить получит значение, посчитанное в предыдущей параллельной области.


Слайд 53

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 54 из 137 Конструкция DEFAULT Меняет класс переменной по умолчанию: DEFAULT (SHARED) – действует по умолчанию DEFAULT (PRIVATE) – есть только в Fortran DEFAULT (NONE) – требует определить класс для каждой переменной itotal = 100 #pragma omp parallel private(np,each) { np = omp_get_num_threads() each = itotal/np ……… } itotal = 100 #pragma omp parallel default(none) private(np,each) shared (itotal) { np = omp_get_num_threads() each = itotal/np ……… }


Слайд 54

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 55 из 137 Параллельная область (директива PARALLEL) #pragma omp parallel [ клауза[ [, ] клауза] ...] структурный блок где клауза одна из : default(shared | none) private(list) firstprivate(list) shared(list) reduction(operator: list) if(scalar-expression) num_threads(integer-expression) copyin(list)


Слайд 55

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 56 из 137 Вычисление числа ?


Слайд 56

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 57 из 137 #include <stdio.h> int main () { int n =100000, i; double pi, h, sum, x; h = 1.0 / (double) n; sum = 0.0; for (i = 1; i <= n; i ++) { x = h * ((double)i - 0.5); sum += (4.0 / (1.0 + x*x)); } pi = h * sum; printf("pi is approximately %.16f”, pi); return 0; } Вычисление числа ?. Последовательная программа.


Слайд 57

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 58 из 137 При взаимодействии через общую память нити должны синхронизовать свое выполнение. int i=0; #pragma omp parallel { i++; } Модификация общих переменных в параллельной области


Слайд 58

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 59 из 137 #include <stdio.h> #include <omp.h> #define NUM_THREADS 32 int main () { int n =100000, i; double pi, h, sum[NUM_THREADS], x; h = 1.0 / (double) n; #pragma omp parallel default (none) private (i,x) shared (n,h,sum) { int id = omp_get_thread_num(); int numt = omp_get_num_threads(); for (i = id + 1, sum[id] = 0.0; i <= n; i=i+numt) { x = h * ((double)i - 0.5); sum[id] += (4.0 / (1.0 + x*x)); } } for(i=0, pi=0.0; i<NUM_THREADS; i++) pi += sum[i] * h; printf("pi is approximately %.16f”, pi); return 0; } Вычисление числа ?.


Слайд 59

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 60 из 137 #include <stdio.h> #include <omp.h> int main () { int n =100000, i; double pi, h, sum, x; h = 1.0 / (double) n; sum = 0.0; #pragma omp parallel default (none) private (i,x) shared (n,h) reduction(+:sum) { int id = omp_get_thread_num(); int numt = omp_get_num_threads(); for (i = id + 1; i <= n; i=i+numt) { x = h * ((double)i - 0.5); sum += (4.0 / (1.0 + x*x)); } } pi = h * sum; printf("pi is approximately %.16f”, pi); return 0; } Вычисление числа ?. Клауза reduction


Слайд 60

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 61 из 137 Клауза reduction reduction(operator:list) Внутри паралельной области для каждой переменной из списка list создается копия этой переменной. Эта переменная инициализируется в соответствии с оператором operator (например, 0 для «+»). Для каждой нити компилятор заменяет в параллельной области обращения к редукционной переменной на обращения к созданной копии. По завершении выполнения параллельной области осуществляется объединение полученных результатов.


Слайд 61

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 62 из 137 Клауза num_threads num_threads(integer-expression) integer-expression задает максимально возможное число нитей, которые будут созданы для выполнения структурного блока #include <omp.h> int main() { int n = 0; printf("Enter the number of intervals: (0 quits) "); scanf("%d",&n); omp_set_dynamic(1); #pragma omp parallel num_threads(10) { int id = omp_get_thread_num (); func (n, id); } return 0; }


Слайд 62

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 63 из 137 Клауза copyin copyin(list) Значение каждой threadprivate-переменной из списка list, устанавливается равным значению этой переменной в master-нити #include <stdlib.h> float* work; int size; float tol; #pragma omp threadprivate(work,size,tol) void build() { int i; work = (float*)malloc( sizeof(float)*size ); for( i = 0; i < size; ++i ) work[i] = tol; } int main() { read_from_file (&tol, &size); #pragma omp parallel copyin(tol,size) build(); }


Слайд 63

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 64 из 137 Содержание Современные направления развития параллельных вычислительных систем OpenMP – модель параллелизма по управлению Конструкции распределения работы Конструкции для синхронизации нитей Система поддержки выполнения OpenMP-программ. Переменные окружения, управляющие выполнением OpenMP-программы Наиболее часто встречаемые ошибки в OpenMP-программах. Функциональная отладка OpenMP-программ Отладка эффективности OpenMP-программ Использование OpenMP на кластере


Слайд 64

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 65 из 137 Конструкции распределения работы Распределение витков циклов (директива for) Распределение нескольких структурных блоков между нитями (директива section) Выполнение структурного блока одной нитью (директива single)


Слайд 65

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 66 из 137 Вычисление числа ?


Слайд 66

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 67 из 137 #include <stdio.h> int main () { int n =100000, i; double pi, h, sum, x; h = 1.0 / (double) n; sum = 0.0; for (i = 1; i <= n; i ++) { x = h * ((double)i - 0.5); sum += (4.0 / (1.0 + x*x)); } pi = h * sum; printf("pi is approximately %.16f”, pi); return 0; } Вычисление числа ?. Последовательная программа.


Слайд 67

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 68 из 137 int main () { int n =100, i; double pi, h, sum, x; h = 1.0 / (double) n; sum = 0.0; #pragma omp parallel default (none) private (i,x) shared (n,h) reduction(+:sum) { int iam = omp_get_thread_num(); int numt = omp_get_num_threads(); int start = iam * n / numt + 1; int end = (iam + 1) * n / numt; for (i = start; i <= end; i++) { x = h * ((double)i - 0.5); sum += (4.0 / (1.0 + x*x)); } } pi = h * sum; printf(“pi is approximately %.16f”, pi); return 0; } Вычисление числа ? на OpenMP


Слайд 68

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 69 из 137 #include <stdio.h> #include <omp.h> int main () { int n =100, i; double pi, h, sum, x; h = 1.0 / (double) n; sum = 0.0; #pragma omp parallel default (none) private (i,x) shared (n,h) reduction(+:sum) { #pragma omp for schedule (static) for (i = 1; i <= n; i++) { x = h * ((double)i - 0.5); sum += (4.0 / (1.0 + x*x)); } } pi = h * sum; printf(“pi is approximately %.16f”, pi); return 0; } Вычисление числа ? на OpenMP


Слайд 69

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 70 из 137 Распределение витков цикла #pragma omp for [клауза[[,]клауза] ... ] for (init-expr; test-expr; incr-expr) структурный блок где клауза одна из : private(list) firstprivate(list) lastprivate(list) reduction(operator: list) schedule(kind[, chunk_size]) collapse(n) ordered nowait


Слайд 70

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 71 из 137 Вложенность конструкций распределения работы void work(int i, int j) {} void wrong1(int n) { #pragma omp parallel default(shared) { int i, j; #pragma omp for for (i=0; i < n; i++) { /* incorrect nesting of loop regions */ #pragma omp for for (j=0; j < n; j++) work(i, j); } } }


Слайд 71

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 72 из 137 Вложенность конструкций распределения работы void work(int i, int j) {} void good_nesting(int n) { int i, j; #pragma omp parallel default(shared) { #pragma omp for for (i=0; i < n; i++) { #pragma omp parallel shared(i, n) { #pragma omp for for (j=0; j < n; j++) work(i, j); } } } }


Слайд 72

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 73 из 137 Вложенность конструкций распределения работы void work(int i, int j) {} void good_example(int n) { int i, j; #pragma omp parallel default(shared) { #pragma omp for collapse(2) for (i=0; i < n; i++) { for (j=0; j < n; j++) work(i, j); } }


Слайд 73

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 74 из 137 Распределение витков цикла. Клауза schedule #pragma omp parallel for schedule(static, 10) for(int i = 1; i <= 100; i++) Результат выполнения программы на 4-х ядерном процессоре может быть следующим: Поток 0 получает право на выполнение итераций 1-10, 41-50, 81-90. Поток 1 получает право на выполнение итераций 11-20, 51-60, 91-100. Поток 2 получает право на выполнение итераций 21-30, 61-70. Поток 3 получает право на выполнение итераций 31-40, 71-80


Слайд 74

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 75 из 137 Распределение витков цикла. Клауза schedule #pragma omp parallel for schedule(dynamic, 15) for(int i = 1; i <= 100; i++) Результат выполнения программы на 4-х ядерном процессоре может быть следующим: Поток 0 получает право на выполнение итераций 1-15. Поток 1 получает право на выполнение итераций 16-30. Поток 2 получает право на выполнение итераций 31-45. Поток 3 получает право на выполнение итераций 46-60. Поток 3 завершает выполнение итераций. Поток 3 получает право на выполнение итераций 61-75. Поток 2 завершает выполнение итераций. Поток 2 получает право на выполнение итераций 76-90. Поток 0 завершает выполнение итераций. Поток 0 получает право на выполнение итераций 91-100.


Слайд 75

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 76 из 137 Распределение витков цикла. Клауза schedule число_выполняемых_потоком_итераций = max(число_нераспределенных_итераций/omp_get_num_threads(), число_итераций) #pragma omp parallel for schedule(guided, 10) for(int i = 1; i <= 100; i++) Пусть программа запущена на 4-х ядерном процессоре. Поток 0 получает право на выполнение итераций 1-25. Поток 1 получает право на выполнение итераций 26-44. Поток 2 получает право на выполнение итераций 45-59. Поток 3 получает право на выполнение итераций 60-69. Поток 3 завершает выполнение итераций. Поток 3 получает право на выполнение итераций 70-79. Поток 2 завершает выполнение итераций. Поток 2 получает право на выполнение итераций 80-89. Поток 3 завершает выполнение итераций. Поток 3 получает право на выполнение итераций 90-99. Поток 1 завершает выполнение итераций. Поток 1 получает право на выполнение 100 итерации.


Слайд 76

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 77 из 137 Распределение витков цикла. Клауза schedule #pragma omp parallel for schedule(runtime) for(int i = 1; i <= 100; i++) /* способ распределения витков цикла между нитями будет задан во время выполнения программы*/ При помощи переменных среды: csh: setenv OMP_SCHEDULE "dynamic,4“ ksh: export OMP_SCHEDULE="static,10“ Windows: set OMP_SCHEDULE=auto или при помощи функции системы поддержки: void omp_set_schedule(omp_sched_t kind, int modifier);


Слайд 77

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 78 из 137 Распределение витков цикла. Клауза schedule #pragma omp parallel for schedule(auto) for(int i = 1; i <= 100; i++) Способ распределения витков цикла между нитями определяется реализацией компилятора. На этапе компиляции программы или во время ее выполнения определяется оптимальный способ распределения.


Слайд 78

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 79 из 137 Распределение витков цикла. Клауза nowait void example(int n, float *a, float *b, float *с, float *z) { int i; float sum = 0.0; #pragma omp parallel { #pragma omp for schedule(static) nowait reduction (+: sum) for (i=0; i<n; i++) { c[i] = (a[i] + b[i]) / 2.0; sum += c[i]; } #pragma omp for schedule(static) nowait for (i=0; i<n; i++) z[i] = sqrt(b[i]); #pragma omp barrier … = sum } }


Слайд 79

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 80 из 137 Распределение витков цикла. Клауза и директива ordered void print_iteration(int iter) { #pragma omp ordered printf("iteration %d\n", iter); } int main( ) { int i; #pragma omp parallel { #pragma omp for ordered for (i = 0 ; i < 5 ; i++) { print_iteration(i); another_work (i); } } } Результат выполнения программы: iteration 0 iteration 1 iteration 2 iteration 3 iteration 4


Слайд 80

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 81 из 137 Распределение нескольких структурных блоков между нитями (директива sections). #pragma omp sections [клауза[[,] клауза] ...] { [#pragma omp section] структурный блок [#pragma omp section структурный блок ] ... } где клауза одна из : private(list) firstprivate(list) lastprivate(list) reduction(operator: list) nowait void XAXIS(); void YAXIS(); void ZAXIS(); void example() { #pragma omp parallel { #pragma omp sections { #pragma omp section XAXIS(); #pragma omp section YAXIS(); #pragma omp section ZAXIS(); } } }


Слайд 81

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 82 из 137 Выполнение структурного блока одной нитью (директива single). #pragma omp single [клауза[[,] клауза] ...] структурный блок где клауза одна из : private(list) firstprivate(list) copyprivate(list) nowait Структурный блок будет выполнен одной из нитей. Все остальные нити будут дожидаться результатов выполнения блока, если не указана клауза NOWAIT. #include <stdio.h> float x, y; #pragma omp threadprivate(x, y) void init(float *a, float *b ) { #pragma omp single copyprivate(a,b,x,y) scanf("%f %f %f %f", a, b, &x, &y); } int main () { #pragma omp parallel { float x1,y1; init (&x1,&y1); parallel_work (); } }


Слайд 82

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 83 из 137 Содержание Современные направления развития параллельных вычислительных систем OpenMP – модель параллелизма по управлению Конструкции распределения работы Конструкции для синхронизации нитей Система поддержки выполнения OpenMP-программ. Переменные окружения, управляющие выполнением OpenMP-программы Наиболее часто встречаемые ошибки в OpenMP-программах. Функциональная отладка OpenMP-программ Отладка эффективности OpenMP-программ Использование OpenMP на кластере


Слайд 83

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 84 из 137 Конструкции для синхронизации нитей Директива master Директива critical Директива atomic Семафоры Директива barrier Директива flush Директива ordered


Слайд 84

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 85 из 137 #pragma omp master структурный блок /*Структурный блок будет выполнен MASTER-нитью группы. По завершении выполнения структурного блока барьерная синхронизация нитей не выполняется*/ #include <stdio.h> void init(float *a, float *b ) { #pragma omp master scanf("%f %f", a, b); #pragma omp barrier } int main () { float x,y; #pragma omp parallel { init (&x,&y); parallel_work (x,y); } } Директива master


Слайд 85

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 86 из 137 При взаимодействии через общую память нити должны синхронизовать свое выполнение. int i=0; #pragma omp parallel { i++; } Взаимное исключение критических интервалов Результат зависит от порядка выполнения команд. Требуется взаимное исключение критических интервалов.


Слайд 86

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 87 из 137 Решение проблемы взаимного исключения должно удовлетворять требованиям: в любой момент времени только одна нить может находиться внутри критического интервала; если ни одна нить не находится в критическом интервале, то любая нить, желающая войти в критический интервал, должна получить разрешение без какой либо задержки; ни одна нить не должна бесконечно долго ждать разрешения на вход в критический интервал (если ни одна нить не будет находиться внутри критического интервала бесконечно). Взаимное исключение критических интервалов


Слайд 87

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 88 из 137 Вычисление числа ?


Слайд 88

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 89 из 137 int main () { int n =100000, i; double pi, h, sum, x; h = 1.0 / (double) n; sum = 0.0; for (i = 1; i <= n; i ++) { x = h * ((double)i - 0.5); sum += (4.0 / (1.0 + x*x)); } pi = h * sum; printf("pi is approximately %.16f”, pi); return 0; } Вычисление числа ?. Последовательная программа.


Слайд 89

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 90 из 137 #include <stdio.h> #include <omp.h> int main () { int n =100000, i; double pi, h, sum, x; h = 1.0 / (double) n; sum = 0.0; #pragma omp parallel default (none) private (i,x) shared (n,h,sum) { double local_sum = 0.0; #pragma omp for for (i = 1; i <= n; i++) { x = h * ((double)i - 0.5); local_sum += (4.0 / (1.0 + x*x)); } #pragma omp critical sum += local_sum; } pi = h * sum; printf("pi is approximately %.16f”, pi); return 0; } Вычисление числа ? на OpenMP с использованием критической секции #pragma omp critical [(name)] структурный блок


Слайд 90

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 91 из 137 #pragma omp atomic expression-stmt где expression-stmt: x binop= expr x++ ++x x-- --x Здесь х – скалярная переменная, expr – выражение со скалярными типами, в котором не присутствует переменная х. где binop - не перегруженный оператор: + * - / & ^ | << >> Директива atomic


Слайд 91

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 92 из 137 int main () { int n =100000, i; double pi, h, sum, x; h = 1.0 / (double) n; sum = 0.0; #pragma omp parallel default (none) private (i,x) shared (n,h,sum) { double local_sum = 0.0; #pragma omp for for (i = 1; i <= n; i++) { x = h * ((double)i - 0.5); local_sum += (4.0 / (1.0 + x*x)); } #pragma omp atomic sum += local_sum; } pi = h * sum; printf("pi is approximately %.16f”, pi); return 0; } Вычисление числа ? на OpenMP с использованием директивы atomic


Слайд 92

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 93 из 137 Концепцию семафоров описал Дейкстра (Dijkstra) в 1965 Семафор - неотрицательная целая переменная, которая может изменяться и проверяться только посредством двух функций: P - функция запроса семафора P(s): [if (s == 0) <заблокировать текущий процесс>; else s = s-1;] V - функция освобождения семафора V(s): [if (s == 0) <разблокировать один из заблокированных процессов>; s = s+1;] Семафоры


Слайд 93

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 94 из 137 Состояния семафора: uninitialized unlocked locked void omp_init_lock(omp_lock_t *lock); /* uninitialized to unlocked*/ void omp_destroy_lock(omp_lock_t *lock); /* unlocked to uninitialized */ void omp_set_lock(omp_lock_t *lock); /*P(lock)*/ void omp_unset_lock(omp_lock_t *lock); /*V(lock)*/ int omp_test_lock(omp_lock_t *lock); void omp_init_nest_lock(omp_nest_lock_t *lock); void omp_destroy_nest_lock(omp_nest_lock_t *lock); void omp_set_nest_lock(omp_nest_lock_t *lock); void omp_unset_nest_lock(omp_nest_lock_t *lock); int omp_test_nest_lock(omp_nest_lock_t *lock); Семафоры в OpenMP


Слайд 94

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 95 из 137 int main () { int n =100000, i; double pi, h, sum, x; omp_lock_t lck; h = 1.0 / (double) n; sum = 0.0; omp_init_lock(&lck); #pragma omp parallel default (none) private (i,x) shared (n,h,sum,lck) { double local_sum = 0.0; #pragma omp for for (i = 1; i <= n; i++) { x = h * ((double)i - 0.5); local_sum += (4.0 / (1.0 + x*x)); } omp_set_lock(&lck); sum += local_sum; omp_unset_lock(&lck); } pi = h * sum; printf("pi is approximately %.16f”, pi); omp_destroy_lock(&lck); return 0; } Вычисление числа ? на OpenMP с использованием семафоров


Слайд 95

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 96 из 137 int main() { omp_lock_t lck; int id; omp_init_lock(&lck); #pragma omp parallel shared(lck) private(id) { id = omp_get_thread_num(); omp_set_lock(&lck); printf("My thread id is %d.\n", id); /* only one thread at a time can execute this printf */ omp_unset_lock(&lck); while (! omp_test_lock(&lck)) { skip(id); /* we do not yet have the lock, so we must do something else*/ } work(id); /* we now have the lock and can do the work */ omp_unset_lock(&lck); } omp_destroy_lock(&lck); return 0; } Использование семафоров void skip(int i) {} void work(int i) {}


Слайд 96

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 97 из 137 Точка в программе, достижимая всеми нитями группы, в которой выполнение программы приостанавливается до тех пор пока все нити группы не достигнут данной точки. #pragma omp barrier По умолчанию барьерная синхронизация нитей выполняется: по завершению конструкции parallel; при выходе из конструкций распределения работ (for, single, sections) , если не указана клауза nowait. int size; #pragma omp parallel { #pragma omp master { scanf("%d",&size); } #pragma omp barrier process(size); } Директива barrier


Слайд 97

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 98 из 137 #pragma omp flush [(список переменных)] По умолчанию все переменные приводятся в консистентное состояние (#pragma omp flush): При барьерной синхронизации При входе и выходе из конструкций parallel, critical и ordered. При выходе из конструкций распределения работ (for, single, sections, workshare), если не указана клауза nowait. При вызове omp_set_lock и omp_unset_lock. При вызове omp_test_lock, omp_set_nest_lock, omp_unset_nest_lock и omp_test_nest_lock, если изменилось состояние семафора. При входе и выходе из конструкции atomic выполняется #pragma omp flush(x), где x – переменная, изменяемая в конструкции atomic. Директива flush


Слайд 98

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 99 из 137 Содержание Современные направления развития параллельных вычислительных систем OpenMP – модель параллелизма по управлению Конструкции распределения работы Конструкции для синхронизации нитей Система поддержки выполнения OpenMP-программ. Переменные окружения, управляющие выполнением OpenMP-программы Наиболее часто встречаемые ошибки в OpenMP-программах. Функциональная отладка OpenMP-программ Отладка эффективности OpenMP-программ Использование OpenMP на кластере


Слайд 99

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 100 из 137 Система поддержки выполнения OpenMP-программ. Внутренние переменные, управляющие выполнением OpenMP-программы (ICV-Internal Control Variables). Задание/опрос значений ICV-переменных. Функции работы со временем.


Слайд 100

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 101 из 137 Для параллельных областей: nthreads-var thread-limit-var dyn-var nest-var max-active-levels-var Для циклов: run-sched-var def-sched-var Для всей программы: stacksize-var wait-policy-var Internal Control Variables.


Слайд 101

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 102 из 137 Internal Control Variables. nthreads-var Определяет максимально возможное количество нитей в создаваемой параллельной области. Начальное значение: зависит от реализации. Значение переменной можно изменить: C shell: setenv OMP_NUM_THREADS 16 Korn shell: export OMP_NUM_THREADS=16 Windows: set OMP_NUM_THREADS=16 void omp_set_num_threads(int num_threads); Узнать значение переменной можно: int omp_get_max_threads(void);


Слайд 102

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 103 из 137 Internal Control Variables. run-sched-var Задает способ распределения витков цикла между нитями, если указана клауза schedule(runtime). Начальное значение: зависит от реализации. Существует одна копия этой переменной для каждой нити. Значение переменной можно изменить: C shell: setenv OMP_SCHEDULE "guided,4" Korn shell: export OMP_SCHEDULE "dynamic,5" Windows: set OMP_SCHEDULE=static void omp_set_schedule(omp_sched_t kind, int modifier); Узнать значение переменной можно: void omp_get_schedule(omp_sched_t * kind, int * modifier ); typedef enum omp_sched_t { omp_sched_static = 1, omp_sched_dynamic = 2, omp_sched_guided = 3, omp_sched_auto = 4 } omp_sched_t;


Слайд 103

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 104 из 137 Internal Control Variables. run-sched-var void work(int i); int main () { omp_sched_t schedules [] = {omp_sched_static, omp_sched_dynamic, omp_sched_guided, omp_sched_auto}; omp_set_num_threads (4); #pragma omp parallel { omp_set_schedule (schedules[omp_get_thread_num()],0); #pragma omp parallel for schedule(runtime) for (int i=0;i<N;i++) work (i); } }


Слайд 104

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 105 из 137 int omp_get_num_threads(void); -возвращает количество нитей в текущей параллельной области #include <omp.h> void work(int i); void test() { int np; np = omp_get_num_threads(); /* np == 1*/ #pragma omp parallel private (np) { np = omp_get_num_threads(); #pragma omp for schedule(static) for (int i=0; i < np; i++) work(i); } } Система поддержки выполнения OpenMP-программ.


Слайд 105

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 106 из 137 int omp_get_thread_num(void); -возвращает номер нити в группе [0: omp_get_num_threads()-1] #include <omp.h> void work(int i); void test() { int iam; iam = omp_get_thread_num(); /* iam == 0*/ #pragma omp parallel private (iam) { iam = omp_get_thread_num(); work(iam); } } Система поддержки выполнения OpenMP-программ.


Слайд 106

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 107 из 137 int omp_get_num_procs(void); -возвращает количество процессоров, на которых программа выполняется #include <omp.h> void work(int i); void test() { int nproc; nproc = omp_get_num_ procs(); #pragma omp parallel num_threads(nproc) { int iam = omp_get_thread_num(); work(iam); } } Система поддержки выполнения OpenMP-программ.


Слайд 107

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 108 из 137 double omp_get_wtime(void); возвращает для нити астрономическое время в секундах, прошедшее с некоторого момента в прошлом. Если некоторый участок окружить вызовами данной функции, то разность возвращаемых значений покажет время работы данного участка. Гарантируется, что момент времени, используемый в качестве точки отсчета, не будет изменен за время выполнения программы. double start; double end; start = omp_get_wtime(); /*... work to be timed ...*/ end = omp_get_wtime(); printf("Work took %f seconds\n", end - start); double omp_get_wtick(void); - возвращает разрешение таймера в секундах (количество секунд между последовательными импульсами таймера). Система поддержки выполнения OpenMP-программ. Функции работы со временем


Слайд 108

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 109 из 137 Содержание Современные направления развития параллельных вычислительных систем OpenMP – модель параллелизма по управлению Конструкции распределения работы Конструкции для синхронизации нитей Система поддержки выполнения OpenMP-программ. Переменные окружения, управляющие выполнением OpenMP-программы Наиболее часто встречаемые ошибки в OpenMP-программах. Функциональная отладка OpenMP-программ Отладка эффективности OpenMP-программ Использование OpenMP на кластере


Слайд 109

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 110 из 137 Наиболее часто встречаемые ошибки в OpenMP-программах. Трудно обнаруживаемые ошибки типа race condition (конфликт доступа к данным). Ошибки типа deadlock (взаимная блокировка нитей). Использование неинициализированных переменных. Автоматизированный поиск ошибок в OpenMP-программах при помощи Intel Thread Checker.


Слайд 110

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 111 из 137 Ошибка возникает при одновременном выполнении следующих условий: Две или более нитей обращаются к одной и той же ячейке памяти. По крайней мере, один из этих доступов к памяти является записью. Нити не синхронизируют свой доступ к данной ячейки памяти. При одновременном выполнении всех трех условий порядок доступа становится неопределенным. Конфликт доступа к данным


Слайд 111

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 112 из 137 Использование различных компиляторов (различных опций оптимизации, включение/отключение режима отладки при компиляции программы), применение различных стратегий планирования выполнения нитей в различных ОС, может приводить к тому, что в каких-то условиях (например, на одной вычислительной машине) ошибка не будет проявляться, а в других (на другой машине) – приводить к некорректной работе программы. От запуска к запуску программа может выдавать различные результаты в зависимости от порядка доступа. Отловить такую ошибку очень тяжело. Причиной таких ошибок как правило являются: неверное определение класса переменной, отсутствие синхронизации. Конфликт доступа к данным


Слайд 112

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 113 из 137 Конфликт доступа к данным #define N float a[N], tmp #pragma omp parallel { #pragma omp for for(int i=0; i<N;i++) { tmp= a[i]*a[i]; a[i]=1-tmp; } } #define N float a[N], sum #pragma omp parallel { #pragma omp for private(tmp) for(int i=0; i<N;i++) { tmp= a[i]*a[i]; a[i]=1-tmp; } }


Слайд 113

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 114 из 137 Конфликт доступа к данным file1.c int counter = 0; #pragma omp threadprivate(counter) int increment_counter() { counter++; return(counter); } file2.c extern int counter; // нет директивы threadprivate int decrement_counter() { counter--; return(counter); }


Слайд 114

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 115 из 137 Конфликт доступа к данным #define N float a[N], sum #pragma omp parallel { #pragma omp master sum = 0.0; #pragma omp for for(int i=0; i<N;i++) { #omp atomic sum += a[i]; } } #define N float a[N], sum #pragma omp parallel { #pragma omp master sum = 0.0; #pragma omp barrier #pragma omp for for(int i=0; i<N;i++) { #omp atomic sum += a[i]; } }


Слайд 115

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 116 из 137 Взаимная блокировка нитей #pragma omp parallel { int iam=omp_get_thread_num(); if (iam ==0) { omp_set_lock (&lcka); omp_set_lock (&lckb); x = x + 1; omp_unset_lock (&lckb); omp_unset_lock (&lcka); } else { omp_set_lock (&lckb); omp_set_lock (&lcka); x = x + 2; omp_unset_lock (&lcka); omp_unset_lock (&lckb); } } }


Слайд 116

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 117 из 137 Автоматизированный поиск ошибок. Intel Thread Checker KAI Assure Threads (Kuck and Associates) Анализ программы основан на процедуре инструментации. Инструментация – вставка обращений для записи действий, потенциально способных привести к ошибкам: работа с памятью, вызовы операций синхронизации и работа с потоками. Может выполняться автоматически (бинарная инструментация) на уровне исполняемого модуля (а также dll-библиотеки) и/или по указанию программиста на уровне исходного кода (компиляторная инструментация - Windows: /Qtcheck Linux:-tcheck).


Слайд 117


Слайд 118


Слайд 119

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 120 из 137 Содержание Современные направления развития параллельных вычислительных систем OpenMP – модель параллелизма по управлению Конструкции распределения работы Конструкции для синхронизации нитей Система поддержки выполнения OpenMP-программ. Переменные окружения, управляющие выполнением OpenMP-программы Наиболее часто встречаемые ошибки в OpenMP-программах. Функциональная отладка OpenMP-программ Отладка эффективности OpenMP-программ


Слайд 120

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 121 из 137 Отладка эффективности OpenMP-программ Основные характеристики производительности Стратегии распределения витков цикла между нитями (клауза schedule) Отмена барьерной синхронизации по окончании выполнения цикла (клауза nowait) Локализация данных Задание поведения нитей во время ожидания (переменная OMP_WAIT_POLICY) Оптимизация OpenMP-программы при помощи Intel Thread Profiler


Слайд 121

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 122 из 137 Основные характеристики производительности Полезное время - время, которое потребуется для выполнения программы на однопроцессорной ЭВМ. Общее время использования процессоров равно произведению времени выполнения программы на многопроцессорной ЭВМ (максимальное значение среди времен выполнения программы на всех используемых ею процессорах) на число используемых процессоров. Главная характеристика эффективности параллельного выполнения - коэффициент эффективности равен отношению полезного времени к общему времени использования процессоров. Разница между общим временем использования процессоров и полезным временем представляет собой потерянное время. Существуют следующие составляющие потерянного времени: накладные расходы на создание группы нитей; потери из-за простоев тех нитей, на которых выполнение программы завершилось раньше, чем на остальных (несбалансированная нагрузка нитей); потери из-за синхронизации нитей (например, из-за чрезмерного использования общих данных); потери из-за недостатка параллелизма, приводящего к дублированию вычислений на нескольких процессорах (недостаточный параллелизм).


Слайд 122

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 123 из 137 Накладные расходы на создание группы нитей void work(int i, int j) {} for (int i=0; i < n; i++) { for (int j=0; j < n; j++) { work(i, j); } } #pragma omp parallel for for (int i=0; i < n; i++) { for (int j=0; j < n; j++) { work(i, j); } } for (int i=0; i < n; i++) { #pragma omp parallel for for (int j=0; j < n; j++) { work(i, j); } }


Слайд 123

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 124 из 137 Алгоритм Якоби for (int it=0;it<ITMAX; it++) { for (int i=1; i<N-1; i++ ) for( int j=1; j<N-1; j++ ) tmp[i][j] = 0.25 * ( grid[i-1][j] + grid[i+1][j] + grid[i][j-1] + grid[i][j+1]); for (int i=0; i<N; i++ ) for( int j=0; j<N; j++ ) grid[i][j] = tmp[i][j]; } for (int it=0;it<ITMAX; it++) { #pragma omp parallel for for (int i=1; i<N-1; i++ ) for (int j=1; j<N-1; j++ ) tmp[i][j] = 0.25 * ( grid[i-1][j] + grid[i+1][j] + grid[i][j-1] + grid[i][j+1]); #pragma omp parallel for for (int i=1; i<N-1; i++ ) for (int j=1; j<N-1; j++ ) grid[i][j] = tmp[i][j]; } #pragma omp parallel { for (int it=0;it<ITMAX; it++) { #pragma omp for for (int i=1; i<N-1; i++ ) for (int j=1; j<N-1; j++ ) tmp[i][j] = 0.25 * ( grid[i-1][j] + grid[i+1][j] + grid[i][j-1] + grid[i][j+1]); #pragma omp for for (int i=1; i<N-1; i++ ) for (int j=1; j<N-1; j++ ) grid[i][j] = tmp[i][j]; } }


Слайд 124

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 125 из 137 Балансировка нагрузки нитей. Клауза schedule Клауза schedule: schedule(алгоритм планирования[, число_итераций]) Где алгоритм планирования один из: schedule(static[, число_итераций]) - статическое планирование; schedule(dynamic[, число_итераций]) - динамическое планирование; schedule(guided[, число_итераций]) - управляемое планирование; schedule(runtime) - планирование в период выполнения; schedule(auto) - автоматическое планирование (OpenMP 3.0). #pragma omp parallel for schedule(static) for(int i = 1; i <= 100; i++) A[i]=0.;


Слайд 125

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 126 из 137 Балансировка нагрузки нитей. Клауза schedule #pragma omp parallel for private(tmp) shared (a) schedule (runtime) for (int i=0; i<N-2; i++) for (int j = i+1; j< N-1; j++) { tmp = a[i][j]; a[i][j]=a[j][i]; a[j][i]=tmp; } export OMP_SCHEDULE="static" export OMP_SCHEDULE="static,10" export OMP_SCHEDULE="dynamic" export OMP_SCHEDULE="dynamic,10"


Слайд 126

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 127 из 137 Отмена барьерной синхронизации по окончании выполнения цикла. Клауза nowait void example(int n, float *a, float *b, float *c, float *z, int n) { int i; #pragma omp parallel { #pragma omp for schedule(static) nowait for (i=0; i<n; i++) c[i] = (a[i] + b[i]) / 2.0; #pragma omp for schedule(static) nowait for (i=0; i<n; i++) z[i] = sqrt(c[i]); } }


Слайд 127

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 128 из 137 Локализация данных #pragma omp parallel shared (var) { <критическая секция> { var = … } } Модификация общей переменной в параллельной области должна осуществляться в критической секции (critical/atomic/omp_set_lock). Если локализовать данную переменную (например, private(var)), то можно сократить потери на синхронизацию нитей.


Слайд 128

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 129 из 137 Intel Thread Profiler Предназначен для анализа производительности OpenMP-приложений или многопоточных приложений с использованием потоков Win32 API и POSIX. Визуализация выполнения потоков во времени помогает понять их функции и взаимодействие. Инструмент указывает на узкие места, снижающие производительность. Инструментация программы: Linux: -g [-openmp_profile] Windows: /Zi [/-Qopenmp_profile], link with /fixed:no


Слайд 129


Слайд 130


Слайд 131


Слайд 132


Слайд 133


Слайд 134

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 135 из 137 Материалы по курсу Презентация доступна: ftp://ftp.keldysh.ru/K_student/OpenMp/SpeckursMSU2011_OpenMP.ppt


Слайд 135

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 136 из 137 Литература OpenMP Application Program Interface Version 3.0, May 2008. http://www.openmp.org/mp-documents/spec30.pdf Антонов А.С. Параллельное программирование с использованием технологии OpenMP: Учебное пособие.-М.: Изд-во МГУ, 2009. http://parallel.ru/info/parallel/openmp/OpenMP.pdf Э. Таненбаум, М. ван Стеен. Распределенные системы. Принципы и парадигмы. – СПб. Питер, 2003 Воеводин В.В., Воеводин Вл.В. Параллельные вычисления. – СПб.: БХВ-Петербург, 2002.


Слайд 136

14 сентября Москва, 2011 Параллельное программирование с использованием технологии OpenMP. 137 из 137 Автор Бахтин Владимир Александрович, кандидат физико-математических наук, заведующий сектором Института прикладной математики им. М.В. Келдыша РАН, bakhtin@keldysh.ru


×

HTML:





Ссылка: