除了以下内容外,我没有太多要添加到高性能标记已经编写的内容。您实际上可以调用MPI_FINALIZE
和退出过多的进程,但您必须意识到这将破坏世界通信器上所有进一步的集体操作MPI_COMM_WORLD
- 它们中的大多数根本不会完成(MPI_BARRIER
作为肯定会挂起的那个) . 为了防止这种情况,您可能需要首先创建一个新的通信器,排除所有不必要的进程:
int rank, size;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
// Obtain the group of processes in the world communicator
MPI_Group world_group;
MPI_Comm_group(MPI_COMM_WORLD, &world_group);
// Remove all unnecessary ranks
MPI_Group new_group;
int ranges[3] = { process_limit, size-1, 1 };
MPI_Group_range_excl(world_group, 1, ranges, &new_group);
// Create a new communicator
MPI_Comm newworld;
MPI_Comm_create(MPI_COMM_WORLD, new_group, &newworld);
if (newworld == MPI_COMM_NULL)
{
// Bye bye cruel world
MPI_Finalize();
exit(0);
}
// From now on use newworld instead of MPI_COMM_WORLD
此代码首先获取进程组,MPI_COMM_WORLD
然后创建一个新组,该组从process_limit
以后排除所有进程。然后它从新的进程组创建一个新的通信器。该MPI_COMM_CREATE
操作将MPI_COMM_NULL
在不属于新组的这些进程中返回,并且此事实用于终止此类进程。鉴于在这一点之后,一些进程将从 中“消失” MPI_COMM_WORLD
,它不再可用于广播、屏障等集体操作,而newworld
应改为使用。
此外,正如 Mark 所指出的,在某些架构上,即使在从main
. 例如,在 Blue Gene、Cray 或任何其他使用硬件分区来管理 MPI 作业的系统上,在整个 MPI 作业完成之前不会释放额外的资源。如果程序在资源管理器(例如 SGE、LSF、Torque、PBS、SLURM 等)控制下的集群或其他系统上运行,也会出现这种情况。
我对这种情况的通常做法是非常务实的:
int size, rank;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
if (size != process_limit)
{
if (rank == 0)
printf("Please run this program with %d MPI processes\n", process_limit);
MPI_Finalize();
exit(1);
}
您也可以使用MPI_Abort(MPI_COMM_WORLD, 0);
而不是MPI_Finalize()
惹恼用户:)
您还可以使用 MPI 的进程生成功能,但这会使代码更加复杂,因为您必须处理相互通信器。