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

Call `Op.make_thunk` before generating the C code.

上级 b2d3d192
......@@ -1663,6 +1663,45 @@ class _Linker(gof.link.LocalLinker):
node_input_storage = [storage_map[r] for r in node.inputs]
node_output_storage = [storage_map[r] for r in node.outputs]
# Some Ops define a make_thunk with the expectation that
# it will be called before the C code is compiled, because
# the compilation of some dependency is triggered there.
thunk_other = None
if get_unbound_function(node.op.make_thunk) not in default_make_thunk:
compute_map = {}
for k in node.inputs:
compute_map[k] = [True]
for k in node.outputs:
compute_map[k] = [False]
thunk = node.op.make_thunk(node,
storage_map,
compute_map,
no_recycling)
thunk.inputs = [storage_map[v] for v in node.inputs]
thunk.outputs = [storage_map[v] for v in node.outputs]
# Right now there is no op that when called check if
# its ouputs are computed and don't recompute itself.
# I think it is not a good idea to do so as we only
# call thunk when we want them computed. So those
# check would be useless. In case some ops do it at
# some point, we reset the compute_map of outputs to
# False.
#
# Note RP: this warp_thunk doesn't work. What happens is
# that for all ops that have a make_thunk, the same instance
# of `wrap_thunk` gets used ( that has the same `thunk`
# function, probably the one of the first of all those ops (
# or the last .. I'm not sure). I don't know suffcient about
# how python works to understand why. A bunch of tests fail
# because of this, one of them being
# theano/scan_module/tests/scan_tests.py:T_Scan.test_backwards
# def wrap_thunk():
# for k in node.outputs:
# compute_map[k] = [False]
# thunk()
thunk_other = thunk
try:
if not self.maker.mode.check_c_code:
raise utils.MethodNotDefined()
......@@ -1713,48 +1752,15 @@ class _Linker(gof.link.LocalLinker):
else:
thunks_py.append(None)
# If the op define its own make_thunk, check it
if get_unbound_function(node.op.make_thunk) not in default_make_thunk:
compute_map = {}
for k in node.inputs:
compute_map[k] = [True]
for k in node.outputs:
compute_map[k] = [False]
thunk = node.op.make_thunk(node,
storage_map,
compute_map,
no_recycling)
thunk.inputs = [storage_map[v] for v in node.inputs]
thunk.outputs = [storage_map[v] for v in node.outputs]
# Right now there is no op that when called check if
# its ouputs are computed and don't recompute itself.
# I think it is not a good idea to do so as we only
# call thunk when we want them computed. So those
# check would be useless. In case some ops do it at
# some point, we reset the compute_map of outputs to
# False.
#
# Note RP: this warp_thunk doesn't work. What happens is
# that for all ops that have a make_thunk, the same instance
# of `wrap_thunk` gets used ( that has the same `thunk`
# function, probably the one of the first of all those ops (
# or the last .. I'm not sure). I don't know suffcient about
# how python works to understand why. A bunch of tests fail
# because of this, one of them being
# theano/scan_module/tests/scan_tests.py:T_Scan.test_backwards
# def wrap_thunk():
# for k in node.outputs:
# compute_map[k] = [False]
# thunk()
# If the op defined its own make_thunk, use the generated thunk
if thunk_other is not None:
if thunks_py[-1] is None:
thunks_py[-1] = thunk
thunks_py[-1] = thunk_other
elif thunks_c[-1] is None:
thunks_c[-1] = thunk
thunks_c[-1] = thunk_other
else:
_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
thunks_py[-1] = thunk_other
# Use self.no_recycling (that was passed in accept()) to always
# use new memory storage when it is needed, in particular for the
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论