除了以下内容外,我没有太多要补充的内容。您实际上可以调用MPI_FINALIZE 并退出多余的进程,但您必须意识到这将破坏世界通信器MPI_COMM_WORLD 上所有进一步的集体操作 - 其中大多数根本无法完成(@987654323 @ 是肯定会挂起的那个)。为了防止这种情况,您可能需要首先创建一个排除所有不必要进程的新通信器:
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 的进程生成功能,但这会使代码变得更加复杂,因为您必须处理相互通信器。