В функции update
каждая задача должна обменять конечные точки
(граничные значения) с ее левым и правым соседями до обновления ее амплитуд вдоль волны.
Каждая задача указывает на npoints
точек на волне. Атрибуты для
этих точек запоминаются от values[1]
до values[npoints]
,
где values
есть действительный массив двойной точности.
Величины values[0]
и values[npoints+1]
будут содержать
граничные значения из соседних задач.
Итак, задача, обменивающая конечные точки с ее левым соседом отправляет ее значение
values[1]
крайней левой точки и получает некое граничное значение в
values[0]
. Первое
указывает индекс первой точки,
управляемой этой задачей в полной (нераспределенной) волне. Задача, которая владеет
точкой 1
на волне не имеет левого соседа и не будет призводить
этот обмен.
if (first != 1) { MPI_Isend(&values[1], 1, MPI_DOUBLE, left, E_RtoL, MPI_COMM_WORLD, &Prequest[0]); MPI_Irecv(&values[0], 1, MPI_DOUBLE, left, E_LtoR, MPI_COMM_WORLD, &Prequest[1]); }
Теги сообщения E_RtoL
и E_LtoR
предлагают
направление, в котором сообщение передается (справа-налево или слева-направо).
Коммуникатор MPI_COMM_WORLD
. Так как этот коммуникатор является неблокирующим, то
возвращается запрос Prequest[n]
, который будет использован для проверки статуса коммуникации.
Обмен с левым соседом сопровождается обменом с правым соседом
Задача, которая владеет абсолютно последней точкой (индекс
tpoints
) на волне не имеет правого соседа и не будет делать
этот обмен.
if (first + npoints -1 != tpoints) { MPI_Isend(&values[npoints], 1, MPI_DOUBLE, right, E_LtoR, MPI_COMM_WORLD, &Prequest[2]); MPI_Irecv(&values[npoints+1], 1, MPI_DOUBLE, right, E_RtoL, MPI_COMM_WORLD, &Prequest[3]); }
Связи затем блокируют, поскольку последующие вычисления требуют конечных точек, которые передаются:
MPI_Waitall(4, Prequest, Pstatus);