只是一个普遍的问题:
我想问一下是否有办法在不使用MPI_SendandMPI_Recv例程的情况下仅将元素广播到 MPI 中的某些等级。
只是一个普遍的问题:
我想问一下是否有办法在不使用MPI_SendandMPI_Recv例程的情况下仅将元素广播到 MPI 中的某些等级。
我想问一下,是否有办法在不使用 MPI_Send MPI_Recv 的情况下仅将元素广播到 MPI 中的某些等级。
让我们从查看MPI_Bcast例程的描述开始。
将消息从具有“root”等级的进程广播到 通信器的所有其他进程
广播例程是一种MPI_Bcast集体通信。因此:
集体通信是一种通信方法,它涉及到一个通信器中的所有进程的参与。
注意粗体字,即 “通讯器中的所有进程”。因此,一种方法(实现您想要的)是创建一个由将参与广播例程的进程组成的子集。这个子集可以通过创建一个新的 MPI通信器来实现。要创建该通信器,可以使用 MPI 函数MPI_Comm_split。关于源代码中的该例程,可以阅读:
顾名思义,
MPI_Comm_split通过根据输入值颜色和键将通信器“拆分”为一组子通信器来创建新的通信器。这里需要注意的是,原来的通信器不会消失,而是在每个进程上创建一个新的通信器。
第一个参数 comm 是将用作新通信器基础的通信器。这可能是 MPI_COMM_WORLD,但也可能是任何其他通信器。
第二个参数颜色决定了每个进程将属于哪个新的通信器。传递相同颜色值的所有进程都分配给相同的通信器。如果颜色是 MPI_UNDEFINED,则该进程将不会包含在任何新的通信器中。第三个参数 key 决定了每个新通信器中的排序(等级)。传入键最小值的过程将是 0 级,下一个最小的将是 1 级,依此类推。如果出现平局,则在原始通信器中排名较低的进程将是第一个。最后一个参数 newcomm 是 MPI 如何将新的通信器返回给用户。
假设我们只想让具有偶数等级的进程参与MPI_Bcast;我们将首先创建通信器:
MPI_Comm new_comm;
int color = (world_rank % 2 == 0) ? 1 : MPI_UNDEFINED;
MPI_Comm_split(MPI_COMM_WORLD, color, world_rank, &new_comm);
并最终调用MPI_Bcast新的通信器:
if(world_rank % 2 == 0){
....
MPI_Bcast(&bcast_value, 1, MPI_INT, 0, new_comm);
...
}
最后,我们将释放通信器使用的内存:
MPI_Comm_free(&new_comm);
运行代码示例:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
int main(int argc,char *argv[]){
MPI_Init(NULL,NULL); // Initialize the MPI environment
int world_rank;
int world_size;
MPI_Comm_rank(MPI_COMM_WORLD,&world_rank);
MPI_Comm_size(MPI_COMM_WORLD,&world_size);
int bcast_value = world_rank;
MPI_Bcast(&bcast_value, 1, MPI_INT, 0, MPI_COMM_WORLD);
printf("MPI_Bcast 1 : MPI_COMM_WORLD ProcessID = %d, bcast_value = %d \n", world_rank, bcast_value);
MPI_Comm new_comm;
int color = (world_rank % 2 == 0) ? 1 : MPI_UNDEFINED;
MPI_Comm_split(MPI_COMM_WORLD, color, world_rank, &new_comm);
if(world_rank % 2 == 0){
int new_comm_rank, new_comm_size;
MPI_Comm_rank(new_comm, &new_comm_rank);
MPI_Comm_size(new_comm, &new_comm_size);
bcast_value = 1000;
MPI_Bcast(&bcast_value, 1, MPI_INT, 0, new_comm);
printf("MPI_Bcast 2 : MPI_COMM_WORLD ProcessID = %d, new_comm = %d, bcast_value = %d \n", world_rank, new_comm_rank, bcast_value);
MPI_Comm_free(&new_comm);
}
MPI_Finalize();
return 0;
}
此代码示例展示了两个MPI_Bcast调用,一个包含MPI_COMM_WORLD( ie, MPI_Bcast 1 ) 的所有进程,另一个仅包含这些进程的一个子集 ( ie, MPI_Bcast 2 )。
输出(8个进程):
MPI_Bcast 1 : MPI_COMM_WORLD ProcessID = 0, bcast_value = 0
MPI_Bcast 1 : MPI_COMM_WORLD ProcessID = 4, bcast_value = 0
MPI_Bcast 1 : MPI_COMM_WORLD ProcessID = 5, bcast_value = 0
MPI_Bcast 1 : MPI_COMM_WORLD ProcessID = 6, bcast_value = 0
MPI_Bcast 1 : MPI_COMM_WORLD ProcessID = 7, bcast_value = 0
MPI_Bcast 1 : MPI_COMM_WORLD ProcessID = 1, bcast_value = 0
MPI_Bcast 1 : MPI_COMM_WORLD ProcessID = 2, bcast_value = 0
MPI_Bcast 1 : MPI_COMM_WORLD ProcessID = 3, bcast_value = 0
MPI_Bcast 2 : MPI_COMM_WORLD ProcessID = 0, new_comm = 0, bcast_value = 1000
MPI_Bcast 2 : MPI_COMM_WORLD ProcessID = 4, new_comm = 2, bcast_value = 1000
MPI_Bcast 2 : MPI_COMM_WORLD ProcessID = 2, new_comm = 1, bcast_value = 1000
MPI_Bcast 2 : MPI_COMM_WORLD ProcessID = 6, new_comm = 3, bcast_value = 1000