From 73f42f9be925c66cad63e2406e823f56ff36b64a Mon Sep 17 00:00:00 2001 From: hzhou-muse Date: Tue, 6 Oct 2026 03:56:05 +0000 Subject: [PATCH] comm: fix HW_GUIDED split returning MPI_COMM_NULL for non-proper subset MPI_COMM_TYPE_HW_GUIDED should return the largest subset of processes that match the resource type. Unlike HW_UNGUIDED, it is not required to be a proper subset. Previously, we returned MPI_COMM_NULL whenever the split did not reduce the node comm, e.g. "package" on a single-package node, while "mpi_shared_memory" returned a valid comm. The proper-subset check was a proxy for detecting processes that are not contained in a single instance of the resource (gid falls back to the root gid). Check that per process instead and use MPI_UNDEFINED as the color, so all processes still participate in the split (no hang). "node" and "machine" resolve to the root gid by design, so return the node comm directly for them. This does not depend on hwtopo, so check it before returning MPI_COMM_NULL for an uninitialized hwtopo, e.g. on osx, where the process binding cannot be queried. Fixes #7160 Co-Authored-By: Claude Opus 5.5 --- src/mpi/comm/comm_split_type.c | 26 +++++++++++++++++--------- test/mpi/comm/cmsplit_type.c | 13 +++++++++++++ 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/mpi/comm/comm_split_type.c b/src/mpi/comm/comm_split_type.c index ec45c6aeb6c..84ad77a166a 100644 --- a/src/mpi/comm/comm_split_type.c +++ b/src/mpi/comm/comm_split_type.c @@ -165,23 +165,31 @@ static int split_type_hw_guided(MPIR_Comm * comm_ptr, int key, const char *resou goto fn_exit; } + if (MPIR_hwtopo_get_type_id(resource_type) == MPIR_HWTOPO_TYPE__NODE) { + /* "node" or "machine": the node comm is the result. It does not depend + * on hwtopo, e.g. on osx, where the process binding cannot be queried. */ + *newcomm_ptr = node_comm; + node_comm = NULL; + goto fn_exit; + } + if (!MPIR_hwtopo_is_initialized()) { /* if hwtopo is not available, return MPI_COMM_NULL */ *newcomm_ptr = NULL; goto fn_exit; } - /* only proceed when we have a proper gid, i.e. bindset belongs to a - * single instance of given resource_type */ + /* A process that is not within a single instance of the given + * resource_type gets MPI_COMM_NULL. Such processes still need to + * participate in the split. NOTE: unlike HW_UNGUIDED, the result is + * not required to be a proper subset. */ + int color = MPI_UNDEFINED; MPIR_hwtopo_gid_t gid = MPIR_hwtopo_get_obj_by_name(resource_type); - mpi_errno = MPIR_Comm_split_impl(node_comm, gid, key, newcomm_ptr); - MPIR_ERR_CHECK(mpi_errno); - - if ((*newcomm_ptr)->remote_size == node_comm->remote_size) { - /* failed to result in a proper split */ - MPIR_Comm_free_impl(*newcomm_ptr); - *newcomm_ptr = NULL; + if (gid != MPIR_HWTOPO_GID_ROOT) { + color = gid; } + mpi_errno = MPIR_Comm_split_impl(node_comm, color, key, newcomm_ptr); + MPIR_ERR_CHECK(mpi_errno); fn_exit: if (node_comm) { diff --git a/test/mpi/comm/cmsplit_type.c b/test/mpi/comm/cmsplit_type.c index d0fe7d21364..bdaea490cb8 100644 --- a/test/mpi/comm/cmsplit_type.c +++ b/test/mpi/comm/cmsplit_type.c @@ -73,6 +73,19 @@ int main(int argc, char *argv[]) MPI_Info_free(&info); } + /* Test MPI_COMM_TYPE_HW_GUIDED: "machine" always matches, it must not return + * MPI_COMM_NULL even when it is not a proper subset (e.g. single node). */ + MPI_Info_create(&info); + MPI_Info_set(info, "mpi_hw_resource_type", "machine"); + MPI_Comm_split_type(MPI_COMM_WORLD, MPI_COMM_TYPE_HW_GUIDED, 0, info, &comm); + if (comm == MPI_COMM_NULL) { + printf("MPI_COMM_TYPE_HW_GUIDED (machine) returned MPI_COMM_NULL\n"); + errs++; + } else { + MPI_Comm_free(&comm); + } + MPI_Info_free(&info); + /* Test MPI_COMM_TYPE_HW_GUIDED: pass MPI_INFO_NULL, it must return MPI_COMM_NULL. */ info = MPI_INFO_NULL; MPI_Comm_split_type(MPI_COMM_WORLD, MPI_COMM_TYPE_HW_GUIDED, 0, info, &comm);