Search code examples
c++cparallel-processingmpiopenmpi

Openmpi mpmd get communication size


I have two openmpi programs which I start like this

mpirun -n 4 ./prog1 : -n 2 ./prog2

Now how do I use MPI_Comm_size(MPI_COMM_WORLD, &size) such that i get size values as

prog1 size=4
prog2 size=2.

As of now I get "6" in both programs.


Solution

  • This is doable albeit a bit cumbersome to get that. The principle is to split MPI_COMM_WORLD into communicators based on the value of argv[0], which contains the executable's name.

    That could be something like that:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <mpi.h>
    
    int main( int argc, char *argv[] ) {
    
        MPI_Init( &argc, &argv );
    
        int wRank, wSize;
        MPI_Comm_rank( MPI_COMM_WORLD, &wRank );
        MPI_Comm_size( MPI_COMM_WORLD, &wSize );
    
        int myLen = strlen( argv[0] ) + 1;
        int maxLen;
        // Gathering the maximum length of the executable' name
        MPI_Allreduce( &myLen, &maxLen, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD );
    
        // Allocating memory for all of them
        char *names = malloc( wSize * maxLen );
        // and copying my name at its place in the array
        strcpy( names + ( wRank * maxLen ), argv[0] );
    
        // Now collecting all executable' names
        MPI_Allgather( MPI_IN_PLACE, 0, MPI_DATATYPE_NULL,
                       names, maxLen, MPI_CHAR, MPI_COMM_WORLD );
    
        // With that, I can sort-out who is executing the same binary as me
        int binIdx = 0;
        while( strcmp( argv[0], names + binIdx * maxLen ) != 0 ) {
            binIdx++;
        }
        free( names );
    
        // Now, all processes with the same binIdx value are running the same binary
        // I can split MPI_COMM_WORLD accordingly
        MPI_Comm binComm;
        MPI_Comm_split( MPI_COMM_WORLD, binIdx, wRank, &binComm );
    
        int bRank, bSize;
        MPI_Comm_rank( binComm, &bRank );
        MPI_Comm_size( binComm, &bSize );
    
        printf( "Hello from process WORLD %d/%d running %d/%d %s binary\n",
                wRank, wSize, bRank, bSize, argv[0] );
    
        MPI_Comm_free( &binComm );
    
        MPI_Finalize();
    
        return 0;
    }
    

    On my machine, I compiled and ran it as follow:

    ~> mpicc mpmd.c
    ~> cp a.out b.out
    ~> mpirun -n 3 ./a.out : -n 2 ./b.out
    Hello from process WORLD 0/5 running 0/3 ./a.out binary
    Hello from process WORLD 1/5 running 1/3 ./a.out binary
    Hello from process WORLD 4/5 running 1/2 ./b.out binary
    Hello from process WORLD 2/5 running 2/3 ./a.out binary
    Hello from process WORLD 3/5 running 0/2 ./b.out binary
    

    Ideally, this could be greatly simplified by using MPI_Comm_split_type() if the corresponding type for sorting out by binaries existed. Unfortunately, there is no such MPI_COMM_TYPE_ pre-defined in the 3.1 MPI standard. The only pre-defined one is MPI_COMM_TYPE_SHARED to sort-out between processes running on the same shared memory compute nodes... Too bad! Maybe something to consider for the next version of the standard?