# Process groups (MPI) `MPI_Comm_split` partitions all processes by a color value, which works well when membership can be computed from a formula — even/odd rank, row and column in a grid. When the subset is defined by an explicit list of ranks with no clean formula, `MPI_Comm_split` has no natural expression for it. **Process groups** are the general mechanism: `MPI_Group_incl` builds a new group from an explicit list of ranks taken from an existing group, and `MPI_Comm_create` turns it into a communicator. `MPI_Group_excl` does the same by exclusion. ```c MPI_Group world_group, sub_group; MPI_Comm sub_comm; MPI_Comm_group(MPI_COMM_WORLD, &world_group); int ranks[] = {0, 2, 4}; MPI_Group_incl(world_group, 3, ranks, &sub_group); MPI_Comm_create(MPI_COMM_WORLD, sub_group, &sub_comm); if (sub_comm != MPI_COMM_NULL) { // ranks 0, 2, 4 enter here with new ranks 0, 1, 2 in sub_comm do_work(sub_comm); MPI_Comm_free(&sub_comm); } MPI_Group_free(&sub_group); MPI_Group_free(&world_group); ``` `MPI_Comm_create` is collective over the parent communicator: every process must call it, and those excluded receive `MPI_COMM_NULL`. `MPI_Comm_create_group` (MPI-3) is collective only over the group itself, which is more efficient when the subset is small. Groups are lightweight objects; they do not enable communication on their own and have no communication context until wrapped in a communicator.