wiki:MPI_jobs

MPI on Grid

This wiki page is a summary of the more detailed  documentation. Though in this wiki page some files have been adapted and corrected.

MPI-start wrapper

Let's call it mpi-start-wrapper.sh

#!/bin/bash

# Pull in the arguments.
MY_EXECUTABLE=`pwd`/$1
MPI_FLAVOR=$2

# Convert flavor to lowercase for passing to mpi-start.
MPI_FLAVOR_LOWER=`echo $MPI_FLAVOR | tr '[:upper:]' '[:lower:]'`

# Pull out the correct paths for the requested flavor.
eval MPI_PATH=`printenv MPI_${MPI_FLAVOR}_PATH`

# Ensure the prefix is correctly set.  Don't rely on the defaults.
eval I2G_${MPI_FLAVOR}_PREFIX=$MPI_PATH
export I2G_${MPI_FLAVOR}_PREFIX

# Touch the executable.  It exist must for the shared file system check.
# If it does not, then mpi-start may try to distribute the executable
# when it shouldn't.
touch $MY_EXECUTABLE

# Setup for mpi-start.
export I2G_MPI_APPLICATION=$MY_EXECUTABLE
export I2G_MPI_APPLICATION_ARGS=
export I2G_MPI_TYPE=$MPI_FLAVOR_LOWER
export I2G_MPI_PRE_RUN_HOOK=mpi-hooks.sh
export I2G_MPI_POST_RUN_HOOK=mpi-hooks.sh

# If these are set then you will get more debugging information.
export I2G_MPI_START_VERBOSE=1
#export I2G_MPI_START_DEBUG=1

# Invoke mpi-start.
$I2G_MPI_START

Hooks

Let's call the file mpi-hooks.sh

#!/bin/sh

#
# This function will be called before the MPI executable is started.
# You can, for example, compile the executable itself.
#
pre_run_hook () {

  # Compile the program.
  echo "Compiling ${I2G_MPI_APPLICATION}"

  # Actually compile the program.
  cmd="mpicc ${MPI_MPICC_OPTS} -o ${I2G_MPI_APPLICATION} ${I2G_MPI_APPLICATION}.c"
  echo $cmd
  $cmd
  if [ ! $? -eq 0 ]; then
    echo "Error compiling program.  Exiting..."
    exit 1
  fi

  # Everything's OK.
  echo "Successfully compiled ${I2G_MPI_APPLICATION}"

  return 0
}

#
# This function will be called before the MPI executable is finished.
# A typical case for this is to upload the results to a storage element.
#
post_run_hook () {

  echo "Executing post hook."
  echo "Finished the post hook."

  return 0
}

The JDL file

Let's call it mpi-job.jdl

JobType = "MPICH";
NodeNumber = 4;
Executable = "mpi-start-wrapper.sh";
Arguments = "mpi-test OPENMPI";
StdOutput = "mpi-test.out";
StdError = "mpi-test.err";
InputSandbox = {"mpi-start-wrapper.sh","mpi-hooks.sh","mpi-test.c"};
OutputSandbox = {"mpi-test.err","mpi-test.out"};
Requirements =
  Member("MPI-START", other.GlueHostApplicationSoftwareRunTimeEnvironment)
  && Member("OPENMPI", other.GlueHostApplicationSoftwareRunTimeEnvironment)
  # && (other.GlueCEUniqueID == "gridce.iihe.ac.be:2119/jobmanager-pbs-betest")
  ;

The other supported implementations can be selected by changing "OPENMPI" (in two places) to the name of the desired implementation. The other names are "LAM", "MPICH", and "MPICH2". Note again that the "JobType?" attribute must be "MPICH" in all cases

Executable Source Code

Let's call it mpi-test.c

/*  hello.c
 *
 *  Simple "Hello World" program in MPI.
 *
 */

#include "mpi.h"
#include <stdio.h>
int main(int argc, char *argv[]) {

  int numprocs;  /* Number of processors */
  int procnum;   /* Processor number */

  /* Initialize MPI */
  MPI_Init(&argc, &argv);

  /* Find this processor number */
  MPI_Comm_rank(MPI_COMM_WORLD, &procnum);

  /* Find the number of processors */
  MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
  printf ("Hello world! from processor %d out of %d\n", procnum, numprocs);

  /* Shut down MPI */
  MPI_Finalize();
  return 0;
}

Output

As a result, in mpi-test.out you should have something similar to:

Modified mpirun: Executing command: ./mpi-start-wrapper.sh mpi-test OPENMPI
************************************************************************
UID     =  betest046
HOST    =  node15-9.wn.iihe.ac.be
DATE    =  Thu Mar 6 14:22:10 CET 2008
VERSION =  0.0.52
************************************************************************
mpi-start [INFO   ]: search for scheduler
mpi-start [INFO   ]: activate support for pbs
mpi-start [INFO   ]: activate support for openmpi
mpi-start [INFO   ]: call backend MPI implementation
mpi-start [INFO   ]: start program with mpirun
-<START PRE-RUN HOOK>---------------------------------------------------
Compiling /user/betest046/gram_scratch_fkK23UZSoS/.mpi/https_3a_2f_2flaranja.iihe.ac.be_3a9000_2f4TtvVjtG6CQgaftNJz2flQ/mpi-test
mpicc -m32 -o /user/betest046/gram_scratch_fkK23UZSoS/.mpi/https_3a_2f_2flaranja.iihe.ac.be_3a9000_2f4TtvVjtG6CQgaftNJz2flQ/mpi-test /user/betest046/gram_scratch_fkK23UZSoS/.mpi/https_3a_2f_2flaranja.iihe.ac.be_3a9000_2f4TtvVjtG6CQgaftNJz2flQ/mpi-test.c
Successfully compiled /user/betest046/gram_scratch_fkK23UZSoS/.mpi/https_3a_2f_2flaranja.iihe.ac.be_3a9000_2f4TtvVjtG6CQgaftNJz2flQ/mpi-test
-<STOP PRE-RUN HOOK>----------------------------------------------------
=[START]================================================================
Hello world! from processor 1 out of 4
Hello world! from processor 3 out of 4
Hello world! from processor 2 out of 4
Hello world! from processor 0 out of 4
=[FINISHED]=============================================================
-<START POST-RUN HOOK>---------------------------------------------------
Executing post hook.
Finished the post hook.
-<STOP POST-RUN HOOK>----------------------------------------------------

Other MPI exercises

 https://computing.llnl.gov/tutorials/mpi/exercise.html

Simple job

/*  hello.c
 *
 *  Simple "Hello World" program in MPI.
 *
 */
   
#include "mpi.h"
#include <stdio.h>
int main(int argc, char *argv[])
{
  int numprocs;  /* Number of processors */
  int procnum;   /* Processor number */
  /* Initialize MPI */
  MPI_Init(&argc, &argv);
  /* Find this processor number */
  MPI_Comm_rank(MPI_COMM_WORLD, &procnum);
  /* Find the number of processors */
  MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
  printf ("Hello world! from processor %d out of %d\n", procnum, numprocs);
  /* Shut down MPI */
  MPI_Finalize();
  return 0;
}

check.jdl

Type = "Job";
JobType = "MPICH";
NodeNumber = 6;
Executable = "check.sh";
StdOutput = "check.out";
StdError = "check.err";
InputSandbox = {"check.sh","mpihello.c","Makefile"};
OutputSandbox = {"check.err","check.out"};
#Requirements = (other.GlueCEInfoLRMSType == "PBS");
RetryCount = 0;
Lrms_Type = "PBS";

check.sh

#!/bin/sh -x
date
echo "SITE: $SITE_NAME"
echo "GIIS: $SITE_GIIS_URL"
echo "LOG: $GLITE_WMS_LOG_DESTINATION"
echo "==== Info ===="
env | sort
echo "==== Task ===="

make
mpiexec mpihello

echo "==== End ====="