Внимание ! Вопросы к тесту выложены исключительно в ознакомительных целях: количество вопросов может не совпадать с действительным, актуальность не поддерживается,- за решением теста Welcome to the cashier! Строгая модель консистентности памяти определяется следующим условием:
все процессы наблюдают все обращения к ячейкам памяти, связанные причинно-следственной связью в одном и том же порядке все обращения к ячейкам памяти абсолютно упорядочены во времени все процессы наблюдают все обращения к ячейкам памяти в одном и том же порядке. Обращения не упорядочены по времени
Последовательная модель консистентности памяти определяется следующим условием:
все процессы наблюдают все обращения к ячейкам памяти в одном и том же порядке. Обращения не упорядочены по времени все процессы наблюдают все обращения к ячейкам памяти, связанные причинно-следственной связью в одном и том же порядке все обращения к ячейкам памяти абсолютно упорядочены во времени
Причинная модель консистентности памяти определяется следующим условием:
все процессы наблюдают все обращения к ячейкам памяти, связанные причинно-следственной связью в одном и том же порядке все процессы наблюдают все обращения к ячейкам памяти в одном и том же порядке. Обращения не упорядочены по времени все процессы наблюдают операции записи любого процесса в порядке их выполнения. Операции записи различных процессов могут наблюдаться разными процессами в разном порядке
Процессорная модель консистентности памяти определяется следующим условием:
все процессы наблюдают операции записи любого процесса в порядке их выполнения. Операции записи различных процессов могут наблюдаться разными процессами в разном порядке все процессы наблюдают все обращения к ячейкам памяти в одном и том же порядке. Обращения не упорядочены по времени все процессы наблюдают операции записи любого процесса в порядке их выполнения. Для каждой переменной существует общее согласие относительно порядка, в котором процессы модифицируют эту переменную. Операции записи различных процессов могут наблюдаться разными процессами в разном порядке
PRAM модель консистентности памяти определяется следующим условием:
все процессы наблюдают все обращения к ячейкам памяти, связанные причинно-следственной связью в одном и том же порядке все процессы наблюдают операции записи любого процесса в порядке их выполнения. Операции записи различных процессов могут наблюдаться разными процессами в разном порядке все процессы наблюдают все обращения к ячейкам памяти в одном и том же порядке. Обращения не упорядочены по времени
Слабая модель консистентности памяти определяется следующим условием:
совместно используемые данные, относящиеся к данной критической области, становятся консистентными при входе в эту область совместно используемые данные могут считаться консистентными после выхода из критической области совместно используемые данные могут считаться консистентными только после операции синхронизации;
Пусть W(x)a – операция записи в переменную x значения a. Пусть R(x)a – операция чтения переменной x, где a – прочитанное значение переменной x. Пусть S - операция синхронизации. Следующая последовательность событий:
допустима при слабой модели консистентности допустима при модели консистентности по выходу не допустима при слабой модели консистентности
Пусть W(x)a – операция записи в переменную x значения a. Пусть R(x)a – операция чтения переменной x, где a – прочитанное значение переменной x. Следующая последовательность событий:
допустима при строгой модели консистентности допустима при причинной модели консистентности допустима при последовательной модели консистентности
Найдите ошибку в следующем фрагменте программы:
#define N 10 int i; #pragma omp parallel { int tmp = 0; #pragma omp for private(tmp) for (i=0; i<N; i++) { tmp += i; } }
в данном фрагменте программы ошибки нет начальное значение переменной tmp в параллельном цикле не определено не определен класс для переменной i (отсутствует клауза private (i))
Найдите ошибку в следующем фрагменте программы:
#define N 10 int i; int tmp = 0; #pragma omp parallel { #pragma omp for firstprivate(tmp) lastprivate(tmp) for (i=0; i<N; i++) { if (i != N - 1 ) tmp += i; } }
одна и та же переменная не может быть указана в клаузах firstprivate и lastprivate одновременно не определен класс для переменной i (отсутствует клауза private (i)) по завершении выполнения цикла значение переменой tmp не определено
Найдите ошибку в следующем фрагменте программы:
#define N 10 int icount; #pragma omp threadprivate(icount) #pragma omp parallel { #pragma omp for for (icount=0; icount<N; icount++) { … } }
в качестве индексной переменной цикла, распределяемого между нитями при помощи директивы for, не могут использоваться переменные, указанные в директиве threadprivate в данном фрагменте программы ошибки нет только статические переменные могут быть указаны в директиве threadprivate (static int icount)
Определите класс по умолчанию для переменной numt:
inti=0; int numt = omp_get_max_threads(); #pragma omp parallel for for(i=0; i< numt; i++) Work(i);
threadprivate shared Вариант 3private
Найдите ошибку в следующем фрагменте программы:
int i=0; int numt = omp_get_max_threads(); #pragma omp parallel default (none) private (i) { #pragma omp for for(i=0; i< numt; i++) Work(i); }
не описан класс для переменной numt. Необходимо добавить спецификацию private(numt) не описан класс для переменной numt. Необходимо добавить спецификацию shared(numt) в данном фрагменте программы ошибки нет
Исполняемыми директивами в OpenMP являются:
threadprivate taskwait barrier
Использование операторов перехода (goto) в структурном блоке OpenMP возможно:
если оператор перехода не выводит за пределы блока поскольку в стандарте нет никаких ограничений на операторы перехода в некоторых OpenMP-компиляторах (зависит от реализации)
Использование оператора exit в структурном блоке OpenMP:
запрещено в стандарте возможно в некоторых OpenMP-компиляторах (зависит от реализации) разрешено в стандарте
Функция omp_get_num_threads возвращает:
количество нитей в текущей параллельной области номер нити в группе максимально возможное количество нитей, которые могут быть использованы при выполнении всей программы
Параллельная область в OpenMP создается при помощи:
вызова функции omp_set_num_threads директивы parallel вызова функции omp_set_max_active_levels
Функция omp_get_thread_num возвращает:
уникальный идентификатор нити количество нитей в текущей параллельной области номер нити в группе
При реализации компилятором редукционного оператора, описанного при помощи клаузы reduction (*: prod), где переменная prod имеет тип integer, для каждой нити создается локальная копия переменной prod, начальное значение которой будет инициализировано:
0 1 MAXINT (максимально возможное целое число)
При реализации компилятором редукционного оператора, описанного при помощи клаузы reduction (+: sum), где переменная sum имеет тип integer, для каждой нити создается локальная копия переменной sum, начальное значение которой будет инициализировано:
При реализации компилятором редукционного оператора, описанного при помощи клаузы reduction (-: sub), где переменная sub имеет тип integer, для каждой нити создается локальная копия переменной sub, начальное значение которой будет инициализировано:
максимально возможное число нитей, которые будут созданы при входе в параллельную область число нитей, которые обязательно будут созданы при входе в параллельную область максимально возможное количество нитей, которые могут быть использованы при выполнении всей программы
Найдите ошибку в следующем фрагменте программы:
#define N 10 int i; #pragma omp parallel firstprivate(i) lastprivate(i) { for (i=0; i<N; i++) { … } }
клауза lastprivate не может использоваться в директиве parallel одна и та же переменная не может быть указана в клаузах firstprivate и lastprivate одновременно клауза firstprivate не может использоваться в директиве parallel
Клауза copyin:
может быть использована только для переменных, указанных в директиве threadprivate может быть использована только для переменных, указанных в клаузе private может быть использована как для переменных указанных в директиве threadprivate, так и для переменных, указанных в клаузе private
Рассмотрим фрагмент OpenMP-программы: #include <omp.h> int n=1; int main (void) { omp_set_nested(1); omp_set_dynamic(1); omp_set_num_threads(2); #pragma omp parallel if (n>10) {/*параллельная область*/ … } } Для выполнения параллельной области будет создана группа нитей, состоящая из:
2-х нитей 1-ой нити нескольких нитей (количество создаваемых нитей зависит от переменной окружения OMP_NUM_THREADS)
Для выполнения вложенной параллельной области будет создана группа нитей, состоящая из:
2-х нитей 1-ой нити нескольких нитей (количество создаваемых нитей зависит от переменной окружения OMP_NUM_THREADS)
Найдите ошибку в следующем фрагменте программы:
#pragma omp parallel default(shared) { int i, j; #pragma omp for for (i=0; i<n; i++) { #pragma omp parallel private (i,n) { #pragma omp for for (j=0; j<n; j++) work(i, j); } } }
в результате использования клаузы private, значение переменных i и n во вложенном параллельном цикле не определено используются конструкции распределения работ, которые вложены одна в другую в данном фрагменте программы ошибки нет
Пусть перед входом в параллельную область вызывается функция omp_set_num_threads. Пусть в директиве создания этой параллельной области указана клауза num_threads. Количество создаваемых нитей будет:
определяться клаузой num_threads определяться вызовом функции omp_set_num_threads зависеть от реализации компилятора
Найдите ошибку в следующем фрагменте программы:
#pragma omp parallel default(shared) { int i, j; #pragma omp for for (i=0; i<n; i++) { #pragma omp parallel { #pragma omp for shared (i,n) for (j=0; j<n; j++) work(i, j); } } }
клауза shared не может быть использована в директиве for используются конструкции распределения работ, которые вложены одна в другую в данном фрагменте программы ошибки нет
Найдите ошибку в следующем фрагменте программы:
#pragma omp parallel default(shared) { int i, j; #pragma omp for for (i=0; i<n; i++) { #pragma omp for for (j=0; j<n; j++) work(i, j); } }
в результате использования клаузы default(shared), счетчики циклов i и j являются общими для всех нитей используются конструкции распределения работ, которые непосредственно вложены одна в другую в данном фрагменте программы ошибки нет
Найдите ошибку в следующем фрагменте программы:
int i, j; #pragma omp parallel default(shared) { #pragma omp for collapse (2) for (i=0; i<n; i++) { work_with_i (i); for (j=0; j < n; j++) work(i, j); } }
в результате использования клаузы default(shared), счетчики циклов - переменные i и j являются общими для всех нитей в данном фрагменте программы ошибки нет между заголовками циклов указан вызов процедуры work_with_i (клауза collapsе может быть использована только распределения витков тесно-вложенных циклов)
Найдите ошибку в следующем фрагменте программы:
int i, j; #pragma omp parallel default(shared) { #pragma omp for collapse (2) for (i=0; i<n; i++) { for (j=0; j < i; j++) work(i, j); } }
в данном фрагменте программы ошибки нет в результате использования клаузы default(shared), счетчики циклов - переменные i и j являются общими для всех нитей граница вложенного цикла зависит от индексной переменной внешнего цикла (клауза collapsе может быть использована только распределения витков циклов с прямоугольным индексным пространством)
Найдите ошибку в следующем фрагменте программы:
int i, j; #pragma omp parallel default(shared) { #pragma omp for collapse (3) for (i=0; i<n; i++) { for (j=0; j < n; j++) work(i, j); } }
количество заголовков циклов не соответствуют значению, указанному в клаузе collapse в данном фрагменте программы ошибки нет в результате использования клаузы default(shared), счетчики циклов - переменные i и j являются общими для всех нитей
Найдите ошибку в следующем фрагменте программы:
#define N 10 int i; #pragma omp parallel { #pragma omp for private(i) lastprivate(i) for (i=0; i<N; i++) { … } #pragma omp single printf (“Number of iteration=%d\n”, i); }
одна и та же переменная не может быть указана в клаузах private и lastprivate одновременно в данном фрагменте программы ошибки нет индексная переменная цикла, витки которого распределяются между нитями при помощи директивы for, не может быть указана в клаузе lastprivate
Найдите ошибку в следующем фрагменте программы:
#define N 10 int i; #pragma omp parallel { #pragma omp for firstprivate(i) lastprivate(i) for (i=0; i<N; i++) { … } #pragma omp single printf (“Number of iteration=%d\n”, i); }
одна и та же переменная не может быть указана в клаузах firstprivate и lastprivate одновременно индексная переменная цикла, витки которого распределяются между нитями при помощи директивы for, не может быть указана в клаузе firstprivate индексная переменная цикла, витки которого распределяются между нитями при помощи директивы for, не может быть указана в клаузе lastprivate
Найдите ошибку в следующем фрагменте программы:
#define N 10 float c[N]; float sum = 0.0; #pragma omp parallel shared(sum, c) { #pragma omp for reduction (+: sum) nowait for (int i=0; i<N; i++) { sum += c[i]; } #pragma omp single printf (“Sum of array=%4.2f\n”, sum); }
до использования значения редукционной переменной sum в операторе печати в блоке single отсутствует барьерная синхронизация нитей в директиве for нельзя одновременно указать клаузу reduction и клаузу nowait редукционная переменная sum объявлена общей(shared)
Найдите ошибку в следующем фрагменте программы:
#pragma omp parallel default(shared) { int i; #pragma omp for lastprivate(i) for (i=0; i<n + omp_get_thread_num (); i++) { work(i); } }
в данном фрагменте программы ошибки нет индексная переменная цикла, витки которого распределяются между нитями при помощи директивы for, не может быть указана в клаузе lastprivate значения выражений, указанных в заголовке цикла for, отличаются для каждой нити группы
Найдите ошибку в следующем фрагменте программы:
#pragma omp parallel default(shared) { int i; #pragma omp for lastprivate(i) for (i=0; i<n; i++) { i+=2; work(i); } }
изменение значения индексной переменной цикла for внутри цикла (при помощи оператора i+=2) не допускается индексная переменная цикла, витки которого распределяются между нитями при помощи директивы for, не может быть указана в клаузе lastprivate в данном фрагменте программы ошибки нет
Способ распределения витков цикла между нитями группы задается при помощи клаузы schedule(<алгоритм планирования>[,<число итераций>]). Найдите ошибку в следующем фрагменте программы:
#pragma omp parallel default(shared) { int i; #pragma omp for schedule(dynamic, omp_get_thread_num()) for (i=0; i<n; i++) { work(i); } }
значение параметра <число итераций> клаузы schedule отличается для каждой нити группы в данном фрагменте программы ошибки нет при динамическом планировании, задаваемом клаузой schedule(dynamic), параметр <число итераций> задать нельзя
Способ распределения витков цикла между нитями группы задается при помощи клаузы schedule(<алгоритм планирования>[,<число итераций>]). Найдите ошибку в следующем фрагменте программы:
#pragma omp parallel default(shared) { int i; #pragma omp for schedule(static, omp_get_thread_num()) for (i=0; i<n; i++) { work(i); } }
в данном фрагменте программы ошибки нет при статическом планировании, задаваемом клаузой schedule(static), параметр <число итераций> задать нельзя значение параметра <число итераций> клаузы schedule отличается для каждой нити группы
Найдите ошибку в следующем фрагменте программы:
#pragma omp parallel default(shared) { int i; #pragma omp for schedule(dynamic) for (i=0; i<n; i++) { #pragma omp ordered printf("iteration %d\n", i); } }
в данном фрагменте программы ошибки нет использование клаузы schedule(dynamic) для цикла for, в котором используется директива ordered запрещено в директиве for отсутствует клауза ordered
Найдите ошибку в следующем фрагменте программы:
#define N 10 int A[N],B[N]; #pragma omp parallel default(shared) { int i; ..…#pragma omp master for (i=0; i<N; i++) { A[i]=0; } #pragma omp for for (i=0; i<N; i++) B[i]=A[i]; }
по завершении конструкции master отсутствует директива barrier оператор for не может быть использован внутри конструкции master в данном фрагменте программы ошибки нет
Директива master
определяет блок операторов в программе, который будет выполнен master-нитью. Остальные нити группы не дожидаются завершения выполнения этого блока определяет блок операторов в программе, который будет выполнен master-нитью. Остальные нити группы дожидаются завершения выполнения этого блока определяет блок операторов в программе, который будет выполнен одной нитью группы. Остальные нити группы дожидаются завершения выполнения этого блока
Найдите ошибку в следующем фрагменте программы:
#define N 10 int A[N],B[N]; #pragma omp parallel default(shared) { int i; ..…#pragma omp master for (i=0; i<N; i++) { A[i]=0; } ..…#pragma omp barrier B[N-1]=B[N-1] + A[N-1]; }
оператор, в котором изменяется значение общей переменной B[N-1] выполняется без какой-либо синхронизации оператор for не может быть использован внутри конструкции master в данном фрагменте программы ошибки нет
Найдите ошибку в следующем фрагменте программы:
#define N 10 int A[N],B[N], sum; #pragma omp parallel default(shared) num_threads(10) { int iam=omp_get_thread_num(); if (iam ==0) { #pragma omp critical (update_a) #pragma omp critical (update_b) sum +=A[iam]; } else { #pragma omp critical (update_b) #pragma omp critical (update_a) sum +=B[iam]; } }
дедлок - взаимная блокировка нитей, возникающая при входе master-нитью в критическую секцию с именем update_a и любой другой нитью в секцию с именем update_b (в этом случае вложенные критические секции не смогут быть обработаны) в данном фрагменте программы ошибки нет критические секции, определяемые директивой critical, не могут быть вложены друг в друга
Найдите ошибку в следующем фрагменте программы:
#define N 10 int A[N],B[N]; #pragma omp parallel default(shared) num_threads(10) { int iam=omp_get_thread_num(); int tmp; tmp=A[iam]; B[iam]=tmp; }
чтение/изменение переменной tmp выполняется без какой-либо синхронизации в данном фрагменте программы ошибки нет изменение общей переменной B[iam] выполняется без какой-либо синхронизации
Найдите ошибку в следующем фрагменте программы:
#define N 10 int A[N], sum; #pragma omp parallel default(shared) num_threads(10) { int iam=omp_get_thread_num(); #pragma omp critical (update_a) #pragma omp critical (update_a) sum +=A[iam]; }
в данном фрагменте программы ошибки нет одноименные критические секции не могут быть вложены друг в друга критические секции не могут быть вложены друг в друга
Найдите ошибку в следующем фрагменте программы:
#define N 10 int A[N],B[N],tmp; #pragma omp parallel default(shared) num_threads(10) { int iam=omp_get_thread_num(); tmp=A[iam]; B[iam]=tmp; }
чтение/изменение общей переменной tmp выполняется без какой-либо синхронизации изменение общей переменной B[iam] выполняется без какой-либо синхронизации в данном фрагменте программы ошибки нет
Найдите ошибку в следующем фрагменте программы:
#define N 10 int A[N],B[N], sum; #pragma omp parallel default(shared) num_threads(10) { int iam=omp_get_thread_num(); if (A[iam] > 0) { #pragma omp critical (update_a) sum +=A[iam]; } if (B[iam] > 0) { #pragma omp critical (update_b) sum +=B[iam]; } }
в данном фрагменте программы ошибки нет чтение общих переменных А[iam] и B[iam] в операторах вида A[iam]>0 и B[iam]>0 выполняется без какой-либо синхронизации изменение общей переменной sum внутри критических секций update_a и update_b может выполняться одновременно несколькими нитями, поскольку названия критических секций отличаются
директива barrier не может быть использована внутри конструкции single в данном фрагменте программы ошибки нет директива critical не может быть использована внутри конструкции single
директива flush не может быть использована внутри критической секции (конструкции critical) в данном фрагменте программы ошибки нет директива barrier не может быть использована внутри критической секции (конструкции critical)
в данном фрагменте программы ошибки нет директива critical не может быть использована внутри конструкции master; директива barrier не может быть использована внутри конструкции master
при вычислении выражения в правой части оператора присваивания, указанного в конструкции atomic, не может быть использована переменная, указанная в левой части оператора присваивания в данном фрагменте программы ошибки нет оператор & (побитовое И) не может быть использован в конструкции atomic
Найдите ошибку в следующем фрагменте программы:
int x=0; omp_lock_t lcka, lckb; omp_init_lock (&lcka); omp_init_lock (&lckb); #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); } } } omp_destroy_lock (&lcka); omp_destroy_lock (&lckb);
в данном фрагменте программы ошибки нет дедлок - взаимная блокировка нитей, возникающая, в случае если master-нить, выполнила omp_set_lock (&lcka), а другая нить выполнила omp_set_lock (&lckb) после установки блокировки в результате вызова функции omp_set_lock(&lcka), повторное обращение нитью к функции omp_set_lock(&lckb) некорректно (повторное обращение omp_set_lock(&lckb) должно быть заменено на omp_set_nest_lock(&lckb))
в данном фрагменте программы ошибки нет оператор вида x=sqrt(x) не может быть использован в конструкции atomic оператор & (побитовое И) не может быть использован в конструкции atomic
Определите способ распределения витков цикла между нитями для следующего фрагмента программы:
#define N 100 #include "omp.h" void work(int i); int main () { #pragma omp parallel { omp_set_schedule (omp_sched_dynamic); #pragma omp for schedule(static) for (int i=0;i<N;i++) work (i); } }
зависит от значения переменной окружения OMP_SCHEDULE. статический (static) динамический (dynamic)
Определите способ распределения витков цикла между нитями для следующего фрагмента программы:
#define N 100 void work(int i); int main () { #pragma omp parallel { #pragma omp for for (int i=0;i<N;i++) work (i); } }
зависит от реализации компилятора зависит от значения переменной окружения OMP_SCHEDULE статический (static)
Определите способ распределения витков цикла между нитями для следующего фрагмента программы:
#define N 100 #include "omp.h" void work(int i); int main () { #pragma omp parallel { omp_set_schedule (omp_sched_static); #pragma omp for schedule(dynamic) for (int i=0;i<N;i++) work (i); } }
статический (static) динамический (dynamic) зависит от значения переменной окружения OMP_SCHEDULE
Определите способ распределения витков цикла между нитями для следующего фрагмента программы:
#define N 100 #include "omp.h" void work(int i); int main () { #pragma omp parallel { omp_set_schedule (omp_sched_guided); #pragma omp for for (int i=0;i<N;i++) work (i); } }
зависит от реализации компилятора зависит от значения переменной окружения OMP_SCHEDULE управляемый(guided)
Определите способ распределения витков цикла между нитями для следующего фрагмента программы:
#define N 100 #include "omp.h" void work(int i); int main () { #pragma omp parallel { omp_set_schedule (omp_sched_dynamic); #pragma omp for for (int i=0;i<N;i++) work (i); } }
зависит от значения переменной окружения OMP_SCHEDULE зависит от реализации компилятора динамический (dynamic)
Определите способ распределения витков цикла между нитями для следующего фрагмента программы:
#define N 100 #include "omp.h" void work(int i); int main () { #pragma omp parallel { omp_set_schedule (omp_sched_static); #pragma omp for for (int i=0;i<N;i++) work (i); } }
зависит от значения переменной окружения OMP_SCHEDULE зависит от реализации компилятора статический (static)
Определите количество нитей, между которыми будет распределена работа в параллельной области:
#include "omp.h" void work(int i); int main () { int n; n=10; omp_set_num_threads(2); #pragma omp parallel num_threads(4) if (n>20) { #pragma omp for for (int i=0;i<n;i++) work (i); } }
4 2 1
Определите количество нитей, между которыми будет распределена работа в параллельной области:
#define N 100 #include "omp.h" void work(int i); int main () { omp_set_num_threads(2); #pragma omp parallel num_threads(4) { #pragma omp for for (int i=0;i<N;i++) work (i); } }
зависит от значения переменной окружения OMP_NUM _THREADS 4 2
Определите количество нитей, между которыми будет распределена работа в параллельной области:
#include "omp.h" void work(int i); int main () { int n; n=10; #pragma omp parallel num_threads(4) if (n>20) { #pragma omp for for (int i=0;i<n;i++) work (i); } }
4 1 зависит от значения переменных окружения OMP_THREAD_LIMIT и OMP_NUM_THREADS
Пусть следующая программа скомпилирована компилятором, поддерживающим вложенный параллелизм.
Определите значение переменной counter по завершении выполнения этой программы:
1 2 4
Внимание ! Вопросы к тесту выложены исключительно в ознакомительных целях: количество вопросов может не совпадать с действительным, актуальность не поддерживается,- за решением теста Welcome to the cashier! Пусть следующая программа скомпилирована компилятором, поддерживающим вложенный параллелизм.
Определите значение переменной counter по завершении выполнения этой программы:
4 2 1
Определите значение переменной team_size по завершении выполнения следующей программы:
#include <stdio.h> #include "omp.h" int main() { int team_size; team_size=omp_get_team_size(omp_get_level ()); printf("Team Size=%d\n",team_size); }
0 1 -1
Определите значение переменной team_size по завершении выполнения следующей программы:
#include <stdio.h> #include "omp.h" int main() { int team_size; team_size=0; #pragma omp parallel num_threads(2) { if (omp_get_thread_num() == 0) { team_size=omp_get_team_size(0); } } printf("Team Size=%d\n",team_size); }
2 0 1
Определите значение переменной team_size по завершении выполнения следующей программы:
#include <stdio.h> #include "omp.h" int main() { int team_size; team_size=0; #pragma omp parallel num_threads(2) { if (omp_get_thread_num() == 0) { team_size=omp_get_team_size(omp_get_level ()); } } printf("Team Size=%d\n",team_size); }
1 2 0
Найдите ошибку в следующем фрагменте программы:
#define N 1000 int main (void){ float a[N]; #pragma omp parallel { #pragma omp for for(int i=0; i<N;i++) { float tmp; tmp= a[i]*a[i]; a[i]=1-tmp; } } }
в данном фрагменте программы ошибки нет в директиве for отсутствует клауза private(i) в директиве for отсутствует клауза private(tmp)
Найдите ошибку в следующем фрагменте программы:
#define N 1000 int main (void){ 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; } } }
в директиве for отсутствует клауза private(i) в данном фрагменте программы ошибки нет в директиве for отсутствует клауза private(tmp)
Найдите ошибку в следующем фрагменте программы:
#define N 1000 int main (void){ float a[N], tmp; #pragma omp parallel { int i; #pragma omp for private(i) for(i=0; i<N;i++) { tmp= a[i]*a[i]; a[i]=1-tmp; } } }
в директиве parallel отсутствует клауза shared(a) в данном фрагменте программы ошибки нет в директиве for отсутствует клауза private(tmp)
Найдите ошибку в следующем фрагменте программы:
int main (void){ int a; #pragma omp parallel private(a) { #pragma omp single a = 0; #pragma omp for reduction(+:a) for (int i = 0; i < 10; i++) { a += i; } } }
в директиве parallel клауза private (a) должна быть заменена на shared(a) в данном фрагменте программы ошибки нет перед директивой for отсутствует директива barrier
Найдите ошибку в следующем фрагменте программы:
int main (void){ int a, i; #pragma omp parallel shared(a) private(i) { #pragma omp master a = 0; #pragma omp for reduction(+:a) for (i = 0; i < 10; i++) { a += i; } } }
в директиве parallel клауза shared(a) должна быть заменена на private(a) перед директивой for отсутствует директива barrier в данном фрагменте программы ошибки нет
int main (void){ int a, i; #pragma omp parallel shared(a) private(i) { #pragma omp single a = 0; #pragma omp for for (i = 0; i < 10; i++) { a += i; } } }
в данном фрагменте программы ошибки нет в директиве for отсутствует клауза reduction(+:a) перед директивой for отсутствует директива barrier
Найдите ошибку в следующем фрагменте программы:
#include <omp.h> int main (void){ #pragma omp parallel { int numt; #pragma omp single numt=omp_get_num_threads(); if (numt < 4) do_small_work(); else do_big_work (); } }
в данном фрагменте программы ошибки нет в директиве single отсутствует клауза copyprivate(numt) после конструкции single отсутствует директива barrier
Найдите ошибку в следующем фрагменте программы:
#include <omp.h> int numproc; #pragma omp threadprivate(numproc) int main (void){ numproc=omp_get_num_procs(); #pragma omp parallel { if (numproc < 4) do_small_work(); else do_big_work (); } }
функция omp_get_num_procs не может быть вызвана вне параллельной области в директиве parallel отсутствует клауза copyin(numproc) в данном фрагменте программы ошибки нет
Найдите ошибку в следующем фрагменте программы:
#define N 1000 float a[N], b[N]; int main (void){ int i; #pragma omp parallel { #pragma omp for for (i=0; i<N-1; i++) { a[i] = b[i] + b[i+1]; } a[i]=b[i]; } }
в директиве for отсутствует клауза lastpivate(i) в директиве parallel отсутствует клауза shared(a,b) в директиве parallel отсутствует клауза private(i)
#define N 10
int A[N],B[N], sum; #pragma omp parallel default(shared) num_threads(10) { int iam=omp_get_thread_num(); if (iam ==0) { #pragma omp critical (update_a) #pragma omp critical (update_b) sum +=A[iam]; } else { #pragma omp critical (update_b) #pragma omp critical (update_a) sum +=B[iam]; } }
дедлок - взаимная блокировка нитей, возникающая при входе master-нитью в критическую секцию с именем update_a и любой другой нитью в секцию с именем update_b (в этом случае вложенные критические секции не смогут быть обработаны) в данном фрагменте программы ошибки нет критические секции, определяемые директивой critical, не могут быть вложены друг в друга
Найдите ошибку в следующем фрагменте программы:
#define N 10 int A[N], sum; #pragma omp parallel default(shared) num_threads(10) { int iam=omp_get_thread_num(); #pragma omp critical (update_a) #pragma omp critical (update_a) sum +=A[iam]; }
дедлок - взаимная блокировка нитей, возникающая в результате того что одноименные критические секции вложены друг в друга в данном фрагменте программы ошибки нет критические секции не могут быть вложены друг в друга
Найдите ошибку в следующем фрагменте программы:
#pragma omp parallel { int me; me = omp_get_thread_num (); if (me == 0) goto Master; #pragma omp barrier Master: #pragma omp single }
в директиве parallel отсутствует клауза private(me) оператор goto не может быть использован внутри конструкции parallel дедлок - взаимная блокировка нитей, возникающая в результате того что master-нить не попадает на директиву barrier
Intel Thread Checker:
обнаруживает все возможные ошибки типа datarace и deadlock в программе ошибки, которые проявились при выполнении программы на заданном наборе входных тестовых данных
Поиск ошибок в OpenMP-программе, выполняемый Intel Thread Checker, основан на:
методе сравнительной отладки нескольких запусков одной программы методе статического анализа кода программы методе динамического анализа корректности программы
Выберите наилучшую стратегию распределения витков цикла между нитями, которая для следующего фрагмента программы даст минимальное время выполнения:
#include <omp.h> #include <unistd.h> #define msec 1000 int main (void){ omp_set_num_threads (8); #pragma omp parallel { #pragma omp for schedule (runtime) for(int i=0; i<100;i++) { sleep (i*msec); } } }
Выберите наиболее походящую оптимизацию, которая позволит сократить время выполнения следующего фрагмента программы:
#include <omp.h> #include <stdio.h> #define N 100 float c[N]; float sum = 0.0; int main (void) { omp_set_num_threads (8); #pragma omp parallel shared(sum, c) { #pragma omp for for (int i=0; i<N; i++) { #pragma omp critical sum += c[i]; } } printf (“Sum of array=%4.2f\n”, sum); }
заменить директиву critical на директиву atomic заменить директиву critical на директиву critical (<имя_критической_секции>) добавить к директиве for клаузу reduction(+:sum) и убрать директиву critical
Выберите наиболее походящую оптимизацию, которая позволит сократить время выполнения следующего фрагмента программы:
#include <omp.h> #include <stdio.h> #define N 100 int c[N]; int val = 0; int main (void) { omp_set_num_threads (8); #pragma omp parallel shared(val, c) { #pragma omp for for (int i=0; i<N; i++) { #pragma omp critical val ^= c[i]; } } printf (“Result=%d\n”, var); }
заменить директиву critical на директиву critical (<имя_критической_секции>) заменить директиву critical на директиву atomic добавить к директиве for клаузу reduction(^:val) и убрать директиву critical
Выберите наиболее походящую оптимизацию, которая позволит сократить время выполнения следующего фрагмента программы:
#include <omp.h> #include <stdio.h> #define N 100 int c[N]; int val= 1; int main (void) { omp_set_num_threads (8); #pragma omp parallel shared(val, c) { #pragma omp for for (int i=0; i<N; i++) { #pragma omp critical val = val && (c[i]<100); } } printf (“Result=%4.2f\n”, val); }
добавить к директиве for клаузу reduction(&&:val) и убрать директиву critical заменить директиву critical на директиву critical (<имя_критической_секции>) вместо директивы critical использовать механизм семафоров (omp_set_lock/omp_unset_lock)
Выберите наиболее походящую оптимизацию, которая позволит сократить время выполнения следующего фрагмента программы:
#define N 80 omp_set_num_threads (8); #pragma omp parallel shared(a,b,c,x,y,z) { #pragma omp for for (int i=0; i<N; i++) { z[i] = x[i] + y[i]; } #pragma omp for for (int i=0; i<N; i++) { a[i] = b[i] + c[i]; } }
для циклов, выполнение витков которых распределяется между нитями при помощи директивы for, добавить клаузу schedule(dynamic) для циклов, выполнение витков которых распределяется между нитями при помощи директивы for, добавить клаузу schedule(static,10) для первого цикла, выполнение витков которого распределяется между нитями при помощи директивы for, добавить клаузу nowait
Выберите наиболее походящую оптимизацию, которая позволит сократить время выполнения следующего фрагмента программы:
#define N 100 omp_set_num_threads (4); #pragma omp parallel shared(a,b,c,x,y,z) { #pragma omp for for (int i=0; i<N; i++) { z[i] = x[i] + y[i]; } #pragma omp for for (int i=0; i<N; i++) { a[i] = b[i] + c[i]; } }
для циклов, выполнение витков которых распределяется между нитями при помощи директивы for, добавить клаузу nowait для циклов, выполнение витков которых распределяется между нитями при помощи директивы for, добавить клаузу schedule(static,25) для циклов, выполнение витков которых распределяется между нитями при помощи директивы for, добавить клаузу schedule(dynamic)
Выберите наиболее походящую оптимизацию, которая позволит сократить время выполнения следующего фрагмента программы:
#include <omp.h> #include <unistd.h> #define msec 1000 int main (void){ omp_set_num_threads (8); for (int i=0; i<80; i++) #pragma omp parallel for for (int j=0; j<80; j++) sleep (msec); }
добавить к директиве parallel for клаузу schedule(static,10) переставить директиву parallel for (распределить между нитями выполнение витков цикла по i) добавить к директиве parallel for клаузу schedule(dynamic)
Выберите наиболее походящую оптимизацию, которая позволит сократить время выполнения следующего фрагмента программы:
#include <omp.h> #include <unistd.h> #define msec 1000 int main (void){ omp_set_num_threads (8); #pragma omp parallel { #pragma omp for for(int i=0; i<80;i++) { sleep (i*msec); } #pragma omp for for(int i=0; i<80;i++) { sleep ((80-i)*msec); } } }
для циклов, выполнение витков которых распределяется между нитями при помощи директивы for, добавить клаузу schedule(static,10) для циклов, выполнение витков которых распределяется между нитями при помощи директивы for, добавить клаузу nowait для циклов, выполнение витков которых распределяется между нитями при помощи директивы for, добавить клаузу schedule(dynamic)
Выберите наиболее походящую оптимизацию, которая позволит сократить время выполнения следующего фрагмента программы:
#include <omp.h> #include <unistd.h> #define msec 1000 int main (void){ int i; omp_set_num_threads (8); #pragma omp parallel for for (i=0; i<80; i++) sleep (msec); #pragma omp parallel for for (i=0; i<80; i++) sleep (msec); }
объединить две подряд стоящие параллельные области в одну для второго цикла, выполнение витков которого распределяется между нитями при помощи директивы for, добавить клаузу schedule(dynamic) для первого цикла, выполнение витков которого распределяется между нитями при помощи директивы for, добавить клаузу schedule(dynamic)
Выберите наиболее походящую оптимизацию, которая позволит сократить время выполнения следующего фрагмента программы:
#include <omp.h> #include <unistd.h> #define msec 1000 int main (void){ omp_set_num_threads (8); #pragma omp parallel for for (int i=0; i<5; i++) for (int j=0; j<5; j++) sleep (msec); }
добавить к директиве parallel for клаузу schedule(dynamic) добавить к директиве parallel for клаузу schedule(static,1) добавить к директиве parallel for клаузу collapse(2)
Переменные, которые разделяются нитями, и доступ к которым обрабатывается в технологии Intel Cluster OpenMP механизмом DSM, могут быть заданы при помощи:
Для выделения памяти для SHARABLE-переменных в технологии Intel Cluster OpenMP требуется использовать:
специальные функции kmp_sharable_malloc, kmp_sharable_realloc и т.д обычные функции malloc, realloc и т.д как обычные, так и специальные функции. Доступ к переменным, для которых память выделена при помощи специальных функций осуществляется быстрее
Директива SHARABLE в технологии Intel Cluster OpenMP:
задает, какие переменные, на какой узел кластера необходимо отобразить определяет разделяемые нитями переменные, доступ к которым обрабатывается механизмом DSM определяет разделяемые нитями переменные, доступ к которым возможен только на одном из узлов кластера
При использовании технологии Intel Cluster OpenMP программист:
при помощи соответствующих директив определяет разделяемые нитями переменные, доступ к которым обрабатывается механизмом DSM. Вычисления распределяются по узлам кластера компилятором при помощи соответствующих директив распределяет по узлам кластера разделяемые нитями переменные и вычисления, проводимые над этими переменными при помощи соответствующих директив распределяет вычисления по узлам кластера. Данные по узлам кластера распределяются в соответствии с распределением вычислений
Использование технологии Intel Cluster OpenMP целесообразно:
для OpenMP-программ с нерегулярными вычислениями, проводимыми над общими данными для OpenMP-программ, с хорошей локализацией данных и требующих малой синхронизации для любых OpenMP-программ
При использовании гибридной модели параллельного программирования MPI/OpenMP:
все нити взаимодействуют друг с другом только через обмены сообщений все нити, выполняемые на узле кластера, взаимодействуют через общую память, а MPI используется для обмена информацией между узлами кластера все нити, выполняемые на различных узлах кластера, взаимодействуют друг с другом через общую память
При использовании гибридной модели параллельного программирования DVM/OpenMP:
все нити взаимодействуют друг с другом при помощи механизмов, предоставляемых DVM-системой все нити, выполняемые на узле кластера, взаимодействуют через общую память, а для обмена информацией между узлами кластера используются механизмы, предоставляемые DVM-системой все нити, выполняемые на различных узлах кластера, взаимодействуют друг с другом через общую память
Технология OpenMP по сравнению с MPI имеет следующие преимущества (отметьте все подходящие варианты):
упрощение программирования и эффективность на нерегулярных вычислениях, проводимых над общими данными ликвидация дублирования данных в памяти (массивов констант, теневых граней и т.п.) возможность инкрементального распараллеливания
Найдите ошибку в следующем фрагменте MPI/OpenMP-программы, вычисляющей число Пи:
в данном фрагменте программы ошибки нет функции MPI_Init, MPI_Comm_Rank, MPI_Comm_Size должны вызываться из параллельной области до завершения выполнения редукционного OpenMP-оператора выполняется вызов функции MPI_Reduce
Найдите ошибку в следующем фрагменте MPI/OpenMP-программы, вычисляющей число Пи:
все обращения к MPI-функциям в параллельной области должны выполняться одной нитью (например, внутри конструкции single) в данном фрагменте программы ошибки нет переменные numprocs, myid, mysteps должны быть объявлены как private(numprocs, myid, mysteps)
Найдите ошибку в следующем фрагменте MPI/OpenMP-программы, вычисляющей число Пи:
функции MPI_Init, MPI_Comm_Rank, MPI_Comm_Size и MPI_Reduce должны вызываться из параллельной области в данном фрагменте программы ошибки нет конфликт доступа к данным (race condition), возникающий в результате выполнения оператора sum *= step в параллельной области
Найдите ошибку в следующем фрагменте MPI/OpenMP-программы, реализующей метод релаксации Якоби:
int jacobi(int p, int id, int my_rows, double **u, double **w) { double diff, global_diff, tdiff; int i,j,it; MPI_Status status; it=0; for(;;) { if (id>0) MPI_Send (u[1], N, MPI_DOUBLE, id-1, 0, MPI_COMM_WORLD); if (id<p-1) { MPI_Send (u[my_rows-2], N, MPI_DOUBLE, id+1, 0, MPI_COMM_WORLD); MPI_Recv (u[my_rows-1], N, MPI_DOUBLE, id+1, 0, MPI_COMM_WORLD, &status); } if (id>0) MPI_Recv (u[0], N, MPI_DOUBLE, id-1, 0, MPI_COMM_WORLD, &status); diff=0.0; #pragma omp parallel private (i,j,tdiff) { tdiff=0.0; #pragma omp for for (i=1; i<my_rows; i++) for (j=1; j<N-1; j++) { w[i][j]=(u[i-1][j]+u[i+1][j]+u[i][j-1]+u[i][j+1])/4.0; if (fabs(w[i][j]-u[i][j]) >tdiff) tdiff=fabs(w[i][j]-u[i][j]); } #pragma omp for nowait for (i=1; i<my_rows; i++) for (j=1; j<N-1; j++) u[i][j]=w[i][j]; #pragma omp critical if (tdiff > diff) diff=tdiff; MPI_Allreduce (&diff, &global_diff, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); } if (global_diff <= EPSILON) break; it++; } return it; }
в данном фрагменте программы ошибки нет обращения к функции MPI_Allreduce в параллельной области должны выполняться одной нитью (например, внутри конструкции single) не определен класс для переменных u, w, my_rows, diff, global_diff, используемых в параллельной области -shared(u,w,my_rows,diff,global_diff)
Вы можете обратится к нам напрямую, через:
По Skype: molodoyberkut По Telegram: @MolodoyBerkut По ICQ: 657089516