wiki:tutoMPI

Comment compiler et exécuter un job MPI simple sur la grille

Ce tutoriel décrit comment lancer un job MPI simple.

Pour lancer un job, vous avez besoin des fichiers que vous trouverez en attachement en bas de page.

  • Le fichier JDL (Job Description Langage)
    Le fichier mpi-test.jdl est le fichier qui décrit votre job.
  • Le fichier source de l'exécutable
    Le fichier mpi-test.c est la source du programme à exécuter sur la machine distante (le WN)
  • Le fichier des hooks
    Le fichier mpi-hooks.sh est le script qui défini les actions à effectuer avant et après avoir lancer l'exécutable.
  • Le fichier wrapper
    Le fichier mpi-start-wrapper.sh est le script du job proprement dit.

MPI et ses implémentation

La Message Passing Interface (MPI) est utilisé habituellement pour assurer la communication entre les tâches d'applications utilisant la parallélisation. Il existe deux versions de MPI, MPI-1 et MPI-2.
La grille supporte deux implémentation de MPI-1 (LAM et MPICH) et deux implémentations de MPI-2 (OpenMPI et MPICH2). Un site grille peut choisir de supporter seulement un sous ensemble de ces implémentations, voir même aucune...

Auparavant, exécuter des applications MPI sur la grille demandait beaucoup de configuration manuelle sur chaque site. Cela était du au besoin de compenser le fait d'avoir ou pas un système de fichiers partagé, un espace scratch par défaut etc. La configuration actuelle permet d'améliorer la portabilité des jobs et donne à l'utilisateur plus de flexibilité.

L'augmentation de portabilité et de flexibilité a été réalisé en prenant en compte les contraintes des RB et en déléguant une grosse partie des procédures d'initialisation à un script mpi-start. Le script mpi-start à été développé par le projet int.eu.grid et est basé sur le travail du MPI working group qui contient des membres de int.eu.grid et EGEE.

Utiliser le système mpi-start requiert que l'utilisateur définisse un script 'wrapper' et un ensemble de 'hooks'. Le système mpi-start s'occupe alors de la plupart des détails de bas niveau afin de faire tourner le job sur un site grille.

Wrapper script pour mpi-start

En général, un utilisateur exécute un script qui initialise les 'paths' et d'autres réglages internes pour initier le process mpi-start. Le script suivant (nommé mpi-start-wrapper.sh) est générique et ne devrait pas nécessiter de modifications.

#!/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

Le script initialise l'environnement pour le type de MPI choisi en utilisant les variables d'environnement fournies par le système. Il défini alors l'exécutable, les arguments, le type de MPI, et la localisation des scripts hook pour mpi-start. L'utilisateur peut demander optionnellement plus d'information avec les variables d'environnement 'verbose' et 'debug'. Enfin, le wrapper exécute mpi-start lui même.

Hooks for mpi-start

L'utilisateur à la possibilité d'écrire un script pour qu'il soit appelé avant ou/et après que l'exécutable MPI soit lancé. Le 'pre-hook', par exemple, peut être utilisé pour compiler l'exécutable lui même ou télécharger des données. Le 'post-hook' peut être utilisé pour analyser les résultats ou pour sauver ceux ci sur un SE de la grille. L'exemple suivant (nommé 'mpi-hooks.sh') compile l'exécutable avant de le lancer; le 'post-hook' écrit seulement un message dans la sortie standard. Un job réel aurait sauvegardé ses résultats sur la grille pour qu'un utilisateur puisse les exploiter.

#!/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
}

Définir le job et l'exécutable

Lancer le job MPI n'est pas fondamentalement différend que de lancer un job standard sur la grille. L'utilisateur doit définir un fichier JDL de 'requirements' pour le job. En voici un exemple :

#
# 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)
  # && RegExp("grid.*.lal.in2p3.fr.*sdj$",other.GlueCEUniqueID)
  ;
#
# - the end
#

Le type de job doit être 'MPICH' et l'attribut CPUNumber ( NodeNumber si vous utiliser les commandes edg-* de LCG-2) doit être défini (16 dans cet exemple). Comme son nom l'indique, cet attribut défini le nombre de CPU requis par le job.

Cet exemple utilise l'implémentation OpenMPI de MPI-2 standard. Les autres implémentations peuvent être choisies en changeant l'attribut OPENMPI (à deux endroits) par le nom de l'implémentation voulue. Les autres noms sont LAM, MPICH et MPICH2. L'attribut JobType doit être MPICH dans tous les cas, il indique juste que le job est de type MPI et n'a rien à voir avec l'implémentation utilisée.

Tous les fichiers du JDL ci-dessus ont été décrits excepté le programme MPI lui-même. C'est un simple programme 'Hello World' écrit en C dont voici le code source:

/*  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;
}

Il est fortement recommandé de compiler le programme MPI localement. Beaucoup d'option de compilation sont spécifiques au software installé sur un site. Envoyer un fichier binaire c'est risquer des performances non optimales au mieux et un crash au pire.

Lancer le job MPI

Lancer un job MPI est similaire à lancer d'autres jobs sur la grille. Utiliser les commandes glite-wms-job-submit, glite-wms-job-status, and glite-wms-job-output pour soumettre, obtenir le statut, et retrouver la sortie du job. Si le job tourne correctement, la sortie standard doit contenir quelque chose comme ça :

Hello world! from processor 15 out of 16
Hello world! from processor 0 out of 16
Hello world! from processor 1 out of 16
Hello world! from processor 7 out of 16
Hello world! from processor 2 out of 16
Hello world! from processor 3 out of 16
Hello world! from processor 4 out of 16
Hello world! from processor 6 out of 16
Hello world! from processor 8 out of 16
Hello world! from processor 9 out of 16
Hello world! from processor 12 out of 16
Hello world! from processor 5 out of 16
Hello world! from processor 10 out of 16
Hello world! from processor 14 out of 16
Hello world! from processor 11 out of 16
Hello world! from processor 13 out of 16

Si il y a des problèmes, les sorties standards et erreurs ne contiendront pas assez d'informations, utiliser le flag de debug mpi-start dans le wrapper peut vous aider.

up

Last modified 15 years ago Last modified on 11/12/2008 16:16:16

Attachments (4)

Download all attachments as: .zip

Note: See TracWiki for help on using the wiki.