我试图弄清楚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以上,但这样做还不错。为什么会这样?
答案 0 :(得分: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没有线程化;当您使用mpiexec
或mpirun
启动程序时,将启动n个任务,并且每个任务在其自己的进程中运行完全相同的程序 - 例如,没有共享变量。特别是,每个任务都有自己的变量message
,并且该变量在上面的代码片段中最多会增加一次,这意味着message
最后总是2或3发布的代码。
答案 1 :(得分:2)
mpirun -np N
命令启动N
MPI进程,而不是具有N
个线程的一个进程。在每个进程中,您有变量message
,每个进程都有自己的变量设置为2.接下来的第0个进程将其message == 3
发送到第1个进程。在它之后,第一个过程发送他自己的message == 3
和第二个捕获它......
答案 2 :(得分: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);
}
因此,每个过程(等级0除外)将从先前等级接收值,将其递增1然后将其传递到下一等级(除最后等级之外)。例如:
2
发送到排名1 2
,递增它并将3
发送到等级2 3
,递增它并将4
发送到排名3 2+nthreads-1