diff --git a/.gitignore b/.gitignore index e077508..1581228 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,15 @@ spool/minos15 spool/minos26 spool/minos27 spool/qmaster/users +local/examples/src/OpenMPI/connectivity_c +local/examples/src/OpenMPI/hello_c +local/examples/src/OpenMPI/hello_cxx +local/examples/src/OpenMPI/hello_f77 +local/examples/src/OpenMPI/hello_f90 +local/examples/src/OpenMPI/ring_c +local/examples/src/OpenMPI/ring_cxx +local/examples/src/OpenMPI/ring_f77 +local/examples/src/OpenMPI/ring_f90 +local/examples/jobsbin/ompi_connectivity_* +local/examples/jobsbin/ompi_hello_* +local/examples/jobsbin/ompi_ring_* diff --git a/examples/jobs/ompi_connectivity.sh b/examples/jobs/ompi_connectivity.sh new file mode 120000 index 0000000..c845229 --- /dev/null +++ b/examples/jobs/ompi_connectivity.sh @@ -0,0 +1 @@ +../../local/examples/jobs/ompi_connectivity.sh \ No newline at end of file diff --git a/examples/jobs/ompi_hello.sh b/examples/jobs/ompi_hello.sh new file mode 120000 index 0000000..1a895f4 --- /dev/null +++ b/examples/jobs/ompi_hello.sh @@ -0,0 +1 @@ +../../local/examples/jobs/ompi_hello.sh \ No newline at end of file diff --git a/examples/jobs/ompi_ring.sh b/examples/jobs/ompi_ring.sh new file mode 120000 index 0000000..2b3fd88 --- /dev/null +++ b/examples/jobs/ompi_ring.sh @@ -0,0 +1 @@ +../../local/examples/jobs/ompi_ring.sh \ No newline at end of file diff --git a/local/examples/jobs/ompi_connectivity.sh b/local/examples/jobs/ompi_connectivity.sh new file mode 100755 index 0000000..494ff66 --- /dev/null +++ b/local/examples/jobs/ompi_connectivity.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# This is a simple example of a SGE batch script +#$ -pe mpi-rr 4-20 +#$ -l low + +# request Bourne shell as shell for job +#$ -S /bin/bash + +# +# print hostname +hostname +# print date and time +date +if [ "X$PE_HOSTFILE" != "X" ]; then + # print pe_hostfile + cat $PE_HOSTFILE + # Run ompi_connectivity + echo Starting OpenMPI job. + mpirun -v /data/gridengine/local/examples/jobsbin/ompi_connectivity_`/usr/bin/lsb_release -cs` +fi +# print date and time again +date diff --git a/local/examples/jobs/ompi_hello.sh b/local/examples/jobs/ompi_hello.sh new file mode 100755 index 0000000..f80f4e0 --- /dev/null +++ b/local/examples/jobs/ompi_hello.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# This is a simple example of a SGE batch script +#$ -pe mpi-rr 4-20 +#$ -l low + +# request Bourne shell as shell for job +#$ -S /bin/bash + +# +# print hostname +hostname +# print date and time +date +if [ "X$PE_HOSTFILE" != "X" ]; then + # print pe_hostfile + cat $PE_HOSTFILE + # Run ompi_hello + echo Starting OpenMPI job. + mpirun -v /data/gridengine/local/examples/jobsbin/ompi_hello_$(/usr/bin/lsb_release -cs) +fi +# print date and time again +date diff --git a/local/examples/jobs/ompi_ring.sh b/local/examples/jobs/ompi_ring.sh new file mode 100755 index 0000000..6a2e748 --- /dev/null +++ b/local/examples/jobs/ompi_ring.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# This is a simple example of a SGE batch script +#$ -pe mpi-rr 4-20 +#$ -l low + +# request Bourne shell as shell for job +#$ -S /bin/bash + +# +# print hostname +hostname +# print date and time +date +if [ "X$PE_HOSTFILE" != "X" ]; then + # print pe_hostfile + cat $PE_HOSTFILE + # Run ompi_ring + echo Starting OpenMPI job. + mpirun -v /data/gridengine/local/examples/jobsbin/ompi_ring_`/usr/bin/lsb_release -cs` +fi +# print date and time again +date diff --git a/local/examples/src/OpenMPI/Makefile b/local/examples/src/OpenMPI/Makefile new file mode 100644 index 0000000..321fd9a --- /dev/null +++ b/local/examples/src/OpenMPI/Makefile @@ -0,0 +1,77 @@ +# +# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana +# University Research and Technology +# Corporation. All rights reserved. +# Copyright (c) 2004-2005 The University of Tennessee and The University +# of Tennessee Research Foundation. All rights +# reserved. +# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, +# University of Stuttgart. All rights reserved. +# Copyright (c) 2004-2005 The Regents of the University of California. +# All rights reserved. +# Copyright (c) 2006-2007 Sun Microsystems, Inc. All rights reserved. +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# + +# Use the Open MPI-provided wrapper compilers. Note that gmake +# requires the CXX macro, while other versions of make (such as Sun's +# make) require the CCC macro. + +CC = mpicc +CXX = mpic++ +CCC = mpic++ +F77 = mpif77 +FC = mpif90 + +# Using -g is not necessary, but it is helpful for example programs, +# especially if users want to examine them with debuggers. Note that +# gmake requires the CXXFLAGS macro, while other versions of make +# (such as Sun's make) require the CCFLAGS macro. + +CFLAGS = -g +CXXFLAGS = -g +CCFLAGS = -g +F77FLAGS = -g +FCFLAGS = -g + +# Example programs to build + +EXAMPLES = hello_c hello_cxx hello_f77 hello_f90 \ + ring_c ring_cxx ring_f77 ring_f90 connectivity_c + +# Default target. Always build the C example. Only build the others +# if Open MPI was build with the relevant language bindings. + +all: hello_c ring_c connectivity_c + @ if test "`ompi_info --parsable | grep bindings:cxx:yes`" != ""; then \ + $(MAKE) hello_cxx ring_cxx; \ + fi + @ if test "`ompi_info --parsable | grep bindings:f77:yes`" != ""; then \ + $(MAKE) hello_f77 ring_f77; \ + fi + @ if test "`ompi_info --parsable | grep bindings:f90:yes`" != ""; then \ + $(MAKE) hello_f90 ring_f90; \ + fi + + +# The usual "clean" target + +clean: + rm -f $(EXAMPLES) *~ *.o + +# Don't rely on default rules for the fortran examples + +hello_f77: hello_f77.f + $(F77) $(F77FLAGS) $^ -o $@ +ring_f77: ring_f77.f + $(F77) $(F77FLAGS) $^ -o $@ + +hello_f90: hello_f90.f90 + $(FC) $(FCFLAGS) $^ -o $@ +ring_f90: ring_f90.f90 + $(FC) $(FCFLAGS) $^ -o $@ + diff --git a/local/examples/src/OpenMPI/Makefile.include b/local/examples/src/OpenMPI/Makefile.include new file mode 100644 index 0000000..724ccdf --- /dev/null +++ b/local/examples/src/OpenMPI/Makefile.include @@ -0,0 +1,42 @@ +# -*- makefile -*- +# +# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana +# University Research and Technology +# Corporation. All rights reserved. +# Copyright (c) 2004-2005 The University of Tennessee and The University +# of Tennessee Research Foundation. All rights +# reserved. +# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, +# University of Stuttgart. All rights reserved. +# Copyright (c) 2004-2005 The Regents of the University of California. +# All rights reserved. +# Copyright (c) 2006 Cisco Systems, Inc. All rights reserved. +# Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# + +# Note that this file does not stand on its own. It is included by a +# higher-level Makefile so that Automake features such as "make dist" +# work properly (and include all the relevant files in this directory +# in the distribution tarball). + +# If you are looking for the file that builds these examples, look at +# "Makefile" in this same directory (it is *NOT* generated by +# Automake). + +EXTRA_DIST += \ + examples/README \ + examples/Makefile \ + examples/hello_c.c \ + examples/hello_cxx.cc \ + examples/hello_f77.f \ + examples/hello_f90.f90 \ + examples/ring_c.c \ + examples/ring_cxx.cc \ + examples/ring_f77.f \ + examples/ring_f90.f90 \ + examples/connectivity_c.c diff --git a/local/examples/src/OpenMPI/README b/local/examples/src/OpenMPI/README new file mode 100644 index 0000000..02203f4 --- /dev/null +++ b/local/examples/src/OpenMPI/README @@ -0,0 +1,46 @@ +Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana + University Research and Technology + Corporation. All rights reserved. +Copyright (c) 2006 Cisco Systems, Inc. All rights reserved. +Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + +The files in this directory are sample MPI applications provided both +as a trivial primer to MPI as well as simple tests to ensure that your +Open MPI installation is working properly. + +If you are looking for a comprehensive MPI tutorial, these samples are +not enough. An excellent MPI tutorial is available here: + + http://webct.ncsa.uiuc.edu:8900/public/MPI/ + +There are 2 MPI examples in this directory, each in four languages: + +- Hello world + C: hello_c.c + C++: hello_cxx.cc + F77: hello_f77.f + F90: hello_f90.f90 + +- Send a trivial message around in a ring + C: ring_c.c + C++: ring_cxx.cc + F77: ring_f77.f + F90: ring_f90.f90 + +- Test the connectivity between all processes + C: connectivity_c.c + +The Makefile in this directory will build as many of the examples as +you have language support (e.g., if you do not have F90 bindings +compiled as part of Open MPI, the F90 examples will be skipped). + +The Makefile assumes that the wrapper compilers mpicc, mpic++, mpif77, +and mpif90 are in your path. + +Although the Makefile is tailored for Open MPI (e.g., it checks the +"ompi_info" command to see if you have support for C++, F77, and F90), +all of the example programs are pure MPI, and therefore not specific +to Open MPI. Hence, you can use a different MPI implementation to +complie and run these programs if you wish. + +Make today an Open MPI day! diff --git a/local/examples/src/OpenMPI/connectivity_c.c b/local/examples/src/OpenMPI/connectivity_c.c new file mode 100644 index 0000000..f52c8a3 --- /dev/null +++ b/local/examples/src/OpenMPI/connectivity_c.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + */ + +/* + * Test the connectivity between all processes. + */ + +#include +#include +#include +#include +#include +#include +#include + +int +main(int argc, char **argv) +{ + MPI_Status status; + int verbose = 0; + int rank; + int np; /* number of processes in job */ + int peer; + int i; + int j; + int length; + char name[MPI_MAX_PROCESSOR_NAME+1]; + + MPI_Init(&argc, &argv); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &np); + + /* + * If we cannot get the name for whatever reason, just + * set it to unknown. */ + if (MPI_SUCCESS != MPI_Get_processor_name(name, &length)) { + strcpy(name, "unknown"); + } + + if (argc>1 && strcmp(argv[1], "-v")==0) + verbose = 1; + + for (i=0; ii) { + /* receive from and reply to rank i */ + MPI_Recv(&peer, 1, MPI_INT, i, i, MPI_COMM_WORLD, &status); + MPI_Send(&rank, 1, MPI_INT, i, rank, MPI_COMM_WORLD); + } + } + + MPI_Barrier(MPI_COMM_WORLD); + if (rank==0) + printf("Connectivity test on %d processes PASSED.\n", np); + + MPI_Finalize(); + return 0; +} diff --git a/local/examples/src/OpenMPI/hello_c.c b/local/examples/src/OpenMPI/hello_c.c new file mode 100644 index 0000000..75c1aa7 --- /dev/null +++ b/local/examples/src/OpenMPI/hello_c.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2006 Cisco Systems, Inc. All rights reserved. + * + * Sample MPI "hello world" application in C + */ + +#include +#include "mpi.h" + +int main(int argc, char* argv[]) +{ + int rank, size; + + MPI_Init(&argc, &argv); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + printf("Hello, world, I am %d of %d\n", rank, size); + MPI_Barrier(MPI_COMM_WORLD); + MPI_Finalize(); + + return 0; +} diff --git a/local/examples/src/OpenMPI/hello_cxx.cc b/local/examples/src/OpenMPI/hello_cxx.cc new file mode 100644 index 0000000..6047266 --- /dev/null +++ b/local/examples/src/OpenMPI/hello_cxx.cc @@ -0,0 +1,24 @@ +// +// Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana +// University Research and Technology +// Corporation. All rights reserved. +// Copyright (c) 2006 Cisco Systems, Inc. All rights reserved. +// +// Sample MPI "hello world" application in C++ +// + +#include "mpi.h" +#include + +int main(int argc, char **argv) +{ + int rank, size; + + MPI::Init(); + rank = MPI::COMM_WORLD.Get_rank(); + size = MPI::COMM_WORLD.Get_size(); + std::cout << "Hello, world! I am " << rank << " of " << size << std::endl; + MPI::Finalize(); + + return 0; +} diff --git a/local/examples/src/OpenMPI/hello_f77 b/local/examples/src/OpenMPI/hello_f77 new file mode 100644 index 0000000..1294d2f Binary files /dev/null and b/local/examples/src/OpenMPI/hello_f77 differ diff --git a/local/examples/src/OpenMPI/hello_f77.f b/local/examples/src/OpenMPI/hello_f77.f new file mode 100644 index 0000000..684b5d9 --- /dev/null +++ b/local/examples/src/OpenMPI/hello_f77.f @@ -0,0 +1,20 @@ +C +C Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana +C University Research and Technology +C Corporation. All rights reserved. +C Copyright (c) 2006 Cisco Systems, Inc. All rights reserved. +C +C Sample MPI "hello world" application in Fortran 77 +C + program main + implicit none + include 'mpif.h' + integer ierr, rank, size + + call MPI_INIT(ierr) + call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr) + call MPI_COMM_SIZE(MPI_COMM_WORLD, size, ierr) + print *, "Hello, world, I am ", rank, " of ", size + call MPI_FINALIZE(ierr) + + end diff --git a/local/examples/src/OpenMPI/hello_f90 b/local/examples/src/OpenMPI/hello_f90 new file mode 100644 index 0000000..c653ea1 Binary files /dev/null and b/local/examples/src/OpenMPI/hello_f90 differ diff --git a/local/examples/src/OpenMPI/hello_f90.f90 b/local/examples/src/OpenMPI/hello_f90.f90 new file mode 100644 index 0000000..c5db03f --- /dev/null +++ b/local/examples/src/OpenMPI/hello_f90.f90 @@ -0,0 +1,21 @@ +! +! Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana +! University Research and Technology +! Corporation. All rights reserved. +! Copyright (c) 2004-2005 The Regents of the University of California. +! All rights reserved. +! Copyright (c) 2006 Cisco Systems, Inc. All rights reserved. +! +! Sample MPI "hello world" application in Fortran 90 +! +program main + use mpi + implicit none + integer :: ierr, rank, size + + call MPI_INIT(ierr) + call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr) + call MPI_COMM_SIZE(MPI_COMM_WORLD, size, ierr) + print *, "Hello, world, I am ", rank, " of ", size + call MPI_FINALIZE(ierr) +end diff --git a/local/examples/src/OpenMPI/install.sh b/local/examples/src/OpenMPI/install.sh new file mode 100755 index 0000000..ab6f55c --- /dev/null +++ b/local/examples/src/OpenMPI/install.sh @@ -0,0 +1,12 @@ +#/bin/bash + +# run makefile +make + +# list of executables to install +files="connectivity_c hello_cxx ring_cxx" + +# cp executables to ../../jobsbin +for file in $files; do + cp -p $file ../../jobsbin/ompi_${file%%_c*}_$(lsb_release -cs) +done diff --git a/local/examples/src/OpenMPI/ring_c.c b/local/examples/src/OpenMPI/ring_c.c new file mode 100644 index 0000000..353be3b --- /dev/null +++ b/local/examples/src/OpenMPI/ring_c.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2006 Cisco Systems, Inc. All rights reserved. + * + * Simple ring test program + */ + +#include +#include "mpi.h" + +int main(int argc, char *argv[]) +{ + int rank, size, next, prev, message, tag = 201; + + /* Start up MPI */ + + MPI_Init(&argc, &argv); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + + /* Calculate the rank of the next process in the ring. Use the + modulus operator so that the last process "wraps around" to + rank zero. */ + + next = (rank + 1) % size; + prev = (rank + size - 1) % size; + + /* If we are the "master" process (i.e., MPI_COMM_WORLD rank 0), + put the number of times to go around the ring in the + message. */ + + if (0 == rank) { + message = 10; + + printf("Process 0 sending %d to %d, tag %d (%d processes in ring)\n", + message, next, tag, size); + MPI_Send(&message, 1, MPI_INT, next, tag, MPI_COMM_WORLD); + printf("Process 0 sent to %d\n", next); + } + + /* Pass the message around the ring. The exit mechanism works as + follows: the message (a positive integer) is passed around the + ring. Each time it passes rank 0, it is decremented. When + each processes receives a message containing a 0 value, it + passes the message on to the next process and then quits. By + passing the 0 message first, every process gets the 0 message + and can quit normally. */ + + while (1) { + MPI_Recv(&message, 1, MPI_INT, prev, tag, MPI_COMM_WORLD, + MPI_STATUS_IGNORE); + + if (0 == rank) { + --message; + printf("Process 0 decremented value: %d\n", message); + } + + MPI_Send(&message, 1, MPI_INT, next, tag, MPI_COMM_WORLD); + if (0 == message) { + printf("Process %d exiting\n", rank); + break; + } + } + + /* The last process does one extra send to process 0, which needs + to be received before the program can exit */ + + if (0 == rank) { + MPI_Recv(&message, 1, MPI_INT, prev, tag, MPI_COMM_WORLD, + MPI_STATUS_IGNORE); + } + + /* All done */ + + MPI_Finalize(); + return 0; +} diff --git a/local/examples/src/OpenMPI/ring_cxx.cc b/local/examples/src/OpenMPI/ring_cxx.cc new file mode 100644 index 0000000..3ec3d9c --- /dev/null +++ b/local/examples/src/OpenMPI/ring_cxx.cc @@ -0,0 +1,78 @@ +// +// Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana +// University Research and Technology +// Corporation. All rights reserved. +// Copyright (c) 2006 Cisco Systems, Inc. All rights reserved. +// +// Simple ring test program +// + +#include "mpi.h" +#include + +int main(int argc, char *argv[]) +{ + int rank, size, next, prev, message, tag = 201; + + // Start up MPI + + MPI::Init(); + rank = MPI::COMM_WORLD.Get_rank(); + size = MPI::COMM_WORLD.Get_size(); + + // Calculate the rank of the next process in the ring. Use the + // modulus operator so that the last process "wraps around" to + // rank zero. + + next = (rank + 1) % size; + prev = (rank + size - 1) % size; + + // If we are the "master" process (i.e., MPI_COMM_WORLD rank 0), + // put the number of times to go around the ring in the message. + + if (0 == rank) { + message = 10; + + std::cout << "Process 0 sending " << message << " to " << next + << ", tag " << tag << " (" << size << " processes in ring)" + << std::endl; + MPI::COMM_WORLD.Send(&message, 1, MPI::INT, next, tag); + std::cout << "Process 0 sent to " << next << std::endl; + } + + // Pass the message around the ring. The exit mechanism works as + // follows: the message (a positive integer) is passed around the + // ring. Each time it passes rank 0, it is decremented. When + // each processes receives a message containing a 0 value, it + // passes the message on to the next process and then quits. By + // passing the 0 message first, every process gets the 0 message + // and can quit normally. + + while (1) { + MPI::COMM_WORLD.Recv(&message, 1, MPI::INT, prev, tag); + + if (0 == rank) { + --message; + std::cout << "Process 0 decremented value: " << message + << std::endl; + } + + MPI::COMM_WORLD.Send(&message, 1, MPI::INT, next, tag); + if (0 == message) { + std::cout << "Process " << rank << " exiting" << std::endl; + break; + } + } + + // The last process does one extra send to process 0, which needs + // to be received before the program can exit */ + + if (0 == rank) { + MPI::COMM_WORLD.Recv(&message, 1, MPI::INT, prev, tag); + } + + // All done + + MPI::Finalize(); + return 0; +} diff --git a/local/examples/src/OpenMPI/ring_f77 b/local/examples/src/OpenMPI/ring_f77 new file mode 100644 index 0000000..a978658 Binary files /dev/null and b/local/examples/src/OpenMPI/ring_f77 differ diff --git a/local/examples/src/OpenMPI/ring_f77.f b/local/examples/src/OpenMPI/ring_f77.f new file mode 100644 index 0000000..7f86a96 --- /dev/null +++ b/local/examples/src/OpenMPI/ring_f77.f @@ -0,0 +1,78 @@ +C +C Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana +C University Research and Technology +C Corporation. All rights reserved. +C Copyright (c) 2006 Cisco Systems, Inc. All rights reserved. +C +C Simple ring test program +C + program ring_f77 + implicit none + include 'mpif.h' + integer rank, size, tag, next, from, message, ierr + +C Start up MPI */ + + call MPI_INIT(ierr) + call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr) + call MPI_COMM_SIZE(MPI_COMM_WORLD, size, ierr) + +C Calculate the rank of the next process in the ring. Use the +C modulus operator so that the last process "wraps around" to rank +C zero. + + tag = 201 + next = mod((rank + 1), size) + from = mod((rank + size - 1), size) + +C If we are the "master" process (i.e., MPI_COMM_WORLD rank 0), put +C the number of times to go around the ring in the message. + + if (rank .eq. 0) then + message = 10 + + print *, 'Process 0 sending ', message, ' to ', next, ' tag ', + & tag, ' (', size, ' processes in ring)' + call MPI_SEND(message, 1, MPI_INTEGER, next, tag, + & MPI_COMM_WORLD, ierr) + print *, 'Process 0 sent to ', next + endif + +C Pass the message around the ring. The exit mechanism works as +C follows: the message (a positive integer) is passed around the +C ring. Each time it passes rank 0, it is decremented. When each +C processes receives a message containing a 0 value, it passes the +C message on to the next process and then quits. By passing the 0 +C message first, every process gets the 0 message and can quit +C normally. + + 10 call MPI_RECV(message, 1, MPI_INTEGER, from, tag, + & MPI_COMM_WORLD, MPI_STATUS_IGNORE, ierr) + + if (rank .eq. 0) then + message = message - 1 + print *, 'Process 0 decremented value:', message + endif + + call MPI_SEND(message, 1, MPI_INTEGER, next, tag, + & MPI_COMM_WORLD, ierr) + + if (message .eq. 0) then + print *, 'Process ', rank, ' exiting' + goto 20 + endif + goto 10 + +C The last process does one extra send to process 0, which needs to +C be received before the program can exit + + 20 if (rank .eq. 0) then + call MPI_RECV(message, 1, MPI_INTEGER, from, tag, + & MPI_COMM_WORLD, MPI_STATUS_IGNORE, ierr) + endif + +C All done + + call MPI_FINALIZE(ierr) + end + diff --git a/local/examples/src/OpenMPI/ring_f90 b/local/examples/src/OpenMPI/ring_f90 new file mode 100644 index 0000000..3ffc170 Binary files /dev/null and b/local/examples/src/OpenMPI/ring_f90 differ diff --git a/local/examples/src/OpenMPI/ring_f90.f90 b/local/examples/src/OpenMPI/ring_f90.f90 new file mode 100644 index 0000000..d74fdd2 --- /dev/null +++ b/local/examples/src/OpenMPI/ring_f90.f90 @@ -0,0 +1,73 @@ +! +! Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana +! University Research and Technology +! Corporation. All rights reserved. +! Copyright (c) 2006 Cisco Systems, Inc. All rights reserved. +! +! Simple ring test program +! +program ring + use mpi + implicit none + integer :: rank, size, tag, next, from, message, ierr + +! Start up MPI + + call MPI_INIT(ierr) + call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr) + call MPI_COMM_SIZE(MPI_COMM_WORLD, size, ierr) + +! Calculate the rank of the next process in the ring. Use the modulus +! operator so that the last process "wraps around" to rank zero. + + tag = 201 + next = mod((rank + 1), size) + from = mod((rank + size - 1), size) + +! If we are the "master" process (i.e., MPI_COMM_WORLD rank 0), put +! the number of times to go around the ring in the message. + + if (rank .eq. 0) then + message = 10 + + print *, 'Process 0 sending ', message, ' to ', next, ' tag ', tag, ' (', size, ' processes in ring)' + call MPI_SEND(message, 1, MPI_INTEGER, next, tag, MPI_COMM_WORLD, ierr) + print *, 'Process 0 sent to ', next + endif + +! Pass the message around the ring. The exit mechanism works as +! follows: the message (a positive integer) is passed around the ring. +! Each time it passes rank 0, it is decremented. When each processes +! receives a message containing a 0 value, it passes the message on to +! the next process and then quits. By passing the 0 message first, +! every process gets the 0 message and can quit normally. + +10 call MPI_RECV(message, 1, MPI_INTEGER, from, tag, MPI_COMM_WORLD, & + MPI_STATUS_IGNORE, ierr) + + if (rank .eq. 0) then + message = message - 1 + print *, 'Process 0 decremented value:', message + endif + + call MPI_SEND(message, 1, MPI_INTEGER, next, tag, MPI_COMM_WORLD, ierr) + + if (message .eq. 0) then + print *, 'Process ', rank, ' exiting' + goto 20 + endif + goto 10 + +! The last process does one extra send to process 0, which needs to be +! received before the program can exit + + 20 if (rank .eq. 0) then + call MPI_RECV(message, 1, MPI_INTEGER, from, tag, MPI_COMM_WORLD, & + MPI_STATUS_IGNORE, ierr) + endif + +! All done + + call MPI_FINALIZE(ierr) +end program +