ACCC Home Page ACADEMIC COMPUTING and COMMUNICATIONS CENTER
Accounts / Passwords Email Labs / Classrooms Telecom Network Security Software Computing and Network Services Education / Teaching Getting Help
 

Argo Beowulf Cluster: MPI Commands and Examples

 
MPI routines: Basic Commands
MPI_Comm_rank Return the rank of the calling process in a communicator.
MPI_Comm_size Return the size of the group associated with a communicator.
MPI_Finalize Terminate the MPI execution environment.
MPI_Get_processor_name Return the name of the processing node.
MPI_Init Start the MPI execution environment.
MPI_Initialized See if the MPI environment has been initialized (has MPI_Init been called).
MPI_Recv Receive a message.
MPI_Send Send a message.

MPI routines: Collective Communication
MPI_Allgather Send data from each process in a group to all the other processes in the group. Also see MPI_Gather.
MPI_Allreduce Perform an operation on an operand and distribute the result to all processes in the group. Also see MPI_reduce.
MPI_Bcast Broadcasts a message from the root process to all other processes in the group.
MPI_Gather Send data from processes in a group to the root process (reverse of MPI_Scatter).
MPI_Reduce Perform an operation on an operand and store the result on the root process. Also see MPI_Allreduce.
MPI_Scatter Send data from one process to all other processes in the group (reverse of MPI_Gather).

MPI routines: Derived datatypes
MPI_Address Return the address of a variable.
MPI_Type_commit Commit the datatype.
MPI_Type_contiguous Build a derived datatype whose elements are contiguous entries in an array.
MPI_Type_free Mark datatype for deallocation.
MPI_Type_indexed Build a derived datatype whose elements are arbitrary entries in an array.
MPI_Type_struct Build a derived datatype.
MPI_Type_vector Build a derived datatype whose elements are equally spaced entries in an array.

MPI routines: Groups
MPI_Comm_Group Get the underlying group for a communicator.
MPI_Comm_incl Form a new group.

MPI_Comm_rank

    Return the rank of the calling process in a communicator.

  • Syntax
      int MPI_Comm_rank(MPI_Comm comm int *rank)

  • Notes
    • None

  • Example program (C) including output:
    #include "mpi.h"
    #include ‹stdio.h›
    
    int main( int argc, char *argv[] )
    {
    	int numprocs, myrank,work;
    
    MPI_Init(&argc, &argv ); 
    MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
    MPI_Comm_rank(MPI_COMM_WORLD,&myrank);
    if (myrank) printf("My process rank ==> %d\n",myrank);
    MPI_Finalize();
    }
    
    mpirun -np 2 example
    /opt/scali/bin/mpimon -stdin all  example  --  argo4-4 1 argo4-3 1
    My process rank ==> 1
    

MPI_Comm_size

    Return the size of the group associated with a communicator.

  • Syntax
      int MPI_Comm_Size(MPI_Comm comm int *size)

  • Notes
    • None

  • Example program (C) including output:
    #include "mpi.h"
    #include ‹stdio.h›
    
    int main( int argc, char *argv[] )
    {
    	int numprocs, myrank,work;
    
    MPI_Init(&argc, &argv ); 
    MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
    MPI_Comm_rank(MPI_COMM_WORLD,&myrank);
    if (!myrank) printf("Number of processes ==> %d\n",numprocs);
    MPI_Finalize();
    }
    
    mpirun -np 2 example
    /opt/scali/bin/mpimon -stdin all  example  --  argo4-4 1 argo4-3 1
    Number of processes ==> 2
    

MPI_Finalize

    Terminate the MPI execution environment.

  • Syntax
      int MPI_Finalize(void)

  • Notes
    • This routine does not have to be the last line in your program. It may be placed anywhere so long as no other MPI library calls follow it.

  • Example program (C) including output:
    #include "mpi.h"
    #include ‹stdio.h›
    
    int main( int argc, char *argv[] )
    {
    MPI_Init(&argc, &argv );
    printf ("The return code from MPI_Finalize is %d\n",MPI_Finalize());
    }
    
    mpirun -np 1 example
    /opt/scali/bin/mpimon -stdin all  example  --  argo4-4 1
    The return code from MPI_Finalize is 0
    

MPI_Get_processor_name

    Return the name of the processing node.

  • Syntax
      int MPI_Get_processor_name(char* name int resultlen)

  • Notes
    • None

  • Example program (C) including output:
    #include "mpi.h"
    #include ‹stdio.h›
    
    int main( int argc, char *argv[] )
    {
    	int numprocs, myrank, namelen, i;
            char processor_name[MPI_MAX_PROCESSOR_NAME];
            char greeting[MPI_MAX_PROCESSOR_NAME + 80];
            MPI_Status status;
    
    MPI_Init(&argc, &argv );
    MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
    MPI_Comm_rank(MPI_COMM_WORLD,&myrank);
    MPI_Get_processor_name(processor_name,&namelen);
    sprintf(greeting, "hello, world from process %d of %d on %s",myrank,numprocs,processor_name);
    if (myrank == 0) {
         printf("%s\n", greeting);
         for (i=1;i‹numprocs;i++) {
            MPI_Recv(greeting,sizeof(greeting),MPI_CHAR,i,1,MPI_COMM_WORLD,&status);
            printf("%s\n",greeting);
           }
      }
    else 
        MPI_Send(greeting,strlen(greeting)+1,MPI_CHAR,0,1,MPI_COMM_WORLD);
    MPI_Finalize();
    return 0;
    }
    
    mpirun -np 2 example
    /opt/scali/bin/mpimon -stdin all  example  --  argo4-4 1 argo4-3 1
    hello, world from process 0 of 2 on argo4-4
    hello, world from process 1 of 2 on argo4-3
    

MPI_Init

    Start the MPI execution environment.

  • Syntax
      int MPI_Init(int* argc_ptr,char** argv_ptr[])

  • Notes
    • This routine does not have to be the first line in your program. It may be placed anywhere so long as it is executed before any calls to other MPI routines.

  • Example program (C) including output:
    #include "mpi.h"
    #include ‹stdio.h›
    
    int main( int argc, char *argv[] )
    {
    printf ("The return code from MPI_Init is %d\n",MPI_Init(&argc, &argv ));
    MPI_Finalize();
    }
    
    mpirun -np 1 example
    /opt/scali/bin/mpimon -stdin all  example  --  argo4-4 1
    The return code from MPI_Init is 0
    

MPI_Initialize

    See if the MPI environment has been initialized (has MPI_Init been called).

  • Syntax
      int MPI_Initialize(int*)

  • Notes
    • None.

  • Example program (C) including output:
    #include "mpi.h"
    #include ‹stdio.h›
    
    int main( int argc, char *argv[] )
    {
            int* rc1;
    
    MPI_Initialized(rc1) ?  printf("MPI_init called\n") : printf("MPI_Init not called\n");
    MPI_Init(&argc, &argv);
    !(MPI_Initialized(rc1)) ?  printf("MPI_init called\n") : printf("MPI_Init not called\n");
    MPI_Finalize();
    }
    
    mpirun -np 1 example
    /opt/scali/bin/mpimon -stdin all  example  --  argo4-4 1
    MPI_Init not called
    MPI_init called
    

MPI_Recv

    Receive a message.

  • Syntax
      int MPI_Recv(void* message, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status* status)

  • Notes
    • None

  • Example program (C) including output:
    #include "mpi.h"
    #include ‹stdio.h›
    
    int main( int argc, char *argv[] )
    {
    	int numprocs, myrank, namelen, i, num_chars, src;
            char processor_name[MPI_MAX_PROCESSOR_NAME];
            char greeting[100], *greeting1;
            MPI_Status status;
    
    MPI_Init(&argc, &argv );
    MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
    MPI_Comm_rank(MPI_COMM_WORLD,&myrank);
    MPI_Get_processor_name(processor_name,&namelen);
    
    sprintf(greeting,"Hello world from %s - process %d of %d",processor_name,myrank,numprocs);
    
    if (myrank == 0) {
         printf("Hello world from %s - process %d of %d\n",processor_name,myrank,numprocs);
         for (i=1;i‹numprocs;i++) {
            MPI_Probe(MPI_ANY_SOURCE,1,MPI_COMM_WORLD,&status);
            MPI_Get_count(&status,MPI_CHAR,&num_chars);
            src = status.MPI_SOURCE;
            MPI_Recv(greeting,num_chars,MPI_CHAR,src,1,MPI_COMM_WORLD,&status);
            printf("%s\n",greeting); 
          }
      }
    else {
        MPI_Send(greeting,strlen(greeting)+1,MPI_CHAR,0,1,MPI_COMM_WORLD);
      }
    MPI_Finalize();
    return 0;
    }
    
    mpirun -np 2 example
    /opt/scali/bin/mpimon -stdin all  example  --  argo4-4 1 argo4-3 1
    Hello world from argo4-4 - process 0 of 2
    Hello world from argo4-3 - process 1 of 2
    

MPI_Send

    Send a message.

  • Syntax
      int MPI_Send(void* message, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm)

  • Notes
    • None

  • Example program (C) including output:
    #include "mpi.h"
    #include ‹stdio.h›
    
    int main( int argc, char *argv[] )
    {
    	int numprocs, myrank, namelen, i, num_chars, src;
            char processor_name[MPI_MAX_PROCESSOR_NAME];
            char greeting[100], *greeting1;
            MPI_Status status;
    
    MPI_Init(&argc, &argv );
    MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
    MPI_Comm_rank(MPI_COMM_WORLD,&myrank);
    MPI_Get_processor_name(processor_name,&namelen);
    
    sprintf(greeting,"Hello world from %s - process %d of %d",processor_name,myrank,numprocs);
    
    if (myrank == 0) {
         printf("Hello world from %s - process %d of %d\n",processor_name,myrank,numprocs);
         for (i=1;i‹numprocs;i++) {
            MPI_Probe(MPI_ANY_SOURCE,1,MPI_COMM_WORLD,&status);
            MPI_Get_count(&status,MPI_CHAR,&num_chars);
            src = status.MPI_SOURCE;
            MPI_Recv(greeting,num_chars,MPI_CHAR,src,1,MPI_COMM_WORLD,&status);
            printf("%s\n",greeting); 
          }
      }
    else {
        MPI_Send(greeting,strlen(greeting)+1,MPI_CHAR,0,1,MPI_COMM_WORLD);
      }
    MPI_Finalize();
    return 0;
    }
    
    mpirun -np 2 example
    /opt/scali/bin/mpimon -stdin all  example  --  argo4-4 1 argo4-3 1
    Hello world from argo4-4 - process 0 of 2
    Hello world from argo4-3 - process 1 of 2
    

MPI_Allgather

    Send data from each processes to all the other processes in the group associated with communicator comm.

  • Syntax
      int MPI_Gather(void* send_data, int send_count, MPI_Datatype sendtype, void* receive_data, int receive_count, MPI_Datatype receivetype, int root, MPI_Comm comm)

  • Notes
    • Diagram of an allgather operation:
                                   Buffer location                       Buffer location
                                   0      1      2                       0       1       2
                          +---+ +------+------+------+         +---+ +-------+-------+-------+
                          | 0 | |Data X|Data Y|Data Z|  --->   | 0 | | Data X| Data Y| Data Z|
                          +---+ +------+------+------+         +---+ +-------+-------+-------+
               Process    | 1 |                        Process | 1 | | Data X| Data Y| Data Z|
                          +---+                                +---+ +-------+-------+-------+
                          | 2 |                                | 2 | | Data X| Data Y| Data Z|
                          +---+                                +---+ +-------+-------+-------+
      
                          Compare that to the a gather operation:
      
                                   Buffer location                       Buffer location
                                   0      1      2                       0       1       2
                          +---+ +------+------+------+         +---+ +-------+-------+-------+
                          | 0 | |Data X|Data Y|Data Z|  <---   | 0 | | Data X|       |       |
                          +---+ +------+------+------+         +---+ +-------+-------+-------+
               Process    | 1 |                        Process | 1 | | Data Y|       |       |
                          +---+                                +---+ +-------+-------+-------+
                          | 2 |                                | 2 | | Data Z|       |       |
                          +---+                                +---+ +-------+-------+-------+
  • Example program (C) including output:
    #include "mpi.h"
    #include ‹stdio.h›
    
    int main (int argc, char *argv[])
    {
      int numprocs, myrank, loop, loop1;
      int send_data[3] = { 3, 4, 5 };
      int rec_data[3] = {-1,-1,-1};
    
    	MPI_Init(&argc,&argv);
    	MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
    	MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
            for (loop=0;loop‹=2;loop++) {
               if (myrank == loop) {
                   printf ("Process %d of %d:  send_data[%d] ==> %d\n",myrank, numprocs, loop, send_data[loop]);
                 }
              }
            MPI_Allgather(send_data,3,MPI_INT,rec_data,3,MPI_INT,MPI_COMM_WORLD);
            for (loop=0;loop<=numprocs;loop++) {
                if (myrank == loop) {
                    printf("Process %d of %d\n",myrank,numprocs);
                    for (loop1=0;loop1‹=2;loop1++) {
                        printf("rec_data[%d] ==> %d\n",loop1,rec_data[loop1]);
                      }
                    printf("\n");
                  }
              }
    	MPI_Finalize();
    	return 0;
    }
    
    mpirun -np 3 example
    /opt/scali/bin/mpimon -stdin all  example  --  argo4-4 1 argo4-3 1 argo4-2 1
    Process 1 of 3:  send_data[1] ==> 4
    Process 2 of 3:  send_data[2] ==> 5
    Process 0 of 3:  send_data[0] ==> 3
    Process 1 of 3
    rec_data[0] ==> 3
    rec_data[1] ==> 4
    rec_data[2] ==> 5
    
    Process 0 of 3
    rec_data[0] ==> 3
    rec_data[1] ==> 4
    rec_data[2] ==> 5
    
    Process 2 of 3
    rec_data[0] ==> 3
    rec_data[1] ==> 4
    rec_data[2] ==> 5
    

MPI_Allreduce

    Peform the operation operator on each processes' copy of operand and store the result in result on all the processes in the communicator comm (unlike MPI_Reduce which stores the result just on the root process.

  • Syntax
      int MPI_Allreduce(void* operand, void* result, int count, MPI_Datatype datatype, MPI_Op operator, MPI_Comm comm)

  • Notes
    • As is also the case for MPI_Reduce aliasing, referencing the same variable for the fields operand and result is not permitted. For example:

        MPI_Allreduce(&total,&total,1,MPI_FLOAT,MPI_SUM,MPI_COMM_WORLD)

    • Click here to see a list reduction operands.

  • Example program (C) including output:
    #include "mpi.h"
    #include ‹stdio.h›
    
    int main( int argc, char *argv[] )
    {
    	int numprocs, myrank;
            float a1,a2;
            float subtotal,total=0;
    
    MPI_Init(&argc, &argv );
    MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
    MPI_Comm_rank(MPI_COMM_WORLD,&myrank);
    if (!myrank) {
    	printf("Enter a and b\n");
    	scanf("%f %f", &a1, &a2);
      }
    MPI_Bcast(&a1,1,MPI_FLOAT,0,MPI_COMM_WORLD); 
    MPI_Bcast(&a2,1,MPI_FLOAT,0,MPI_COMM_WORLD); 
    subtotal = a1 + a2;
    printf("rank ==> %d of %d -- Subtotal ==> %f\n",myrank,numprocs,subtotal);
    
    MPI_Allreduce(&subtotal,&total,1,MPI_FLOAT,MPI_SUM,MPI_COMM_WORLD);
    printf("rank ==> %d of %d -- Grand total ==> %f\n",myrank,numprocs,total);
    MPI_Finalize();
    return 0;
    }
    
    mpirun -np 3 example
    /opt/scali/bin/mpimon -stdin all  example  --  argo4-4 1 argo4-3 1 argo4-2 1
    Enter a and b
    1 2
    rank ==> 1 of 3 -- Subtotal ==> 3.000000
    rank ==> 2 of 3 -- Subtotal ==> 3.000000
    rank ==> 0 of 3 -- Subtotal ==> 3.000000
    rank ==> 0 of 3 -- Grand total ==> 9.000000
    rank ==> 1 of 3 -- Grand total ==> 9.000000
    rank ==> 2 of 3 -- Grand total ==> 9.000000
    

MPI_Bcast

    Broadcast a message buffer from the root process to every process in the communicator comm.

  • Syntax
      int MPI_Bcast(void* buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm)

  • Notes
    • Diagram of a broadcast operation:
                                   Buffer location                       Buffer location
                                   0      1      2                       0       1       2
                          +---+ +------+------+------+         +---+ +-------+-------+-------+
                          | 0 | |Data X|Data Y|Data Z|  --->   | 0 | | Data X|       |       |
                          +---+ +------+------+------+         +---+ +-------+-------+-------+
               Process    | 1 |                        Process | 1 | | Data X|       |       |
                          +---+                                +---+ +-------+-------+-------+
                          | 2 |                                | 2 | | Data X|       |       |
                          +---+                                +---+ +-------+-------+-------+
  • Example program (C) including output:
    #include "mpi.h"
    #include ‹stdio.h›
    
    int main( int argc, char *argv[] )
    {
            int numprocs, myrank;
            float a1,a2;
    MPI_Init(&argc, &argv );
    MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
    MPI_Comm_rank(MPI_COMM_WORLD,&myrank);
    if (!myrank) {
            printf("Enter a and b\n");
            scanf("%f %f", &a1, &a2);
    }
    MPI_Bcast(&a1,1,MPI_FLOAT,0,MPI_COMM_WORLD);
    MPI_Bcast(&a2,1,MPI_FLOAT,0,MPI_COMM_WORLD);
    printf("rank ==> %d of %d -- a1 ==> %f a2 ==> %f \n",myrank,numprocs,a1,a2);
    MPI_Finalize();
    return 0;
    }
    
    mpirun -np 2 example
    /opt/scali/bin/mpimon -stdin all  example  --  argo4-4 1 argo4-3 1
    Enter a and b
    1.01 2.02
    rank ==> 0 of 2 -- a1 ==> 1.010000 a2 ==> 2.020000 
    rank ==> 1 of 2 -- a1 ==> 1.010000 a2 ==> 2.020000 
    

MPI_Gather

    MPI_Gather collects data from each process in a group and returns it to the root process. Datum is placed in a location in the receive buffer that matches the sending process id. Datum from process id zero is placed in the zero location, datum from process id one is placed in location one, and so on (see diagram below).

  • Syntax
      int MPI_Gather(void* send_data, int send_count, MPI_Datatype sendtype, void* receive_data, int receive_count, MPI_Datatype receivetype, int root, MPI_Comm comm)

  • Notes
    • Diagram of a gather operation:
                                   Buffer location                       Buffer location
                                   0      1      2                       0       1       2
                          +---+ +------+------+------+         +---+ +-------+-------+-------+
                          | 0 | |Data X|Data Y|Data Z|  <---   | 0 | | Data X|       |       |
                          +---+ +------+------+------+         +---+ +-------+-------+-------+
               Process    | 1 |                        Process | 1 | | Data Y|       |       |
                          +---+                                +---+ +-------+-------+-------+
                          | 2 |                                | 2 | | Data Z|       |       |
                          +---+                                +---+ +-------+-------+-------+
  • Example program (C) including output:
    #include "mpi.h"
    #include ‹stdio.h›
    
    int main( int argc, char *argv[])
    {
    	int numprocs, myrank,loop;
    	int      send_data[3]={3,4,5};
    	int      rec_data[3];
    
    	MPI_Init(&argc,&argv);
    	MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
    	MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
            for (loop=0;loop‹=2;loop++) {
               if (myrank == loop) {
                   printf ("Process %d of %d:  send_data[%d] ==> %d\n",myrank, numprocs, loop, send_data[loop]);
                 }
              }
            MPI_Gather(send_data,1,MPI_INT,rec_data,1,MPI_INT,0,MPI_COMM_WORLD);
            if (!myrank) {
                printf("\n");
                for (loop=0;loop‹=2;loop++) {
                   printf("Process root:  rec_data[%d] ==> %d\n",loop,rec_data[loop]);
                 }
              }
    	MPI_Finalize();
    	return 0;
    }
    
    mpirun -np 3 example
    /opt/scali/bin/mpimon -stdin all  example  --  argo4-4 1 argo4-3 1 argo4-2 1
    Process 1 of 3:  send_data[1] ==> 4
    Process 2 of 3:  send_data[2] ==> 5
    Process 0 of 3:  send_data[0] ==> 3
    
    Process root:  rec_data[0] ==> 3
    Process root:  rec_data[1] ==> 4
    Process root:  rec_data[2] ==> 5
    

MPI_Reduce

    Peform the operation operator on each processes' copy of operand and store the result in result on the root process.

  • Syntax
      int MPI_Reduce(void* operand, void* result, int count, MPI_Datatype datatype, MPI_Op operator, int root, MPI_Comm comm)

  • Notes
    • Aliasing, referencing the same variable for the fields operand and result is not permitted. For example:

        MPI_Reduce(&total,&total,1,MPI_FLOAT,MPI_SUM,0,MPI_COMM_WORLD)

    • MPI reduction operands
      MPI_MAX Maximum
      MPI_MIN Minimum
      MPI_SUM Sum
      MPI_PROD Product
      MPI_LAND Logical and
      MPI_BAND Bitwise and
      MPI_LOR Logical or
      MPI_BOR Bitwise or
      MPI_LXOR Logical exclusive or
      MPI_BXOR Bitwise exclusive or
      MPI_MAXLOC Maximum and location of maximum
      MPI_MINLOC Minimum and location of minimum

  • Example program (C) including output:
    #include "mpi.h"
    #include ‹stdio.h›
    int main( int argc, char *argv[] )
    {
            int numprocs, myrank;
            float a1,a2;
            float subtotal,total=0;
    
    MPI_Init(&argc, &argv );
    MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
    MPI_Comm_rank(MPI_COMM_WORLD,&myrank);
    if (!myrank) {
            printf("Enter a and b\n");
            scanf("%f %f", &a1, &a2);
      }
    MPI_Bcast(&a1,1,MPI_FLOAT,0,MPI_COMM_WORLD);
    MPI_Bcast(&a2,1,MPI_FLOAT,0,MPI_COMM_WORLD);
    subtotal = a1 + a2;
    printf("rank ==> %d of %d -- Subtotal ==> %f\n",myrank,numprocs,subtotal);
    
    MPI_Reduce(&subtotal,&total,1,MPI_FLOAT,MPI_SUM,0,MPI_COMM_WORLD);
    if (!myrank) printf("Grand total ==> %f\n",total);
    MPI_Finalize();
    return 0;
    }
    
    mpirun -np 3 example
    /opt/scali/bin/mpimon -stdin all  example  --  argo4-4 1 argo4-3 1 argo4-2 1
    Enter a and b
    2 3
    rank ==> 1 of 3 -- Subtotal ==> 5.000000
    rank ==> 2 of 3 -- Subtotal ==> 5.000000
    rank ==> 0 of 3 -- Subtotal ==> 5.000000
    Grand total ==> 15.000000
    

MPI_Scatter

    MPI_Scatter makes a subset of the data send_data on the processs with rank root and sends to each process in the communicator comm one of the subsets.

  • Syntax
      int MPI_Scatter(void* send_data, int send_count, MPI_Datatype sendtype, void* receive_data, int receive_count, MPI_Datatype receivetype, int root, MPI_Comm comm)

  • Notes
    • Diagram of a scatter operation:
                                   Buffer location                       Buffer location
                                   0      1      2                       0       1       2
                          +---+ +------+------+------+         +---+ +-------+-------+-------+
                          | 0 | |Data X|Data Y|Data Z|  --->   | 0 | | Data X|       |       |
                          +---+ +------+------+------+         +---+ +-------+-------+-------+
               Process    | 1 |                        Process | 1 | | Data Y|       |       |
                          +---+                                +---+ +-------+-------+-------+
                          | 2 |                                | 2 | | Data Z|       |       |
                          +---+                                +---+ +-------+-------+-------+
  • Example program (C) including output:
    #include "mpi.h"
    #include ‹stdio.h›
    
    int main( int argc, char *argv[])
    {
    	int numprocs, myrank,loop;
    	int      send_data[6]={3,4,5,6,7,8};
    	int      rec_data[2];
    
    	MPI_Init(&argc,&argv);
    	MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
    	MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
            if (!myrank) printf("\nExample of scattering 2 data points from array send_data to each of 3 processes in MPI_COMM_WORLD\n\n");
            MPI_Scatter(send_data,2,MPI_INT,rec_data,2,MPI_INT,0,MPI_COMM_WORLD);
            printf("Process %d of %d:  rec_data[%d] ==> %d\n",myrank,numprocs,0,rec_data[0]);
            printf("Process %d of %d:  rec_data[%d] ==> %d\n\n",myrank,numprocs,1,rec_data[1]);
    	MPI_Finalize();
    	return 0;
    }
    
    mpirun -np 3 example
    /opt/scali/bin/mpimon -stdin all  example  --  argo4-4 1 argo4-3 1 argo4-2 1
    
    Example of scattering 2 data points from array send_data to each of 3 processes in MPI_COMM_WORLD
    
    Process 1 of 3:  rec_data[0] ==> 5
    Process 1 of 3:  rec_data[1] ==> 6
    
    Process 0 of 3:  rec_data[0] ==> 3
    Process 0 of 3:  rec_data[1] ==> 4
    
    Process 2 of 3:  rec_data[0] ==> 7
    Process 2 of 3:  rec_data[1] ==> 8
    

MPI_Address

    Return the address of the variable location.

  • Syntax
      int MPI_Address(void* location MPI_Aint* address)

  • Notes
    • None

  • Example program (C) including output:
    #include "mpi.h"
    #include ‹stdio.h›
    /* Derived datatype example program. Sending different types of data to other
       processes */
    int main( int argc, char *argv[])
    {
    #define elements 5        
    	int numprocs, myrank,loop;
    
            /* variables to pass to other processes */
            float    x=10.0, y=20.0, z=30.0;
    	int      a=9;
    	int      b[6]={3,4,5,6,7,8};
    
    	int blocks[elements] = {1,1,1,1,1};
    	MPI_Aint disp[elements];
            MPI_Aint addresses[elements];
    
            /* Define the types of variables to transmit */
            MPI_Datatype type_of_data[elements] = {MPI_FLOAT,MPI_FLOAT,MPI_FLOAT,MPI_INT,MPI_INT};
    
            MPI_Aint next_address;
            MPI_Datatype pointer_to_new_mpi_type;
            MPI_Status status;
       
    	MPI_Init(&argc,&argv);
    	MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
    	MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
            if (!myrank) printf("\nExample of sending multiple variables, of various types, to other processes.\n\n");
    
            /* Element #5 in the list of items to pass is a pointer to a six 
               element element array. Indicate that there are six elements. 
    
            blocks[4] = 6;
    
            /* Get the address of each element to pass */
    
    	MPI_Address(&x,addresses+0); MPI_Address(&y,addresses+1);
            MPI_Address(&z,addresses+2); MPI_Address(&a,addresses+3);
            MPI_Address(&b,addresses+4);
    
            /* Calculate relative address of the variables from the first 
               variable, x, in the list of items to pass */
            for (loop = 0; loop ‹elements; loop++){
               disp[loop] = addresses[loop] - addresses[0];
             }
         
            /* Build the derived datatype for the items to pass */
    	MPI_Type_struct(elements,blocks,disp,type_of_data,&pointer_to_new_mpi_type);
            MPI_Type_commit(&pointer_to_new_mpi_type);
    
            /* Root contains the elements. Send them to other processes */
            if (!myrank) MPI_Send(&x,1,pointer_to_new_mpi_type,1,0,MPI_COMM_WORLD);
    	else {
                /* Non-root processes receive the variables and print them */
                MPI_Recv(&x,1,pointer_to_new_mpi_type,0,0,MPI_COMM_WORLD,&status);
    
                printf("In process with rank %d\n",myrank);
    	    printf("\tx ==> %f y ==> %f z ==> %f a ==> %d\n",x,y,z,a);
                for(loop=0;loop‹=elements;loop++){
    		printf("\tb[%d]==> %d\n",loop,b[loop]);
    	      }
    	  }
    
            /* finish up */
            MPI_Type_free(&pointer_to_new_mpi_type);
    	MPI_Finalize();
    	return 0;
    }
    
    mpirun -np 2 example
    /opt/scali/bin/mpimon -stdin all  example  --  argo4-4 1 argo4-3 1
    
    Example of sending multiple variables, of various types, to other processes.
    
    In process with rank 1
    	x ==> 10.000000 y ==> 20.000000 z ==> 30.000000 a ==> 9
    	b[0]==> 3
    	b[1]==> 4
    	b[2]==> 5
    	b[3]==> 6
    	b[4]==> 7
    	b[5]==> 8
    

MPI_Type_commit

    Commit the datatype.

  • Syntax
      int MPI_Type_commit(MPI_Datatype* datatype)

  • Notes
    • None

  • Example program (C) including output:
      The example program is in the section MPI_Address. Click here to go there.

MPI_Type_free

    Mark the datatype for deallocation.

  • Syntax
      int MPI_Type_free(MPI_Datatype* datatype)

  • Notes
    • MPI_Type free frees the datatype by marking the datatype variable to MPI_TYPE_NULL.

  • Example program (C) including output:
      The example program is in the section MPI_Address. Click here to go there.

MPI_Type_struct

    Build a general derived datatype constructor.

  • Syntax
      int MPI_Type_struct(int count int block_lengths[],MPI_Aint displacements[],MPI_Datatype[], MPI_Datatype* new_derived_type)

      • Field #1 (count): the number of blocks of elements. In the example program, there are five blocks. Don't confuse the number of blocks with the number of elements within a block. Each block, whether it contains a single variable or an array, constitutes one block.

      • Field #2 (block_lengths[]): the number of elements in each block. In the example, the first four blocks each contain single variables; the fifth block is an array containing six elements.

      • Field #3 (displacements[]): the relative address of each block from the first block. Each address is of type MPI_Aint, a special MPI datatype that allows for addresses larger than what can be represented by a standard C-type INTEGER.

      • Field #4 (typelist[]): the type of data contained in each block. In the example, the first three blocks each contain a single variable of type FLOAT. The fourth block contains a single INTEGER variable. The fifth block contains an array each element of that array is an INTEGER.

      • Field #5 (new_derived_type): a pointer to the new MPI datatype. Also used by the call MPI_Type_commit.

      • Notice the correspondence among the positional elements in arrays block_lengths, displacements, and typelist. For example, the first element in block_lengths, block_lengths[0], contains the number of entries in the first block. The displacement of that first block is in displacement[0] and the type of data elements (FLOAT, INT, etc) in that first block is given in typelist[0]. Information regarding the second element is contained within position one, [1], of the appropriate arrays.

  • Notes
    • None

  • Example program (C) including output:
      The example program is in the section MPI_Address. Click here to go there.

MPI_Type_vector

    A more strigent version of MPI_type_struct. Builds a derived datatype constructor consisting of a subset of entries in an array.

  • Syntax
      int MPI_Type_vector(int count int block_length, int stride,MPI_Datatype, MPI_Datatype* new_derived_type)

      • Field #1 (count): the number of elements to pass (in the example program, the number of rows is the count).

      • Field #2 (block_length): the number of entries in each element. In the example program, there is one entry in each column).

      • Field #3 (stride): the number of elements between successive elements to pass. In the following matrix, the stride is four when passing column entries. For example, between [0][1] and the next entry in the column [1][1], the entries that make up the stride are [0][1], [0][2], [0][3], and [1][0]:
               [0][0]  [0][1]  [0][2]  [0][3]  
               [1][0]  [1][1]  [1][2]  [1][3]
               [2][0]  [2][1]  [2][2]  [2][3]  
               [3][0]  [3][1]  [3][2]  [3][3]
      • In the example program, the stride is six.

      • Field #4 (typelist): the type of data being passed.

      • Field #5 (new_derived_type): a pointer to the new MPI datatype. Also used by the call MPI_Type_commit.

  • Notes
      None

  • Example program (C) including output:
    #include "mpi.h"
    #include ‹stdio.h›
    /* Derived datatype example program. Sending subset of entries in an array */
    int main( int argc, char *argv[])
    {
    #define elements 4        
    	int numprocs, myrank, loop, count, block_length, stride;
            MPI_Datatype pointer_to_new_mpi_type;
            MPI_Status status;
    
            /* two dimensional array. Pass column 3 to other processes */
    	int      x[elements][6]={
                          {10,20,30,40,50,60},
                          {70,80,90,100,110,120},
                          {130,140,150,160,170,180},
                          {190,200,210,220,230,240}
                       };
    
    	MPI_Init(&argc,&argv);
    	MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
    	MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
    
           if (!myrank) printf("\nExample program to print noncontiguous items in a two-dimensional array\n\n");
    
            /* Build the derived datatype to pass column 3 
               Pass b[0][3] containing 40
                    b[1][3]     "      100
                    b[2][3]     "      160
                    b[3][3]     "      220
            count:  number of elements (# of array entries) to pass 
            block_length: number of entries in each element 
            stride:  number of elements between each element to pass
            */
    
            count = elements; block_length = 1; stride = 6;
    	MPI_Type_vector(count,block_length,stride,MPI_INT,&pointer_to_new_mpi_type);
            /* commit the new datatype */
            MPI_Type_commit(&pointer_to_new_mpi_type);
    
            /* Root contains the elements. Send them to other processes */
            if (!myrank) MPI_Send(&x[0][3],1,pointer_to_new_mpi_type,1,0,MPI_COMM_WORLD);
    	else {
                /* Non-root processes receive the variables and print them */
                MPI_Recv(&x[0][3],1,pointer_to_new_mpi_type,0,0,MPI_COMM_WORLD,&status);
                printf("In process with rank %d\n",myrank);
                for(loop=0;loop‹elements;loop++){
    		printf("\tx[%d][3]==> %d\n",loop,x[loop][3]);
    	      }
    	  }
    
            /* finish up */
            MPI_Type_free(&pointer_to_new_mpi_type);
    	MPI_Finalize();
    	return 0;
    }
    
    
    mpirun -np 2 example 
    /opt/scali/bin/mpimon -stdin all  example  --  argo4-4 1 argo4-3 1
    
    Example program to print noncontiguous items in a two-dimensional array
    
    In process with rank 1
    	x[0][3]==> 40
    	x[1][3]==> 100
    	x[2][3]==> 160
    	x[3][3]==> 220

MPI_Comm_group

    Get the underlying group associated with a communicator.

  • Syntax
      int MPI_Comm_group(MPI_Comm comm,MPI_Group* group)

  • Notes
    • None

  • Example program (C) including output:
    #include "mpi.h"
    #include ‹stdio.h›
    int main( int argc, char *argv[] )
    {
    	int numprocs, myrank, namelen, i, myrank_in_sub_group, num_chars, src;
            char processor_name[MPI_MAX_PROCESSOR_NAME];
            char greeting[MPI_MAX_PROCESSOR_NAME + 80];
            MPI_Status status;
            MPI_Group group_world;
            MPI_Group sub_group;
            MPI_Comm sub_group_comm;
            int process_ranks[3]={0,1,2};
            
    MPI_Init(&argc, &argv );
    /* Get rank, number, and processor of processes in group whose tag is MPI_COMM_WORLD */
    MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
    MPI_Comm_rank(MPI_COMM_WORLD,&myrank);
    MPI_Get_processor_name(processor_name,&namelen);
    
    sprintf(greeting,"Hello world from %s - process %d of %d in communicator MPI_COMM_WORLD",processor_name,myrank,numprocs);
    if (myrank == 0) {
          printf("%s\n",greeting); 
          for (i=1;i‹numprocs;i++) {
               MPI_Probe(MPI_ANY_SOURCE,1,MPI_COMM_WORLD,&status);
               MPI_Get_count(&status,MPI_CHAR,&num_chars);
               src = status.MPI_SOURCE;
               MPI_Recv(greeting,num_chars,MPI_CHAR,src,1,MPI_COMM_WORLD,&status);
               printf("%s\n",greeting); 
            }
      }
    else {
          MPI_Send(greeting,strlen(greeting)+1,MPI_CHAR,0,1,MPI_COMM_WORLD);
      } 
    /* Get the group for communicator MPI_COMM_WORLD */
    MPI_Comm_group(MPI_COMM_WORLD,&group_world);
    /* Create a new group composed of three members of group underlying MPI_COMM_WORLD */ 
    MPI_Group_incl(group_world,3,process_ranks,&sub_group);
    /* Create a communicator for the new group */
    MPI_Comm_create(MPI_COMM_WORLD,sub_group,&sub_group_comm);
    /* Get my rank in the subgroup (communicator: sub_group_comm) */
    MPI_Comm_rank(sub_group_comm,&myrank_in_sub_group); 
    /* Format a message and send it to root process for printing to STDOUT */
    sprintf(greeting,"Hello again from %s - process %d of 3 in communicator sub_group_comm",processor_name,myrank_in_sub_group);
    if (myrank == 0) {
          printf("\n%s\n",greeting);
          for (i=1;i‹3;i++) {
               MPI_Probe(MPI_ANY_SOURCE,1,sub_group_comm,&status);
               MPI_Get_count(&status,MPI_CHAR,&num_chars);
               src = status.MPI_SOURCE;
               MPI_Recv(greeting,num_chars,MPI_CHAR,src,1,sub_group_comm,&status);
               printf("%s\n",greeting);
            }
      } 
    else {
          MPI_Send(greeting,strlen(greeting)+1,MPI_CHAR,0,1,sub_group_comm);
      }
    MPI_Finalize();
    return 0;
    }
    
    mpimon hello -- argo4-3 1 argo4-2 1 argo4-1 1
    Hello world from argo4-3 - process 0 of 3 in communicator MPI_COMM_WORLD
    Hello world from argo4-2 - process 1 of 3 in communicator MPI_COMM_WORLD
    Hello world from argo4-1 - process 2 of 3 in communicator MPI_COMM_WORLD
    
    Hello again from argo4-3 - process 0 of 3 in communicator sub_group_comm
    Hello again from argo4-2 - process 1 of 3 in communicator sub_group_comm
    Hello again from argo4-1 - process 2 of 3 in communicator sub_group_comm
    
    

MPI_Comm_incl

    Form a new group.

  • Syntax
      int MPI_Comm_rank(MPI_Group group,int n,int ranks[],MPI_Group* newgroup)

  • Notes
    • None

  • Example program (C) including output:

 


2004-12-3  ACCC Systems Group
UIC Home Page Search UIC Pages Contact UIC