I need to divide the processes into several communicators. In one write even, and in others odd. I wrote the code, but when I run, I get errors. Help me figure out what the gap. There is an opinion that it is necessary to use MPI_Comm_split (), but I do not understand how to do it correctly.

#include <stdio.h> #include <mpi.h> #include <iostream> #include <Windows.h> #include <vector> using namespace std; int main(int argc, char *argv[]){ SetConsoleOutputCP(1251); int errCode; if ((errCode = MPI_Init(&argc, &argv)) != 0) { return errCode; } int world_rank, world_size; int *odd, *even; MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); MPI_Comm_size(MPI_COMM_WORLD, &world_size); int oddSize = world_size / 2; int evenSize = world_size - oddSize; odd = new int[oddSize]; even = new int[evenSize]; MPI_Comm odd_comm, even_comm; MPI_Group group11, group12, group13, group21, group22, group31, group32, odd_group, even_group, group_world; MPI_Comm_group(MPI_COMM_WORLD, &group_world); for (int i = 0, j = 0, p = 0; i < world_size; i++) { if (i % 2 == 0) { odd[j] = i; j++; } else { even[p] = i; p++; } } MPI_Group_incl(group_world, oddSize, odd, &odd_group); MPI_Group_incl(group_world, evenSize, even, &even_group); MPI_Comm_create(MPI_COMM_WORLD, odd_group, &odd_comm); int row_rank, row_size, size; MPI_Comm_rank(odd_comm, &row_rank); MPI_Comm_size(odd_comm, &row_size); if (world_rank == 0) cout << "Rank = " << row_rank << " Size = " << row_size << endl;/**/ MPI_Comm_free(&odd_comm); MPI_Finalize(); return 0; } 

Errors of this type appear.

 job aborted: [ranks] message [0] terminated [1] fatal error Fatal error in MPI_Comm_rank: Invalid communicator, error stack: MPI_Comm_rank(MPI_COMM_NULL, rank=0x0111FC70) failed Invalid communicator [2] terminated [3] fatal error Fatal error in MPI_Comm_rank: Invalid communicator, error stack: MPI_Comm_rank(MPI_COMM_NULL, rank=0x009FFDB8) failed Invalid communicator [4] terminated [5] fatal error Fatal error in MPI_Comm_rank: Invalid communicator, error stack: MPI_Comm_rank(MPI_COMM_NULL, rank=0x00BDF7E4) failed Invalid communicator [6-8] terminated [9] fatal error Fatal error in MPI_Comm_rank: Invalid communicator, error stack: MPI_Comm_rank(MPI_COMM_NULL, rank=0x005FF7C0) failed Invalid communicator [10-16] terminated [17] fatal error Fatal error in MPI_Comm_rank: Invalid communicator, error stack: MPI_Comm_rank(MPI_COMM_NULL, rank=0x00DFFB58) failed Invalid communicator [18-29] terminated ---- error analysis ----- [1,3,5,9,17] on DRON mpi has detected a fatal error and aborted Debug\lab2_1.exe 
  • one
    "it does not work out" what did you expect to receive (a specific example)? what happens instead? - jfs
  • @jfs Attached a screen with errors. And I expected to get several communicators and work without errors. - Alexey Medvedev
  • and what is there unclear? @jfs - Alexey Medvedev

1 answer 1

MPI_Comm_create () returns a non-empty communicator handle only to group members. The rest get a stub MPI_COMM_NULL . So the correct code will look like this:

 // ... MPI_Comm_create(MPI_COMM_WORLD, odd_group, &odd_comm); int row_rank, row_size; if (odd_comm != MPI_COMM_NULL) { MPI_Comm_rank(odd_comm, &row_rank); MPI_Comm_size(odd_comm, &row_size); if (row_rank == 0) cout << "Rank = " << row_rank << " Size = " << row_size << endl;/**/ } else { row_rank = -1; row_size = -1; } // ... if (odd_comm != MPI_COMM_NULL) { MPI_Comm_free(&odd_comm); } 

In this case, MPI_Comm_create () creates one communicator common to the specified group, but by-design it must be called from all processes of the parent communicator (for several reasons - see the MPI standard).

Also for MPI ≥2.2 MPI_Comm_create () can create several communicators for non-intersecting groups of processes at once:

 int *new_grp_members = malloc (grpSz * sizeof(int)); MPI_Group group_world, new_grp; MPI_Comm_group(MPI_COMM_WORLD, &group_world); for (int i = 0; i < grpSz; ++i) { int num = (i<<1) | is_odd; new_grp_members[i] = num; } MPI_Group_incl(group_world, grpSz, new_grp_members, &new_grp); free (new_grp_members); MPI_Comm odd_even_comm; MPI_Comm_create (MPI_COMM_WORLD, new_grp, &odd_even_comm); MPI_Group_free (&new_grp); assert ( odd_even_comm != MPI_COMM_NULL ) int row_rank, row_size; MPI_Comm_rank(odd_even_comm, &row_rank); MPI_Comm_size(odd_even_comm, &row_size); printf ("WorldRank = %d: LocalRank=%d, LocalSize = %d\n", world_rank, row_rank, row_size); MPI_Comm_free(&odd_even_comm); 

In this case, a separate communicator is created for even processes and for odd ones. Exactly the same effect can be achieved with MPI_Comm_split () :

 MPI_Comm odd_even_comm; MPI_Comm_split (MPI_COMM_WORLD, world_rank % 2, world_rank, &odd_even_comm); assert ( odd_even_comm != MPI_COMM_NULL ) // ... 
  • It really helped, thanks. Can you explain the logic to me, please?) I have 30 processes and each process is executed by the same code, i.e. creates a group, then a communicator. Will it be the same communicator and group or 30 different ones? I don't understand - Alexey Medvedev
  • @ Alexey Medvedev, added in reply - Fat-Zer