Параллельное программирование с OpenMP - ответы
Количество вопросов - 119
Пусть следующая программа скомпилирована компилятором, поддерживающим вложенный параллелизм.#include <stdio.h>#include "omp.h"int counter;int main(){ counter=0; omp_set_nested(1); #pragma omp parallel num_threads(2) { if (omp_get_thread_num() == 0) { #pragma omp parallel num_threads(2) { #pragma omp atomic counter++; } } } printf("Counter=%d\n",counter);}
Определите значение переменной counter по завершении выполнения этой программы:
Способ распределения витков цикла между нитями группы задается при помощи клаузы 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); }}
Найдите ошибку в следующем фрагменте программы:#include <math.h>double x=1024.0;int n=1024;#pragma omp parallel{ #pragma omp atomic x+=sqrt(x); #pragma omp atomic n&=0177;}
Найдите ошибку в следующем фрагменте программы: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; } }}
Выберите наилучшую стратегию распределения витков цикла между нитями, которая для следующего фрагмента программы даст минимальное время выполнения:#include <omp.h>#include <unistd.h>#define msec 1000int main (void){ omp_set_num_threads (4); #pragma omp parallel { #pragma omp for schedule (runtime) for(int i=0; i<40;i++) { sleep (msec); } }}
Найдите ошибку в следующем фрагменте программы: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); } }
При реализации компилятором редукционного оператора, описанного при помощи клаузы reduction (-: sub), где переменная sub имеет тип integer, для каждой нити создается локальная копия переменной sub, начальное значение которой будет инициализировано:
Найдите ошибку в следующем фрагменте программы:#pragma omp parallel default(shared){ int i; #pragma omp for lastprivate(i) for (i=0; i<n + omp_get_thread_num (); i++) { work(i); }}
Определите значение переменной 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);}
Пусть W(x)a – операция записи в переменную x значения a. Пусть R(x)a – операция чтения переменной x, где a – прочитанное значение переменной x. Следующая последовательность событий:
P1: W(x)a | W(x)c | ||||
---|---|---|---|---|---|
P2: | R(x)a | W(x)b | |||
P3: | R(x)a | R(x)c | R(x)b | ||
P4: | R(x)a | R(x)b | R(x)c |
Найдите ошибку в следующем фрагменте программы:#define N 1000float 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]; }}
Найдите ошибку в следующем фрагменте программы:#define N 10int 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];}
Найдите ошибку в следующем фрагменте программы:#define N 1000int 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; } }}
Найдите ошибку в следующем фрагменте MPI/OpenMP-программы, вычисляющей число Пи:#include <mpi.h>#include <omp.h>#define num_steps 100000void main (int argc, char *argv[]){ double pi, step, sum = 0.0 ; step = 1.0/(double) num_steps ; #pragma omp parallel { int numprocs, myid, mysteps; MPI_Init(&argc, &argv) ; MPI_Comm_Rank(MPI_COMM_WORLD, &myid) ; MPI_Comm_Size(MPI_COMM_WORLD, &numprocs) ; mysteps = num_steps/numprocs ; #pragma omp for reduction(+:sum) for (int i=myid*mysteps; i<(myid+1)*mysteps ; i++){ double x = (i+0.5)*step; sum += 4.0*step/(1.0+x*x); } MPI_Reduce(&sum, &pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); } MPI_Finalize();}
Выберите наиболее походящую оптимизацию, которая позволит сократить время выполнения следующего фрагмента программы:#include <omp.h>#include <unistd.h>#define msec 1000int 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);}
Найдите ошибку в следующем фрагменте 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]; 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;}
Найдите ошибку в следующем фрагменте программы:#pragma omp parallel{ int me; me = omp_get_thread_num (); if (me == 0) goto Master; #pragma omp barrierMaster: #pragma omp single}
Найдите ошибку в следующем фрагменте программы:#define N 10int 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; }}
Определите способ распределения витков цикла между нитями для следующего фрагмента программы:#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); }}
Определите количество нитей, между которыми будет распределена работа в параллельной области:#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); }}
Определите способ распределения витков цикла между нитями для следующего фрагмента программы:#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); }}
Найдите ошибку в следующем фрагменте программы:#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); }}
Найдите ошибку в следующем фрагменте программы:#define N 10float 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);}
Пусть W(x)a – операция записи в переменную x значения a. Пусть R(x)a – операция чтения переменной x, где a – прочитанное значение переменной x. Пусть S - операция синхронизации. Следующая последовательность событий:
P1: W(x)a | W(x)b | S | ||
---|---|---|---|---|
P2: | S | R(x)a |
Найдите ошибку в следующем фрагменте программы:#define N 10int i;#pragma omp parallel{ int tmp = 0; #pragma omp for private(tmp) for (i=0; i<N; i++) { tmp += i; }}
Определите класс по умолчанию для переменной numt:int i=0;int numt = omp_get_max_threads();#pragma omp parallel forfor(i=0; i< numt; i++) Work(i);
Рассмотрим фрагмент OpenMP-программы:#include <omp.h>int main (void){ omp_set_nested(0); omp_set_max_active_levels(8); omp_set_num_threads(2); #pragma omp parallel { omp_set_num_threads(2); #pragma omp parallel { /*вложенная параллельная область*/ … } }}
Для выполнения вложенной параллельной области будет создана группа нитей, состоящая из:
Найдите ошибку в следующем фрагменте программы:#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); } }}
Найдите ошибку в следующем фрагменте программы: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); } }
Найдите ошибку в следующем фрагменте программы:#define N 10int 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);}
Способ распределения витков цикла между нитями группы задается при помощи клаузы 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); }}
Найдите ошибку в следующем фрагменте программы:#define N 10int 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;}
Найдите ошибку в следующем фрагменте программы:#define N 10int 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]; }}
Найдите ошибку в следующем фрагменте программы:int numt=0;#pragma omp parallel{ #pragma omp master { #pragma omp critical { numt=omp_get_num_threads(); } #pragma omp barrier }}
Найдите ошибку в следующем фрагменте программы: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);
Определите способ распределения витков цикла между нитями для следующего фрагмента программы:#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); }}
Определите количество нитей, между которыми будет распределена работа в параллельной области:#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); }}
Определите значение переменной 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);}
Найдите ошибку в следующем фрагменте программы:#define N 1000int 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; } }}
Найдите ошибку в следующем фрагменте программы:#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 (); }}
#define N 10int 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]; }}
Выберите наилучшую стратегию распределения витков цикла между нитями, которая для следующего фрагмента программы даст минимальное время выполнения:#include <omp.h>#include <unistd.h>#define msec 1000int main (void){ omp_set_num_threads (8); #pragma omp parallel { #pragma omp for schedule (runtime) for(int i=0; i<100;i++) { sleep ((100-i)*msec); } }}
Выберите наиболее походящую оптимизацию, которая позволит сократить время выполнения следующего фрагмента программы:#include <omp.h>#include <stdio.h>#define N 100int 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);}
Выберите наиболее походящую оптимизацию, которая позволит сократить время выполнения следующего фрагмента программы:#define N 80omp_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]; }}
Для выделения памяти для SHARABLE-переменных в технологии Intel Cluster OpenMP требуется использовать:
Технология OpenMP по сравнению с MPI имеет следующие преимущества (отметьте все подходящие варианты):
Найдите ошибку в следующем фрагменте 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; #pragma omp parallel private (i,j,tdiff) { for(;;) { #pragma omp master { diff=0.0; 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); } /*end of master*/ 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; #pragma omp barrier #pragma omp single { it++; MPI_Allreduce (&diff, &global_diff, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); } /*end of single*/ if (global_diff <= EPSILON) break; } return it;}
Определите количество нитей, между которыми будет распределена работа в параллельной области:#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); }}
Выберите наилучшую стратегию распределения витков цикла между нитями, которая для следующего фрагмента программы даст минимальное время выполнения:#include <omp.h>#include <unistd.h>#define msec 1000int main (void){ omp_set_num_threads (4); #pragma omp parallel { #pragma omp for schedule (runtime) for(int i=0; i<60;i++) { sleep (msec); } }}
Рассмотрим фрагмент 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) {/*параллельная область*/ … }}Для выполнения параллельной области будет создана группа нитей, состоящая из:
При реализации компилятором редукционного оператора, описанного при помощи клаузы reduction (+: sum), где переменная sum имеет тип integer, для каждой нити создается локальная копия переменной sum, начальное значение которой будет инициализировано:
Найдите ошибку в следующем фрагменте программы:#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); } }}
Выберите наилучшую стратегию распределения витков цикла между нитями, которая для следующего фрагмента программы даст минимальное время выполнения:#include <omp.h>#include <unistd.h>#define msec 1000int 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); } }}
Найдите ошибку в следующем фрагменте программы:#pragma omp parallel default(shared){ int i; #pragma omp for lastprivate(i) for (i=0; i!=n; i++) { work(i); }}
Найдите ошибку в следующем фрагменте программы:#define N 1000int 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; } }}
Найдите ошибку в следующем фрагменте программы:#define N 10int 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 single B[N-1]=A[N-1];}
Найдите ошибку в следующем фрагменте программы:#define N 10int 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;}
Найдите ошибку в следующем фрагменте 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;}
Найдите ошибку в следующем фрагменте программы: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); } }
Пусть W(x)a – операция записи в переменную x значения a. Пусть R(x)a – операция чтения переменной x, где a – прочитанное значение переменной x. Пусть S - операция синхронизации. Следующая последовательность событий:
P1: W(x)a | W(x)b | S | |||
---|---|---|---|---|---|
P2: | R(x)a | R(x)b | S | ||
P3: | R(x)b | R(x)a | S |