LSSTApplications  18.1.0
LSSTDataManagementBasePackage
Classes | Functions | Variables
lsst.ctrl.pool.pool Namespace Reference

Classes

class  Cache
 
class  Comm
 
class  Debugger
 
class  NoOp
 
class  PickleHolder
 
class  Pool
 
class  PoolMaster
 
class  PoolNode
 
class  PoolSlave
 
class  PoolWrapper
 
class  PoolWrapperMeta
 
class  ReductionThread
 
class  SingletonMeta
 Metaclass to produce a singleton. More...
 
class  Tags
 

Functions

def unpickleInstanceMethod (obj, name)
 
def pickleInstanceMethod (method)
 
def unpickleFunction (moduleName, funcName)
 
def pickleFunction (function)
 
def getBatchType ()
 
def setBatchType (batchType)
 
def abortOnError (func)
 
def guessPickleObj ()
 
def pickleSniffer (abort=False)
 
def catchPicklingError (func)
 
def startPool (comm=None, root=0, killSlaves=True)
 Start a process pool. More...
 

Variables

string NODE = "%s:%d" % (os.uname()[1], os.getpid())
 

Function Documentation

◆ abortOnError()

def lsst.ctrl.pool.pool.abortOnError (   func)
Function decorator to throw an MPI abort on an unhandled exception

Definition at line 108 of file pool.py.

108 def abortOnError(func):
109  """Function decorator to throw an MPI abort on an unhandled exception"""
110  @wraps(func)
111  def wrapper(*args, **kwargs):
112  try:
113  return func(*args, **kwargs)
114  except Exception as e:
115  sys.stderr.write("%s on %s in %s: %s\n" % (type(e).__name__, NODE, func.__name__, e))
116  import traceback
117  traceback.print_exc(file=sys.stderr)
118  sys.stdout.flush()
119  sys.stderr.flush()
120  if getBatchType() is not None:
121  mpi.COMM_WORLD.Abort(1)
122  else:
123  raise
124  return wrapper
125 
126 
def abortOnError(func)
Definition: pool.py:108
table::Key< int > type
Definition: Detector.cc:167
def getBatchType()
Definition: pool.py:97

◆ catchPicklingError()

def lsst.ctrl.pool.pool.catchPicklingError (   func)
Function decorator to catch errors in pickling and print something useful

Definition at line 235 of file pool.py.

235 def catchPicklingError(func):
236  """Function decorator to catch errors in pickling and print something useful"""
237  @wraps(func)
238  def wrapper(*args, **kwargs):
239  with pickleSniffer(True):
240  return func(*args, **kwargs)
241  return wrapper
242 
243 
def pickleSniffer(abort=False)
Definition: pool.py:188
def catchPicklingError(func)
Definition: pool.py:235

◆ getBatchType()

def lsst.ctrl.pool.pool.getBatchType ( )
Return a string giving the type of batch system in use

Definition at line 97 of file pool.py.

97 def getBatchType():
98  """Return a string giving the type of batch system in use"""
99  return _batchType
100 
101 
def getBatchType()
Definition: pool.py:97

◆ guessPickleObj()

def lsst.ctrl.pool.pool.guessPickleObj ( )
Try to guess what's not pickling after an exception

This tends to work if the problem is coming from the
regular pickle module.  If it's coming from the bowels
of mpi4py, there's not much that can be done.

Definition at line 163 of file pool.py.

163 def guessPickleObj():
164  """Try to guess what's not pickling after an exception
165 
166  This tends to work if the problem is coming from the
167  regular pickle module. If it's coming from the bowels
168  of mpi4py, there's not much that can be done.
169  """
170  import sys
171  excType, excValue, tb = sys.exc_info()
172  # Build a stack of traceback elements
173  stack = []
174  while tb:
175  stack.append(tb)
176  tb = tb.tb_next
177 
178  try:
179  # This is the code version of a my way to find what's not pickling in pdb.
180  # This should work if it's coming from the regular pickle module, and they
181  # haven't changed the variable names since python 2.7.3.
182  return stack[-2].tb_frame.f_locals["obj"]
183  except Exception:
184  return None
185 
186 
187 @contextmanager
def guessPickleObj()
Definition: pool.py:163

◆ pickleFunction()

def lsst.ctrl.pool.pool.pickleFunction (   function)
Pickle a function

This assumes that we can recreate the function object by grabbing
it from the proper module.  This may be violated if the function
is a lambda or in __main__.  In that case, I recommend recasting
the function as an object with a __call__ method.

Another problematic case may be a wrapped (e.g., decorated) method
in a class: the 'method' is then a function, and recreating it is
not as easy as we assume here.

Definition at line 72 of file pool.py.

72 def pickleFunction(function):
73  """Pickle a function
74 
75  This assumes that we can recreate the function object by grabbing
76  it from the proper module. This may be violated if the function
77  is a lambda or in __main__. In that case, I recommend recasting
78  the function as an object with a __call__ method.
79 
80  Another problematic case may be a wrapped (e.g., decorated) method
81  in a class: the 'method' is then a function, and recreating it is
82  not as easy as we assume here.
83  """
84  moduleName = function.__module__
85  funcName = function.__name__
86  return unpickleFunction, (moduleName, funcName)
87 
88 
89 copyreg.pickle(types.FunctionType, pickleFunction)
90 
91 try:
92  _batchType
def pickleFunction(function)
Definition: pool.py:72

◆ pickleInstanceMethod()

def lsst.ctrl.pool.pool.pickleInstanceMethod (   method)
Pickle an instance method

The instance method is divided into the object and the
method name.

Definition at line 47 of file pool.py.

47 def pickleInstanceMethod(method):
48  """Pickle an instance method
49 
50  The instance method is divided into the object and the
51  method name.
52  """
53  obj = method.__self__
54  name = method.__name__
55  return unpickleInstanceMethod, (obj, name)
56 
57 
58 copyreg.pickle(types.MethodType, pickleInstanceMethod)
59 
60 
def pickleInstanceMethod(method)
Definition: pool.py:47

◆ pickleSniffer()

def lsst.ctrl.pool.pool.pickleSniffer (   abort = False)
Context manager to sniff out pickle problems

If there's a pickle error, you're normally told what the problem
class is.  However, all SWIG objects are reported as "SwigPyObject".
In order to figure out which actual SWIG-ed class is causing
problems, we need to go digging.

Use like this:

    with pickleSniffer():
        someOperationInvolvingPickle()

If 'abort' is True, will call MPI abort in the event of problems.

Definition at line 188 of file pool.py.

188 def pickleSniffer(abort=False):
189  """Context manager to sniff out pickle problems
190 
191  If there's a pickle error, you're normally told what the problem
192  class is. However, all SWIG objects are reported as "SwigPyObject".
193  In order to figure out which actual SWIG-ed class is causing
194  problems, we need to go digging.
195 
196  Use like this:
197 
198  with pickleSniffer():
199  someOperationInvolvingPickle()
200 
201  If 'abort' is True, will call MPI abort in the event of problems.
202  """
203  try:
204  yield
205  except Exception as e:
206  if "SwigPyObject" not in str(e) or "pickle" not in str(e):
207  raise
208  import sys
209  import traceback
210 
211  sys.stderr.write("Pickling error detected: %s\n" % e)
212  traceback.print_exc(file=sys.stderr)
213  obj = guessPickleObj()
214  heldObj = PickleHolder().obj
215  if obj is None and heldObj is not None:
216  # Try to reproduce using what was being pickled using the regular pickle module,
217  # so we've got a chance of figuring out what the problem is.
218  import pickle
219  try:
220  pickle.dumps(heldObj)
221  sys.stderr.write("Hmmm, that's strange: no problem with pickling held object?!?!\n")
222  except Exception:
223  obj = guessPickleObj()
224  if obj is None:
225  sys.stderr.write("Unable to determine class causing pickle problems.\n")
226  else:
227  sys.stderr.write("Object that could not be pickled: %s\n" % obj)
228  if abort:
229  if getBatchType() is not None:
230  mpi.COMM_WORLD.Abort(1)
231  else:
232  sys.exit(1)
233 
234 
def guessPickleObj()
Definition: pool.py:163
def getBatchType()
Definition: pool.py:97
def pickleSniffer(abort=False)
Definition: pool.py:188

◆ setBatchType()

def lsst.ctrl.pool.pool.setBatchType (   batchType)
Return a string giving the type of batch system in use

Definition at line 102 of file pool.py.

102 def setBatchType(batchType):
103  """Return a string giving the type of batch system in use"""
104  global _batchType
105  _batchType = batchType
106 
107 
def setBatchType(batchType)
Definition: pool.py:102

◆ startPool()

def lsst.ctrl.pool.pool.startPool (   comm = None,
  root = 0,
  killSlaves = True 
)

Start a process pool.

Process Pool

Use this class to automatically provide 'context' to
the PoolMaster class.  If you want to call functions
that don't take a 'cache' object, use the PoolMaster
class directly, and specify context=None.

Returns a PoolMaster object for the master node. Slave nodes are run and then optionally killed.

If you elect not to kill the slaves, note that they will emerge at the point this function was called, which is likely very different from the point the master is at, so it will likely be necessary to put in some rank dependent code (e.g., look at the 'rank' attribute of the returned pools).

Note that the pool objects should be deleted (either by going out of scope or explicit 'del') before program termination to avoid a segmentation fault.

Parameters
commMPI communicator
rootRank of root/master node
killSlavesKill slaves on completion?

Definition at line 1217 of file pool.py.

1217 def startPool(comm=None, root=0, killSlaves=True):
1218  """!Start a process pool.
1219 
1220  Returns a PoolMaster object for the master node.
1221  Slave nodes are run and then optionally killed.
1222 
1223  If you elect not to kill the slaves, note that they
1224  will emerge at the point this function was called,
1225  which is likely very different from the point the
1226  master is at, so it will likely be necessary to put
1227  in some rank dependent code (e.g., look at the 'rank'
1228  attribute of the returned pools).
1229 
1230  Note that the pool objects should be deleted (either
1231  by going out of scope or explicit 'del') before program
1232  termination to avoid a segmentation fault.
1233 
1234  @param comm: MPI communicator
1235  @param root: Rank of root/master node
1236  @param killSlaves: Kill slaves on completion?
1237  """
1238  if comm is None:
1239  comm = Comm()
1240  if comm.rank == root:
1241  return PoolMaster(comm, root=root)
1242  slave = PoolSlave(comm, root=root)
1243  slave.run()
1244  if killSlaves:
1245  del slave # Required to prevent segmentation fault on exit
1246  sys.exit()
1247  return slave
1248 
def startPool(comm=None, root=0, killSlaves=True)
Start a process pool.
Definition: pool.py:1217

◆ unpickleFunction()

def lsst.ctrl.pool.pool.unpickleFunction (   moduleName,
  funcName 
)
Unpickle a function

This has to be a named function rather than a lambda because
pickle needs to find it.

Definition at line 61 of file pool.py.

61 def unpickleFunction(moduleName, funcName):
62  """Unpickle a function
63 
64  This has to be a named function rather than a lambda because
65  pickle needs to find it.
66  """
67  import importlib
68  module = importlib.import_module(moduleName)
69  return getattr(module, funcName)
70 
71 
def unpickleFunction(moduleName, funcName)
Definition: pool.py:61

◆ unpickleInstanceMethod()

def lsst.ctrl.pool.pool.unpickleInstanceMethod (   obj,
  name 
)
Unpickle an instance method

This has to be a named function rather than a lambda because
pickle needs to find it.

Definition at line 38 of file pool.py.

38 def unpickleInstanceMethod(obj, name):
39  """Unpickle an instance method
40 
41  This has to be a named function rather than a lambda because
42  pickle needs to find it.
43  """
44  return getattr(obj, name)
45 
46 
def unpickleInstanceMethod(obj, name)
Definition: pool.py:38

Variable Documentation

◆ NODE

string lsst.ctrl.pool.pool.NODE = "%s:%d" % (os.uname()[1], os.getpid())

Definition at line 35 of file pool.py.