提交 f0f84950 authored 作者: Razvan Pascanu's avatar Razvan Pascanu

merge

...@@ -519,16 +519,48 @@ class Function(object): ...@@ -519,16 +519,48 @@ class Function(object):
else: else:
try: try:
s.storage[0] = s.type.filter(arg, strict=s.strict) s.storage[0] = s.type.filter(arg, strict=s.strict)
except Exception, e: except Exception, e:
e.args = tuple(list(e.args)+["Bad input argument at index %d" % arg_index]) e.args = tuple(list(e.args)+["Bad input argument at index %d" % arg_index])
raise raise
s.provided += 1 s.provided += 1
i+=1 i+=1
# Set keyword arguments # Set keyword arguments
for k, arg in kwargs.iteritems(): for k, arg in kwargs.iteritems():
self[k] = arg self[k] = arg
## Collect aliased inptus among the storage space
args_share_memory = []
for i in xrange(len(self.input_storage)):
if self.input_storage[i].storage[0] != None:
is_aliased = False
for j in xrange(len(args_share_memory)):
if numpy.may_share_memory(
self.input_storage[i].storage[0] ,
self.input_storage[args_share_memory[j][0]].storage[0]):
is_aliased = True
args_share_memory[j] += [i]
break
if not is_aliased:
args_share_memory.append( [i] )
# Check for groups of more than one argument that share memory
for group in args_share_memory:
if len(group) > 1:
# see if any of these arguments are mutable
mutable = numpy.any( [self.maker.inputs[idx].mutable for
idx in group])
# copy all but the first
for idx in group[1:]:
self.input_storage[i].storage[0] = copy.copy(
self.input_storage[i].storage[0])
# Check if inputs are missing, or if inputs were set more than once, or # Check if inputs are missing, or if inputs were set more than once, or
# if we tried to provide inputs that are supposed to be implicit. # if we tried to provide inputs that are supposed to be implicit.
for c in self.input_storage: for c in self.input_storage:
......
...@@ -517,6 +517,35 @@ class Test_aliasing_rules(unittest.TestCase): ...@@ -517,6 +517,35 @@ class Test_aliasing_rules(unittest.TestCase):
assert not numpy.may_share_memory(A.get_value(borrow=False), data_of(A)) assert not numpy.may_share_memory(A.get_value(borrow=False), data_of(A))
def test_potential_input_aliasing_affecting_inplace_operations(self):
## Note: to trigger this bug with theano rev 4586:2bc6fc7f218b,
# you need to make in inputs mutable ( so that inplace
# operations are used) and to break the elemwise composition
# with some non-elemwise op ( here dot )
x = theano.tensor.dvector()
y = theano.tensor.dvector()
m1 = theano.tensor.dmatrix()
m2 = theano.tensor.dmatrix()
f = theano.function( [theano.In(x, mutable = True),
theano.In(y, mutable = True),
theano.In(m1, mutable = True),
theano.In(m2, mutable = True)],
theano.dot(x*2,m1)+theano.dot(y*3,m2))
# Compute bogus values
v = numpy.asarray([1,2], dtype = 'float64')
m = numpy.asarray([[1,0],[0,1]], dtype = 'float64')
bogus_vals = f(v,v,m,m)
# Since we used inplace operation v and m may be corrupted
# so we need to recreate them
m = numpy.asarray([[1,0],[0,1]], dtype = 'float64')
v = numpy.asarray([1,2], dtype = 'float64')
m_copy = m.copy()
v_copy = v.copy()
vals = f(v,v_copy,m,m_copy)
assert numpy.allclose(vals, bogus_vals)
def test_potential_output_aliasing_induced_by_updates(self): def test_potential_output_aliasing_induced_by_updates(self):
A = self.shared(numpy.zeros((2,2))) A = self.shared(numpy.zeros((2,2)))
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论