【问题标题】:Changing value of a variable with MPI使用 MPI 更改变量的值
【发布时间】:2014-02-17 04:46:28
【问题描述】:
#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 次 print 语句,每个进程一个呢?

【问题讨论】:

    标签: c mpi


    【解决方案1】:

    认为mpi_init 启动请求数量的进程(或任何用于实现 MPI 的机制)而mpi_finalize 停止它们是一种常见的误解。最好考虑mpi_init 在一组操作系统进程之上启动 MPI 系统。 MPI 标准对 MPI 实际运行在什么之上以及如何启动底层机制保持沉默。在实践中,调用mpiexec(或mpirun)可能会触发请求数量的进程,这些进程在程序启动时都处于活动状态。在调用mpi_finalize 之后,这些进程也可能会继续存在,直到程序结束。

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

    至于为什么a 的值设置为2 而不是4,好吧,本质上你是在运行同一程序的n 副本(其中n 是进程数)每个都将1 添加到自己的a 版本中。一个进程内存中的变量与另一个进程内存中的同名变量没有关系。所以每个进程都将a设置为2

    要将任何数据从一个进程获取到另一个进程,进程需要参与消息传递

    编辑,以回应 OP 的评论

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

    打个比方:玩具城高街 1 号与乐高城高街 1 号的地址不同;跨地址空间的名称存在重合。

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

    【讨论】:

    • 谢谢。您对创建的进程数的回答很好,但是关于为什么将值设置为 2 的答案仍然不能满足我。因为,我尝试为每个进程打印存储在指针 p 中的内存位置(参见注释行)。它对所有进程显示相同的值。这意味着即使该程序的三个实例正在为 3 个进程运行,它们都在内存中显示相同的“a”地址。这怎么可能?
    • 因为您的进程(全部)使用虚拟地址。由于操作系统的分页系统,它们在所有进程中都可以相同,但它们都指向不同的内存位置。
    • 在多个进程之间共享信息(即“a”变量的当前值)的唯一方法是通过消息传递。这就是 MPI 的意义所在。
    【解决方案2】:

    由于 MPI 仅允许您选择在不同进程之间进行通信,因此您必须进行消息传递。出于您的目的,有类似 MPI_Allreduce 之类的东西,它可以通过单独的进程汇总数据。请注意,这会添加值,因此在您的情况下,您想要对增量求和,然后将总和添加到 p:

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

    【讨论】:

      【解决方案3】:

      在您的实现中,生成的线程之间没有通信。每个进程都有自己的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;
      }
      

      【讨论】:

        猜你喜欢
        • 2017-08-28
        • 2021-11-09
        • 2012-06-24
        • 2016-02-24
        • 2014-09-06
        • 2021-07-09
        • 2014-09-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多