提交 0a01d19a authored 作者: Olivier Delalleau's avatar Olivier Delalleau

Merge pull request #572 from lamblin/fix_alloc_opt

Always introduce Alloc node when calling alloc()
...@@ -2897,6 +2897,12 @@ class Alloc(gof.Op): ...@@ -2897,6 +2897,12 @@ class Alloc(gof.Op):
def __call__(self, val, *shapes): def __call__(self, val, *shapes):
""" """
If the alloc would be useless, this function returns val. If the alloc would be useless, this function returns val.
If this function is called outside of a graph optimization context
(for instance, it is manually called by a user building a graph),
then we always return an Alloc node, to allow for DebugMode to check
for size mismatches.
If you always want an Alloc node, call make_node. If you always want an Alloc node, call make_node.
""" """
ret = super(Alloc, self).__call__(val, *shapes) ret = super(Alloc, self).__call__(val, *shapes)
...@@ -2904,7 +2910,7 @@ class Alloc(gof.Op): ...@@ -2904,7 +2910,7 @@ class Alloc(gof.Op):
# It makes optimization difficult when useless allocs are thrown # It makes optimization difficult when useless allocs are thrown
# into the graph at every stage of optimization. This little logic # into the graph at every stage of optimization. This little logic
# tries to help at least in some cases. # tries to help at least in some cases.
if val.type == ret.type: if hasattr(val, 'env') and (val.type == ret.type):
return val return val
except AttributeError: except AttributeError:
pass pass
......
...@@ -1073,6 +1073,7 @@ def local_fill_to_alloc(node): ...@@ -1073,6 +1073,7 @@ def local_fill_to_alloc(node):
@register_specialize @register_specialize
@register_stabilize
@register_canonicalize @register_canonicalize
@gof.local_optimizer([T.alloc]) @gof.local_optimizer([T.alloc])
def local_useless_alloc(node): def local_useless_alloc(node):
......
...@@ -2194,6 +2194,28 @@ def test_local_fill_useless(): ...@@ -2194,6 +2194,28 @@ def test_local_fill_useless():
f(m_, x_) f(m_, x_)
class Test_local_useless_alloc(unittest.TestCase):
def setUp(self):
self.rng = numpy.random.RandomState(utt.fetch_seed())
def test0(self):
x = shared(self.rng.randn(3, 7))
a = tensor.alloc(x, 6, 7)
# It is a bad idea to have tensor.alloc return x directly,
# because the shape mismatch cannot be caught.
assert a.owner and isinstance(a.owner.op, tensor.Alloc)
f = function([], a, mode=mode_opt)
# The optimization should then be applied, and remove Alloc
assert ([node.op for node in f.maker.env.toposort()]
== [compile.deep_copy_op])
# In DebugMode, the shape mismatch should be detected
if isinstance(mode_opt, compile.DebugMode):
self.assertRaises(ValueError, f)
class test_shapeoptimizer(unittest.TestCase): class test_shapeoptimizer(unittest.TestCase):
def setUp(self): def setUp(self):
utt.seed_rng() utt.seed_rng()
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论