Презентация Параллельное программирование. Модель данных в OpenMP онлайн
На нашем сайте вы можете скачать и просмотреть онлайн доклад-презентацию на тему Параллельное программирование. Модель данных в OpenMP абсолютно бесплатно. Урок-презентация на эту тему содержит всего 43 слайда. Все материалы созданы в программе PowerPoint и имеют формат ppt или же pptx. Материалы и темы для презентаций взяты из открытых источников и загружены их авторами, за качество и достоверность информации в них администрация сайта не отвечает, все права принадлежат их создателям. Если вы нашли то, что искали, отблагодарите авторов - поделитесь ссылкой в социальных сетях, а наш сайт добавьте в закладки.
Презентации » Устройства и комплектующие » Параллельное программирование. Модель данных в OpenMP
Оцените!
Оцените презентацию от 1 до 5 баллов!
- Тип файла:ppt / pptx (powerpoint)
- Всего слайдов:43 слайда
- Для класса:1,2,3,4,5,6,7,8,9,10,11
- Размер файла:0.98 MB
- Просмотров:86
- Скачиваний:0
- Автор:неизвестен
Слайды и текст к этой презентации:
№2 слайд
![Модель данных Модель данных в](/documents_6/e837dfbfa206720bc5d636b2484559e1/img1.jpg)
Содержание слайда: Модель данных
Модель данных в OpenMP предполагает наличие как общей для всех нитей
области памяти, так и локальной области памяти для каждой нити. В параллельных областях переменные программы разделяются на два основных класса:
• shared - все нити видят одну и ту же переменную;
• private - каждая нить видит свой экземпляр данной переменной.
Общая переменная всегда существует лишь в одном экземпляре для всей области действия и доступна всем нитям под одним и тем же именем. Объявление локальной переменной вызывает порождение своего экземпляра данной переменной (того же типа и размера) для каждой нити. Изменение нитью значения своей локальной переменной никак не влияет на изменение значения этой же локальной переменной в других нитях.
Если несколько переменных одновременно записывают значение общей переменной без выполнения синхронизации или если как минимум одна нить читает значение общей переменной и как минимум одна нить записывает значение этой переменной без выполнения синхронизации, то возникает ситуация так называемой «гонки данных» (data race), при которой результат выполнения программы непредсказуем.
По умолчанию, все переменные, порождённые вне параллельной области, при входе в эту область остаются общими. Исключение составляют переменные, являющиеся счетчиками итераций в цикле. Переменные, порождённые внутри параллельной области, по умолчанию являются локальными.
№3 слайд
![Пример include quot stdafx.h](/documents_6/e837dfbfa206720bc5d636b2484559e1/img2.jpg)
Содержание слайда: Пример 12
#include "stdafx.h"
#include <iostream>
#include "windows.h"
#include <omp.h>
using namespace std;
int main(int argc, char *argv[]){
SetConsoleCP(1251); SetConsoleOutputCP(1251);
int n=1;
printf("n в последовательной области (начало): %d\n", n);
#pragma omp parallel private(n)
{ int n=2;
printf("Значение n на нити (на входе): %d\n", n);
n=omp_get_thread_num();
printf("Значение n на нити (на выходе): %d\n", n);
}
printf("n в последовательной области (конец): %d\n", n);
system("Pause");
}
№4 слайд
![Результаты выполнения примера](/documents_6/e837dfbfa206720bc5d636b2484559e1/img3.jpg)
Содержание слайда: Результаты выполнения примера 12
n в последовательной области (начало): 1
Значение n на нити (на входе): 2
Значение n на нити (на выходе): 0
Значение n на нити (на входе): 2
Значение n на нити (на выходе): 2
Значение n на нити (на входе): 2
Значение n на нити (на выходе): 5
Значение n на нити (на входе): 2
Значение n на нити (на выходе): 3
Значение n на нити (на входе): 2
Значение n на нити (на выходе): 1
Значение n на нити (на входе): 2
Значение n на нити (на выходе): 7
Значение n на нити (на входе): 2
Значение n на нити (на выходе): 4
Значение n на нити (на входе): 2
Значение n на нити (на выходе): 6
n в последовательной области (конец): 1
№5 слайд
![Пример include quot stdafx.h](/documents_6/e837dfbfa206720bc5d636b2484559e1/img4.jpg)
Содержание слайда: Пример 13
#include "stdafx.h"
#include <iostream>
#include "windows.h"
#include <omp.h>
using namespace std;
int main(int argc, char *argv[]){
SetConsoleCP(1251); SetConsoleOutputCP(1251);
int i, m[10];
cout<<"Массив m в начале:\n";
for (i=0; i<10; i++){ m[i]=0; cout<<m[i]<<", "; }
cout<<"\n Нить: ";
#pragma omp parallel shared(m)
{ m[omp_get_thread_num()]=1;
cout<< omp_get_thread_num()<< ", "; } cout<<"\n";
cout<<"Массив m в конце:\n";
for (i=0; i<10; i++) cout<< m[i] <<", "; cout<<"\n";
system("Pause");
}
№6 слайд
![Статические и динамические](/documents_6/e837dfbfa206720bc5d636b2484559e1/img5.jpg)
Содержание слайда: Статические и динамические переменные
В языке Си статические (static) переменные, определённые в параллельной области программы, являются общими (shared). Динамически выделенная память также является общей, однако указатель на неё может быть как общим, так и локальным. Отдельные правила определяют назначение классов переменных при входе и выходе из параллельной области или параллельного цикла при использовании опций reduction, firstprivate, lastprivate, copyin
№7 слайд
![Пример include quot stdafx.h](/documents_6/e837dfbfa206720bc5d636b2484559e1/img6.jpg)
Содержание слайда: Пример 14
#include "stdafx.h"
#include <iostream>
#include "windows.h"
#include <omp.h>
using namespace std;
int main(int argc, char *argv[]){
SetConsoleCP(1251); SetConsoleOutputCP(1251);
int n=1;
printf("Значение n в начале: %d\n", n);
#pragma omp parallel firstprivate(n)
{
printf("Значение n на нити (на входе): %d\n", n);
n=omp_get_thread_num();
printf("Значение n на нити (на выходе): %d\n", n);
}
printf("Значение n в конце: %d\n", n);
system("Pause"); }
№8 слайд
![Результат выполнения примера](/documents_6/e837dfbfa206720bc5d636b2484559e1/img7.jpg)
Содержание слайда: Результат выполнения примера 14
Значение n в начале: 1
Значение n на нити (на входе): 1
Значение n на нити (на выходе): 0
Значение n на нити (на входе): 1
Значение n на нити (на выходе): 2
Значение n на нити (на входе): 1
Значение n на нити (на выходе): 5
Значение n на нити (на входе): 1
Значение n на нити (на выходе): 1
Значение n на нити (на входе): 1
Значение n на нити (на выходе): 3
Значение n на нити (на входе): 1
Значение n на нити (на выходе): 4
Значение n на нити (на входе): 1
Значение n на нити (на выходе): 6
Значение n на нити (на входе): 1
Значение n на нити (на выходе): 7
Значение n в конце: 1
№9 слайд
![Директива threadprivate](/documents_6/e837dfbfa206720bc5d636b2484559e1/img8.jpg)
Содержание слайда: Директива threadprivate
Директива threadprivate указывает, что переменные из списка должны быть размножены с тем, чтобы каждая нить имела свою локальную копию:
#pragma omp threadprivate(список)
Директива threadprivate может позволить сделать локальные копии для статических переменных, которые по умолчанию являются общими. Для корректного использования локальных копий глобальных объектов нужно гарантировать, что они используются в разных частях программы одними и теми же нитями. Если на локальные копии ссылаются в разных параллельных областях, то для сохранения их значений необходимо, чтобы не было объемлющих параллельных областей, количество нитей в обеих областях совпадало, а переменная OMP_DYNAMIC была установлена в false с начала первой области до начала второй. Переменные, объявленные как threadprivate, не могут использоваться в опциях директив OpenMP, кроме copyin, copyprivate, schedule, num_threads, if.
№10 слайд
![Пример include quot stdafx.h](/documents_6/e837dfbfa206720bc5d636b2484559e1/img9.jpg)
Содержание слайда: Пример 15
#include "stdafx.h
#include <iostream>
#include "windows.h"
#include <omp.h>
using namespace std;
int n;
#pragma omp threadprivate(n)
int main(int argc, char *argv[]){ SetConsoleCP(1251); SetConsoleOutputCP (1251);
int num; n=1;
#pragma omp parallel private (num)
{ num=omp_get_thread_num();
printf("Значение n на нити %d (на входе): %d\n", num, n);
n=omp_get_thread_num();
printf("Значение n на нити %d (на выходе): %d\n", num, n); }
printf("Значение n (середина): %d\n", n);
#pragma omp parallel private (num)
{ num=omp_get_thread_num();
printf("Значение n на нити %d (ещё раз): %d\n", num, n); }
system("Pause"); }
№11 слайд
![Результаты выполнения примера](/documents_6/e837dfbfa206720bc5d636b2484559e1/img10.jpg)
Содержание слайда: Результаты выполнения примера 15
Значение n на нити 0 (на входе): 1
Значение n на нити 0 (на выходе): 0
Значение n на нити 6 (на входе): 0
Значение n на нити 6 (на выходе): 6
Значение n на нити 4 (на входе): 0
Значение n на нити 4 (на выходе): 4
Значение n на нити 1 (на входе): 0
Значение n на нити 1 (на выходе): 1
Значение n на нити 5 (на входе): 0
Значение n на нити 5 (на выходе): 5
Значение n на нити 2 (на входе): 0
Значение n на нити 2 (на выходе): 2
Значение n на нити 3 (на входе): 0
Значение n на нити 3 (на выходе): 3
Значение n на нити 7 (на входе): 0
Значение n на нити 7 (на выходе): 7
Значение n (середина): 0
Значение n на нити 7 (ещё раз): 7
Значение n на нити 0 (ещё раз): 0
Значение n на нити 6 (ещё раз): 6
Значение n на нити 5 (ещё раз): 5
Значение n на нити 3 (ещё раз): 3
Значение n на нити 1 (ещё раз): 1
Значение n на нити 4 (ещё раз): 4
Значение n на нити 2 (ещё раз): 2
Для продолжения нажмите любую клавишу . . .
№12 слайд
![Если необходимо переменную,](/documents_6/e837dfbfa206720bc5d636b2484559e1/img11.jpg)
Содержание слайда: Если необходимо переменную, объявленную как threadprivate, инициализировать значением размножаемой переменной из нити-мастера, то на входе в параллельную область можно использовать опцию copyin. Если значение локальной переменной или переменной, объявленной как threadprivate, необходимо переслать от одной нити всем, работающим в данной параллельной области, для этого можно использовать опцию copyprivate директивы single.
№13 слайд
![Пример include quot stdafx.h](/documents_6/e837dfbfa206720bc5d636b2484559e1/img12.jpg)
Содержание слайда: Пример 16
#include "stdafx.h"
#include <iostream>
#include "windows.h"
#include <omp.h>
using namespace std;
int n;
#pragma omp threadprivate(n)
int main(int argc, char *argv[]){
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
n=1;
#pragma omp parallel copyin(n)
{
printf("Значение n: %d (нить %d) \n", n, omp_get_thread_num());
}
system("Pause");
}
№16 слайд
![Распределение работы OpenMP](/documents_6/e837dfbfa206720bc5d636b2484559e1/img15.jpg)
Содержание слайда: Распределение работы
OpenMP предлагает несколько вариантов распределения работы между запущенными нитями. Конструкции распределения работ в OpenMP не порождают новых нитей.
Низкоуровневое распараллеливание Все нити в параллельной области нумеруются последовательными целыми числами от 0 до N-1, где N — количество нитей, выполняющих данную область.
Можно программировать на самом низком уровне, распределяя работу с помощью функций omp_get_thread_num() и omp_get_num_threads(), возвращающих номер нити и общее количество порождённых нитей в текущей параллельной области, соответственно.
Вызов функции omp_get_thread_num() позволяет нити получить свой уникальный номер в текущей параллельной области:
int omp_get_thread_num(void);
Вызов функции omp_get_num_threads() позволяет нити получить количество нитей в текущей параллельной области:
int omp_get_num_threads(void);
№17 слайд
![Пример include quot stdafx.h](/documents_6/e837dfbfa206720bc5d636b2484559e1/img16.jpg)
Содержание слайда: Пример 17
#include "stdafx.h"
#include <iostream>
#include "windows.h"
#include <omp.h>
using namespace std;
int main(int argc, char *argv[]){
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
int count, num;
#pragma omp parallel
{
count=omp_get_num_threads();
num=omp_get_thread_num();
if (num == 0) printf("Всего нитей: %d\n", count);
else printf("Нить номер %d\n", num);
}
system("Pause");
}
№18 слайд
![Использование omp get thread](/documents_6/e837dfbfa206720bc5d636b2484559e1/img17.jpg)
Содержание слайда: Использование omp_get_thread_num() и omp_get_num_threads()
Использование функций omp_get_thread_num() и omp_get_num_threads() позволяет назначать каждой нити свой кусок кода для выполнения, и таким образом распределять работу между нитями в стиле технологии MPI. Однако использование этого стиля программирования в OpenMP далеко не всегда оправдано – программист в этом случае должен явно организовывать синхронизацию доступа к общим данным. Другие способы распределения работ в OpenMP обеспечивают значительную часть этой работы автоматически.
№19 слайд
![Параллельные циклы Если в](/documents_6/e837dfbfa206720bc5d636b2484559e1/img18.jpg)
Содержание слайда: Параллельные циклы
Если в параллельной области встретился оператор цикла, то, согласно общему правилу, он будет выполнен всеми нитями текущей группы, то есть каждая нить выполнит все итерации данного цикла. Для распределения итераций цикла между различными нитями можно использовать директиву for :
#pragma omp for [опция [[,] опция]...]
Эта директива относится к идущему следом за данной директивой блоку, включающему операторы for .
№20 слайд
![Опции директивы for private](/documents_6/e837dfbfa206720bc5d636b2484559e1/img19.jpg)
Содержание слайда: Опции директивы for :
private(список) – задаёт список переменных, для которых порождается локальная копия в каждой нити; начальное значение локальных копий переменных из списка не определено;
firstprivate(список) – задаёт список переменных, для которых порождается локальная копия в каждой нити; локальные копии переменных инициализируются значениями этих переменных в нити-мастере;
lastprivate(список) – переменным, перечисленным в списке, присваивается результат с последнего витка цикла;
reduction(оператор:список) – задаёт оператор и список общих переменных; для каждой переменной создаются локальные копии в каждой нити; локальные копии инициализируются соответственно типу оператора (для аддитивных операций – 0 или его аналоги, для мультипликативных операций – 1 или её аналоги); над локальными копиями переменных после завершения всех итераций цикла выполняется заданный оператор; оператор это: +, *, -, &, |, ^, &&, ||; порядок выполнения операторов не определён, поэтому результат может отличаться от запуска к запуску;
№21 слайд
![Опции директивы for](/documents_6/e837dfbfa206720bc5d636b2484559e1/img20.jpg)
Содержание слайда: Опции директивы for (продолжение):
schedule(type[, chunk]) – опция задаёт, каким образом итерации цикла распределяются между нитями;
collapse(n) — опция указывает, что n последовательных тесновложенных циклов ассоциируется с данной директивой; для циклов образуется общее пространство итераций, которое делится между нитями; если опция collapse не задана, то директива относится только к одному непосредственно следующему за ней циклу;
ordered – опция, говорящая о том, что в цикле могут встречаться директивы ordered; в этом случае определяется блок внутри тела цикла, который должен выполняться в том порядке, в котором итерации идут в последовательном цикле;
nowait – в конце параллельного цикла происходит неявная барьерная синхронизация параллельно работающих нитей: их дальнейшее выполнение происходит только тогда, когда все они достигнут данной точки; если в подобной задержке нет необходимости, опция nowait позволяет нитям, уже дошедшим до конца цикла, продолжить выполнение без синхронизации с остальными. Если директива end do в явном виде не указана, то в конце параллельного цикла синхронизация все равно будет выполнена
№22 слайд
![На вид параллельных циклов](/documents_6/e837dfbfa206720bc5d636b2484559e1/img21.jpg)
Содержание слайда: На вид параллельных циклов накладываются достаточно жёсткие ограничения. В частности, предполагается, что корректная программа не должна зависеть от того, какая именно нить какую итерацию параллельного цикла выполнит. Нельзя использовать побочный выход из параллельного цикла. Размер блока итераций, указанный в опции schedule, не должен изменяться в рамках цикла. Формат параллельных циклов на языке Си упрощённо можно представить следующим образом:
for([целочисленный тип] i = инвариант цикла;
i {<,>,=,<=,>=} инвариант цикла;
i {+,-}= инвариант цикла)
Эти требования введены для того, чтобы OpenMP мог при входе в цикл точно определить число итераций.
Если директива параллельного выполнения стоит перед гнездом циклов, завершающихся одним оператором, то директива действует только на самый внешний цикл.
Итеративная переменная распределяемого цикла по смыслу должна быть локальной, поэтому в случае, если она специфицирована общей, то она неявно делается локальной при входе в цикл. После завершения цикла значение итеративной переменной цикла не определено, если она не указана в опции
lastprivate.
№23 слайд
![Пример include quot stdafx.h](/documents_6/e837dfbfa206720bc5d636b2484559e1/img22.jpg)
Содержание слайда: Пример 18
#include "stdafx.h"
#include <iostream>
#include "windows.h"
#include <omp.h>
using namespace std;
#define N 15
int main(int argc, char *argv[]){
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
int A[N], B[N], C[N], i, n;
for (i=0; i<N; i++){ A[i]=i; B[i]=2*i; C[i]=0; }
#pragma omp parallel shared(A, B, C) private(i, n)
{ n=omp_get_thread_num();
#pragma omp for
for (i=0; i<N; i++) { C[i]=A[i]+B[i];
printf("Нить %d сложила элементы с номером %d\n", n, i); } }
cout<<"массив A: "; for ( i = 0; i < N; i++) { cout << A[i] <<", " ; } cout<<"\n";
cout<<"массив B: "; for ( i = 0; i < N; i++) { cout << B[i] <<", " ; } cout<<"\n";
cout<<"массив C: "; for ( i = 0; i < N; i++) { cout << C[i] <<", " ; } cout<<"\n";
system("Pause"); }
№24 слайд
![Результаты выполнения примера](/documents_6/e837dfbfa206720bc5d636b2484559e1/img23.jpg)
Содержание слайда: Результаты выполнения примера 18
Нить 0 сложила элементы с номером 0
Нить 0 сложила элементы с номером 1
Нить 2 сложила элементы с номером 4
Нить 2 сложила элементы с номером 5
Нить 1 сложила элементы с номером 2
Нить 1 сложила элементы с номером 3
Нить 5 сложила элементы с номером 10
Нить 5 сложила элементы с номером 11
Нить 7 сложила элементы с номером 14
Нить 6 сложила элементы с номером 12
Нить 6 сложила элементы с номером 13
Нить 4 сложила элементы с номером 8
Нить 4 сложила элементы с номером 9
Нить 3 сложила элементы с номером 6
Нить 3 сложила элементы с номером 7
массив A: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
массив B: 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28,
массив C: 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42,
№25 слайд
![Опция schedule В опции](/documents_6/e837dfbfa206720bc5d636b2484559e1/img24.jpg)
Содержание слайда: Опция schedule
В опции schedule параметр type задаёт следующий тип распределения итераций:
• static – блочно-циклическое распределение итераций цикла; размер блока – chunk. Первый блок из chunk итераций выполняет нулевая нить, второй блок — следующая и т.д. до последней нити, затем распределение снова начинается с нулевой нити. Если значение chunk не указано, то всё множество итераций делится на непрерывные куски примерно одинакового размера (конкретный способ зависит от реализации), и полученные порции итераций распределяются между нитями.
• dynamic – динамическое распределение итераций с фиксированным размером блока: сначала каждая нить получает chunk итераций (по умолчанию chunk=1), та нить, которая заканчивает выполнение своей порции итераций, получает первую свободную порцию из chunk итераций. Освободившиеся нити получают новые порции итераций до тех пор, пока все порции не будут исчерпаны. Последняя порция может содержать меньше итераций, чем все остальные.
№26 слайд
![Опция schedule продолжение](/documents_6/e837dfbfa206720bc5d636b2484559e1/img25.jpg)
Содержание слайда: Опция schedule (продолжение)
guided – динамическое распределение итераций, при котором размер порции уменьшается с некоторого начального значения до величины chunk (по умолчанию chunk=1) пропорционально количеству ещё не распределённых итераций, делённому на количество нитей, выполняющих цикл. Размер первоначально выделяемого блока зависит от реализации. В ряде случаев такое распределение позволяет аккуратнее разделить работу и сбалансировать загрузку нитей. Количество итераций в последней порции может оказаться меньше значения chunk.
auto – способ распределения итераций выбирается компилятором и/или системой выполнения. Параметр chunk при этом не задаётся.
runtime – способ распределения итераций выбирается во время работы программы по значению переменной среды OMP_SCHEDULE. Параметр chunk при этом не задаётся.
№27 слайд
![Пример include quot stdafx.h](/documents_6/e837dfbfa206720bc5d636b2484559e1/img26.jpg)
Содержание слайда: Пример 19
#include "stdafx.h"
#include <iostream>
#include "windows.h"
#include <omp.h>
using namespace std;
int main(int argc, char *argv[]){
SetConsoleCP(1251); SetConsoleOutputCP(1251);
int i;
#pragma omp parallel private(i)
{
#pragma omp for schedule (static)
for (i=0; i<15; i++) {
printf("Нить %d выполнила итерацию %d\n",
omp_get_thread_num(), i);
Sleep(1); } }
system("Pause"); }
№28 слайд
![Результаты выполнения примера](/documents_6/e837dfbfa206720bc5d636b2484559e1/img27.jpg)
Содержание слайда: Результаты выполнения примера 19
#pragma omp for schedule (static)
Нить 0 выполнила итерацию 0
Нить 2 выполнила итерацию 4
Нить 1 выполнила итерацию 2
Нить 3 выполнила итерацию 6
Нить 6 выполнила итерацию 12
Нить 5 выполнила итерацию 10
Нить 7 выполнила итерацию 14
Нить 4 выполнила итерацию 8
Нить 1 выполнила итерацию 3
Нить 2 выполнила итерацию 5
Нить 3 выполнила итерацию 7
Нить 0 выполнила итерацию 1
Нить 5 выполнила итерацию 11
Нить 6 выполнила итерацию 13
Нить 4 выполнила итерацию 9
Для продолжения нажмите любую клавишу . . .
№29 слайд
![Результаты выполнения примера](/documents_6/e837dfbfa206720bc5d636b2484559e1/img28.jpg)
Содержание слайда: Результаты выполнения примера 19
#pragma omp for schedule (static, 1)
Нить 0 выполнила итерацию 0
Нить 1 выполнила итерацию 1
Нить 2 выполнила итерацию 2
Нить 6 выполнила итерацию 6
Нить 5 выполнила итерацию 5
Нить 4 выполнила итерацию 4
Нить 3 выполнила итерацию 3
Нить 7 выполнила итерацию 7
Нить 0 выполнила итерацию 8
Нить 3 выполнила итерацию 11
Нить 4 выполнила итерацию 12
Нить 2 выполнила итерацию 10
Нить 6 выполнила итерацию 14
Нить 5 выполнила итерацию 13
Нить 1 выполнила итерацию 9
Для продолжения нажмите любую клавишу . . .
#pragma omp for schedule (static, 2)
Нить 0 выполнила итерацию 0
Нить 2 выполнила итерацию 4
Нить 4 выполнила итерацию 8
Нить 5 выполнила итерацию 10
Нить 1 выполнила итерацию 2
Нить 3 выполнила итерацию 6
Нить 6 выполнила итерацию 12
Нить 7 выполнила итерацию 14
Нить 2 выполнила итерацию 5
Нить 5 выполнила итерацию 11
Нить 4 выполнила итерацию 9
Нить 0 выполнила итерацию 1
Нить 6 выполнила итерацию 13
Нить 3 выполнила итерацию 7
Нить 1 выполнила итерацию 3
Для продолжения нажмите любую клавишу . . .
№30 слайд
![Результаты выполнения примера](/documents_6/e837dfbfa206720bc5d636b2484559e1/img29.jpg)
Содержание слайда: Результаты выполнения примера 19
#pragma omp for schedule (dynamic)
Нить 0 выполнила итерацию 0
Нить 2 выполнила итерацию 1
Нить 4 выполнила итерацию 2
Нить 5 выполнила итерацию 3
Нить 3 выполнила итерацию 4
Нить 1 выполнила итерацию 5
Нить 6 выполнила итерацию 6
Нить 7 выполнила итерацию 7
Нить 2 выполнила итерацию 8
Нить 5 выполнила итерацию 9
Нить 4 выполнила итерацию 10
Нить 0 выполнила итерацию 11
Нить 6 выполнила итерацию 12
Нить 1 выполнила итерацию 14
Нить 3 выполнила итерацию 13
Для продолжения нажмите любую клавишу . . .
#pragma omp for schedule (dynamic, 2)
Нить 0 выполнила итерацию 0
Нить 1 выполнила итерацию 2
Нить 2 выполнила итерацию 4
Нить 4 выполнила итерацию 6
Нить 3 выполнила итерацию 8
Нить 5 выполнила итерацию 10
Нить 6 выполнила итерацию 12
Нить 7 выполнила итерацию 14
Нить 2 выполнила итерацию 5
Нить 1 выполнила итерацию 3
Нить 0 выполнила итерацию 1
Нить 6 выполнила итерацию 13
Нить 5 выполнила итерацию 11
Нить 3 выполнила итерацию 9
Нить 4 выполнила итерацию 7
Для продолжения нажмите любую клавишу . . .
№31 слайд
![Результаты выполнения примера](/documents_6/e837dfbfa206720bc5d636b2484559e1/img30.jpg)
Содержание слайда: Результаты выполнения примера 19
#pragma omp for schedule (guided)
Нить 0 выполнила итерацию 0
Нить 1 выполнила итерацию 2
Нить 5 выполнила итерацию 4
Нить 4 выполнила итерацию 6
Нить 2 выполнила итерацию 8
Нить 3 выполнила итерацию 9
Нить 6 выполнила итерацию 10
Нить 7 выполнила итерацию 11
Нить 2 выполнила итерацию 12
Нить 4 выполнила итерацию 7
Нить 5 выполнила итерацию 5
Нить 1 выполнила итерацию 3
Нить 0 выполнила итерацию 1
Нить 7 выполнила итерацию 13
Нить 6 выполнила итерацию 14
Для продолжения нажмите любую клавишу . . .
#pragma omp for schedule (guided, 2)
Нить 0 выполнила итерацию 0
Нить 5 выполнила итерацию 6
Нить 3 выполнила итерацию 4
Нить 4 выполнила итерацию 10
Нить 1 выполнила итерацию 8
Нить 2 выполнила итерацию 2
Нить 6 выполнила итерацию 12
Нить 7 выполнила итерацию 14
Нить 1 выполнила итерацию 9
Нить 3 выполнила итерацию 5
Нить 5 выполнила итерацию 7
Нить 4 выполнила итерацию 11
Нить 0 выполнила итерацию 1
Нить 6 выполнила итерацию 13
Нить 2 выполнила итерацию 3
Для продолжения нажмите любую клавишу . . .
№33 слайд
![Пример include quot stdafx.h](/documents_6/e837dfbfa206720bc5d636b2484559e1/img32.jpg)
Содержание слайда: Пример 20
#include "stdafx.h"
#include <iostream>
#include <windows.h
#include <omp.h>
using namespace std;
int main(int argc, char *argv[]){
SetConsoleCP(1251); SetConsoleOutputCP(1251);
int i;
#pragma omp parallel private(i)
{
#pragma omp for schedule (static, 6)
//#pragma omp for schedule (dynamic, 6)
//#pragma omp for schedule (guided, 6)
for (i=0; i<200; i++)
{ printf("Нить %d выполнила итерацию %d\n",
omp_get_thread_num(), i);
Sleep(1); } }
system("Pause"); }
№35 слайд
![Переменная OMP SCHEDULE](/documents_6/e837dfbfa206720bc5d636b2484559e1/img34.jpg)
Содержание слайда: Переменная OMP_SCHEDULE
Значение по умолчанию переменной OMP_SCHEDULE зависит от реализации. Если переменная задана неправильно, то поведение программы при задании опции runtime также зависит от реализации.
Изменить значение переменной OMP_SCHEDULE из программы можно с помощью вызова функции omp_set_schedule() :
void omp_set_schedule(omp_sched_t type, int chunk);
Допустимые значения констант описаны в файле omp.h (omp_lib.h). Как минимум, они должны включать для языка Си следующие варианты:
typedef enum omp_sched_t { omp_sched_static = 1, omp_sched_dynamic = 2, omp_sched_guided = 3, omp_sched_auto = 4 } omp_sched_t;
При помощи вызова функции omp_get_schedule() пользователь может узнать текущее значение переменной OMP_SCHEDULE:
void omp_get_schedule(omp_sched_t* type, int* chunk);
При распараллеливании цикла программист должен убедиться в том, что итерации данного цикла не имеют информационных зависимостей. Если цикл не содержит зависимостей, его итерации можно выполнять в любом порядке, в том числе параллельно. Соблюдение этого важного требования компилятор не проверяет, вся ответственность лежит на программисте. Если дать указание компилятору распараллелить цикл, содержащий зависимости, компилятор это сделает, но результат работы программы может оказаться некорректным.
№36 слайд
![Параллельные секции Директива](/documents_6/e837dfbfa206720bc5d636b2484559e1/img35.jpg)
Содержание слайда: Параллельные секции
Директива sections используется для задания конечного (неитеративного) параллелизма:
#pragma omp sections [опция [[,] опция]...]
Эта директива определяет набор независимых секций кода, каждая из которых выполняется своей нитью.
Директива section задаёт участок кода внутри секции sections для выполнения одной нитью:
#pragma omp section
Перед первым участком кода в блоке sections директива section не обязательна. Какие именно нити будут задействованы для выполнения какой секции, не специфицируется. Если количество нитей больше количества секций, то часть нитей для выполнения данного блока секций не будет задействована. Если количество нитей меньше количества секций, то некоторым (или всем) нитям достанется более одной секции.
№37 слайд
![Возможные опции private](/documents_6/e837dfbfa206720bc5d636b2484559e1/img36.jpg)
Содержание слайда: Возможные опции:
private(список) – задаёт список переменных, для которых порождается локальная копия в каждой нити; начальное значение локальных копий переменных из списка не определено;
firstprivate(список) – задаёт список переменных, для которых порождается локальная копия в каждой нити; локальные копии переменных инициализируются значениями этих переменных в нити-мастере;
lastprivate(список) – переменным, перечисленным в списке, присваивается результат, полученный в последней секции;
reduction(оператор:список) – задаёт оператор и список общих переменных; для каждой переменной создаются локальные копии в каждой нити; локальные копии инициализируются соответственно типу оператора (для аддитивных операций – 0 или его аналоги, для мультипликативных операций – 1 или её аналоги); над локальными копиями переменных после завершения всех секций выполняется заданный оператор; оператор это: для языка Си – +, *, -, &, |, ^, &&, ||; порядок выполнения операторов не определён, поэтому результат может отличаться от запуска к запуску;
nowait – в конце блока секций происходит неявная барьерная синхронизация параллельно работающих нитей: их дальнейшее выполнение происходит только тогда, когда все они достигнут данной точки; если в подобной задержке нет необходимости, опция nowait позволяет нитям, уже дошедшим до конца своих секций, продолжить выполнение без синхронизации с остальными.
№38 слайд
![Пример int main int argc,](/documents_6/e837dfbfa206720bc5d636b2484559e1/img37.jpg)
Содержание слайда: Пример 21
int main(int argc, char *argv[]){
SetConsoleCP(1251); SetConsoleOutputCP(1251);
int n;
#pragma omp parallel private(n)
{ n=omp_get_thread_num();
#pragma omp sections
{
#pragma omp section
{ cout<< "Первая секция, процесс "<< n <<"\n"; }
#pragma omp section
{ cout<< "Вторая секция, процесс "<< n <<"\n"; }
#pragma omp section
{ cout<< "Третья секция, процесс "<< n <<"\n"; }
}
cout<< "Параллельная область, процесс "<< n <<"\n";
}
system("Pause"); }
№39 слайд
![Результаты выполнения примера](/documents_6/e837dfbfa206720bc5d636b2484559e1/img38.jpg)
Содержание слайда: Результаты выполнения примера 21
Вторая секция, процесс 3
Первая секция, процесс 0
Третья секция, процесс 1
Параллельная область, процесс 1
Параллельная область, процесс 2
Параллельная область, процесс 4
Параллельная область, процесс 0
Параллельная область, процесс 3
Параллельная область, процесс 7
Параллельная область, процесс 5
Параллельная область, процесс 6
Для продолжения нажмите любую клавишу . . .
№40 слайд
![Пример int main int argc,](/documents_6/e837dfbfa206720bc5d636b2484559e1/img39.jpg)
Содержание слайда: Пример 22
int main(int argc, char *argv[]){
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
int n=0;
#pragma omp parallel
{
#pragma omp sections lastprivate(n)
{
#pragma omp section
{ n=1; printf("Первая секция, нить %d: %d\n", omp_get_thread_num(), n); }
#pragma omp section
{ n=2; printf("Вторая секция, нить %d: %d\n", omp_get_thread_num(), n); }
#pragma omp section
{ n=3; printf("Третья секция, нить %d: %d\n", omp_get_thread_num(), n); } }
printf("Значение n на нити %d: %d\n", omp_get_thread_num(), n); }
printf("Значение n в последовательной области: %d\n", n);
system("Pause");
}
№41 слайд
![Результаты выполнения примера](/documents_6/e837dfbfa206720bc5d636b2484559e1/img40.jpg)
Содержание слайда: Результаты выполнения примера 22
Первая секция, нить 0: 1
Вторая секция, нить 1: 2
Третья секция, нить 5: 3
Значение n на нити 5: 3
Значение n на нити 0: 3
Значение n на нити 1: 3
Значение n на нити 3: 3
Значение n на нити 7: 3
Значение n на нити 4: 3
Значение n на нити 2: 3
Значение n на нити 6: 3
Значение n в последовательной области: 3
Для продолжения нажмите любую клавишу . . .
№42 слайд
![Задачи tasks Директива task](/documents_6/e837dfbfa206720bc5d636b2484559e1/img41.jpg)
Содержание слайда: Задачи (tasks)
Директива task применяется для выделения отдельной независимой задачи:
#pragma omp task [опция [[,] опция]...]
Текущая нить выделяет в качестве задачи ассоциированный с директивой блок операторов. Задача может выполняться немедленно после создания или быть отложенной на неопределённое время и выполняться по частям. Размер таких частей, а также порядок выполнения частей разных отложенных задач определяется реализацией:
#pragma omp taskwait
Нить, выполнившая данную директиву, приостанавливается до тех пор, пока
не будут завершены все ранее запущенные данной нитью независимые задач
№43 слайд
![Возможные опции if условие](/documents_6/e837dfbfa206720bc5d636b2484559e1/img42.jpg)
Содержание слайда: Возможные опции:
if(условие) — порождение новой задачи только при выполнении некоторого условия; если условие не выполняется, то задача будет выполнена текущей нитью и немедленно;
untied — опция означает, что в случае откладывания задача может быть продолжена любой нитью из числа выполняющих данную параллельную область; если данная опция не указана, то задача может быть продолжена только породившей её нитью;
default(shared|none) – всем переменным в задаче, которым явно не назначен класс, будет назначен класс shared; none означает, что всем переменным в задаче класс должен быть назначен явно;
private(список) – задаёт список переменных, для которых порождается локальная копия в каждой нити; начальное значение локальных копий переменных из списка не определено;
firstprivate(список) – задаёт список переменных, для которых порождается локальная копия в каждой нити; локальные копии переменных инициализируются значениями этих переменных в нити-мастере;
shared(список) – задаёт список переменных, общих для всех нитей. Для гарантированного завершения в точке вызова всех запущенных задач используется директива taskwait.
Скачать все slide презентации Параллельное программирование. Модель данных в OpenMP одним архивом:
Похожие презентации
-
Параллельное программирование с использованием OpenMP. Лекция 2
-
Параллельное программирование с использованием OpenMP. Лекция 1
-
Модель параллельного программирования. Лекция 2
-
Параллельное программирование в стандарте OpenMP
-
Параллельное и многопоточное программирование. OpenMP. (Лекция 6)
-
Язык программирования Паскаль. Организация ввода и вывода данных
-
Простые типы данных на языке программирования Turbo Pascal
-
Базовые типы данных языков программирования высокого уровня
-
Базовые типы данных языков программирования высокого уровня. Лекция 3
-
Построение моделей стратиграфии и вертикальных разрезов толщи горного массива по данным геологоразведочных скважин