Вычислительный центр им. А.А. Дородницына РАН    

Раздел виртуального курса
Параллельное программирование в интерфейсе MPI


Вопросы по MPI коллективному обмену сообщениями I

  1. Утверждение, что функция коллективной коммуникации является локально блокирующей, означает, что следующее предложение в программе на отдельном узле не исполнится пока

A. все процессы в данном задании не завершили это предложение
B. все процессы названного коммуникатора не завершили это предложение
C. локальный процесс не завершил это предложение
D. корневой процесс не завершил это предложение.

  1. Корневой процесс в вызове MPI_Bcast, как это реализовано в MPICH, исполняет следующее предложение, после того как:

A. все процессы в данном задании подтвердили получение данных
B. все процессы названного коммуникатора подтвердили получение данных
C. все процессы названного коммуникатора достигли этого вызова
D. все данные поставлены в очередь на отправку, даже если некоторые процессы могли еще не достичь этого вызова.

  1. Отметьте все, что подходит: какой из следующих фрагментов SPMD-кода на С ошибочен? Предполагаем, что коды запускаются не менее чем на 2-х процессорах, и что все строки кода, существенные для ответа на вопрос, показаны.

ierror = MPI_Comm_rank(MPI_COMM_WORLD, rank)

═══════if (rank == 0) {ierror = MPI_Bcast(buf, 1, MPI_INTEGER, 0, MPI_COMM_WORLD)} else {// нет вызова MPI_Bcast}

rbuf = 1000;

══════ do while (rbuf .gt. 1)

══════ // расчет sbuf не показан

══════ ierror = MPI_Reduce (sbuf, rbuf, 1, MPI_REAL, MPI_MAX, root, MPI_COMM_WORLD);

══════ end do

ierror = MPI_Reduce(buf, buf, 1, MPI_INTEGER, MPI_SUM, 0, MPI_COMM_WORLD);

ierror = MPI_Scatter(sbuf, 5, MPI_REAL, rbuf, 10, MPI_REAL, 0, MPI_COMM_WORLD);

ierror = MPI_Comm_size (MPI_COMM_WORLD, size);

══════ ierror = MPI_Gather(sbuf, 5, MPI_REAL, rbuf, 5*size, MPI_REAL, 0, MPI_COMM_WORLD);

  1. Отметьте все, что подходит. Какое из утверждений наиболее безопасно, после того как вызов MPI_ALLGATHER возвращает управление?

Отправляющий буфер может быть безопасно переписан
Получающий буфер может быть благополучно использован
Все участвующие процессы возвратили управление из вызова

  1. Что не всегда верно при вызове MPI_Scatter?

A. каждый процесс должен получить столько элементов, сколько отправил корневой процесс
B. каждый процесс должен получить столько байт, сколько отправил корневой процесс
C. каждый процесс в названном коммуникаторе должен вызвать MPI_Scatter, определяя тот же самый корневой процесс
D. каждый процесс должен определить получающийся буфер, размер которого равен, по крайней мере, 1/N всех данных, отправленных корневым процессом

  1. Что из перечисленного ниже не всегда верно при вызове MPI_Gather?

A. получающий буфер на корневом узле имеет размер более чем в N раз больше размера буферов на других узлах
B. буфер на корневом узле равен размеру буферов на узлах отправки
C. один из некорневых процессов переходит к своему сообщению прежде, чем это делает корневой процесс
D. корневой процесс переходит к следующему сообщению прежде, чем один из некорневых процессов достигает его вызова MPI_Gather

  1. Что из следующего недопустимо? Один и тот же процесс в коммуникаторе вызывает MPI_Gather с различным

A. буфером получателя
B. буфером отправителя
C. count и datatype, при этом произведение числа и размера типа данных то же самое, как у других процессов
D. корневым рангом

  1. Что недопустимо для вызова MPI_Reduce, но приемлемо для MPI_Gather? Один процесс определяет различный

A. буфер получателя
B. буфер отправителя
C. count и datatype, при этом произведение числа и размера типа данных то же самое, как у других процессов
D. корневой ранг

  1. В "Основах MPI программирования" было введено понятие коммуникатора, и обсуждался вопрос, каким образом различные процессы могли иметь различные разряды в различных коммуникаторах. Процессы имеют следующие разряды в двух коммуникаторах:

Ранг в коммуникаторе

 

процесс 1

процесс 2

процесс 3

процесс 4

comm1

0

1

2

3

comm2

3

2

1

0

      После следующего фрагмента SPMD-кода на С:  

     MPI_Comm_rank (comm1, &rank1);  
     MPI_Gather(&rank1, 1, MPI_INT, &rbuf, 1, MPI_INT, 0, comm1);

     рассмотрим вопрос: Что содержит массив rbuf на корневом процессе?

     {0,1,2,3}
     {3,2,1,0}

  1. Для коммуникаторов, описанных в вопросе 9, укажите, что содержит rbuf на корневом процессе после фрагмента следующего SPMD C-кода?

MPI_Comm_rank (comm2, &rank2);
MPI_Gather(&rank2, 1, MPI_INT, &rbuf, 1, MPI_INT, 0, comm2);

{0,1,2,3}
{3,2,1,0}

11.  Может ли тот же самый процесс быть корневым для вызовов MPI_Gather в вопросах 9 и 10?

да
нет

  1. Некий пользователь вызывает MPI_Reduce с оператором MPI_BOR. Входной вектор на каждой из четырех задач имеет целые числа от 1 до 4 по порядку. Выходным вектором будут

A. целые от 1 до 4 по порядку
B. целые от 1 до 4 в обратном порядке
C. все 0-ые
D. все 7-ки

  1. Некий пользователь снова вызывает MPI_Reduce с оператором MPI_BOR. В это время входной вектор на каждой из четырех задач имеет целые числа от 1 до 4, но они смещены по кругу, так что список начинается с 1 на задаче 0, 2 на задаче 1, и т.д. Выходным вектором будут

A. целые от 1 до 4 по порядку
B. целые от 1 до 4 в обратном порядке
C. все 0-ые
D. все 7-ки

  1. Как много шагов будет в наиболее эффективной реализации функции MPI_Allreduce?

A. 1
B. log2(N)
C. 2*log2(N)
D. N

  1. Код был организован таким образом, чтобы имелся хороший баланс загрузки. Однако, процессы подвержены частым прерываниям, которые заставляют их временно выходить из синхронизации на существенное время. Если задаче 0 требуется распределить большое количество данных (> порогового значения) от буфера во время итерации, то какая стратегия будем иметь наименьшую синхронизационную накладку?

A. MPI_Bcast
B. MPI_Send в цикле на задаче 0
C. MPI_Isend в цикле на задаче 0, сопровожденная вызовом MPI_Waitall непосредственно после цикла
D. все стратегии примерно одинаковы







ФИО (требуется для получения оценки):