提交 4ba6a10a authored 作者: Razvan Pascanu's avatar Razvan Pascanu

merge

...@@ -17,6 +17,7 @@ import theano.gof ...@@ -17,6 +17,7 @@ import theano.gof
import mode as mode_module import mode as mode_module
from io import * from io import *
import logging import logging
_logger = logging.getLogger('theano.compile.function_module') _logger = logging.getLogger('theano.compile.function_module')
...@@ -163,6 +164,18 @@ class AliasedMemoryError(Exception): ...@@ -163,6 +164,18 @@ class AliasedMemoryError(Exception):
### Function ### Function
### ###
class DeepCopyOp(theano.gof.Op):
def __init__(self):
pass
def make_node(self, x):
return theano.gof.Apply(self, [x], [x.type()])
def perform( self, node, args, outs):
outs[0][0] = copy.deepcopy(args[0])
deep_copy_op = DeepCopyOp()
DUPLICATE = ['DUPLICATE'] # unique id object used as a placeholder for duplicate entries DUPLICATE = ['DUPLICATE'] # unique id object used as a placeholder for duplicate entries
class Function(object): class Function(object):
""" """
...@@ -752,6 +765,20 @@ class FunctionMaker(object): ...@@ -752,6 +765,20 @@ class FunctionMaker(object):
t0 = time.time() t0 = time.time()
optimizer(env) optimizer(env)
_logger.debug('Optimizing took %f seconds' % (time.time() - t0)) _logger.debug('Optimizing took %f seconds' % (time.time() - t0))
# This loop was inserted to remove aliasing between outputs when they all
# evaluete to the same value. Originally it was OK for outputs to be aliased,
# but some of the outputs can be shared variables, and is not good for shared
# variables to be aliased. It might be possible to optimize this by making sure
# there is no aliasing only between shared variables.
for i in xrange(len(env.outputs)):
views = set()
view_tree_set(alias_root(env.outputs[i]), views)
for j in xrange(i+1, len(env.outputs)):
if env.outputs[j] in views:
env.change_input('output', j, deep_copy_op(env.outputs[j]))
# initialize the linker # initialize the linker
if not hasattr(linker, 'accept'): if not hasattr(linker, 'accept'):
......
...@@ -474,6 +474,53 @@ class Test_pfunc(unittest.TestCase): ...@@ -474,6 +474,53 @@ class Test_pfunc(unittest.TestCase):
assert f() == 21 assert f() == 21
assert f() == 34 assert f() == 34
def aliasing_test(self):
A = shared(numpy.zeros((2,2)))
B = shared(numpy.zeros((2,2)))
C = numpy.zeros((2,2))
D = tensor.dmatrix()
DD = D + 5
f = pfunc([D], [], updates=[ (A,D), (B,D) ])
f(C)
assert not numpy.may_share_memory(A.value,B.value)
f = pfunc([D], [], updates=[ (A,D[:]), (B,D) ])
f(C)
assert not numpy.may_share_memory(A.value,B.value)
f = pfunc([D], [], updates=[ (A,D+5), (B,D[:]) ])
f(C)
assert not numpy.may_share_memory(A.value,B.value)
f = pfunc([D], [], updates=[ (A,D+5), (B,D) ])
f(C)
assert not numpy.may_share_memory(A.value,B.value)
f = pfunc([D], DD, updates=[ (A,DD[:1]), (B,DD) ])
R=f(C)
assert not numpy.may_share_memory(A.value,B.value)
assert not numpy.may_share_memory(R,B.value)
assert not numpy.may_share_memory(R,A.value)
f = pfunc([D], DD, updates=[ (A,DD[:1]), (B,DD[:1]*2) ])
R=f(C)
assert not numpy.may_share_memory(A.value,B.value)
assert not numpy.may_share_memory(R,B.value)
assert not numpy.may_share_memory(R,A.value)
f = pfunc([D], DD*4, updates=[ (A,DD[:1]*3), (B,DD[:1]*2) ])
R=f(C)
assert not numpy.may_share_memory(A.value,B.value)
assert not numpy.may_share_memory(R,B.value)
assert not numpy.may_share_memory(R,A.value)
f = pfunc([D], DD*4, updates=[ (A,DD[:1]*3), (B,DD[:1]*3) ])
R=f(C)
assert not numpy.may_share_memory(A.value,B.value)
assert not numpy.may_share_memory(R,B.value)
assert not numpy.may_share_memory(R,A.value)
if __name__ == '__main__': if __name__ == '__main__':
theano.config.mode = 'FAST_COMPILE' theano.config.mode = 'FAST_COMPILE'
Test_pfunc().test_default_scalar_container() Test_pfunc().test_default_scalar_container()
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论