MPI Sendrecv с MPI любого источника


Можно ли сделать обмен MPI_Sendrecv, когда одна сторона не знает ранга другой? Если нет, то как лучше всего это сделать (моя следующая догадка будет просто парой посылок и рекв)?

Например, в C, если я хочу обменять целые числа между рангом 0 и каким-то другим рангом, будет ли этот тип вещей работать?:

MPI_Status stat;
if(rank){
  int someval = 0;
  MPI_Sendrecv(&someval, 1, MPI_INT, 0, 1, &recvbuf, 1, MPI_INT, 0, MPI_ANY_TAG, MPI_COMM_WORLD, &stat);
}else{
  int someotherval = 1;
  MPI_Sendrecv(&someotherval, 1, MPI_INT, MPI_ANY_SOURCE, someotherval, &recvbuf, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &stat);
}

Править: Похоже, это невозможно. Я сделал следующее как своего рода обертку, чтобы добавить функциональность, которая мне нужна.

void slave_sendrecv(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
    int dest, int sendtag, void *recvbuf, int recvcount,
    MPI_Datatype recvtype, int source, int recvtag, MPI_Status *status){

    MPI_Send(sendbuf, sendcount, sendtype, dest, sendtag, MPI_COMM_WORLD);
    MPI_Recv(recvbuf, recvcount, recvtype, source, recvtag, MPI_COMM_WORLD, status);
}

void anon_sendrecv(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
    int sendtag, void *recvbuf, int recvcount,
    MPI_Datatype recvtype, int recvtag, MPI_Status *status){

    int anon_rank;
    MPI_Recv(recvbuf, recvcount, recvtype, MPI_ANY_SOURCE, recvtag, MPI_COMM_WORLD, status);
    anon_rank = status -> MPI_SOURCE;
    MPI_Send(sendbuf, sendcount, sendtype, anon_rank, sendtag, MPI_COMM_WORLD);
}

Правка 2: Исходя из ответа Патрика, похоже, что функция slave_sendrecv выше не нужна, вы можете просто использовать обычный MPI_Sendrecv на конце, который знает, кому он посылает.

1 4

1 ответ:

Короткий ответ: Нет.

Стандарт не позволяет использовать MPI_ANY_SOURCE в качестве ранга назначения dest в любой процедуре отправки. Это имеет смысл, так как вы не можете отправить сообщение, не зная адресата.

Стандарт, однако, позволяет вам соединять MPI_Sendrecv с регулярными MPI_Send/MPI_Recv:

Сообщение, отправленное операцией отправки-приема, может быть получено обычной операцией приема. или зондируется операцией зондирования; операция отправки-приема может принимать сообщение отправлено с помощью обычной операции отправки.

В вашем случае процесс 0 должен будет сначала получить, а затем ответить:

MPI_Status stat;
if(rank){
  int someval = 0;
  MPI_Sendrecv(&someval, 1, MPI_INT, 0, 1, &recvbuf, 1, MPI_INT, 0, MPI_ANY_TAG, MPI_COMM_WORLD, &stat);
}else{
  int someotherval = 1;
  MPI_Recv(&recvbuf, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &stat);
  // answer to process `stat.MPI_SOURCE` using `someotherval` as tag
  MPI_Send(&someotherval, 1, MPI_INT, stat.MPI_SOURCE, someotherval, MPI_COMM_WORLD);
}