在 MPI 中收集,但不使用 MPI_Gather
Gathering in MPI, but not with MPI_Gather
我需要做类似 MPI_Gather 的事情,但我需要按照不同于进程等级的顺序存储收集到的数据。我以为我可以做这样的事情:
int i;
int gathervals[10];
int my_val, my_place_in_storage;
/* init MPI etc ... then ... */
my_val = some_fcn_of_rank(my_rank, ...)
my_place_in_storage = some_other_fcn(my_val, my_rank, ...)
if (my_rank == 0){
/* my_val on proc 0 does go in gathervals[0], which simplifies
things */
gathervals[0] = my_val;
for (i=1; i<num_procs; i++){
MPI_Recv(&gathervals[i], 1, MPI_INT, MPI_ANY_SOURCE,
i, MPI_COMM_WORLD, stat_mpi);
}
}else{
MPI_Send(&mv_val, 1, MPI_INT, 0, my_place_in_storage,
MPI_COMM_WORLD);
}
我的想法是 proc 0 将启动循环并等待直到 post 从 my_place_in_storage
为 1 的 proc 发出发送,然后 proc 0 将接收该消息并将值放入进入 gathervals[1]
。然后它将迭代并等待,直到它从 proc 中看到一个 post,其 my_place_in_storage
为 2,等等
这应该有效吗?我在 proc 0 上遇到段错误,我想找出原因。我认为这段代码可能有点非正统,但可以作为起点。我已经验证了所有 my_place_in_storage
值的正确性。
是的,这应该可行,但您有更好的选择。用MPI_Gather
收集my_place_in_storage
作为MPI_Gatherv
的位移数组。沿线的东西:
if (my_rank == 0) {
int displacements[10];
int recvcounts[10] = {1,1,1,1,1,1,1,1,1,1};
MPI_Gather(&my_place_in_storage, 1, MPI_INT,
displacements, 1, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Gatherv(&my_val, 1, MPI_INT, gathervals, recvcounts,
displacements, MPI_INT, 0, MPI_COMM_WORLD);
} else {
MPI_Gather(&my_place_in_storage, 1, MPI_INT,
NULL, 1, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Gatherv(&my_val, 1, MPI_INT, NULL, 1, NULL,
MPI_INT, 0, MPI_COMM_WORLD);
}
一般情况下,最好使用集体而不是多个点对点消息。这更具可扩展性,并允许通过 MPI 实现进行更多优化。
另一种选择是使用 MPI_Comm_split 创建一个新的通信器,它包含与 MPI_COMM_WORLD 所有相同的进程,但排列成基于 "my_place_in_storage" 的新顺序。如果每个人都提供相同的 "color" 值,那么他们都属于同一个通信器,但使用 "my_place_in_storage" 作为 "key"。
,你可以这样做
通信器创建有一些开销,但如果您使用相同的 "my_place_in_storage" 值多次执行此操作,这可能比使用两次收集更有效。请注意,在新的通信器中,您也可以只使用 gather,它也应该比 gatherv 更快。
我需要做类似 MPI_Gather 的事情,但我需要按照不同于进程等级的顺序存储收集到的数据。我以为我可以做这样的事情:
int i;
int gathervals[10];
int my_val, my_place_in_storage;
/* init MPI etc ... then ... */
my_val = some_fcn_of_rank(my_rank, ...)
my_place_in_storage = some_other_fcn(my_val, my_rank, ...)
if (my_rank == 0){
/* my_val on proc 0 does go in gathervals[0], which simplifies
things */
gathervals[0] = my_val;
for (i=1; i<num_procs; i++){
MPI_Recv(&gathervals[i], 1, MPI_INT, MPI_ANY_SOURCE,
i, MPI_COMM_WORLD, stat_mpi);
}
}else{
MPI_Send(&mv_val, 1, MPI_INT, 0, my_place_in_storage,
MPI_COMM_WORLD);
}
我的想法是 proc 0 将启动循环并等待直到 post 从 my_place_in_storage
为 1 的 proc 发出发送,然后 proc 0 将接收该消息并将值放入进入 gathervals[1]
。然后它将迭代并等待,直到它从 proc 中看到一个 post,其 my_place_in_storage
为 2,等等
这应该有效吗?我在 proc 0 上遇到段错误,我想找出原因。我认为这段代码可能有点非正统,但可以作为起点。我已经验证了所有 my_place_in_storage
值的正确性。
是的,这应该可行,但您有更好的选择。用MPI_Gather
收集my_place_in_storage
作为MPI_Gatherv
的位移数组。沿线的东西:
if (my_rank == 0) {
int displacements[10];
int recvcounts[10] = {1,1,1,1,1,1,1,1,1,1};
MPI_Gather(&my_place_in_storage, 1, MPI_INT,
displacements, 1, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Gatherv(&my_val, 1, MPI_INT, gathervals, recvcounts,
displacements, MPI_INT, 0, MPI_COMM_WORLD);
} else {
MPI_Gather(&my_place_in_storage, 1, MPI_INT,
NULL, 1, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Gatherv(&my_val, 1, MPI_INT, NULL, 1, NULL,
MPI_INT, 0, MPI_COMM_WORLD);
}
一般情况下,最好使用集体而不是多个点对点消息。这更具可扩展性,并允许通过 MPI 实现进行更多优化。
另一种选择是使用 MPI_Comm_split 创建一个新的通信器,它包含与 MPI_COMM_WORLD 所有相同的进程,但排列成基于 "my_place_in_storage" 的新顺序。如果每个人都提供相同的 "color" 值,那么他们都属于同一个通信器,但使用 "my_place_in_storage" 作为 "key"。
,你可以这样做通信器创建有一些开销,但如果您使用相同的 "my_place_in_storage" 值多次执行此操作,这可能比使用两次收集更有效。请注意,在新的通信器中,您也可以只使用 gather,它也应该比 gatherv 更快。