提交 e6c7086d authored 作者: Pascal Lamblin's avatar Pascal Lamblin

Make check_preallocated_output work on fct outputs

In DebugMode, do not use the no_recycling list when calling the CLinker to build individual thunks, so that output memory can always be re-used, even for outputs of the actual function. This enables check_preallocated_output to work on Ops that compute the function's outputs. This should close gh-1174.
上级 0421c6b0
......@@ -1609,7 +1609,11 @@ class _Linker(gof.link.LocalLinker):
active_order = self.schedule(fgraph) # an ordering of just the active nodes
active_order_set = set(active_order)
no_recycling = self.no_recycling
# Disable no_recycling, in order to be able to use
# check_preallocated_output even on the output of the function.
# no_recycling in individual thunks does not really matter, since
# the function's outputs will always be freshly allocated.
no_recycling = []
input_storage, output_storage, storage_map = link.map_storage(
fgraph, order, input_storage_, output_storage_)
......@@ -1704,11 +1708,11 @@ class _Linker(gof.link.LocalLinker):
_logger.warn("We won't check the perform function of node '%s' but we will check its make_thunk function" % node)
thunks_py[-1] = thunk
if no_recycling is True:
no_recycling = storage_map.values()
no_recycling = utils.difference(no_recycling, input_storage)
if self.no_recycling is True:
no_recycling_map = storage_map.values()
no_recycling_map = utils.difference(no_recycling_map, input_storage)
else:
no_recycling = [storage_map[r] for r in no_recycling
no_recycling_map = [storage_map[r] for r in self.no_recycling
if r not in fgraph.inputs]
# Precompute some things for storage pre-allocation
......@@ -1729,7 +1733,7 @@ class _Linker(gof.link.LocalLinker):
_logger.debug("starting a DebugMode call")
_logger.debug("self.maker.mode.check_preallocated_output: %s",
self.maker.mode.check_preallocated_output)
for x in no_recycling:
for x in no_recycling_map:
x[0] = None
# nest all this in try-finally to put storage *back* into
......
......@@ -709,7 +709,7 @@ class Test_preallocated_output(unittest.TestCase):
a = theano.tensor.fmatrix('a')
b = theano.tensor.fmatrix('b')
z = BrokenCImplementationAdd()(a, b)
# Needed so that z is not the output of the graph
# In this test, we do not want z to be an output of the graph.
out = theano.tensor.dot(z, numpy.eye(7))
a_val = self.rng.randn(7, 7).astype('float32')
......@@ -737,6 +737,38 @@ class Test_preallocated_output(unittest.TestCase):
# The python code of this op is good.
f(a_val, b_val)
def test_f_contiguous_out(self):
# Same test as test_f_contiguous, but check that it works
# even if z _is_ the output of the graph
a = theano.tensor.fmatrix('a')
b = theano.tensor.fmatrix('b')
out = BrokenCImplementationAdd()(a, b)
a_val = self.rng.randn(7, 7).astype('float32')
b_val = self.rng.randn(7, 7).astype('float32')
# Should work
mode = debugmode.DebugMode(
check_preallocated_output=['c_contiguous'])
f = theano.function([a, b], out, mode=mode)
out_val = f(a_val, b_val)
#print 'out_val =', out_val
#print out_val.strides
# Should raise an Exception, since the output buffer is
# used incorrectly.
mode = debugmode.DebugMode(
check_preallocated_output=['f_contiguous'])
f = theano.function([a, b], out, mode=mode)
if theano.config.cxx:
self.assertRaises(debugmode.BadThunkOutput, f, a_val, b_val)
else:
# The python code of this op is good.
f(a_val, b_val)
def test_output_broadcast_tensor(self):
v = theano.tensor.fvector('v')
c, r = VecAsRowAndCol()(v)
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论