用MPI改变变量的值

时间:2014-01-26 10:35:43

标签: c mpi

#include<stdio.h>
#include<mpi.h>
int a=1;
int *p=&a;
int main(int argc, char **argv)
{

MPI_Init(&argc,&argv);

int rank,size;
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);
//printf("Address val: %u \n",p);

*p=*p+1;


MPI_Barrier(MPI_COMM_WORLD);
MPI_Finalize();

printf("Value of a : %d\n",*p);

return 0;
}

这里,我试图用3个进程执行程序,其中每个进程尝试将a的值递增1,因此所有进程执行结束时的值应为4.那么为什么值打印为2仅在MPI_Finalize()之后的printf语句中。并不是并行执行在MPI_Finalize()停止,并且应该只有一个进程在它之后运行。那为什么我会在执行期间获得3次打印语句,每个进程一次?

3 个答案:

答案 0 :(得分:4)

认为mpi_init启动所请求的进程数(或用于实现MPI的任何机制)并且mpi_finalized阻止它们是一种常见的误解。最好考虑mpi_init在一组操作系统进程之上启动MPI系统。 MPI标准没有说明MPI实际运行的内容以及底层机制是如何启动的。在实践中,对mpiexec(或mpirun)的调用可能会激活所请求数量的进程,所有这些进程在程序启动时都处于活动状态。在调用mpi_finalized之后,流程可能会继续存在,直到程序结束。

这意味着在调用mpi_init之前,以及在调用mpi_finalize之后,可能会有许多o / s进程在运行,每个进程都在执行相同的程序。这解释了为什么您为每个进程执行一次printf语句。

至于为什么a的值设置为2而不是4,实际上,您正在运行同一程序的n个副本(其中{ {1}}是进程数),每个进程都将n添加到其自己的1版本中。一个进程的内存中的变量与另一个进程的内存中的同名变量没有关系。因此,每个流程都会将a设置为a

要从一个流程获取任何数据,流程需要参与消息传递

编辑,回应OP的评论

正如一个进程的内存中的变量与另一个进程的内存中的同名变量没有关系一样,指针(它是一种变量)与同名的指针没有任何关系在另一个过程的记忆中。不要被愚弄,如果''same''指针在多个进程中具有''相同''地址,那些地址在不同的地址空间中并且不相同,指针不指向同一个地方。 / p>

类比:1 High Street,Toytown与1 High Street,Legotown的地址不同;地址空间中的名称巧合。

要从一个进程获取任何数据(指针或其他),进程需要参与消息传递。您似乎坚持MPI进程以某种方式共享内存的概念。他们没有,放弃这个想法。

答案 1 :(得分:0)

由于MPI只为您提供了在不同进程之间进行通信的选项,因此您必须进行消息传递。为了您的目的,有一些像MPI_Allreduce,它可以通过单独的进程汇总数据。请注意,这会添加值,因此在您的情况下,您希望对增量求和,然后将总和添加到p:

int inc = 1;
MPI_Allreduce(MPI_IN_PLACE, &inc, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
*p += inc;

答案 2 :(得分:0)

在您的实现中,生成的线程之间没有通信。每个进程都有自己的int a变量,它会递增并打印到屏幕上。使变量成为全局变量不会使它在进程之间共享,所有指针噱头都会告诉我你不知道自己在做什么。我建议你继续学习更多的C和操作系统。

无论如何,你必须让流程进行沟通。以下是示例的示例:

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

// this program will count the number of spawned processes in a *very* bad way
int main(int argc, char **argv)
{
   int partial = 1;
   int sum;
   int my_id = 0;

   // let's just assume the process with id 0 is root
   int root_process = 0;

   // spawn processes, etc.
   MPI_Init(&argc,&argv);

   // every process learns his id
   MPI_Comm_rank(MPI_COMM_WORLD, &my_id);

   // all processes add their 'partial' to the 'sum'
   MPI_Reduce(&partial, &sum, 1, MPI_INT, MPI_SUM, root_process, MPI_COMM_WORLD); 

   // de-init MPI
   MPI_Finalize();

   // the root process communicates the summation result
   if (my_id == root_process)
   {
      printf("Sum total : %d\n", sum);
   }

   return 0;
}