HWRF  trunk@4391
mpiexec.py
1 ##@namespace produtil.mpi_impl.mpiexec
2 # Adds MPICH or MVAPICH2 support to produtil.run
3 #
4 # This module is part of the mpi_impl package -- see produtil.mpi_impl
5 # for details. This implements the Hydra MPI wrapper and MPICH MPI
6 # implementation with Intel OpenMP, but may work for other MPI
7 # implementations that use the "mpiexec" command and OpenMP
8 # implementations that use the KMP_NUM_THREADS or OMP_NUM_THREADS
9 # environment variables.
10 #
11 # @warning This module assumes the TOTAL_TASKS environment variable is
12 # set to the maximum number of MPI ranks the program has available to
13 # it. That is used when the mpirunner is called with the
14 # allranks=True option.
15 
16 import os, logging
18 
19 from .mpi_impl_base import MPIMixed,CMDFGen
20 
21 ##@var mpiexec_path
22 # Path to the mpiexec program
23 mpiexec_path=produtil.fileop.find_exe('mpiexec',raise_missing=False)
24 module_logger=logging.getLogger('lsf_cray_intel')
25 
26 def runsync(logger=None):
27  """!Runs the "sync" command as an exe()."""
28  if logger is None: logger=module_logger
29  sync=produtil.prog.Runner(['/bin/sync'])
30  p=produtil.pipeline.Pipeline(sync,capture=True,logger=logger)
31  version=p.to_string()
32  status=p.poll()
33 
34 def openmp(arg,threads):
35  """!Adds OpenMP support to the provided object
36 
37  @param arg An produtil.prog.Runner or
38  produtil.mpiprog.MPIRanksBase object tree
39  @param threads the number of threads, or threads per rank, an
40  integer"""
41  if threads is not None:
42  arg.threads=threads
43  return arg.env(OMP_NUM_THREADS=threads,KMP_NUM_THREADS=threads,
44  KMP_AFFINITY='scatter')
45  else:
46  del arg.threads
47  return arg
48 
49 def detect():
50  """!Detects whether the MPICH mpi implementation is available by
51  looking for the mpiexec program in $PATH."""
52  return mpiexec_path is not None
53 
55  """!Does this module represent an MPI implementation? Returns True."""
56  return True
57 
58 def make_bigexe(exe,**kwargs):
59  """!Returns an ImmutableRunner that will run the specified program.
60  @returns an empty list
61  @param exe The executable to run on compute nodes.
62  @param kwargs Ignored."""
63  return produtil.prog.ImmutableRunner([str(exe)],**kwargs)
64 
65 def mpirunner(arg,allranks=False,**kwargs):
66  """!Turns a produtil.mpiprog.MPIRanksBase tree into a produtil.prog.Runner
67  @param arg a tree of produtil.mpiprog.MPIRanksBase objects
68  @param allranks if True, and only one rank is requested by arg, then
69  all MPI ranks will be used
70  @param kwargs passed to produtil.mpi_impl.mpi_impl_base.CMDFGen
71  when mpiserial is in use.
72  @returns a produtil.prog.Runner that will run the selected MPI program
73  @warning Assumes the TOTAL_TASKS environment variable is set
74  if allranks=True"""
75  assert(isinstance(arg,produtil.mpiprog.MPIRanksBase))
76  (serial,parallel)=arg.check_serial()
77  if serial and parallel:
78  raise MPIMixed('Cannot mix serial and parallel MPI ranks in the '
79  'same MPI program.')
80  if arg.nranks()==1 and allranks:
81  arglist=[ a for a in arg.to_arglist(
82  pre=[mpiexec_path],
83  before=['-np',os.environ['TOTAL_TASKS']],
84  between=[':'])]
85  return produtil.prog.Runner(arglist)
86  elif allranks:
87  raise MPIAllRanksError(
88  "When using allranks=True, you must provide an mpi program "
89  "specification with only one MPI rank (to be duplicated across "
90  "all ranks).")
91  elif serial:
92  lines=[a for a in arg.to_arglist(to_shell=True,expand=True)]
93  if produtil.fileop.find_exe('mpiserial') is None:
94  raise MPISerialMissing(
95  'Attempting to run a serial program via mpiexec but the '
96  'mpiserial program is not in your $PATH.')
97  return produtil.prog.Runner(
98  [mpiexec_path,'-np','%s'%(arg.nranks()),'mpiserial'],
99  prerun=CMDFGen('serialcmdf',lines,**kwargs))
100  else:
101  arglist=[ a for a in arg.to_arglist(
102  pre=[mpiexec_path], # command is mpiexec
103  before=['-np','%(n)d'], # pass env, number of procs is kw['n']
104  between=[':']) ] # separate commands with ':'
105  return produtil.prog.Runner(arglist)
106 
This module provides a set of utility functions to do filesystem operations.
Definition: fileop.py:1
def openmp(arg, threads)
Adds OpenMP support to the provided object.
Definition: mpiexec.py:34
This class is a wrapper around launch and manage.
Definition: pipeline.py:564
def detect()
Detects whether the MPICH mpi implementation is available by looking for the mpiexec program in $PATH...
Definition: mpiexec.py:49
Implements the produtil.run: provides the object tree for representing shell commands.
Definition: prog.py:1
def make_bigexe(exe, kwargs)
Returns an ImmutableRunner that will run the specified program.
Definition: mpiexec.py:58
Object structure for describing MPI programs.
Definition: mpiprog.py:1
def can_run_mpi()
Does this module represent an MPI implementation? Returns True.
Definition: mpiexec.py:54
This is the abstract superclass of all classes that represent one or more MPI ranks, including MPI ranks that are actually serial programs.
Definition: mpiprog.py:68
def mpirunner(arg, allranks=False, kwargs)
Turns a produtil.mpiprog.MPIRanksBase tree into a produtil.prog.Runner.
Definition: mpiexec.py:65
Represents a single stage of a pipeline to execute.
Definition: prog.py:299
def find_exe
Searches the $PATH or a specified iterable of directory names to find an executable file with the giv...
Definition: fileop.py:573
Internal module that launches and monitors processes.
Definition: pipeline.py:1
An copy-on-write version of Runner.
Definition: prog.py:884
def runsync
Runs the "sync" command as an exe().
Definition: mpiexec.py:26