1

我试图了解 MPI 的工作原理。因此,我从一个小例子开始:

...
MPI_Comm_rank(MPI_COMM_WORLD, &tid);
MPI_Comm_size(MPI_COMM_WORLD, &nthreads);

int message = 2;

if(tid != 0)
{
    MPI_Recv(&rec, 1, MPI_INT, tid-1, 0, MPI_COMM_WORLD, &status);
    printf("Process %i receive %i\n", tid, rec);
}

if(tid != nthreads-1)
{
    message++;
    printf("Process %i sends %i\n", tid, message);
    MPI_Send(&message, 1, MPI_INT, tid+1, 0, MPI_COMM_WORLD);
}
...

尽管message看起来确实增加到 3 以上,但效果很好。为什么会这样?

4

3 回答 3

2

MPI 等级不是线程,它们是——嗯——“等级”,或者有时用 MPI 来说是处理元素,但一般来说是进程。

这通常是一个小细节,但在这里我认为它实际上反映了潜在的混乱。如果在 OpenMP 中(比如说)你有以下代码

int message = 0;

#pragma omp parallel default(none) shared(message)
{
   int tid = omp_get_thread_num();
   if (tid != nthreads-1) {
       #pragma omp atomic
       message++;
   }
}

然后在并行部分结束时,消息实际上会增加OMP_NUM_THREADS-1次数。

但是 MPI 不是线程;当您使用mpiexecor启动程序时mpirun,会启动 n 个任务,并且每个任务都会在自己的进程中运行完全相同的程序——例如,没有共享变量。特别是,每个任务都有自己的变量message,并且该变量在上面的代码片段中最多会增加一次,这意味着message在发布的代码末尾始终是 2 或 3。

于 2012-12-19T21:59:51.613 回答
2

mpirun -np N命令启动NMPI 进程,而不是一个具有N线程的进程。在每个进程中,您都有变量message,并且每个进程都有自己的变量设置为 2。下一个第 0 个进程将其发送message == 3到第一个进程。之后,第一个进程发送他自己的message == 3,第二个进程捕获它......

于 2012-12-19T22:00:33.083 回答
1

我强烈怀疑您想要的可以通过以下代码实现:

int message = 2;

if(tid != 0)
{
   MPI_Recv(&message, 1, MPI_INT, tid-1, 0, MPI_COMM_WORLD, &status);
   printf("Process %i receive %i\n", tid, message);
}

if(tid != nthreads-1)
{
   message++;
   printf("Process %i sends %i\n", tid, message);
   MPI_Send(&message, 1, MPI_INT, tid+1, 0, MPI_COMM_WORLD);
}

因此,每个进程(除了 rank 0)都会从前一个 rank 接收值,将其递增 1,然后将其传递给下一个 rank(最后一个 rank 除外)。例如:

  • 等级 0 发送2到等级 1
  • rank 12从 rank 0 接收,递增并发3送到 rank 2
  • rank 23从 rank 1 接收,递增并发4送到 rank 3
  • ...
  • rank nthreads -12+nthreads-1从 rank nthreads -2接收
于 2012-12-20T13:08:44.803 回答