C中的MPI。在 I_send 和 Irecv 中使用循环

MPI in c. Using Loop in I_send and Irecv

我在 c 中有一个简单的 MPI 代码,我试图在其中学习如何在进程之间进行通信。这是代码:

已编辑代码 -> 问题已解决

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <mpi.h>
#include <unistd.h>

#define ONE 0
#define TWO 1

int main(int argc, char * argv[])
{
    int dimension = 5,t;
    float ** matrix;
    float * mat1;
    float * mat2,*mat;
    int i,j,numNeighbor, processReceived,rank,size,retval;
    int k = 0;
    retval = MPI_Init(&argc, &argv);

    MPI_Request sendRequest[2], recvRequest[2];
    MPI_Status status[2];//osa kai auta pou perimenw apo to receive
    MPI_Datatype row;

    MPI_Type_vector(dimension, 1, dimension, MPI_FLOAT, &row);
    MPI_Type_commit(&row);

    if(retval != MPI_SUCCESS)
    {
        MPI_Abort(MPI_COMM_WORLD, retval);
        return EXIT_FAILURE;
    }
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    mat1 = malloc(dimension*sizeof(float));
    mat2 = malloc(dimension*sizeof(float));
    matrix = malloc(dimension*sizeof(float*));
    mat = malloc(dimension*dimension*sizeof(float));

    for(i=0; i<dimension; i++)
    {
        matrix[i] = mat + i*dimension;
    }

    printf("MATRIX OF RANK %d\n", rank);
    for(i=0; i<dimension; i++)
    {
        for(j=0; j<dimension; j++)
        {
            matrix[i][j] = (float)(rank+1)*(i*2+j);
            printf("%2.1f ",matrix[i][j]);
        }
        printf("\n");
    }
    printf("\n");

    for(t=0; t<10; t++) //<----------------------PROBLEM WITH THIS LOOP
    {
        MPI_Isend(&(matrix[0][0]), 1, row, 1-rank, rank, MPI_COMM_WORLD, sendRequest + ONE);
        MPI_Isend(&(matrix[0][0]), dimension, MPI_FLOAT, 1-rank, rank, MPI_COMM_WORLD, sendRequest + TWO);

        MPI_Irecv(mat1,dimension, MPI_FLOAT, 1-rank, 1-rank, MPI_COMM_WORLD, recvRequest + ONE);
        MPI_Irecv(mat2,dimension, MPI_FLOAT, 1-rank, 1-rank, MPI_COMM_WORLD, recvRequest + TWO);


        for(i=0; i<2; i++)
        {
            MPI_Waitany(2,recvRequest, &processReceived, status);
            printf("Process Received : %d of rank : %d\n", processReceived,rank);
            if(processReceived == ONE)
            {
                printf("%d ",rank);
                for(j=0; j<dimension; j++)  printf("# %6.1f ",mat1[j]);
                printf("\n");
            }

            if(processReceived == TWO)
            {
                printf("%d ",rank);
                for(j=0; j<dimension; j++)  printf("@ %6.1f ",mat2[j]);
                printf("\n");
            }
        }

        MPI_Waitall(2, sendRequest, status);
        MPI_Type_free(&row);            
    }
    free(mat1);
    free(mat2);
    free(mat);
    free(matrix);

    MPI_Finalize();
    return 0;
}

我执行这个程序时没有带大箭头的循环for(t=0; t<10; t++),一切正常。当我使用循环时,它第一次运行良好,然后出现此错误消息:

Fatal error in PMPI_Isend: Invalid datatype, error stack: PMPI_Isend(149): MPI_Isend(buf=(nil), count=1, MPI_DATATYPE_NULL, dest=1, tag=0, MPI_COMM_WORLD, request=0xbf8764b8) failed PMPI_Isend(102): Datatype for argument datatype is a null datatype Fatal error in PMPI_Isend: Invalid datatype, error stack: PMPI_Isend(149): MPI_Isend(buf=(nil), count=1, MPI_DATATYPE_NULL, dest=0, tag=1, MPI_COMM_WORLD, request=0xbf8e8e18) failed PMPI_Isend(102): Datatype for argument datatype is a null datatype

我假设我有办法重新初始化我的发送、接收和状态。我的假设正确吗?如果是,我该如何解决?如果没有,你能看出什么问题吗?

这是完整的程序,大家可以自己执行

mpiexec -n 2 ./name_exe

只运行2个进程!!!

在您的 for 循环中,您使用 MPI_Type_free(&row);,之后 row 不再是已注册的 MPI_Type,因此您的第一个 MPI_Isend 正在使用无效的数据类型(如错误提示的那样)。将此行移到 for 循环之外。您还释放了 matrix,这意味着在第二次迭代中,您正在尝试发送您不再拥有的内存,这应该会产生段错误。