1   
  2   
  3  """ 
  4  This is the **MPI for Python** package. 
  5   
  6  What is *MPI*? 
  7  ============== 
  8   
  9  The *Message Passing Interface*, is a standardized and portable 
 10  message-passing system designed to function on a wide variety of 
 11  parallel computers. The standard defines the syntax and semantics of 
 12  library routines and allows users to write portable programs in the 
 13  main scientific programming languages (Fortran, C, or C++). Since 
 14  its release, the MPI specification has become the leading standard 
 15  for message-passing libraries for parallel computers. 
 16   
 17  What is *MPI for Python*? 
 18  ========================= 
 19   
 20  *MPI for Python* provides MPI bindings for the Python programming 
 21  language, allowing any Python program to exploit multiple processors. 
 22  This package is constructed on top of the MPI-1/2 specifications and 
 23  provides an object oriented interface which closely follows MPI-2 C++ 
 24  bindings. 
 25  """ 
 26   
 27  __version__ = '3.0.2' 
 28  __author__ = 'Lisandro Dalcin' 
 29  __credits__ = 'MPI Forum, MPICH Team, Open MPI Team' 
 30   
 31   
 32  __all__ = ['MPI'] 
 33   
 34   
 36      """Return the directory in the package that contains header files. 
 37   
 38      Extension modules that need to compile against mpi4py should use 
 39      this function to locate the appropriate include directory. Using 
 40      Python distutils (or perhaps NumPy distutils):: 
 41   
 42        import mpi4py 
 43        Extension('extension_name', ... 
 44                  include_dirs=[..., mpi4py.get_include()]) 
 45   
 46      """ 
 47      from os.path import join, dirname 
 48      return join(dirname(__file__), 'include') 
  49   
 50   
 52      """Return a dictionary with information about MPI.""" 
 53      from os.path import join, dirname 
 54      try: 
 55          from configparser import ConfigParser 
 56      except ImportError:   
 57          from ConfigParser import ConfigParser 
 58      parser = ConfigParser() 
 59      parser.read(join(dirname(__file__), 'mpi.cfg')) 
 60      return dict(parser.items('mpi')) 
  61   
 62   
 64      """Runtime configuration options. 
 65   
 66      Parameters 
 67      ---------- 
 68      initialize : bool 
 69          Automatic MPI initialization at import (default: True). 
 70      threads : bool 
 71          Request for thread support (default: True). 
 72      thread_level : {'multiple', 'serialized', 'funneled', 'single'} 
 73          Level of thread support to request (default: 'multiple'). 
 74      finalize : None or bool 
 75          Automatic MPI finalization at exit (default: None). 
 76      fast_reduce : bool 
 77          Use tree-based reductions for objects (default: True). 
 78      recv_mprobe : bool 
 79          Use matched probes to receive objects (default: True). 
 80      errors : {'exception', 'default', 'fatal'} 
 81          Error handling policy (default: 'exception'). 
 82   
 83      """ 
 84      for key in kargs: 
 85          if not hasattr(rc, key): 
 86              raise TypeError("unexpected argument '{0}'".format(key)) 
 87      for key, value in kargs.items(): 
 88          setattr(rc, key, value) 
 89   
 90  rc.initialize = True 
 91  rc.threads = True 
 92  rc.thread_level = 'multiple' 
 93  rc.finalize = None 
 94  rc.fast_reduce = True 
 95  rc.recv_mprobe = True 
 96  rc.errors = 'exception' 
 97  __import__('sys').modules[__name__ + '.rc'] = rc 
 98   
 99   
101      """Support for the MPI profiling interface. 
102   
103      Parameters 
104      ---------- 
105      name : str 
106         Name of the profiler library to load. 
107      path : list of str, optional 
108         Additional paths to search for the profiler. 
109      logfile : str, optional 
110         Filename prefix for dumping profiler output. 
111   
112      """ 
113      import sys 
114      import os 
115      from .dl import dlopen, dlerror, RTLD_NOW, RTLD_GLOBAL 
116   
117      def lookup_dylib(name, path): 
118           
119          pattern = [] 
120          if sys.platform.startswith('win'):   
121              pattern.append(('', '.dll')) 
122          elif sys.platform == 'darwin':   
123              pattern.append(('lib', '.dylib')) 
124          elif os.name == 'posix':   
125              pattern.append(('lib', '.so')) 
126          pattern.append(('', '')) 
127          for pth in path: 
128              for (lib, dso) in pattern: 
129                  filename = os.path.join(pth, lib + name + dso) 
130                  if os.path.isfile(filename): 
131                      return os.path.abspath(filename) 
132          return None 
 133   
134      logfile = kargs.pop('logfile', None) 
135      if logfile: 
136          if name in ('mpe',): 
137              if 'MPE_LOGFILE_PREFIX' not in os.environ: 
138                  os.environ['MPE_LOGFILE_PREFIX'] = logfile 
139          if name in ('vt', 'vt-mpi', 'vt-hyb'): 
140              if 'VT_FILE_PREFIX' not in os.environ: 
141                  os.environ['VT_FILE_PREFIX'] = logfile 
142   
143      path = kargs.pop('path', []) 
144      if isinstance(path, str): 
145          path = [path] 
146      else: 
147          path = list(path) 
148      prefix = os.path.dirname(__file__) 
149      path.append(os.path.join(prefix, 'lib-pmpi')) 
150      filename = lookup_dylib(name, path) 
151      if filename is None: 
152          raise ValueError("profiler '{0}' not found".format(name)) 
153   
154      handle = dlopen(filename, RTLD_NOW | RTLD_GLOBAL) 
155      if handle: 
156          profile.registry.append((name, (handle, filename))) 
157      else: 
158          from warnings import warn 
159          warn(dlerror()) 
160   
161  profile.registry = [] 
162