提交 c58e0892 authored 作者: Iulian Vlad Serban's avatar Iulian Vlad Serban

Implemented fix for issue #2613: Concatenation bug for negative axes on GPU.

上级 7f5f1f8e
......@@ -3044,6 +3044,24 @@ class GpuJoin(tensor.Join, GpuOp):
as_tensor_variable_args = [as_cuda_ndarray_variable(x)
for x in tensors]
# If axis is negative, we need to increment it with the number
# of dimensions of the smallest tensor variable
axis_int = int(axis.eval())
if (axis_int < 0):
# Find tensor with smallest number of dimensions
min_dim = -1
for cnda in tensors:
if min_dim < 0 or min_dim > len(list(cnda.shape)):
min_dim = len(list(cnda.shape))
# Throw error if it's not safe to increment axis with the
# minimum dim. Normally, this error will be caught in the
# Join op class, but just to be sure we double check it here.
if axis_int + min_dim < 0:
raise ValueError("Cannot join list of tensors at axis (%s) when tensor with smallest dim (%s) is smaller." % (axis_int, min_dim))
axis = axis + min_dim
output_maker = \
lambda bcast: CudaNdarrayType(broadcastable=bcast)()
......
......@@ -273,6 +273,55 @@ def test_opt_gpujoin_joinvectors_elemwise_then_minusone():
assert numpy.allclose(numpy.asarray(f()), concat)
def test_opt_gpujoin_joinvectors_negativeaxes():
"""
Test that negative axis concatenation works as expected.
"""
# Test case for one-dimensional vectors
rng = numpy.random.RandomState(22)
x1 = rng.rand(5)
x2 = rng.rand(10)
t1 = shared(numpy.asarray(x1, theano.config.floatX))
t2 = shared(numpy.asarray(x2, theano.config.floatX))
t = T.concatenate([t1, t2], axis=-1)
f = theano.function(inputs=[], outputs=t)
assert(numpy.allclose(f(), numpy.concatenate([x1, x2], axis=-1)))
# Test case for two-dimensional vectors
x1 = rng.rand(5, 10)
x2 = rng.rand(10, 10)
t1 = shared(numpy.asarray(x1, theano.config.floatX))
t2 = shared(numpy.asarray(x2, theano.config.floatX))
t = T.concatenate([t1, t2], axis=-2)
f = theano.function(inputs=[], outputs=t)
assert(numpy.allclose(f(), numpy.concatenate([x1, x2], axis=-2)))
# Now check that a value error is raised when vectors don't match
# along the negative concatenation axis
try:
t = T.concatenate([t1, t2], axis=-1)
f = theano.function(inputs=[], outputs=t)
f()
assert(False)
except ValueError:
assert(True)
# Finally check that a value error is raised when negative
# axis is larger in absolute value than smallest number of dims
try:
t = T.concatenate([t1, t2], axis=-3)
f = theano.function(inputs=[], outputs=t)
f()
assert(False)
except ValueError:
assert(True)
def test_local_gpu_subtensor():
# Test shared forced on CPU.
t = tensor._shared(numpy.zeros(20, "float32"))
......@@ -632,4 +681,5 @@ if __name__ == '__main__':
test_gpualloc()
test_opt_gpujoin_onlyajoin()
test_opt_gpujoin_joinvectors_elemwise_then_minusone()
test_opt_gpujoin_joinvectors_negativeaxes()
......@@ -3451,8 +3451,7 @@ class Join(Op):
# be broadcastable for the output.
for x in as_tensor_variable_args:
for current_axis, bflag in enumerate(x.type.broadcastable):
# Not sure if this Op supports/supported/will support
# negative indices, but just to be sure...
# This Op supports negative axes, so only consider modulo
if current_axis == axis % ndim:
continue
if bflag:
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论