Технология параллельного программирования OpenMP Бахтин Владимир Александрович к.ф.-м.н., зав. сектором Института прикладной математики им М.В.Келдыша РАН ассистент кафедры системного программирования факультета вычислительной математики и кибернетики Московского университета им. М.В. Ломоносова
25-26 июня Москва, 2012Технология параллельного программирования OpenMP2 из 125 Современные направления развития параллельных вычислительных систем OpenMP – модель параллелизма по управлению Конструкции распределения работы Конструкции для синхронизации нитей Система поддержки выполнения OpenMP-программ. Переменные окружения, управляющие выполнением OpenMP-программы Содержание
25-26 июня Москва, 2012Технология параллельного программирования OpenMP3 из 125 Тенденции развития современных процессоров Существующие подходы для создания параллельных программ Что такое OpenMP? Современные направления развития параллельных вычислительных систем
Тенденции развития современных процессоров июня Москва, 2012 Технология параллельного программирования OpenMP 4 из 125 В течение нескольких десятилетий развитие ЭВМ сопровождалось удвоением их быстродействия каждые года. Это обеспечивалось и повышением тактовой частоты и совершенствованием архитектуры (параллельное и конвейерное выполнение команд). Узким местом стала оперативная память. Знаменитый закон Мура, так хорошо работающий для процессоров, совершенно не применим для памяти, где скорости доступа удваиваются в лучшем случае каждые 6 лет. Совершенствовались системы кэш-памяти, увеличивался объем, усложнялись алгоритмы ее использования. Для процессора Intel Itanium: Latency to L1: 1-2 cycles Latency to L2: cycles Latency to L3: cycles Latency to memory: 180 – 225 cycles Важным параметром становится - GUPS (Giga Updates Per Second)
Время июня Москва, 2012 Технология параллельного программирования OpenMP 5 из 125 В П В П В П В П В П В П Поток Время В П В П В П Поток 1 В П В П В П В П В П В П В П В П В П Поток 2 Поток 3 Поток 4 В - вычисления П - доступ к памяти Chip MultiThreading увеличили производительность процессора в 2 раза Поток или нить (по- английски thread) – это легковесный процесс, имеющий с другими потоками общие ресурсы, включая общую оперативную память. Тенденции развития современных процессоров
25-26 июня Москва, 2012 Технология параллельного программирования OpenMP 6 из 125 Суперкомпьютер Jaguar Cray XT5-HE Opteron Six Core 2.6 GHz Пиковая производительность TFlop/s Число ядер в системе Производительность на Linpack TFlop/s (75.4% от пиковой) Энергопотребление комплекса кВт Важным параметром становится – Power Efficency (Megaflops/watt) Как добиться максимальной производительности на Ватт => Chip MultiProcessing, многоядерность. Тенденции развития современных процессоров
25-26 июня Москва, 2012 Технология параллельного программирования OpenMP 7 из 125 AMD Opteron серии SE 16 2,7 ГГц, 16 МБ L3 Cache ,0 ГГц, 16 МБ L3 Cache ,3 ГГц, 16 МБ L3 Cache встроенный контроллер памяти (4 канала памяти DDR3) 4 канала «точка-точка» с использованием HyperTransort 3.0 Тенденции развития современных процессоров
25-26 июня Москва, 2012 Технология параллельного программирования OpenMP 8 из 125 Intel Xeon серии E ,9 ГГц, 16 нитей, 20 МБ L3 Cache ,5 ГГц, 8 нитей, 10 МБ L3 Cache Intel® Turbo Boost Intel® Hyper-Threading Intel® QuickPath Intel® Intelligent Power Тенденции развития современных процессоров
25-26 июня Москва, 2012 Технология параллельного программирования OpenMP 9 из 125 Intel Core i7-3960X Extreme Edition 3,3 ГГц (3,9 ГГц) 6 ядeр 12 потоков с технологией Intel Hyper-Threading 15 МБ кэш-памяти Intel Smart Cache встроенный контроллер памяти (4 канала памяти DDR3 1066/1333/1600 МГц ) технология Intel QuickPath Interconnect Тенденции развития современных процессоров
25-26 июня Москва, 2012 Технология параллельного программирования OpenMP 10 из 125 Intel Itanium 9350 (Tukwila) 1,73 ГГц 4 ядра 8 потоков с технологией Intel Hyper-Threading 24 МБ L3 кэш-памяти технология Intel QuickPath Interconnect технология Intel Turbo Boost Тенденции развития современных процессоров
25-26 июня Москва, 2012 Технология параллельного программирования OpenMP 11 из 125 IBM Power7 3,5 - 4,0 ГГц 8 ядер x 4 нити Simultaneuos MultiThreading L1 64КБ L2 256 КБ L3 32 МБ встроенный контроллер памяти Тенденции развития современных процессоров
25-26 июня Москва, 2012Технология параллельного программирования OpenMP12 из 125 Темпы уменьшения латентности памяти гораздо ниже темпов ускорения процессоров + прогресс в технологии изготовления кристаллов => CMT (Chip MultiThreading) Опережающий рост потребления энергии при росте тактовой частоты + прогресс в технологии изготовления кристаллов => CMP (Chip MultiProcessing, многоядерность) И то и другое требует более глубокого распараллеливания для эффективного использования аппаратуры Тенденции развития современных процессоров
Автоматическое / автоматизированное распараллеливание Библиотеки нитей Win32 API POSIX Библиотеки передачи сообщений MPI OpenMP июня Москва, 2012 Технология параллельного программирования OpenMP 13 из 125 Тенденции развития современных процессоров
25-26 июня Москва, 2012 Технология параллельного программирования OpenMP 14 из (1+x 2 ) dx = 0 1 F(x i ) x i = 0 N Мы можем аппроксимировать интеграл как сумму прямоугольников: Где каждый прямоугольник имеет ширину x и высоту F(x i ) в середине интервала F(x) = 4.0/(1+x 2 ) X 0.0 Вычисление числа
25-26 июня Москва, 2012Технология параллельного программирования OpenMP15 из 125 #include int main () { int n =100000, i; double pi, h, sum, x; h = 1.0 / (double) n; sum = 0.0; for (i = 1; i
Polaris, CAPO, WPP, SUIF, VAST/Parallel, OSCAR, Intel/OpenMP, ParaWise icc -parallel pi.c pi.c(8): (col. 5) remark: LOOP WAS AUTO-PARALLELIZED. pi.c(8): (col. 5) remark: LOOP WAS VECTORIZED. В общем случае, автоматическое распараллеливание затруднено: косвенная индексация (A[B[i]]); указатели (ассоциация по памяти); сложный межпроцедурный анализ июня Москва, 2012 Технология параллельного программирования OpenMP 16 из 125 Автоматическое распараллеливание
25-26 июня Москва, 2012 Технология параллельного программирования OpenMP 17 из 125 Intel/GAP (Guided Auto-Parallel), CAPTools/ParaWise, BERT77, FORGE Magic/DM, ДВОР (Диалоговый Высокоуровневый Оптимизирующий Распараллеливатель), САПФОР (Система Автоматизации Параллелизации ФОРтран программ) for (i=0; i 0) {b=A[i]; A[i] = 1 / A[i]; } if (A[i] > 1) {A[i] += b;} } icc -guide -parallel test.cpp Автоматизированное распараллеливание
25-26 июня Москва, 2012 Технология параллельного программирования OpenMP 18 из 125 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 0) {A[i] = 1 / A[i];} if (A[i] > 1) {A[i] += b;} } Автоматизированное распараллеливание
25-26 июня Москва, 2012Технология параллельного программирования OpenMP19 из 125 #include #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
25-26 июня Москва, 2012Технология параллельного программирования OpenMP20 из 125 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
25-26 июня Москва, 2012Технология параллельного программирования OpenMP21 из 125 При взаимодействии через общую память нити должны синхронизовать свое выполнение. Thread0: pi = pi + val; && Thread1: pi = pi + val; ВремяThread 0 Thread 1 1LOAD R1,pi 2LOAD R2,val 3ADD R1,R2LOAD R1,pi 4LOAD R2,val 5ADD R1,R2 6STORE R1,pi 7 Результат зависит от порядка выполнения команд. Требуется взаимное исключение критических интервалов. Взаимное исключение критических интервалов
25-26 июня Москва, 2012Технология параллельного программирования OpenMP22 из 125 #include "mpi.h" #include 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; Вычисление числа с использованием MPI
25-26 июня Москва, 2012Технология параллельного программирования OpenMP23 из 125 for (i = myid + 1; i
25-26 июня Москва, 2012Технология параллельного программирования OpenMP24 из 125 #include 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
Возможность инкрементального распараллеливания Упрощение программирования и эффективность на нерегулярных вычислениях, проводимых над общими данными Ликвидация дублирования данных в памяти, свойственного MPI- программам Объем памяти пропорционален быстродействию процессора. В последние годы увеличение производительности процессора достигается удвоением числа ядер, при этом частота каждого ядра снижается. Наблюдается тенденция к сокращению объема оперативной памяти, приходящейся на одно ядро. Присущая OpenMP экономия памяти становится очень важна. Наличие локальных и/или разделяемых ядрами КЭШей будут учитываться при оптимизации OpenMP-программ компиляторами, что не могут делать компиляторы с последовательных языков для MPI-процессов июня Москва, 2012 Технология параллельного программирования OpenMP 25 из 125 Достоинства использования OpenMP вместо MPI для многоядерных процессоров
25-26 июня Москва, 2012 Технология параллельного программирования OpenMP 26 из 125 BT3D Навье-Стокс, метод переменных направлений CGОценка наибольшего собственного значения симметричной разреженной матрицы EPГенерация пар случайных чисел Гаусса FTБыстрое преобразование Фурье, 3D спектральный метод ISПараллельная сортировка LU3D Навье-Стокс, метод верхней релаксации MG3D уравнение Пуассона, метод Multigrid SP3D Навье-Стокс, Beam-Warning approximate factorization Тесты NAS
25-26 июня Москва, 2012 Технология параллельного программирования OpenMP 27 из 125 Analyzing the Effect of Different Programming Models Upon Performance and Memory Usage on Cray XT5 Platforms Тесты NAS
25-26 июня Москва, 2012 Технология параллельного программирования OpenMP 28 из 125 Analyzing the Effect of Different Programming Models Upon Performance and Memory Usage on Cray XT5 Platforms Тесты NAS
25-26 июня Москва, 2012 Технология параллельного программирования OpenMP 29 из 125 OpenMP Fortran 1.1 OpenMP C/C OpenMP Fortran 2.0 OpenMP Fortran 2.0 OpenMP C/C OpenMP C/C OpenMP Fortran OpenMP F/C/C OpenMP F/C/C OpenMP F/C/C OpenMP F/C/C OpenMP F/C/C OpenMP F/C/C История OpenMP
25-26 июня Москва, 2012 Технология параллельного программирования OpenMP 30 из 125 AMD Cray Fujitsu HP IBM Intel NEC The Portland Group, Inc. Oracle Corporation Microsoft Texas Instrument CAPS-Enterprise NVIDIA Convey Computer ANL ASC/LLNL cOMPunity EPCC LANL NASA RWTH Aachen University Texas Advanced Computing Center OpenMP Architecture Review Board
OpenMP 3.1: Intel 12.0: Linux, Windows and MacOS Oracle Solaris Studio12.3: Linux and Solaris GNU gcc (4.7.0) OpenMP 3.0: PGI 8.0: Linux and Windows IBM 10.1: Linux and AIX Cray: Cray XT series Linux environment Absoft Pro FortranMP: 11.1 NAG Fortran Complier 5.3 Предыдущие версии OpenMP: Lahey/Fujitsu Fortran 95 PathScale HP Microsoft Visual Studio 2008 C июня Москва, 2012 Технология параллельного программирования OpenMP 31 из 125 Компиляторы, поддеживающие OpenMP
25-26 июня Москва, 2012Технология параллельного программирования OpenMP32 из 125 Все процессоры имеют доступ к любой точке памяти с одинаковой скоростью. Процессоры подключены к памяти либо с помощью общей шины, либо с помощью crossbar-коммутатора. Аппаратно поддерживается когерентность кэшей. Cимметричные мультипроцессорные системы (SMP)
25-26 июня Москва, 2012Технология параллельного программирования OpenMP33 из 125 Система состоит из однородных базовых модулей (плат), состоящих из небольшого числа процессоров и блока памяти. Модули объединены с помощью высокоскоростного коммутатора. Поддерживается единое адресное пространство. Доступ к локальной памяти в несколько раз быстрее, чем к удаленной. Системы с неоднородным доступом к памяти (NUMA)
25-26 июня Москва, 2012Технология параллельного программирования OpenMP34 из 125 SGI Altix UV (UltraVioloet) Intel® Xeon® quad-, six- or eight-core 7500 series (2048 cores) 16 TB памяти Interconnect Speed 15 ГБ/с, 1мкс Системы с неоднородным доступом к памяти (NUMA)
25-26 июня Москва, 2012Технология параллельного программирования OpenMP35 из 125 Современные направления развития параллельных вычислительных систем OpenMP – модель параллелизма по управлению Конструкции распределения работы Конструкции для синхронизации нитей Система поддержки выполнения OpenMP-программ. Переменные окружения, управляющие выполнением OpenMP-программы Содержание
25-26 июня Москва, 2012Технология параллельного программирования OpenMP36 из 125 Основные понятия Выполнение OpenMP-программы Классы переменных Параллельная область OpenMP- модель параллелизма по управлению
25-26 июня Москва, 2012 Технология параллельного программирования OpenMP 37 из 125 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 DO LASTPRIVATE(XX) 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 лет OpenMP: API для написания многонитевых приложений Множество директив компилятора, набор функции библиотеки системы поддержки, переменные окружения Облегчает создание многонитиевых программ на Фортране, C и C++ Обобщение опыта создания параллельных программ для SMP и DSM систем за последние 20 лет Обзор основных возможностей OpenMP
Спецификации параллелизма в OpenMP представляют собой директивы вида: #pragma omp название-директивы[ клауза[ [,]клауза]...] Например: #pragma omp parallel default (none) shared (i,j) Исполняемые директивы: barrier taskwait flush Описательная директива: threadprivate июня Москва, 2012 Технология параллельного программирования OpenMP 38 из 125 Директивы и клаузы
Действие остальных директив распространяется на структурный блок: #pragma omp название-директивы[ клауза[ [,]клауза]...] { структурный блок } Структурный блок: блок кода с одной точкой входа и одной точкой выхода июня Москва, 2012 Технология параллельного программирования OpenMP 39 из 125 #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; Не структурный блок Структурный блок
25-26 июня Москва, 2012 Технология параллельного программирования OpenMP 40 из 125 ПроизводительКомпиляторОпция компиляции GNUgcc-fopenmp IBM XL C/C++ / Fortran -qsmp=omp Sun MicrosystemsC/C++ / Fortran-xopenmp IntelC/C++ / Fortran -openmp /Qopenmp Portland GroupC/C++ / Fortran-mp MicrosoftVisual Studio 2008 C++/openmp Компиляция OpenMP-программы
25-26 июня Москва, 2012 Технология параллельного программирования OpenMP 41 из 125 #include int main() { #ifdef _OPENMP printf("Compiled by an OpenMP-compliant implementation.\n"); #endif return 0; } В значении переменной _OPENMP зашифрован год и месяц (yyyymm) версии стандарта OpenMP, которую поддерживает компилятор. Условная компиляция OpenMP-программы
25-26 июня Москва, 2012 Технология параллельного программирования OpenMP 42 из 125 #include #include // Описаны прототипы всех функций и типов 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; } Использование функций поддержи выполнения OpenMP- программ (OpenMP API runtime library)
int omp_get_num_threads(void) { return 1; } int omp_get_thread_num(void) { return 0; } 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; } июня Москва, 2012 Технология параллельного программирования OpenMP 43 из 125 В стандарте OpenMP описаны «заглушки» для всех функций библиотеки поддержки – требуются при компиляции данной программы компилятором без поддержки OpenMP. Использование функций поддержи выполнения OpenMP- программ (OpenMP API runtime library)
25-26 июня Москва, 2012 Технология параллельного программирования OpenMP 44 из 125 Fork-Join параллелизм: Главная (master) нить порождает группу (team) нитей по мере небходимости. Параллелизм добавляется инкрементально. Параллельные области Выполнение OpenMP-программы
В модели программирования с разделяемой памятью: Большинство переменных по умолчанию считаются shared Глобальные переменные совместно используются всеми нитями (shared) : Фортран: COMMON блоки, SAVE переменные, MODULE переменные Си: file scope, static Динамически выделяемая память (ALLOCATE, malloc, new) Но не все переменные являются разделяемыми... Стековые переменные в подпрограммах (функциях), вызываемых из параллельного региона, являются private. Переменные объявленные внутри блока операторов параллельного региона являются приватными. Счетчики циклов витки которых распределяются между нитями при помощи конструкций for и parallel for июня Москва, 2012 Технология параллельного программирования OpenMP 45 из 125 Классы переменных
double Array1[100]; int main() { int Array2[100]; #pragma omp parallel work(Array2); printf(%d\n, Array2[0]); } июня Москва, 2012 Технология параллельного программирования OpenMP 46 из 125 extern double Array1[10]; void work(int *Array) { double TempArray[10]; static int count;... } TempArray Array1, Array2, count Классы переменных
Можно изменить класс переменной при помощи конструкций: shared (список переменных) private (список переменных) firstprivate (список переменных) lastprivate (список переменных) threadprivate (список переменных) default (private | shared | none) июня Москва, 2012 Технология параллельного программирования OpenMP 47 из 125 Классы переменных
Конструкция «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; } июня Москва, 2012 Технология параллельного программирования OpenMP 48 из 125 Конструкция private
«firstprivate» является специальным случаем «private» Инициализирует каждую приватную копию соответствующим значением из главной (master) нити. BOOL FirstTime=TRUE; #pragma omp parallel for firstprivate(FirstTime) for (row=0; row
25-26 июня Москва, 2012 Технология параллельного программирования OpenMP 50 из 125 lastprivate передает значение приватной переменной, посчитанной на последней итерации в глобальную переменную. int i; #pragma omp parallel { #pragma omp for lastprivate(i) for (i=0; i
Отличается от применения конструкции private: private скрывает глобальные переменные threadprivate – переменные сохраняют глобальную область видимости внутри каждой нити #pragma omp threadprivate (Var) июня Москва, 2012 Технология параллельного программирования OpenMP 51 из 125 Var = 1 Var = 2 … = Var Если количество нитей не изменилось, то каждая нить получит значение, посчитанное в предыдущей параллельной области. Директива threadprivate
25-26 июня Москва, 2012 Технология параллельного программирования OpenMP 52 из 125 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 ……… } Меняет класс переменной по умолчанию: default (shared) – действует по умолчанию default (private) – есть только в Fortran default (firstprivate) – есть только в Fortran OpenMP 3.1 default (none) – требует определить класс для каждой переменной Конструкция default
#pragma omp parallel [ клауза[ [, ] клауза]...] структурный блок где клауза одна из : default(shared | none) private(list) firstprivate(list) shared(list) reduction(operator: list) if(scalar-expression) num_threads(integer-expression) copyin(list) июня Москва, 2012 Технология параллельного программирования OpenMP 53 из 125 Параллельная область (директива parallel)
25-26 июня Москва, 2012 Технология параллельного программирования OpenMP 54 из (1+x 2 ) dx = 0 1 F(x i ) x i = 0 N Мы можем аппроксимировать интеграл как сумму прямоугольников: Где каждый прямоугольник имеет ширину x и высоту F(x i ) в середине интервала F(x) = 4.0/(1+x 2 ) X 0.0 Вычисление числа
25-26 июня Москва, 2012Технология параллельного программирования OpenMP55 из 125 #include int main () { int n =100000, i; double pi, h, sum, x; h = 1.0 / (double) n; sum = 0.0; for (i = 1; i
25-26 июня Москва, 2012Технология параллельного программирования OpenMP56 из 125 #include 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) { int id = omp_get_thread_num(); int numt = omp_get_num_threads(); for (i = id + 1; i
25-26 июня Москва, 2012Технология параллельного программирования OpenMP57 из 125 #include #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
25-26 июня Москва, 2012Технология параллельного программирования OpenMP58 из 125 #include 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
reduction(operator:list) Внутри паралельной области для каждой переменной из списка list создается копия этой переменной. Эта переменная инициализируется в соответствии с оператором operator (например, 0 для «+»). Для каждой нити компилятор заменяет в параллельной области обращения к редукционной переменной на обращения к созданной копии. По завершении выполнения параллельной области осуществляется объединение полученных результатов июня Москва, 2012 Технология параллельного программирования OpenMP 59 из 125 ОператорНачальное значение +0 *1 -0 &~0 |0 ^0 &&1 ||0 max Least number in reduction list item type min Largest number in reduction list item type Клауза reduction
if(scalar-expression) В зависимости от значения scalar-expression для выполнения структурного блока будет создана группа нитей или он будет выполняться одной нитью. #include int main() { int n = 0; printf("Enter the number of intervals: (0 quits) "); scanf("%d",&n); #pragma omp parallel if (n>10) { int id = omp_get_thread_num (); func (n, id); } return 0; } июня Москва, 2012 Технология параллельного программирования OpenMP 60 из 125 Клауза if
num_threads(integer-expression) integer-expression задает максимально возможное число нитей, которые будут созданы для выполнения структурного блока #include 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; } июня Москва, 2012 Технология параллельного программирования OpenMP 61 из 125 Клауза num_threads
25-26 июня Москва, 2012Технология параллельного программирования OpenMP62 из 125 Современные направления развития параллельных вычислительных систем OpenMP – модель параллелизма по управлению Конструкции распределения работы Конструкции для синхронизации нитей Система поддержки выполнения OpenMP-программ. Переменные окружения, управляющие выполнением OpenMP-программы Содержание
25-26 июня Москва, 2012Технология параллельного программирования OpenMP63 из 125 Распределение витков циклов (директива for) Выполнение структурного блока одной нитью (директива single) Конструкции распределения работы
25-26 июня Москва, 2012 Технология параллельного программирования OpenMP 64 из (1+x 2 ) dx = 0 1 F(x i ) x i = 0 N Мы можем аппроксимировать интеграл как сумму прямоугольников: Где каждый прямоугольник имеет ширину x и высоту F(x i ) в середине интервала F(x) = 4.0/(1+x 2 ) X 0.0 Вычисление числа
25-26 июня Москва, 2012Технология параллельного программирования OpenMP65 из 125 #include int main () { int n =100000, i; double pi, h, sum, x; h = 1.0 / (double) n; sum = 0.0; for (i = 1; i
25-26 июня Москва, 2012Технология параллельного программирования OpenMP66 из 125 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 iam = omp_get_thread_num(); int numt = omp_get_num_threads(); int start = iam * n / numt + 1; int end = (iam + 1) * n / numt; if (iam == numt-1) end = n; for (i = start; i
25-26 июня Москва, 2012Технология параллельного программирования OpenMP67 из 125 #include 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
#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 июня Москва, 2012 Технология параллельного программирования OpenMP 68 из 125 Распределение витков цикла
init-expr : var = loop-invariant-expr1 | integer-type var = loop-invariant-expr1 | random-access-iterator-type var = loop-invariant-expr1 | pointer-type var = loop-invariant-expr1 test-expr: var relational-op loop-invariant-expr2 | loop-invariant-expr2 relational-op var incr-expr: ++var | var++ | --var | var -- | var += loop-invariant-integer- expr | var -= loop-invariant-integer- expr | var = var + loop-invariant-integer- expr | var = loop-invariant-integer- expr + var | var = var - loop-invariant-integer- expr июня Москва, 2012 Технология параллельного программирования OpenMP 69 из 125 relational-op: < | | >= var: signed or unsigned integer type | random access iterator type | pointer type Распределение витков цикла
#include void iterator_example() { std::vector vec(23); std::vector ::iterator it; #pragma omp parallel for default(none) shared(vec) for (it = vec.begin(); it < vec.end(); it++) { // do work with *it // } июня Москва, 2012 Технология параллельного программирования OpenMP 70 из 125 Parallel Random Access Iterator Loop (OpenMP 3.0)
void pointer_example () { char a[N]; #pragma omp for default (none) shared (a,N) for (char *p = a; p < (a+N); p++ ) { use_char (p); } for (char *p = a; p != (a+N); p++ ) - ошибка июня Москва, 2012 Технология параллельного программирования OpenMP 71 из 125 Использование указателей в цикле (OpenMP 3.0)
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); } июня Москва, 2012 Технология параллельного программирования OpenMP 72 из 125 Вложенность конструкций распределения работы
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); } июня Москва, 2012 Технология параллельного программирования OpenMP 73 из 125 Вложенность конструкций распределения работы
void work(int i, int j) {} void good_collapsing(int n) { int i, j; #pragma omp parallel default(shared) { #pragma omp for collapse (2) for (i=0; i
void work(int i, int j) {} void error_collapsing(int n) { int i, j; #pragma omp parallel default(shared) { #pragma omp for collapse (2) for (i=0; i
void work(int i, int j) {} void error_collapsing(int n) { int i, j; #pragma omp parallel default(shared) { #pragma omp for collapse (2) for (i=0; i
Клауза schedule: schedule(алгоритм планирования[, число_итераций]) Где алгоритм планирования один из: schedule(static[, число_итераций]) - статическое планирование; schedule(dynamic[, число_итераций]) - динамическое планирование; schedule(guided[, число_итераций]) - управляемое планирование; schedule(runtime) - планирование в период выполнения; schedule(auto) - автоматическое планирование (OpenMP 3.0) июня Москва, 2012 Технология параллельного программирования OpenMP 77 из 125 Распределение витков цикла. Клауза schedule
#pragma omp parallel for schedule(dynamic, 15) for(int i = 1; i
#pragma omp parallel for schedule(static, 10) for(int i = 1; i
число_выполняемых_потоком_итераций = max(число_нераспределенных_итераций/omp_get_num_threads(), число_итераций) #pragma omp parallel for schedule(guided, 10) for(int i = 1; i
#pragma omp parallel for schedule(runtime) for(int i = 1; i
#pragma omp parallel for schedule(auto) for(int i = 1; i
void example(int n, float *a, float *b, float *z) { int i; #pragma omp parallel { #pragma omp for schedule(static) nowait for (i=0; i
void example(int n, float *a, float *b, float *z) { int i; float sum = 0.0; #pragma omp parallel { #pragma omp for schedule(static) nowait reduction (+: sum) for (i=0; i
#pragma omp single [клауза[[,] клауза]...] структурный блок где клауза одна из : private(list) firstprivate(list) copyprivate(list) nowait Структурный блок будет выполнен одной из нитей. Все остальные нити будут дожидаться результатов выполнения блока, если не указана клауза NOWAIT июня Москва, 2012 Технология параллельного программирования OpenMP 85 из 125 #include 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 (); } Выполнение структурного блока одной нитью (директива single)
25-26 июня Москва, 2012Технология параллельного программирования OpenMP86 из 125 Современные направления развития параллельных вычислительных систем OpenMP – модель параллелизма по управлению Конструкции распределения работы Конструкции для синхронизации нитей Система поддержки выполнения OpenMP-программ. Переменные окружения, управляющие выполнением OpenMP-программы Содержание
25-26 июня Москва, 2012Технология параллельного программирования OpenMP87 из 125 Директива master Директива critical Директива atomic Директива barrier Конструкции для синхронизации нитей
25-26 июня Москва, 2012Технология параллельного программирования OpenMP88 из 125 #pragma omp master структурный блок /*Структурный блок будет выполнен MASTER-нитью группы. По завершении выполнения структурного блока барьерная синхронизация нитей не выполняется*/ #include 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
25-26 июня Москва, 2012Технология параллельного программирования OpenMP89 из 125 При взаимодействии через общую память нити должны синхронизовать свое выполнение. Thread0: pi = pi + val; && Thread1: pi = pi + val; ВремяThread 0 Thread 1 1LOAD R1,pi 2LOAD R2,val 3ADD R1,R2LOAD R1,pi 4LOAD R2,val 5ADD R1,R2 6STORE R1,pi 7 Результат зависит от порядка выполнения команд. Требуется взаимное исключение критических интервалов. Взаимное исключение критических интервалов
25-26 июня Москва, 2012Технология параллельного программирования OpenMP90 из 125 Решение проблемы взаимного исключения должно удовлетворять требованиям: в любой момент времени только одна нить может находиться внутри критического интервала; если ни одна нить не находится в критическом интервале, то любая нить, желающая войти в критический интервал, должна получить разрешение без какой либо задержки; ни одна нить не должна бесконечно долго ждать разрешения на вход в критический интервал (если ни одна нить не будет находиться внутри критического интервала бесконечно). Взаимное исключение критических интервалов
25-26 июня Москва, 2012Технология параллельного программирования OpenMP91 из 125 int main () { int n =100000, i; double pi, h, sum, x; h = 1.0 / (double) n; sum = 0.0; for (i = 1; i
25-26 июня Москва, 2012Технология параллельного программирования OpenMP92 из 125 #include 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
25-26 июня Москва, 2012Технология параллельного программирования OpenMP93 из 125 int from_ list(float *a, int type); void work(int i, float *a); void example () { #pragma omp parallel { float *x; int ix_next; #pragma omp critical (list0) ix_next = from_ list(x,0); work(ix_next, x); #pragma omp critical (list1) ix_next = from_ list(x,1); work(ix_next, x); } Директива critical
Технология параллельного программирования OpenMP94 из 125 #pragma omp atomic expression-stmt где expression-stmt: x binop= expr x++ ++x x-- --x Здесь х – скалярная переменная, expr – выражение со скалярными типами, в котором не присутствует переменная х. где binop - не перегруженный оператор: + * - / & ^ | > Директива atomic
25-26 июня Москва, 2012Технология параллельного программирования OpenMP95 из 125 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
25-26 июня Москва, 2012Технология параллельного программирования OpenMP96 из 125 Точка в программе, достижимая всеми нитями группы, в которой выполнение программы приостанавливается до тех пор пока все нити группы не достигнут данной точки и все задачи, выполняемые группой нитей будут завершены. #pragma omp barrier По умолчанию барьерная синхронизация нитей выполняется: по завершению конструкции parallel; при выходе из конструкций распределения работ (for, single, sections, workshare), если не указана клауза nowait. #pragma omp parallel { #pragma omp master { int i, size; scanf("%d",&size); for (i=0; i
25-26 июня Москва, 2012Технология параллельного программирования OpenMP97 из 125 void work(int i, int j) {} void wrong(int n) { #pragma omp parallel default(shared) { int i; #pragma omp for for (i=0; i
25-26 июня Москва, 2012Технология параллельного программирования OpenMP98 из 125 void work(int i, int j) {} void wrong(int n) { #pragma omp parallel default(shared) { int i; #pragma omp critical { work(i, 0); /* incorrect nesting of barrier region in a critical region */ #pragma omp barrier work(i, 1); } Директива barrier
25-26 июня Москва, 2012Технология параллельного программирования OpenMP99 из 125 void work(int i, int j) {} void wrong(int n) { #pragma omp parallel default(shared) { int i; #pragma omp single { work(i, 0); /* incorrect nesting of barrier region in a single region */ #pragma omp barrier work(i, 1); } Директива barrier
25-26 июня Москва, 2012Технология параллельного программирования OpenMP100 из 125 Современные направления развития параллельных вычислительных систем OpenMP – модель параллелизма по управлению Конструкции распределения работы Конструкции для синхронизации нитей Система поддержки выполнения OpenMP-программ. Переменные окружения, управляющие выполнением OpenMP-программы Содержание
25-26 июня Москва, 2012Технология параллельного программирования OpenMP101 из 125 Внутренние переменные, управляющие выполнением OpenMP-программы (ICV-Internal Control Variables). Задание/опрос значений ICV-переменных. Функции работы со временем. Система поддержки выполнения OpenMP-программ
25-26 июня Москва, 2012Технология параллельного программирования OpenMP102 из 125 Для параллельных областей: 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
25-26 июня Москва, 2012Технология параллельного программирования OpenMP103 из 125 void work(); int main () { omp_set_num_threads(3); #pragma omp parallel { omp_set_num_threads(omp_get_thread_num ()+2); #pragma omp parallel work(); } Не корректно в OpenMP 2.5 Корректно в OpenMP 3.0 Internal Control Variables. nthreads-var
25-26 июня Москва, 2012Технология параллельного программирования OpenMP104 из 125 Определяет максимально возможное количество нитей в создаваемой параллельной области. Начальное значение: зависит от реализации. Существует одна копия этой переменной для каждой задачи. Значение переменной можно изменить: C shell: setenv OMP_NUM_THREADS 4,3,2 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); Internal Control Variables. nthreads-var
25-26 июня Москва, 2012Технология параллельного программирования OpenMP105 из 125 Определяет максимальное количество нитей, которые могут быть использованы для выполнения всей программы. Начальное значение: зависит от реализации. Существует одна копия этой переменной для всей программы. Значение переменной можно изменить: C shell: setenv OMP_THREAD_LIMIT 16 Korn shell: export OMP_THREAD_LIMIT=16 Windows: set OMP_THREAD_LIMIT=16 Узнать значение переменной можно: int omp_get_thread_limit(void) Internal Control Variables. thread-limit-var
25-26 июня Москва, 2012Технология параллельного программирования OpenMP106 из 125 Включает/отключает режим, в котором количество создаваемых нитей при входе в параллельную область может меняться динамически. Начальное значение: Если компилятор не поддерживает данный режим, то false. Существует одна копия этой переменной для каждой задачи. Значение переменной можно изменить: C shell: setenv OMP_DYNAMIC true Korn shell: export OMP_DYNAMIC=true Windows: set OMP_DYNAMIC=true void omp_set_dynamic(int dynamic_threads); Узнать значение переменной можно: int omp_get_dynamic(void); Internal Control Variables. dyn-var
25-26 июня Москва, 2012Технология параллельного программирования OpenMP107 из 125 Включает/отключает режим поддержки вложенного параллелизма. Начальное значение: false. Существует одна копия этой переменной для каждой задачи. Значение переменной можно изменить: C shell: setenv OMP_NESTED true Korn shell: export OMP_NESTED=false Windows: set OMP_NESTED=true void omp_set_nested(int nested); Узнать значение переменной можно: int omp_get_nested(void); Internal Control Variables. nest-var
25-26 июня Москва, 2012Технология параллельного программирования OpenMP108 из 125 Задает максимально возможное количество активных вложенных параллельных областей. Начальное значение: зависит от реализации. Существует одна копия этой переменной для всей программы. Значение переменной можно изменить: C shell: setenv OMP_MAX_ACTIVE_LEVELS 2 Korn shell: export OMP_MAX_ACTIVE_LEVELS=3 Windows: set OMP_MAX_ACTIVE_LEVELS=4 void omp_set_max_active_levels (int max_levels); Узнать значение переменной можно: int omp_get_max_active_levels(void); Internal Control Variables. max-active-levels-var
25-26 июня Москва, 2012Технология параллельного программирования OpenMP109 из 125 Задает способ распределения витков цикла между нитями, если указана клауза 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; Internal Control Variables. run-sched-var
25-26 июня Москва, 2012Технология параллельного программирования OpenMP110 из 125 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
25-26 июня Москва, 2012Технология параллельного программирования OpenMP111 из 125 Задает способ распределения витков цикла между нитями по умолчанию. Начальное значение: зависит от реализации. Существует одна копия этой переменной для всей программы. void work(int i); int main () { #pragma omp parallel { #pragma omp for for (int i=0;i
25-26 июня Москва, 2012Технология параллельного программирования OpenMP112 из 125 Каждая нить представляет собой независимо выполняющийся поток управления со своим счетчиком команд, регистровым контекстом и стеком. Переменная stack-size-var задает размер стека. Начальное значение: зависит от реализации. Существует одна копия этой переменной для всей программы. Значение переменной можно изменить: setenv OMP_STACKSIZE B setenv OMP_STACKSIZE "3000 k" setenv OMP_STACKSIZE 10M setenv OMP_STACKSIZE "10 M" setenv OMP_STACKSIZE "20 m" setenv OMP_STACKSIZE "1G" setenv OMP_STACKSIZE Internal Control Variables. stack-size-var
25-26 июня Москва, 2012Технология параллельного программирования OpenMP113 из 125 int main () { int a[1024][1024]; #pragma omp parallel private (a) { for (int i=0;i
25-26 июня Москва, 2012Технология параллельного программирования OpenMP114 из 125 Подсказка OpenMP-компилятору о желаемом поведении нитей во время ожидания. Начальное значение: зависит от реализации. Существует одна копия этой переменной для всей программы. Значение переменной можно изменить: setenv OMP_WAIT_POLICY ACTIVE setenv OMP_WAIT_POLICY active setenv OMP_WAIT_POLICY PASSIVE setenv OMP_WAIT_POLICY passive IBM AIX SPINLOOPTIME= YIELDLOOPTIME=40000 Internal Control Variables. wait-policy-var
25-26 июня Москва, 2012Технология параллельного программирования OpenMP115 из 125 клаузавызов функциипеременная окруженияICV omp_set_dynamic()OMP_DYNAMICdyn-var omp_set_nested()OMP_NESTEDnest-var num_threadsomp_set_num_threads()OMP_NUM_THREADSnthreads-var scheduleomp_set_schedule()OMP_SCHEDULErun-sched-var scheduledef-sched-var OMP_STACKSIZEstacksize-var OMP_WAIT_POLICYwait-policy-var OMP_THREAD_LIMITthread-limit-var omp_set_max_active_ levels() OMP_MAX_ACTIVE_ LEVELS max-active-levels-var Internal Control Variables. Приоритеты
25-26 июня Москва, 2012Технология параллельного программирования OpenMP116 из 125 int omp_get_num_threads(void); -возвращает количество нитей в текущей параллельной области #include 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-программ
25-26 июня Москва, 2012Технология параллельного программирования OpenMP117 из 125 int omp_get_thread_num(void); -возвращает номер нити в группе [0: omp_get_num_threads()-1] #include 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-программ
25-26 июня Москва, 2012Технология параллельного программирования OpenMP118 из 125 int omp_get_num_procs(void); -возвращает количество процессоров, на которых программа выполняется #include 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-программ
25-26 июня Москва, 2012Технология параллельного программирования OpenMP119 из 125 int omp_get_level(void) - возвращает уровень вложенности для текущей параллельной области. #include void work(int i) { #pragma omp parallel { int ilevel = omp_get_level (); } void test() { int ilevel = omp_get_level (); /*ilevel==0*/ #pragma omp parallel private (ilevel) { ilevel = omp_get_level (); int iam = omp_get_thread_num(); work(iam); } Система поддержки выполнения OpenMP-программ
25-26 июня Москва, 2012Технология параллельного программирования OpenMP120 из 125 int omp_get_active_level(void) - возвращает количество активных параллельных областей (выполняемых 2-мя или более нитями). #include void work(int iam, int size) { #pragma omp parallel { int ilevel = omp_get_active_level (); } void test() { int size = 0; int ilevel = omp_get_active_level (); /*ilevel==0*/ scanf("%d",&size); #pragma omp parallel if (size>10) { int iam = omp_get_thread_num(); work(iam, size); } Система поддержки выполнения OpenMP-программ
25-26 июня Москва, 2012Технология параллельного программирования OpenMP121 из 125 int omp_get_ancestor_thread_num (int level) - для нити, вызвавшей данную функцию, возвращается номер нити- родителя, которая создала указанную параллельную область. omp_get_ancestor_thread_num (0) = 0 If (level==omp_get_level()) { omp_get_ancestor_thread_num (level) == omp_get_thread_num (); } If ((level omp_get_level())) { omp_get_ancestor_thread_num (level) == -1; } Система поддержки выполнения OpenMP-программ
25-26 июня Москва, 2012Технология параллельного программирования OpenMP122 из 125 int omp_get_team_size(int level); - количество нитей в указанной параллельной области. omp_get_team_size (0) = 1 If (level==omp_get_level()) { omp_get_team_size (level) == omp_get_num _threads (); } If ((level omp_get_level())) { omp_get_team_size (level) == -1; } Система поддержки выполнения OpenMP-программ
25-26 июня Москва, 2012Технология параллельного программирования OpenMP123 из 125 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-программ. Функции работы со временем
25-26 июня Москва, 2012Технология параллельного программирования OpenMP124 из 125 OpenMP Application Program Interface Version 3.1, July Антонов А.С. Параллельное программирование с использованием технологии OpenMP: Учебное пособие.-М.: Изд-во МГУ, Э. Таненбаум, М. ван Стеен. Распределенные системы. Принципы и парадигмы. – СПб. Питер, 2003 Воеводин В.В., Воеводин Вл.В. Параллельные вычисления. – СПб.: БХВ-Петербург, Презентация ftp://ftp.keldysh.ru/K_student/MSU2012/Academy2012_OpenMP.ppt ftp://ftp.keldysh.ru/K_student/MSU2012/Academy2012_OpenMP.ppt Литература
25-26 июня Москва, 2012Технология параллельного программирования OpenMP125 из 125 Бахтин Владимир Александрович, кандидат физико-математических наук, заведующий сектором Института прикладной математики им. М.В. Келдыша РАН, ассистент кафедры системного программирования факультета вычислительной математики и кибернетики Московского университета им. М.В. Ломоносова Автор