MPI on the grid

From Begrid Wiki
Jump to navigationJump to search

This will explain how to run MPI jobs on the grid. In this document we will not elaborate on cross site MPI jobs, only jobs within one site (cluster).

MPI code

We use a standard MPI flavor (OpenMPI) and standard C code that uses MPI. This code should run on any MPI-enabled machine (like a cluster).

Code for mpi-test.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;
}

MPI wrapper and JDL file

In this section we will prepare our MPI job for execution on the grid; we need a wrapper like "mpirun", and of course a JDL file.

The wrapper code is necessary to start the job on multiple processors (or cores). This is mpi-start-wrapper.sh:

#!/bin/bash

# Pull in the arguments.
MY_EXECUTABLE=<tt>pwd</tt>/$1
MPI_FLAVOR=$2

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

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

# 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

This is 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
}

And this is the JDL file, mpi-test.jdl:

#
# mpi-test.jdl
#
JobType        = "MPICH";
CPUNumber      = 16;
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);
#
# - the end
#

The requirement-lines make sure the job is only started on a site supporting OpenMPI and MPI-START. The line with CPUNumber configures the job to run on 16 cpu's (or cores); only a site with at least this number of cpu's will be selected.

Execution and result

Submit the job using the standard methods:

$ glite-wms-job-submit -a mpi-test.jdl

Connecting to the service https://wms.begrid.be:7443/glite_wms_wmproxy_server


====================== glite-wms-job-submit Success ======================

The job has been successfully submitted to the WMProxy
Your job identifier is:

https://wms.begrid.be:9000/baN2oRxNEA3vQK6YMLsy8A

==========================================================================

When the job is finished, get the outputs:

$ glite-wms-job-output --noint --dir . https://wms.begrid.be:9000/baN2oRxNEA3vQK6YMLsy8A

Connecting to the service https://wms.begrid.be:7443/glite_wms_wmproxy_server


Warning - Directory already exists:
/data/home/jo/tmp/MPI


Warning - JobPurging not allowed
 (The Operation is not allowed: Unable to complete job purge)


================================================================================

                        JOB GET OUTPUT OUTCOME

Output sandbox files for the job:
https://wms.begrid.be:9000/baN2oRxNEA3vQK6YMLsy8A
have been successfully retrieved and stored in the directory:
/data/home/jo/tmp/MPI

================================================================================

The output of this job should be something resembling this:

$ cat mpi-test.out
Modified mpirun: Executing command: mpi-start-wrapper.sh mpi-test OPENMPI
************************************************************************
UID     =  beapps028
HOST    =  node12-10a.wn.cc.kuleuven.be
DATE    =  Thu Jun 26 16:55:47 CEST 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/beapp<...>/mpi-test
mpicc -m32 -o /user/beapp<...>/mpi-test /user/beapp<...>/mpi-test.c
Successfully compiled /user/beapp<...>/mpi-test
-<STOP PRE-RUN HOOK>----------------------------------------------------
==[START]=================================================================
Hello world! from processor 0 out of 16
Hello world! from processor 2 out of 16
Hello world! from processor 15 out of 16
Hello world! from processor 6 out of 16
Hello world! from processor 3 out of 16
Hello world! from processor 14 out of 16
Hello world! from processor 9 out of 16
Hello world! from processor 4 out of 16
Hello world! from processor 8 out of 16
Hello world! from processor 5 out of 16
Hello world! from processor 10 out of 16
Hello world! from processor 11 out of 16
Hello world! from processor 13 out of 16
Hello world! from processor 12 out of 16
Hello world! from processor 7 out of 16
Hello world! from processor 1 out of 16
==[FINISHED]==============================================================
-<START POST-RUN HOOK>---------------------------------------------------
Executing post hook.
Finished the post hook.
-<STOP POST-RUN HOOK>----------------------------------------------------


Template:TracNotice