如果缓冲区大小超过256,则第二个MPI_Send挂起

时间:2011-03-01 07:28:08

标签: c mpi

int n, j, i, i2, i3, rank, size,  rowChunk,  **cells, **cellChunk;


MPI_Status status;

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


if(!rank){
    printf("\nEnter board size:\n");
    fflush(stdout);
    scanf("%d", &n);

    printf("\nEnter the total iterations to play:\n");
    fflush(stdout);
    scanf("%d", &j);


    srand(3);

    rowChunk = n/size; //how many rows each process will get

    for(i=1; i<size; i++){

        MPI_Send(&n,1, MPI_INT, i, 0, MPI_COMM_WORLD);
        MPI_Send(&j,1, MPI_INT, i, 7, MPI_COMM_WORLD);
    }

    cells = (int**) malloc(n*sizeof(int*));    //create main 2D array

    for(i=0; i<n; i++){

        cells[i] = (int*) malloc(n*sizeof(int));
    }

    for(i=0; i<n; i++){
        for(i2=0; i2<n; i2++){           //fill array with random data

            cells[i][i2] = rand() % 2;
        }
    }       

    for(i=1; i<size; i++){        //send blocks of rows to each process
        for(i2=0; i2<rowChunk; i2++){ //this works for all n

            MPI_Send(cells[i2+(rowChunk*i)], n, MPI_INT, i, i2, MPI_COMM_WORLD);
        }
    }

    cellChunk = (int**) malloc(rowChunk*sizeof(int*));

    for(i=0; i<rowChunk; i++){    //declare 2D array for process zero's array chunk

        cellChunk[i] = (int*) malloc(n*sizeof(int));
    }

    for(i=0; i<rowChunk; i++){   //give process zero it's proper chunk of the array
        for(i2=0; i2<n; i2++){

            cellChunk[i][i2] = cells[i][i2];
        }
    }


    for(i3=1; i3<=j; i3++){

        MPI_Send(cellChunk[0], n, MPI_INT, size-1,1,MPI_COMM_WORLD); //Hangs here if n >256
        MPI_Send(cellChunk[rowChunk-1], n, MPI_INT, 1,2,MPI_COMM_WORLD); //also hangs if n > 256

            ... //Leaving out code that works

如果n(数组大小)小于或等于256,则此代码可以正常工作。任何更大的代码都会在第一个MPI_Send上挂起。此外,当将阵列行块发送到其他进程时(第一MPI_Send),其他进程完美地接收它们的数据,即使n> 1。 256.如果缓冲区大小超过256,会导致此MPI_Send挂起的原因是什么?

3 个答案:

答案 0 :(得分:6)

您永远不会收到任何消息,因此代码将填充本地MPI缓冲区空间,然后等待运行MPI_Recv(或类似)调用的死锁。您需要插入接收操作,以便实际在接收器上发送和处理您的消息。

答案 1 :(得分:1)

MPI_Send是阻止通话。标准要求MPI_Send可以在安全地修改消息缓冲区之前返回控制。或者,MPI_Send可以等待直到MPI_Recv开始或完成之后的某个时间。

如果消息是&lt; 256 count(使用MPI_INT数据类型,这将是1k消息),您正在使用的MPI的实现可能正在进行“急切”消息进展。消息被复制到另一个缓冲区,并且“提前”返回控制。对于大(r)消息,MPI_Send调用直到(至少)执行匹配的MPI_Recv调用才返回。

如果您发布完整的复制品,您可能会得到更好的答案。

答案 2 :(得分:0)

MPI_Send“可能会阻止,直到收到消息。”,因此很可能未达到匹配的接收。您需要确保MPI_Recv按正确的顺序排列。由于您没有发布您的接收部分,因此无法详细说明。

您可以重新构建应用程序,以确保匹配的接收顺序。您也可以方便地使用合并的MPI_Sendrecv或非阻止MPI_IsendMPI_IrecvMPI_Wait