LSST Applications g0b6bd0c080+a72a5dd7e6,g1182afd7b4+2a019aa3bb,g17e5ecfddb+2b8207f7de,g1d67935e3f+06cf436103,g38293774b4+ac198e9f13,g396055baef+6a2097e274,g3b44f30a73+6611e0205b,g480783c3b1+98f8679e14,g48ccf36440+89c08d0516,g4b93dc025c+98f8679e14,g5c4744a4d9+a302e8c7f0,g613e996a0d+e1c447f2e0,g6c8d09e9e7+25247a063c,g7271f0639c+98f8679e14,g7a9cd813b8+124095ede6,g9d27549199+a302e8c7f0,ga1cf026fa3+ac198e9f13,ga32aa97882+7403ac30ac,ga786bb30fb+7a139211af,gaa63f70f4e+9994eb9896,gabf319e997+ade567573c,gba47b54d5d+94dc90c3ea,gbec6a3398f+06cf436103,gc6308e37c7+07dd123edb,gc655b1545f+ade567573c,gcc9029db3c+ab229f5caf,gd01420fc67+06cf436103,gd877ba84e5+06cf436103,gdb4cecd868+6f279b5b48,ge2d134c3d5+cc4dbb2e3f,ge448b5faa6+86d1ceac1d,gecc7e12556+98f8679e14,gf3ee170dca+25247a063c,gf4ac96e456+ade567573c,gf9f5ea5b4d+ac198e9f13,gff490e6085+8c2580be5c,w.2022.27
LSST Data Management Base Package
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 107 of file pool.py.

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

◆ catchPicklingError()

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

Definition at line 234 of file pool.py.

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

◆ getBatchType()

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

Definition at line 96 of file pool.py.

96def getBatchType():
97 """Return a string giving the type of batch system in use"""
98 return _batchType
99
100

◆ 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 162 of file pool.py.

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

◆ 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 71 of file pool.py.

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

◆ 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 46 of file pool.py.

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

◆ 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 187 of file pool.py.

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

◆ setBatchType()

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

Definition at line 101 of file pool.py.

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

◆ startPool()

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

Start a process pool.

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.

@param comm: MPI communicator
@param root: Rank of root/master node
@param killSlaves: Kill slaves on completion?

Definition at line 1216 of file pool.py.

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

◆ 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 60 of file pool.py.

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

◆ 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 37 of file pool.py.

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

Variable Documentation

◆ NODE

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

Definition at line 34 of file pool.py.