Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用C语言在MPI中调用相同的秩?_C_Mpi - Fatal编程技术网

如何使用C语言在MPI中调用相同的秩?

如何使用C语言在MPI中调用相同的秩?,c,mpi,C,Mpi,我正在努力学习MPI编程,并编写了以下程序。它添加整个数组行并输出总和。在秩0(或进程0)处,它将调用其所有从属秩来进行计算。我只想使用另外两个从属列组/进程来实现这一点。每当我尝试调用相同的排名两次,如代码波纹管中所示,我的代码将只是挂在中间,不会执行。如果我不调用同一个秩两次,代码将正常工作 #include "mpi.h" #include <stdio.h> #include <stdlib.h> int main (int argc, char *argv[]

我正在努力学习MPI编程,并编写了以下程序。它添加整个数组行并输出总和。在秩0(或进程0)处,它将调用其所有从属秩来进行计算。我只想使用另外两个从属列组/进程来实现这一点。每当我尝试调用相同的排名两次,如代码波纹管中所示,我的代码将只是挂在中间,不会执行。如果我不调用同一个秩两次,代码将正常工作

#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 tag2 = 1;       
        int arr[30] = {0};

        MPI_Request request;
        MPI_Status status;

        printf ("\n--Current Rank: %d\n", world_rank);
        int index;
        int source = 0;
        int dest;
        if (world_rank == 0)
        {
            int i;

            printf("* Rank 0 excecuting\n");
            index = 0;
            dest = 1;
            for ( i = 0; i < 30; i++ )
            {
                arr[ i ] = i + 1; 
            }           
            MPI_Send(&arr[0], 30, MPI_INT, dest, tag2, MPI_COMM_WORLD); 

            index = 0;
            dest = 2;
            for ( i = 0; i < 30; i++ )
            {
                arr[ i ] = 0; 
            }
            MPI_Send(&arr[0], 30, MPI_INT, dest, tag2, MPI_COMM_WORLD);         

            index = 0;
            dest = 2; //Problem happens here when I try to call the same destination(or rank 2) twice
            //If I change this dest value to 3 and run using: mpirun -np 4 test, this code will work correctly
            for ( i = 0; i < 30; i++ )
            {
                arr[ i ] = 1; 
            }
            MPI_Send(&arr[0], 30, MPI_INT, dest, tag2, MPI_COMM_WORLD);
        }
        else 
        {
            int sum = 0;
            int i;
            MPI_Irecv(&arr[0], 30, MPI_INT, source, tag2, MPI_COMM_WORLD, &request);
            MPI_Wait (&request, &status);
            for(i = 0; i<30; i++)
            {   
                sum = arr[i]+sum;
            }
            printf("\nSum is: %d at rank: %d\n", sum, world_rank);
        }       

        MPI_Finalize();
}
请让我知道我怎样才能叫同一个等级两次。例如,如果我只能调用另外两个从进程。
如果可能的话,请举例说明在MPI中,每个进程执行相同的代码,并且在您执行时,主要通过检查if/else语句中的秩来区分不同的进程。秩为0的主进程正在执行3次发送:一次发送到进程1,然后两次发送到进程2。从属进程每个只执行一次接收,这意味着秩1接收其第一条消息,秩2接收其第一条消息。当您在进程0上调用第三个
MPI_Send
时,由于从机已完成执行其else块,因此在该点之后不会有任何从机等待接收消息。当主机等待发送最终消息时,程序被阻止

为了解决这个问题,您必须确保秩2的从机执行两次接收,或者只为该进程添加一个循环,或者只为该进程重复一次(因此,如果(world_rank==2)检查)代码块

        sum = 0; //resetting sum
        MPI_Irecv(&arr[0], 1024, MPI_INT, source, tag2, MPI_COMM_WORLD, &request);
        MPI_Wait (&request, &status);
        for(i = 0; i<1024; i++)
        {   
            sum = arr[i]+sum;
        }
        printf("\nSum is: %d at rank: %d\n", sum, world_rank); 
sum=0//重置总和
MPI_Irecv(&arr[0],1024,MPI_INT,source,tag2,MPI_COMM_WORLD,&request);
MPI_等待(&请求,&状态);

对于(i=0;i来说,这只是一句话,主/从方法不受欢迎,可能会长期影响程序员的思维,导致在投入生产时产生糟糕的代码


尽管Clarissa是完全正确的,她的答案也非常清楚,但我想补充几点一般性的意见,不是关于代码本身,而是关于并行计算哲学和良好习惯

首先是一个简短的前言:当一个人想要并行化自己的代码时,可能有两个主要原因:提高速度和/或允许它通过克服单机上的限制(如内存限制)来处理更大的问题。但在所有情况下,性能都很重要,我始终认为MPI(或者一般来说是并行的)程序员对性能感兴趣,所以我的文章的其余部分会假设你是

现在写这篇文章的主要原因是:在过去的几天里,我在这里看到了一些关于MPI和并行化的问题,显然是来自渴望学习MPI(或OpenMP)的人们。这太棒了!并行编程太棒了,而且永远不会有足够的并行程序员。所以我很高兴(我相信很多会员也是)回答帮助人们学习如何并行编程的问题。在学习如何并行编程的背景下,你必须编写一些简单的代码,做一些简单的事情,以便理解API的功能和工作原理。从远处看,这些程序可能看起来很愚蠢,效率很低,但没关系,就是这样学习是有效的。每个人都是这样学习的

然而,你必须记住,你写的这些程序只是:API学习练习。它们不是真实的东西,它们没有反映出实际并行程序是什么或应该是什么的哲学。我在这里的答案是,我在这里看到的以及在其他问题和答案中反复提出的f“主”过程和“从”过程。这是错误的,根本上是错误的!让我解释一下原因:

正如Clarissa完美指出的,“在MPI中,每个进程执行相同的代码”。其想法是找到一种方法,使多个进程相互作用,共同解决一个(可能更大的)问题(希望更快).但在这些进程中,没有一个进程获得任何特殊的地位,它们都是平等的。它们被赋予一个id来处理它们,但秩0并不比秩1或秩1025好……通过人为地确定进程#0是“主”而其他进程是其“从”,你打破了这种对称性,并产生了以下后果:

现在秩#0是主控,它命令,对吗?主控就是这样做的。因此,它将获得运行代码所需的信息,将其共享分配给工作人员,并指示他们进行处理。然后它将等待处理结束(可能在这两者之间忙得不可开交,但更可能只是等待或戳工人,因为这是大师的工作),收集结果,重新组装并输出。工作完成了!这有什么不对

好吧,以下是错误的:

  • 在主机获取数据的过程中,从机处于空闲状态。这是一种顺序的、无效的处理
  • 然后,数据的分布和要做的工作意味着大量的传输。这需要时间,而且因为它仅在进程0和所有其他进程之间,这可能会在一条链路中造成网络上的大量拥塞
  • 当工人做他们的工作时,主人应该做什么?也工作吗?如果是的话,那么当奴隶来的时候,它可能无法处理奴隶的请求,从而延迟了整个并行处理。等待这些请求?然后它会因闲置而浪费大量计算能力……最终,没有好的答案
  • 然后以相反的顺序重复第1点和第2点,收集结果并输出结果。这是大量的数据传输和顺序处理,这将严重损害全局可扩展性、有效性和性能
  • 所以我希望你们现在明白为什么主/从方法是(通常,不总是)
            sum = 0; //resetting sum
            MPI_Irecv(&arr[0], 1024, MPI_INT, source, tag2, MPI_COMM_WORLD, &request);
            MPI_Wait (&request, &status);
            for(i = 0; i<1024; i++)
            {   
                sum = arr[i]+sum;
            }
            printf("\nSum is: %d at rank: %d\n", sum, world_rank);