Parallelize now reseeds random number generators after fork()

Bugfix -- AxisItem enforces tick boundaries more strictly
This commit is contained in:
Luke Campagnola 2012-06-30 23:32:26 -04:00
parent 3d71a1f555
commit 73e94f543c
2 changed files with 36 additions and 5 deletions

View File

@ -537,6 +537,10 @@ class AxisItem(GraphicsWidget):
else:
xScale = bounds.width() / dif
offset = self.range[0] * xScale
xRange = [x * xScale - offset for x in self.range]
xMin = min(xRange)
xMax = max(xRange)
prof.mark('init')
@ -545,6 +549,7 @@ class AxisItem(GraphicsWidget):
## draw ticks
## (to improve performance, we do not interleave line and text drawing, since this causes unnecessary pipeline switching)
## draw three different intervals, long ticks first
for i in range(len(tickLevels)):
tickPositions.append([])
ticks = tickLevels[i][1]
@ -557,7 +562,13 @@ class AxisItem(GraphicsWidget):
lineAlpha = self.grid
for v in ticks:
## determine actual position to draw this tick
x = (v * xScale) - offset
if x < xMin or x > xMax: ## last check to make sure no out-of-bounds ticks are drawn
tickPositions[i].append(None)
continue
tickPositions[i].append(x)
p1 = [x, x]
p2 = [x, x]
p1[axis] = tickStart
@ -570,7 +581,6 @@ class AxisItem(GraphicsWidget):
tickPen.setColor(color)
p.setPen(tickPen)
p.drawLine(Point(p1), Point(p2))
tickPositions[i].append(x)
prof.mark('draw ticks')
## Draw text until there is no more room (or no more text)
@ -585,10 +595,15 @@ class AxisItem(GraphicsWidget):
if len(strings) == 0:
continue
## ignore strings belonging to ticks that were previously ignored
for j in range(len(strings)):
if tickPositions[i][j] is None:
strings[j] = None
if i > 0: ## always draw top level
## measure all text, make sure there's enough room
textRects.extend([p.boundingRect(QtCore.QRectF(0, 0, 100, 100), QtCore.Qt.AlignCenter, s) for s in strings])
textRects.extend([p.boundingRect(QtCore.QRectF(0, 0, 100, 100), QtCore.Qt.AlignCenter, s) for s in strings if s is not None])
if axis == 0:
textSize = np.sum([r.height() for r in textRects])
else:
@ -603,6 +618,8 @@ class AxisItem(GraphicsWidget):
#strings = self.tickStrings(values, self.scale, spacing)
for j in range(len(strings)):
vstr = strings[j]
if vstr is None:## this tick was ignored because it is out of bounds
continue
x = tickPositions[i][j]
textRect = p.boundingRect(QtCore.QRectF(0, 0, 100, 100), QtCore.Qt.AlignCenter, vstr)
height = textRect.height()

View File

@ -37,7 +37,7 @@ class Parallelize:
since it is automatically sent via pipe back to the parent process.
"""
def __init__(self, tasks, workers=None, block=True, progressDialog=None, **kwds):
def __init__(self, tasks, workers=None, block=True, progressDialog=None, randomReseed=True, **kwds):
"""
=============== ===================================================================
Arguments:
@ -47,6 +47,9 @@ class Parallelize:
system
progressDialog optional dict of arguments for ProgressDialog
to update while tasks are processed
randomReseed If True, each forked process will reseed its random number generator
to ensure independent results. Works with the built-in random
and numpy.random.
kwds objects to be shared by proxy with child processes (they will
appear as attributes of the tasker)
=============== ===================================================================
@ -68,6 +71,7 @@ class Parallelize:
workers = 1
self.workers = workers
self.tasks = list(tasks)
self.reseed = randomReseed
self.kwds = kwds.copy()
self.kwds['_taskStarted'] = self._taskStarted
@ -112,7 +116,7 @@ class Parallelize:
## fork and assign tasks to each worker
for i in range(workers):
proc = ForkedProcess(target=None, preProxy=self.kwds)
proc = ForkedProcess(target=None, preProxy=self.kwds, randomReseed=self.reseed)
if not proc.isParent:
self.proc = proc
return Tasker(proc, chunks[i], proc.forkedProxies)
@ -150,7 +154,17 @@ class Parallelize:
#print "remove:", [ch.childPid for ch in rem]
for ch in rem:
activeChilds.remove(ch)
os.waitpid(ch.childPid, 0)
while True:
try:
os.waitpid(ch.childPid, 0)
break
except OSError as ex:
if ex.errno == 4: ## If we get this error, just try again
continue
#print "Ignored system call interruption"
else:
raise
#print [ch.childPid for ch in activeChilds]
if self.showProgress and self.progressDlg.wasCanceled():