Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 357
Pbd Avatar asked Sep 03 '25 04:09

Pbd


2 Answers

I know the question is outdated but I wanted to add to the answer by Hristo Lliev to make it work not just for OpenMPI:

you can use the value of an MPI parameter MPI_APPNUM which will be different for each executable as "color" and split the MPI_COMM_WORLD into separate communicators, then print the size of those sub-communicators. Use MPI_Comm_get_attr(MPI_COMM_WORLD, MPI_APPNUM, &val, &flag ); to get the value of MPI_APPNUM.

like image 195
maneka m Avatar answered Sep 04 '25 18:09

maneka m


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?

like image 40
Gilles Avatar answered Sep 04 '25 20:09

Gilles