Операция MPI RMA: порядок между MPI_Win_free и локальной загрузкой
Я пытаюсь сделать простой тест на работу RMA MPI с помощью MPI_Win_lock
а также MPI_Win_unlock
, Программа просто позволила процессу 0 обновить целочисленное значение в процессе 1 и отобразить его.
Приведенная ниже программа работает правильно (по крайней мере, результат мне кажется правильным):
#include "mpi.h"
#include "stdio.h"
#define root 0
int main(int argc, char *argv[])
{
int myrank, nprocs;
int send, recv, err;
MPI_Win nwin;
int *st;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
MPI_Alloc_mem(1*sizeof(int), MPI_INFO_NULL, &st);
st[0] = 0;
if (myrank != root) {
MPI_Win_create(st, 1*sizeof(int), sizeof(int), MPI_INFO_NULL, MPI_COMM_WORLD, &nwin);
}
else {
MPI_Win_create(NULL, 0, sizeof(int), MPI_INFO_NULL, MPI_COMM_WORLD, &nwin);
}
if (myrank == root) {
st[0] = 1;
MPI_Win_lock(MPI_LOCK_EXCLUSIVE, 1, 0, nwin);
MPI_Put(st, 1, MPI_INT, 1, 0, 1, MPI_INT, nwin);
MPI_Win_unlock(1, nwin);
MPI_Win_free(&nwin);
}
else { // rank 1
MPI_Win_free(&nwin);
printf("Rank %d, st = %d\n", myrank, st[0]);
}
MPI_Free_mem(st);
MPI_Finalize();
return 0;
}
Вывод, который я получил Rank 1, st = 1
, Но любопытно, если я переключу строки в блоке else для ранга 1 на
else { // rank 1
printf("Rank %d, st = %d\n", myrank, st[0]);
MPI_Win_free(&nwin);
}
Выход Rank 1, st = 0
,
Я не могу выяснить причину этого и почему мне нужно поставить MPI_Win_free
после загрузки данных изначально мне нужно поместить все вещи в цикл while и присвоить рангу 0, чтобы определить, когда остановить цикл. Когда условие выполнено, я пытаюсь дать рангу 0 обновить флаг (st) в ранге 1. Я пытаюсь поместить MPI_Win_free вне цикла while, чтобы окно было освобождено только после цикла. Теперь кажется, что я не могу этого сделать и мне нужно создавать и освобождать окно каждый раз в цикле?
1 ответ
Честно говоря, MPI RMA - не моя специальность, но я попробую:
Проблема в том, что вы попали в состояние гонки. Когда вы делаете MPI_PUT
Во время этой операции данные от ранга 0 до ранга 1 отправляются в буфер в какой-то момент в будущем. Вы не имеете никакого контроля над этим с точки зрения ранга 0.
Одна сторона ранга 1, вы ничего не делаете для завершения операции. Я знаю, что RMA (или односторонние операции) звучат так, как будто они не требуют какого-либо вмешательства на целевой стороне, но они требуют немного. Когда вы используете односторонние операции, на принимающей стороне должно быть что-то, что также синхронизирует данные. В этом случае вы пытаетесь использовать операции ввода / вывода MPI в сочетании с операциями сохранения нагрузки без MPI. Это ошибочно и приводит к состоянию гонки, которое вы видите. Когда вы переключаете MPI_WIN_FREE
чтобы быть первым, вы выполняете все незавершенные операции, чтобы ваши данные были правильными.
Вы можете узнать больше о пассивной синхронизации целей (что вы здесь делаете) с этим вопросом: MPI с C: пассивной синхронизацией RMA.