Personal tools

MPI

From MohidWiki

Revision as of 10:27, 3 December 2008 by Guillaume (talk | contribs) (1 revision)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Is an acronym standing for Message Passing Interface. MPI are programing directives which allow a program to launch child processes in different nodes (other computers) through the network and communicate between them. This allows parallel processing. To Build a MOHID project for MPI refer to Compiling Mohid with MPI.

MPICH

MPICH are the libraries containing the MPI directives.

Linux installation

  • To build the MPICH libraries in linux, get them and:
>./configure FC=ifort --enable-f90
>make
>make testing
>make install
  • To compile Mohid in linux in MPI refer to this wiki.
  • To compile any program in linux simply type
>mpif90 -i-static foo.f90
  • To use an MPI program on a Linux machine simply type these lines:
mpd &
mpiexec -n 4 ./MohidWater
mpdallexit

The three lines do the following: i) install the mpi daemon, ii) run MohidWater in 4 processes, iii)once the program is finished, kill all daemons.

Samples

cpi

This little C program calculates pi.

#include "mpi.h"
#include <stdio.h>
#include <math.h>

double f(double);

double f(double a)
{
   return (4.0 / (1.0 + a*a));
}

int main(int argc,char *argv[])
{
   int    n, myid, numprocs, i;
   double PI25DT = 3.141592653589793238462643;
   double mypi, pi, h, sum, x;
   double startwtime = 0.0, endwtime;
   int    namelen;
   char   processor_name[MPI_MAX_PROCESSOR_NAME];

   MPI_Init(&argc,&argv);
   MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
   MPI_Comm_rank(MPI_COMM_WORLD,&myid);
   MPI_Get_processor_name(processor_name,&namelen);

   fprintf(stdout,"Process %d of %d is on %s\n",
           myid, numprocs, processor_name);
   fflush(stdout);

   n = 10000;                  /* default # of rectangles */
   if (myid == 0)
       startwtime = MPI_Wtime();
   MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);

   h   = 1.0 / (double) n;
   sum = 0.0;
   /* A slightly better approach starts from large i and works back */
   for (i = myid + 1; i <= n; i += numprocs)
   {
       x = h * ((double)i - 0.5);
       sum += f(x);
   }
   mypi = h * sum;

   MPI_Reduce(&mypi, &pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);

   if (myid == 0) {
       endwtime = MPI_Wtime();
       printf("pi is approximately %.16f, Error is %.16f\n",
              pi, fabs(pi - PI25DT));
       printf("wall clock time = %f\n", endwtime-startwtime);
       fflush(stdout);
   }

   MPI_Finalize();
   return 0;
}

f90pi

The same little program in fortran 90:

!**********************************************************************
!   pi3f90.f - compute pi by integrating f(x) = 4/(1 + x**2)
!
!  (C) 2001 by Argonne National Laboratory.
!      See COPYRIGHT in top-level directory.
!
!   Each node:
!    1) receives the number of rectangles used in the approximation.
!    2) calculates the areas of it's rectangles.
!    3) Synchronizes for a global summation.
!   Node 0 prints the result.
!
!  Variables:
!
!    pi  the calculated result
!    n   number of points of integration.
!    x           midpoint of each rectangle's interval
!    f           function to integrate
!    sum,pi      area of rectangles
!    tmp         temporary scratch space for global summation
!    i           do loop index
!****************************************************************************
program main

use mpi

double precision  PI25DT
parameter        (PI25DT = 3.141592653589793238462643d0)

double precision  mypi, pi, h, sum, x, f, a
integer n, myid, numprocs, i, rc
!                                 function to integrate
f(a) = 4.d0 / (1.d0 + a*a)

call MPI_INIT( ierr )
call MPI_COMM_RANK( MPI_COMM_WORLD, myid, ierr )
call MPI_COMM_SIZE( MPI_COMM_WORLD, numprocs, ierr )
print *, 'Process ', myid, ' of ', numprocs, ' is alive'

sizetype   = 1
sumtype    = 2

do
   if ( myid .eq. 0 ) then
      write(6,98)
98    format('Enter the number of intervals: (0 quits)')
      read(5,99) n
99    format(i10)
   endif

   call MPI_BCAST(n,1,MPI_INTEGER,0,MPI_COMM_WORLD,ierr)

!                                 check for quit signal
   if ( n .le. 0 ) exit

!                                 calculate the interval size
   h = 1.0d0/n

   sum  = 0.0d0
   do i = myid+1, n, numprocs
      x = h * (dble(i) - 0.5d0)
      sum = sum + f(x)
   enddo
   mypi = h * sum

!                                 collect all the partial sums
   call MPI_REDUCE(mypi,pi,1,MPI_DOUBLE_PRECISION,MPI_SUM,0, &
                   MPI_COMM_WORLD,ierr)

!                                 node 0 prints the answer.
   if (myid .eq. 0) then
       write(6, 97) pi, abs(pi - PI25DT)
97     format('  pi is approximately: ', F18.16, &
              '  Error is: ', F18.16)
   endif

enddo
call MPI_FINALIZE(rc)
stop
end

Other references