Сертификат "Параллельное программирование с OpenMP"
  • Сертификат "Параллельное программирование с OpenMP"
  • Сертификат "Параллельное программирование с OpenMP"
Сертификат "Параллельное программирование с OpenMP"
  • Сертификат "Параллельное программирование с OpenMP"
  • Сертификат "Параллельное программирование с OpenMP"

Параллельное программирование с OpenMP

700,00 руб.
В течение часа!
Экзамен "Параллельное программирование с OpenMP" для пользователей и системных администраторов.
Количество
Есть в наличии!

Форма сдачи теста: Экстерн
Количество вопросов: 30
Проходной балл: 90% и выше
Срок действия сертификата: неограничен

Сертификат появляется в профиле ресурса INTUIT, и Вы можете заказать его бумажную версию на сайте INTUIT.
12553 шт.
Внимание !
Вопросы к тесту выложены исключительно в ознакомительных целях: количество вопросов может не совпадать с действительным, актуальность не поддерживается,- за решением теста 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, начальное значение которой будет инициализировано:

MAXINT (максимально возможное целое число)
0
-MAXINT (минимально возможное целое число)


При реализации компилятором редукционного оператора, описанного при помощи клаузы reduction (-: sub), где переменная sub имеет тип integer, для каждой нити создается локальная копия переменной sub, начальное значение которой будет инициализировано:

-MAXINT (минимально возможное целое число)
0
MAXINT (максимально возможное целое число)


Клауза num_threads задает:

максимально возможное число нитей, которые будут созданы при входе в параллельную область
число нитей, которые обязательно будут созданы при входе в параллельную область
максимально возможное количество нитей, которые могут быть использованы при выполнении всей программы


Найдите ошибку в следующем фрагменте программы:

#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)


Рассмотрим фрагмент 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
             { /*вложенная параллельная область*/
             …
              }
         }
}

Для выполнения вложенной параллельной области будет создана группа нитей, состоящая из:

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 может выполняться одновременно несколькими нитями, поскольку названия критических секций отличаются


Найдите ошибку в следующем фрагменте программы:

int numt=0;
#pragma omp parallel
{
      #pragma omp single
      {
          #pragma omp critical
          {
                numt=omp_get_num_threads();
          }
          #pragma omp barrier
       }
}

директива barrier не может быть использована внутри конструкции single
в данном фрагменте программы ошибки нет
директива critical не может быть использована внутри конструкции single


Найдите ошибку в следующем фрагменте программы:

int numt=0;
#pragma omp parallel
{
    #pragma omp critical
       {
            numt=omp_get_num_threads();
           #pragma omp barrier
           #pragma omp flush (numt)
       }
}

директива flush не может быть использована внутри критической секции (конструкции critical)
в данном фрагменте программы ошибки нет
директива barrier не может быть использована внутри критической секции (конструкции critical)


Найдите ошибку в следующем фрагменте программы:

int numt=0;
#pragma omp parallel
{
      #pragma omp master
      {
          #pragma omp critical
          {
                numt=omp_get_num_threads();
          }
          #pragma omp barrier
       }
}

в данном фрагменте программы ошибки нет
директива critical не может быть использована внутри конструкции master;
директива barrier не может быть использована внутри конструкции master


Найдите ошибку в следующем фрагменте программы:

#include <math.h>
double x=1024.0;
int n=1024;
#pragma omp parallel
{
    #pragma omp atomic
    x+=sqrt(x);
    #pragma omp atomic
    n&=0177;
}

при вычислении выражения в правой части оператора присваивания, указанного в конструкции 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))


Найдите ошибку в следующем фрагменте программы:

#include <math.h>
double x=1024.0;
int n=1024;
#pragma omp parallel
{
    #pragma omp atomic
    x=sqrt(x);
    #pragma omp atomic
    n&=0177;
}

в данном фрагменте программы ошибки нет
оператор вида 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


Пусть следующая программа скомпилирована компилятором, поддерживающим вложенный параллелизм.

#include <stdio.h>
#include "omp.h"
int counter;
int main()
{
   counter=0;
   omp_set_nested(0);
  #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 по завершении выполнения этой программы:

1
2
4


Внимание !
Вопросы к тесту выложены исключительно в ознакомительных целях: количество вопросов может не совпадать с действительным, актуальность не поддерживается,- за решением теста Welcome to the cashier!

Пусть следующая программа скомпилирована компилятором, поддерживающим вложенный параллелизм.

#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 по завершении выполнения этой программы:

4
2
1


Пусть следующая программа скомпилирована компилятором, поддерживающим вложенный параллелизм.

#include <stdio.h>
#include "omp.h"
int counter;
int main()
{
   counter=0;
   omp_set_nested(0);
  #pragma omp parallel num_threads(2)
  {
      #pragma omp parallel num_threads(2)
      {
       #pragma omp atomic
        counter++;
      }
  }
  printf("Counter=%d\n",counter);
}

Определите значение переменной 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);
           }
     }
}

export OMP_SCHEDULE=”static”
export OMP_SCHEDULE=”static,10”
export OMP_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 schedule (runtime)
           for(int i=0; i<100;i++) {
                   sleep ((100-i)*msec);
           }
     }
}

export OMP_SCHEDULE=”static,10”
export OMP_SCHEDULE=”dynamic”
export OMP_SCHEDULE=”static”


Выберите наилучшую стратегию распределения витков цикла между нитями, которая для следующего фрагмента программы даст минимальное время выполнения:

#include <omp.h>
#include<stdio.h>
#include<stdlib.h>
#include <time.h>
#define msec 1000
int main (void){
     srand (time(NULL));
     omp_set_num_threads (8);
     #pragma omp parallel
     {
           #pragma omp for schedule (runtime)
           for(int i=0; i<100;i++) {
                   sleep (rand()*msec); 
           }
     }
}

export OMP_SCHEDULE=”static”
export OMP_SCHEDULE=”guided”
export OMP_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 schedule (runtime)
           for(int i=0; i<80;i++) {
                   sleep (msec);
           }
     }
}

export OMP_SCHEDULE=”static,10”
export OMP_SCHEDULE=”static,20”
export OMP_SCHEDULE=”static,15”


Выберите наилучшую стратегию распределения витков цикла между нитями, которая для следующего фрагмента программы даст минимальное время выполнения:

#include <omp.h>
#include <unistd.h>
#define msec 1000
int main (void){
     omp_set_num_threads (4);
     #pragma omp parallel
     {
           #pragma omp for schedule (runtime)
           for(int i=0; i<40;i++) {
                   sleep (msec);
           }
     }
}

export OMP_SCHEDULE=”dynamic,15”
export OMP_SCHEDULE=”static,10”
export OMP_SCHEDULE=”static,20”


Выберите наилучшую стратегию распределения витков цикла между нитями, которая для следующего фрагмента программы даст минимальное время выполнения:

#include <omp.h>
#include <unistd.h>
#define msec 1000
int main (void){
     omp_set_num_threads (4);
     #pragma omp parallel
     {
           #pragma omp for schedule (runtime)
           for(int i=0; i<60;i++) {
                   sleep (msec);
           }
     }
}

export OMP_SCHEDULE=”dynamic,15”
export OMP_SCHEDULE=”static,10”
export OMP_SCHEDULE=”static,20”


Выберите наиболее походящую оптимизацию, которая позволит сократить время выполнения следующего фрагмента программы:

#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, могут быть заданы при помощи:

клаузы SHARED
опции компилятора
директивы SHARABLE


Для выделения памяти для 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-программы, вычисляющей число Пи:

#include <mpi.h>
#include <omp.h>
#define num_steps 100000
void main (int argc, char *argv[])
{
    int numprocs, myid, mysteps;
    double pi, step, sum = 0.0 ;
    MPI_Init(&argc, &argv) ;
    MPI_Comm_Rank(MPI_COMM_WORLD, &myid) ;
    MPI_Comm_Size(MPI_COMM_WORLD, &numprocs) ;
    step = 1.0/(double) num_steps ;
    mysteps = num_steps/numprocs ;
    #pragma omp parallel shared(myid, mysteps, step) reduction(+:sum)
   {
       #pragma omp for
       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();
}

в данном фрагменте программы ошибки нет
функции MPI_Init, MPI_Comm_Rank, MPI_Comm_Size должны вызываться из параллельной области
до завершения выполнения редукционного OpenMP-оператора выполняется вызов функции MPI_Reduce


Найдите ошибку в следующем фрагменте MPI/OpenMP-программы, вычисляющей число Пи:

#include <mpi.h>
#include <omp.h>
#define num_steps 100000
void 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();
}

все обращения к MPI-функциям в параллельной области должны выполняться одной нитью (например, внутри конструкции single)
в данном фрагменте программы ошибки нет
переменные numprocs, myid, mysteps должны быть объявлены как private(numprocs, myid, mysteps)


Найдите ошибку в следующем фрагменте MPI/OpenMP-программы, вычисляющей число Пи:

#include <mpi.h>
#include <omp.h>
#define num_steps 100000
void main (int argc, char *argv[])
{
    int numprocs, myid, mysteps;
    double pi, step, sum = 0.0 ;
    MPI_Init(&argc, &argv) ;
    MPI_Comm_Rank(MPI_COMM_WORLD, &myid) ;
    MPI_Comm_Size(MPI_COMM_WORLD, &numprocs) ;
    step = 1.0/(double) num_steps ;
    mysteps = num_steps/numprocs ;
    #pragma omp parallel shared(myid, mysteps, step)
   {
       #pragma omp for reduction(+:sum)
       for (int i=myid*mysteps; i<(myid+1)*mysteps ; i++){
           double x = (i+0.5)*step;
           sum += 4.0 /(1.0+x*x);
       }
       sum *= step ;
   }
   MPI_Reduce(&sum, &pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
   MPI_Finalize();
}

функции 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 По Skype: molodoyberkut
telegram По Telegram: @MolodoyBerkut
icq По ICQ: 657089516

Или через форму обратной связи на нашем сайте
Пока сочиняется...
4.png