MPI从许多流程接收

时间:2013-12-16 03:49:55

标签: mpi

这是我的代码:

 if (rank != 0) {

        // trimitem numarul de pixeli prelucrati
        rc = MPI_Send(&pixeli, 1, MPI_INT, 0, tag, MPI_COMM_WORLD);

        // trimitem coordonatele de unde am inceput prelucrarea 
        rc = MPI_Send(&first_line, 1, MPI_INT, 0, tag, MPI_COMM_WORLD);
        rc = MPI_Send(&first_col, 1, MPI_INT, 0, tag, MPI_COMM_WORLD);

        for (i = 0; i < pixeli; i++) {
            rc = MPI_Send(&results[i], 1, MPI_INT, 0, tag, MPI_COMM_WORLD);         
        }       
}
else {

        for (i = 1; i < numtasks; i++) {
            rc = MPI_Recv(&received_pixels, 1, MPI_INT, i, tag, MPI_COMM_WORLD, &Stat);
            results_recv = (int*) calloc (received_pixels, sizeof(int));

            rc = MPI_Recv(&start_line_recv, 1, MPI_INT, i, tag, MPI_COMM_WORLD, &Stat);
            rc = MPI_Recv(&start_col_recv, 1, MPI_INT, i, tag, MPI_COMM_WORLD, &Stat);

            for (j = 0; j < received_pixels; j++) {
                rc = MPI_Recv(&results_recv[j], 1, MPI_INT, i, tag, MPI_COMM_WORLD, &Stat);                 
            }
            free(results_recv);
}

如果我用2个程序运行它就可以了,因为一个会发送而另一个会接收。

如果我通过4个程序运行此程序,则会收到以下错误消息:

Fatal error in MPI_Recv: Other MPI error, error stack:
MPI_Recv(186)...........................: MPI_Recv(buf=0xbff05324, count=1, MPI_INT, src=1, tag=1, MPI_COMM_WORLD, status=0xbff053ec) failed
MPIDI_CH3I_Progress(461)................: 
MPID_nem_handle_pkt(636)................: 
MPIDI_CH3_PktHandler_EagerShortSend(308): Failed to allocate memory for an unexpected message. 261895 unexpected messages queued.

我该怎么做才能解决这个问题?

2 个答案:

答案 0 :(得分:1)

这些行:

for (i = 0; i < pixeli; i++) {
    rc = MPI_Send(&results[i], 1, MPI_INT, 0, tag, MPI_COMM_WORLD);         
}       

并且相应的MPI_Recvs看起来基本上是重新实现MPI_Gather。使用大小设置为pixeli而不是1的MPI_Gather调用可以允许实现更有效地调度发送和接收,但更重要的是,它可能会大大减少所需的发送/接收对的总数。完成整批沟通。您可以通过删除for循环并执行以下操作来执行类似操作:

rc = MPI_Send(&results[i], pixeli, MPI_INT, 0, tag, MPI_COMM_WORLD);   

但同样,使用内置的MPI_Gather将是首选的方式。

答案 1 :(得分:0)

最简单的答案是告诉您使用同步通信,即MPI_Ssend()而不是MPI_Send()。

麻烦的是你发送了很多缓冲的消息(我猜......但是我虽然MPI_Send()阻塞了......)。内存消耗一直持续到失败...同步消息避免缓冲,但它不会减少消息数量,而且可能会更慢。

您可以通过一次发送多个像素来减少消息数量并提高性能:MPI_Send()或MPI_Recv()的第二个参数... 发送3 int [pixeli,first_line,first_col]的缓冲区也会限制通信。

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include "mpi.h"

int main(int argc,char *argv[])
{
    int rank, size;


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

    int pixeli=1000000;
    int received_pixels;
    int first_line,first_col,start_line_recv,start_col_recv;
    int tag=0;
    int results[pixeli];
    int i,j;
    for(i=0;i<pixeli;i++){
        results[i]=rank*pixeli+i;
    }
    int* results_recv;
    int rc;
    MPI_Status Stat;
    if (rank != 0) {

        // trimitem numarul de pixeli prelucrati
        rc = MPI_Ssend(&pixeli, 1, MPI_INT, 0, tag, MPI_COMM_WORLD);

        // trimitem coordonatele de unde am inceput prelucrarea 
        rc = MPI_Ssend(&first_line, 1, MPI_INT, 0, tag, MPI_COMM_WORLD);
        rc = MPI_Ssend(&first_col, 1, MPI_INT, 0, tag, MPI_COMM_WORLD);

        MPI_Send(&results[0], pixeli, MPI_INT, 0, tag, MPI_COMM_WORLD); 
        //for (i = 0; i < pixeli; i++) {
        //    rc = MPI_Send(&results[i], 1, MPI_INT, 0, tag, MPI_COMM_WORLD);         
        //}       
    }
    else {

        for (i = 1; i < size; i++) {
            rc = MPI_Recv(&received_pixels, 1, MPI_INT, i, tag, MPI_COMM_WORLD, &Stat);
            results_recv = (int*) calloc (received_pixels, sizeof(int));

            rc = MPI_Recv(&start_line_recv, 1, MPI_INT, i, tag, MPI_COMM_WORLD, &Stat);
            rc = MPI_Recv(&start_col_recv, 1, MPI_INT, i, tag, MPI_COMM_WORLD, &Stat);

            MPI_Recv(&results_recv[0], received_pixels, MPI_INT, i, tag, MPI_COMM_WORLD, &Stat); 

            //for (j = 0; j < received_pixels; j++) {
            //    rc = MPI_Recv(&results_recv[j], 1, MPI_INT, i, tag, MPI_COMM_WORLD, &Stat); 
            //printf("proc %d %d\n",rank,results_recv[j]);                
            //}
            free(results_recv);
        }
    }


    MPI_Finalize();
    return 0;
}

再见,

弗朗西斯