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