MPI - неограниченная отправка и получение

Если я использую блокировку отправки и получения (MPI_send(), MPI_recv()), как сделать эти две операции неопределенными? Типа они повторяются снова и снова?

Образец кода:

MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD,&numtasks);
MPI_Comm_rank (MPI_COMM_WORLD,&rank);
if(rank==0){
  rc=MPI_Send(msg,1,MPI_CHAR,1,1,MPI_COMM_WORLD);
  rc=MPI_Recv(msg,1,MPI_CHAR,1,1,MPI_COMM_WORLD,&status);
}else{
  rc=MPI_Recv(msg,1,MPI_CHAR,0,0,MPI_COMM_WORLD,&status);
  rc=MPI_Send(msg,1,MPI_CHAR,0,0,MPI_COMM_WORLD);

}

Я пытался поставить перед if(rank==0) -> while(1), и это сработало, но я вижу, что есть несколько отправок, затем несколько приемов, и я хочу, чтобы это было так - отправить (0), получить (1), отправить (1), получить (0).


c mpi
person Waypoint    schedule 19.02.2011    source источник


Ответы (2)


Вы можете легко закодировать кольцо операций отправки-получения, используя MPI_Sendrecv:

int MPI_Sendrecv(void *sendbuf, int sendcount, MPI_Datatype sendtype,
    int dest, int sendtag, void *recvbuf, int recvcount,
    MPI_Datatype recvtype, int source, int recvtag,
    MPI_Comm comm, MPI_Status *status)

Как видите, это всего лишь сокращенная версия MPI_Send и MPI_Recv, но она удобна, когда всему процессу нужно либо отправить и получить что-то.

Следующий код работает для любого количества процессов (вы можете адаптировать его под свои нужды):

ОБНОВЛЕНИЕ КОДА №1 (с использованием MPI_Sendrecv)

#include <stdio.h>
#include <unistd.h>
#include <mpi.h>

int main (int argc, char *argv[])
{
    int size, rank, value, next, prev, sendval, recval;
    double t0, t;

    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    value = 5;

    if (size > 1)
    {
        next = (rank + 1)% size;
        prev = (size+rank - 1)% size;

        sendval = value + rank;

        for (;;) 
        {
            t0 = MPI_Wtime();
            MPI_Sendrecv(&sendval, 1, MPI_INT, next, 1, &recval, 1, MPI_INT, prev, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
            t = MPI_Wtime();

            fprintf(stdout, "[%d of %d]: Sended %d to process %d, Received %d from process %d (MPI_SendRecv Time: %f)\n",rank, size-1, sendval, next, recval, prev, (t - t0));
        }

    }

    MPI_Finalize();
    return 0;
}

ОБНОВЛЕНИЕ КОДА №2 (с использованием отдельных MPI_Send/MPI_Recv)

#include <stdio.h>
#include <unistd.h>
#include <mpi.h>

int main (int argc, char *argv[])
{
    int size, rank, value, next, prev, sendval, recval;
    double s0, s, r, r0;

    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    value = 5;

    if (size > 1)
    {
        next = (rank + 1)% size;
        prev = (size+rank - 1)% size;

        sendval = value + rank;

        for (;;) 
        {
            s0 = MPI_Wtime();
            MPI_Send(&sendval, 1, MPI_INT, next, 1, MPI_COMM_WORLD);
            s = MPI_Wtime();
            fprintf(stdout, "[%d of %d]: Sended %d to process %d (MPI_Send Time: %f)\n", rank, size-1, sendval, next, s-s0);

            r0 = MPI_Wtime();
            MPI_Recv(&recval, 1, MPI_INT, prev, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
            r = MPI_Wtime();
            fprintf(stdout, "[%d of %d]: Received %d from process %d (MPI_Recv Time: %f)\n", rank, size-1, recval, prev, r-r0);

        }

    }
        MPI_Finalize();
    return 0;
}

Пример запуска

mpicc -o sendrecv sendrecv.c
mpirun -n 2 sendrecv

[0 of 1]: Sended 5 to process 1, Received 6 from process 1 (MPI_SendRecv Time: 0.000121)
[1 of 1]: Sended 6 to process 0, Received 5 from process 0 (MPI_SendRecv Time: 0.000068)
...
person Gianluca Bargelli    schedule 19.02.2011
comment
Спасибо. Я не понимаю только это: if (argc!= 2) value = 5; иначе значение = atoi(argv[1]); Я также измеряю время, необходимое для передачи сообщения от одного процесса к другому, как вы думаете, возможно ли это с помощью этого гибрида, MPI_SendRecv? - person Waypoint; 19.02.2011
comment
А знаете ли вы, есть ли вариант MPI_Send и MPI_recv в качестве сигнальных функций? - person Waypoint; 19.02.2011
comment
Эта часть не важна: она только принимает значение из командной строки (например, mpirun 66 -n 2 устанавливает value в 66) или устанавливает value в значение по умолчанию 5. Время работает нормально, смотрите мое обновление. - person Gianluca Bargelli; 19.02.2011
comment
@Hmyzak Что вы подразумеваете под отдельными функциями? Вы хотите такое же кодирование с использованием отдельных MPI_Send и MPI_Recv вместо использования MPI_SendRecv? - person Gianluca Bargelli; 19.02.2011
comment
Да, я знаю, что это более подходящее решение, но я бы хотел, чтобы оно было написано в MPI_Send и MPI_Recv, если у вас есть время. Я очень ценю вашу помощь! спасибо - person Waypoint; 19.02.2011

Невозможно дать точный ответ на этот вопрос, не видя хотя бы основной макет вашего кода. Как правило, операции отправки и получения следует помещать в бесконечный цикл. Или, если вам не хватает оптимальных затрат на связь (или вы просто хотите приключений), вы можете использовать постоянная отправка и получение.

person suszterpatt    schedule 19.02.2011