用C语言生成数组求和的MPI重叠

用C语言生成数组求和的MPI重叠,c,parallel-processing,mpi,C,Parallel Processing,Mpi,我在学习MPI编程时遇到了以下问题。我使用相同的“已回答”示例来计算每一行的总和,从而增加重叠。这是一个2乘3的数组,我想在这些数组元素达到MPI\u Irecv时计算总和。我已经在MPI\u Irecv和MPI\u Wait之间编辑了代码,以便在数组元素可用时立即开始计算。但是当我运行代码时,我调用的MPI\u Test似乎工作不正常。如果你能举个例子来解决这个问题,我会非常感激 使用mpirun-np3测试0th-rank将生成数组元素。第1级和第2级将计算总和 #include "mpi.

我在学习MPI编程时遇到了以下问题。我使用相同的“已回答”示例来计算每一行的总和,从而增加重叠。这是一个2乘3的数组,我想在这些数组元素达到
MPI\u Irecv
时计算总和。我已经在
MPI\u Irecv
MPI\u Wait
之间编辑了代码,以便在数组元素可用时立即开始计算。但是当我运行代码时,我调用的
MPI\u Test
似乎工作不正常。如果你能举个例子来解决这个问题,我会非常感激

使用
mpirun-np3测试
0th-rank将生成数组元素。第1级和第2级将计算总和

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

int main (int argc, char *argv[])
{
        MPI_Init(&argc, &argv);
        int world_rank;
        MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
        int world_size;
        MPI_Comm_size(MPI_COMM_WORLD, &world_size);        
        int tag = 1;        
        int arr[2][3]; 
        MPI_Request request;
        MPI_Status status;
        int source = 0;
        int dest;
        int flag;

        printf ("\n--Current Rank: %d\n", world_rank);
        //To handle the number of process received by the user will be handled here later
        if (world_rank == 0)
        {
            int i = 1;
            int a, b, x, y;

            printf("* Rank 0 excecuting\n");
            for(x=0; x<2; x++)//Generating the whole 2 by 3  2D array
            {   
                i++;
                for ( y = 0; y < 3; y++ )
                {
                    arr[x][y] = i;//first row contain all 2 
                }                 //second row contain all 3
            }

            int subarray_index;
            for(subarray_index=0; subarray_index < 2; subarray_index++)
            {
                dest = subarray_index%(world_size - 1) + 1;     
                tag = subarray_index;
                MPI_Isend(&arr[subarray_index][0], 3, MPI_INT, dest, tag, MPI_COMM_WORLD, &request);
            }
        }
        else 
        {
            int a, b;                   
            for(b=0; b<2/(world_size-1); b++)
            {
                int sum = 0;
                int i;                
                int my_offset = world_rank-1;
                tag = b*(world_size-1) + my_offset;
                int subarray = b;
                MPI_Irecv(&arr[subarray][0], 3, MPI_INT, source, tag, MPI_COMM_WORLD, &request);
                MPI_Test(&request, &flag, &status);//I think there may be an error at MPI_Test too
                while (flag != 1)
                {
                    MPI_Test(&request, &flag, &status); 
                    for(i = 0; i<3; i++)
                    {   
                        //if(!arr[subarray][i])//want to wait till I recive actual array elements
                        //{//This need to start calculating as soon as array element become avilable 
                            printf("%d) arr[subarray][i]:%d at rank %d\n", tag, arr[subarray][i], world_rank);
                            sum = arr[subarray][i]+sum;
                        //}
                    }
                }                
                printf("\nSum is: %d at rank: %d and tag is:%d\n", sum, world_rank, tag);
                MPI_Wait (&request, &status); 
            }           
        }
        MPI_Finalize();
}

不知道你的问题是什么。但根据您的描述,我可以推断,当消息已经收到时,进程1达到了MPI\U测试。因此,
标志
已经设置,并且从不进入循环

另一方面,在秩2上,由于在等待接收消息时无条件地执行求和,所以将未初始化的值相加

只有在收到消息后才能进行求和。也就是说,当设置标志时,它位于while循环之后,基本上使整个构造无效,您可以这样做:

MPI_Irecv(&arr[subarray][0], 3, MPI_INT, source, tag, MPI_COMM_WORLD, &request);
MPI_Wait (&request, &status);
消息可用时,等待将立即返回,这是MPI_等待的点。现在,上述内容基本上相当于阻塞
MPI\u Recv

另一方面,您需要等待通信在发送端的某个点完成。在这里,您需要为每个
MPI\u Isend
单独请求。然后,您可以在发送循环后使用
MPI_Waitall

因此,您可能想要这样的东西(带有阻塞接收):


非常感谢您如此详细的回答和详细的解释。你是最棒的best@Learner_51很高兴它帮助了你。玩得高兴
MPI_Irecv(&arr[subarray][0], 3, MPI_INT, source, tag, MPI_COMM_WORLD, &request);
MPI_Wait (&request, &status);
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>

int main (int argc, char *argv[])
{
        MPI_Init(&argc, &argv);
        int world_rank;
        MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
        int world_size;
        MPI_Comm_size(MPI_COMM_WORLD, &world_size);
        int tag = 1;
        int arr[2][3];
        MPI_Request request[2];
        int source = 0;
        int dest;
        int flag;

        printf ("\n--Current Rank: %d\n", world_rank);
        //To handle the number of process received by the user will be handled here later
        if (world_rank == 0)
        {
            int i = 1;
            int a, b, x, y;
            MPI_Status status[2];

            printf("* Rank 0 excecuting\n");
            for(x=0; x<2; x++)//Generating the whole 2 by 3  2D array
            {
                i++;
                for ( y = 0; y < 3; y++ )
                {
                    arr[x][y] = i;//first row contain all 2 
                }                 //second row contain all 3
                dest = x%(world_size - 1) + 1;
                tag = x;
                MPI_Isend(&arr[x][0], 3, MPI_INT, dest, tag, MPI_COMM_WORLD, &request[x]);
            }

            MPI_Waitall(2, &request[0], &status[0]);

        }
        else
        {
            int a, b;
            MPI_Status status;

            for(b=0; b<2/(world_size-1); b++)
            {
                int sum = 0;
                int i;
                int my_offset = world_rank-1;
                tag = b*(world_size-1) + my_offset;
                int subarray = b;
                MPI_Recv(&arr[subarray][0], 3, MPI_INT, source, tag, MPI_COMM_WORLD, &status);
                for(i = 0; i<3; i++)
                {
                    //if(!arr[subarray][i])//want to wait till I recive actual array elements
                    //{//This need to start calculating as soon as array element become avilable 
                        printf("%d) arr[subarray][i]:%d at rank %d\n", tag, arr[subarray][i], world_rank);
                        sum = arr[subarray][i]+sum;
                    //}
                }
                printf("\nSum is: %d at rank: %d and tag is:%d\n", sum, world_rank, tag);
            }
        }
        MPI_Finalize();
}
{
    int a, b;
    MPI_Status status;
    MPI_Request request[2/(world_size-1)];

    for(b=0; b<2/(world_size-1); b++)
    {
        int my_offset = world_rank-1;
        tag = b*(world_size-1) + my_offset;
        int subarray = b;
        MPI_Irecv(&arr[subarray][0], 3, MPI_INT, source, tag, MPI_COMM_WORLD, &request[b]);
    }
    for(b=0; b<2/(world_size-1); b++)
    {
        int sum = 0;
        int i;
        MPI_Waitany(2/(world_size-1), &request[0], &a, &status);
        for(i = 0; i<3; i++)
        {
                printf("%d) arr[subarray][i]:%d at rank %d\n", status.MPI_TAG, arr[a][i], world_rank);
                sum = arr[a][i]+sum;
        }
        printf("\nSum is: %d at rank: %d and tag is:%d\n", sum, world_rank, status.MPI_TAG);
    }
}