2016-10-10 60 views
9

本程序使用C拉格朗日和MPI编写。我是MPI的新手,想要使用所有处理器进行一些计算,包括进程0.要学习这个概念,我写了下面这个简单的程序。但这个程序从进程0接收输入后挂在底部,不会将结果发送回流程0如何使用所有处理器在MPI中发送/接收

#include <mpi.h> 
#include <stdio.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 number; 
    int result; 
    if (world_rank == 0) 
    { 
     number = -2; 
     int i; 
     for(i = 0; i < 4; i++) 
     { 
      MPI_Send(&number, 1, MPI_INT, i, 0, MPI_COMM_WORLD); 
     } 
     for(i = 0; i < 4; i++) 
     {   /*Error: can't get result send by other processos bellow*/ 
      MPI_Recv(&number, 1, MPI_INT, i, 99, MPI_COMM_WORLD, MPI_STATUS_IGNORE); 
      printf("Process 0 received number %d from i:%d\n", number, i); 
     } 
    } 
    /*I want to do this without using an else statement here, so that I can use process 0 to do some calculations as well*/ 

    MPI_Recv(&number, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); 
    printf("*Process %d received number %d from process 0\n",world_rank, number); 
    result = world_rank + 1; 
    MPI_Send(&result, 1, MPI_INT, 0, 99, MPI_COMM_WORLD); /* problem happens here when trying to send result back to process 0*/ 

    MPI_Finalize(); 
} 

乳宁,并得到结果:如果你能

:$ mpicc test.c -o test 
:$ mpirun -np 4 test 

*Process 1 received number -2 from process 0 
*Process 2 received number -2 from process 0 
*Process 3 received number -2 from process 0 
/* hangs here and will not continue */ 

,请给我一个例子或者如果可能的话编辑上面的代码。

回答

1

我真的不明白使用2 if语句时会出现什么问题,并且围绕着工作域。但无论如何,这是一个可以做什么的例子。

我修改了您的代码以使用集体通信,因为它们比您使用的一系列发送/接收更有意义。由于初始通信具有统一的值,因此我使用一个MPI_Bcast(),它在一次呼叫中执行相同操作。
相反,由于结果值都不相同,因此致电MPI_Gather()是非常合适的。
我还引入了一个sleep()的调用,目的只是为了模拟这些过程正在运行一段时间,然后再发回它们的结果。

现在,该代码如下所示:

$ mpicc -std=c99 simple_mpi.c -o simple_mpi 

它运行,并给出了这样的:

#include <mpi.h> 
#include <stdlib.h> // for malloc and free 
#include <stdio.h> // for printf 
#include <unistd.h> // for sleep 

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); 

    // sending the same number to all processes via broadcast from process 0 
    int number = world_rank == 0 ? -2 : 0; 
    MPI_Bcast(&number, 1, MPI_INT, 0, MPI_COMM_WORLD); 
    printf("Process %d received %d from process 0\n", world_rank, number); 

    // Do something usefull here 
    sleep(1); 
    int my_result = world_rank + 1; 

    // Now collecting individual results on process 0 
    int *results = world_rank == 0 ? malloc(world_size * sizeof(int)) : NULL; 
    MPI_Gather(&my_result, 1, MPI_INT, results, 1, MPI_INT, 0, MPI_COMM_WORLD); 

    // Process 0 prints what it collected 
    if (world_rank == 0) { 
     for (int i = 0; i < world_size; i++) { 
      printf("Process 0 received result %d from process %d\n", results[i], i); 
     } 
     free(results); 
    } 

    MPI_Finalize(); 

    return 0; 
} 

如下编译它之后

$ mpiexec -n 4 ./simple_mpi 
Process 0 received -2 from process 0 
Process 1 received -2 from process 0 
Process 3 received -2 from process 0 
Process 2 received -2 from process 0 
Process 0 received result 1 from process 0 
Process 0 received result 2 from process 1 
Process 0 received result 3 from process 2 
Process 0 received result 4 from process 3 
1

其实,处理1-3确实将结果发送回处理器0.但是,处理器0停留在此循环的第一次迭代中:

for(i=0; i<4; i++) 
{  
    MPI_Recv(&number, 1, MPI_INT, i, 99, MPI_COMM_WORLD, MPI_STATUS_IGNORE); 
    printf("Process 0 received number %d from i:%d\n", number, i); 
} 

在第一次MPI_Recv调用中,处理器0将阻止等待接收来自其自身的带有标记99的消息,这是0还没有发送的消息。

通常,处理器向自己发送/接收消息,特别是使用阻塞调用是一个坏主意。 0已经具有内存中的值。它不需要发送给自己。

然而,一个解决方法是从i=1

for(i=1; i<4; i++) 
{   
    MPI_Recv(&number, 1, MPI_INT, i, 99, MPI_COMM_WORLD, MPI_STATUS_IGNORE); 
    printf("Process 0 received number %d from i:%d\n", number, i); 
} 

开始接收环路现在运行代码会给你:

Process 1 received number -2 from process 0 
Process 2 received number -2 from process 0 
Process 3 received number -2 from process 0 
Process 0 received number 2 from i:1 
Process 0 received number 3 from i:2 
Process 0 received number 4 from i:3 
Process 0 received number -2 from process 0 

注意,使用MPI_Bcast和MPI_Gather由吉尔提到的是数据分发/收集的效率和标准方式更为有效和标准。