提交 86bd12a0 authored 作者: sentient07's avatar sentient07

inplace optimization

上级 50bbc9f3
......@@ -121,14 +121,7 @@ class GpuFromHost(GpuOp):
check_input = False
def __eq__(self, other):
return type(self) == type(other)
def __hash__(self):
return hash(type(self))
def __str__(self):
return 'GpuFromHost'
__props__ = ()
def make_node(self, x):
if not isinstance(x.type, tensor.TensorType):
......@@ -185,7 +178,7 @@ class GpuElemwise(GpuOp):
"""
__props__ = ("scalar_op", "inplace_pattern", )
__props__ = ("scalar_op", "inplace_pattern", "sync", )
nin = property(lambda self: self.scalar_op.nin)
nout = property(lambda self: self.scalar_op.nout)
......
......@@ -1128,11 +1128,9 @@ def local_gpu_advanced_incsubtensor1(node):
compute_capability = device_properties(active_device_no)['major']
if (compute_capability < 2 or y.ndim != 2 or x.ndim != 2):
gpu_op = GpuAdvancedIncSubtensor1(
set_instead_of_inc=set_instead_of_inc)
gpu_op = tensor.AdvancedIncSubtensor1(**node.op._props_dict())
else:
gpu_op = GpuAdvancedIncSubtensor1_dev20(
set_instead_of_inc=set_instead_of_inc)
gpu_op = GPUAdvancedIncSubtensor1_dev20(**node.op._props_dict())
return [gpu_op(as_cuda_ndarray_variable(x),
as_cuda_ndarray_variable(y), *coords)]
......@@ -1191,10 +1189,7 @@ def local_gpu_incsubtensor(node):
# The IncSubtensor upcast to float32 y, so we do it
# explicitly to move it to the GPU.
y = y.astype('float32')
ret = GpuIncSubtensor(
incsubt.idx_list,
inplace=incsubt.inplace,
set_instead_of_inc=incsubt.set_instead_of_inc)(
ret = GpuIncSubtensor(**node.op._props_dict())(
as_cuda_ndarray_variable(x),
as_cuda_ndarray_variable(y),
*coords)
......@@ -1921,7 +1916,7 @@ def local_gpu_downsample_factor_max(node):
if (pad) != (0, 0) or node.op.mode != 'max' or stride != ws:
return
if (x.owner and isinstance(x.owner.op, HostFromGpu)):
gpu_ds = GpuDownsampleFactorMax(**node.op._props_dict())
gpu_ds = GpuDownsampleFactorMax(node.op.ds, node.op.ignore_border)
return [host_from_gpu(gpu_ds(x.owner.inputs[0]))]
......@@ -2683,7 +2678,7 @@ def gpu_sparse_block_outer_opt(node):
inputs = _clear_host_from_gpu(node.inputs)
return [host_from_gpu(GpuSparseBlockOuter(node.op.inplace)(*inputs))]
return [host_from_gpu(GpuSparseBlockOuter()(*inputs))]
elif isinstance(node.op, GpuFromHost) and \
_owner_isinstance(node.inputs[0], SparseBlockOuter):
......@@ -2691,7 +2686,7 @@ def gpu_sparse_block_outer_opt(node):
meta_node = node.inputs[0].owner
inputs = _clear_host_from_gpu(meta_node.inputs)
return [GpuSparseBlockOuter(meta_node.op.inplace)(*inputs)]
return [GpuSparseBlockOuter()(*inputs)]
@local_optimizer([GpuSparseBlockGemv], inplace=True)
......
......@@ -3513,7 +3513,7 @@ def transpose(x, axes=None):
"""
if axes is None:
axes = list(range((x.ndim - 1), -1, -1))
ret = DimShuffle(x.broadcastable, axes, inplace=False)(x)
ret = DimShuffle(x.broadcastable, axes)(x)
if x.name and axes == list(range((x.ndim - 1), -1, -1)):
ret.name = x.name + '.T'
return ret
......
......@@ -73,8 +73,7 @@ class DimShuffle(Op):
list can either be an index or 'x'. Indices must be encoded
as python integers, not theano symbolic integers.
inplace : bool, optional
If True, the output will be a view of the input.
If False (default), the output will be a copy of the input.
If True (default), the output will be a view of the input.
Note
----
......@@ -136,7 +135,7 @@ class DimShuffle(Op):
check_input = False
__props__ = ("input_broadcastable", "new_order")
def __init__(self, input_broadcastable, new_order, inplace=False):
def __init__(self, input_broadcastable, new_order, inplace=True):
input_broadcastable = tuple(input_broadcastable)
self.input_broadcastable = input_broadcastable
new_order = tuple(new_order)
......@@ -568,8 +567,7 @@ second dimension
# TODO: use LComplete instead
args.append(dim_shuffle(
input.type.broadcastable,
['x'] * difference + list(range(length)),
inplace=False)(input))
['x'] * difference + list(range(length)))(input))
inputs = args
# HERE: all the broadcast dims have the same length now
......@@ -803,6 +801,7 @@ second dimension
res = theano.tensor.constant(numpy.asarray(r.data),
dtype=r.type.dtype)
return DimShuffle((), ['x'] * nd, inplace=False)(res)
new_r = Elemwise(node.op, {})(
*[transform(ipt) for ipt in node.inputs])
return new_r
......
......@@ -650,35 +650,6 @@ def local_lift_transpose_through_dot(node):
return ret
@gof.local_optimizer([DimShuffle])
def dimshuffle_as_view(node):
op = node.op
if not isinstance(op, DimShuffle) or op.inplace:
return False
new_op = op.__class__(op.input_broadcastable, op.new_order, inplace=True)
v = new_op(*node.inputs)
copy_stack_trace(node.outputs[0], v)
return [v]
# Step 60 is the inplace optimization stage.
compile.optdb.register('dimshuffle_as_view',
TopoOptimizer(
dimshuffle_as_view,
failure_callback=TopoOptimizer.warn_inplace),
60,
'fast_run', 'inplace')
register_canonicalize(local_dimshuffle_lift)
register_specialize(local_dimshuffle_lift)
@register_canonicalize
@gof.local_optimizer([T.DimShuffle])
def local_dimshuffle_no_inplace_at_canonicalize(node):
if isinstance(node.op, T.DimShuffle) and node.op.inplace:
return [T.DimShuffle(node.op.input_broadcastable,
node.op.new_order, inplace=False)(node.inputs[0])]
######################
# Casting operations #
######################
......
......@@ -117,7 +117,7 @@ class test_dimshuffle_lift(unittest.TestCase):
x, y, z = inputs()
e = ds(ds(x, (1, 0)), (1, 0))
g = FunctionGraph([x], [e])
self.assertTrue(str(g) == "[DimShuffle{1,0}(DimShuffle{1,0}(x))]")
self.assertTrue(str(g) == "[InplaceDimShuffle{1,0}(InplaceDimShuffle{1,0}(x))]")
dimshuffle_lift.optimize(g)
self.assertTrue(str(g) == "[x]")
# no need to check_stack_trace as graph is supposed to be empty
......@@ -126,11 +126,10 @@ class test_dimshuffle_lift(unittest.TestCase):
x, y, z = inputs()
e = ds(ds(x, (1, 'x', 0)), (2, 0, 'x', 1))
g = FunctionGraph([x], [e])
self.assertTrue(
str(g) == "[DimShuffle{2,0,x,1}(DimShuffle{1,x,0}(x))]",
str(g))
self.assertTrue(str(g) == "[InplaceDimShuffle{2,0,x,1}(InplaceDimShuffle{1,x,0}(x))]",
str(g))
dimshuffle_lift.optimize(g)
self.assertTrue(str(g) == "[DimShuffle{0,1,x,x}(x)]", str(g))
self.assertTrue(str(g) == "[InplaceDimShuffle{0,1,x,x}(x)]", str(g))
# Check stacktrace was copied over correctly after opt was applied
self.assertTrue(check_stack_trace(g, ops_to_check='all'))
......@@ -138,10 +137,9 @@ class test_dimshuffle_lift(unittest.TestCase):
x, y, z = inputs()
e = ds(ds(ds(x, (0, 'x', 1)), (2, 0, 'x', 1)), (1, 0))
g = FunctionGraph([x], [e])
self.assertTrue(
str(g) == "[DimShuffle{1,0}(DimShuffle{2,0,x,1}"
"(DimShuffle{0,x,1}(x)))]",
str(g))
self.assertTrue(str(g) == "[InplaceDimShuffle{1,0}(InplaceDimShuffle{2,0,x,1}"
"(InplaceDimShuffle{0,x,1}(x)))]",
str(g))
dimshuffle_lift.optimize(g)
self.assertTrue(str(g) == "[x]", str(g))
# no need to check_stack_trace as graph is supposed to be empty
......@@ -179,24 +177,22 @@ class test_dimshuffle_lift(unittest.TestCase):
m = T.matrix(dtype="float64")
out = ((v + 42) * (m + 84)).T
g = FunctionGraph([v, m], [out])
init_str_g = ("[DimShuffle{1,0}(Elemwise{mul,no_inplace}"
"(DimShuffle{x,0}(Elemwise{add,no_inplace}"
init_str_g = ("[InplaceDimShuffle{1,0}(Elemwise{mul,no_inplace}"
"(InplaceDimShuffle{x,0}(Elemwise{add,no_inplace}"
"(<TensorType(float64, vector)>, "
"DimShuffle{x}(TensorConstant{42}))), "
"InplaceDimShuffle{x}(TensorConstant{42}))), "
"Elemwise{add,no_inplace}"
"(<TensorType(float64, matrix)>, "
"DimShuffle{x,x}(TensorConstant{84}))))]")
"InplaceDimShuffle{x,x}(TensorConstant{84}))))]")
self.assertTrue(str(g) == init_str_g)
new_out = local_dimshuffle_lift.transform(g.outputs[0].owner)[0]
new_g = FunctionGraph(g.inputs, [new_out])
opt_str_g = ("[Elemwise{mul,no_inplace}(Elemwise{add,no_inplace}"
"(DimShuffle{0,x}(<TensorType(float64, vector)>), "
"DimShuffle{x,x}(TensorConstant{42})), "
"Elemwise{add,no_inplace}(DimShuffle{1,0}"
"(InplaceDimShuffle{0,x}(<TensorType(float64, vector)>), "
"InplaceDimShuffle{x,x}(TensorConstant{42})), "
"Elemwise{add,no_inplace}(InplaceDimShuffle{1,0}"
"(<TensorType(float64, matrix)>), "
"DimShuffle{x,x}(TensorConstant{84})))]")
"InplaceDimShuffle{x,x}(TensorConstant{84})))]")
self.assertTrue(str(new_g) == opt_str_g)
# Check stacktrace was copied over correctly after opt was applied
self.assertTrue(check_stack_trace(new_g, ops_to_check='all'))
......@@ -6301,7 +6297,7 @@ class Test_lift_transpose_through_dot(unittest.TestCase):
def test_matrix_matrix(self):
a, b = matrices('ab')
g = self.simple_optimize(FunctionGraph([a, b], [tensor.dot(a, b).T]))
sg = '[dot(DimShuffle{1,0}(b), DimShuffle{1,0}(a))]'
sg = '[dot(InplaceDimShuffle{1,0}(b), InplaceDimShuffle{1,0}(a))]'
assert str(g) == sg, (str(g), sg)
# Check stacktrace was copied over correctly after opt was applied
self.assertTrue(check_stack_trace(g, ops_to_check='all'))
......@@ -6313,7 +6309,7 @@ class Test_lift_transpose_through_dot(unittest.TestCase):
[a, b],
[tensor.dot(a.dimshuffle('x', 0), b).T]),
level='stabilize')
sg = '[dot(DimShuffle{1,0}(b), DimShuffle{0,x}(a))]'
sg = '[dot(InplaceDimShuffle{1,0}(b), InplaceDimShuffle{0,x}(a))]'
assert str(g) == sg, (str(g), sg)
# Check stacktrace was copied over correctly after opt was applied
self.assertTrue(check_stack_trace(g, ops_to_check='all'))
......@@ -6325,7 +6321,7 @@ class Test_lift_transpose_through_dot(unittest.TestCase):
[a, b],
[tensor.dot(b, a.dimshuffle(0, 'x')).T]),
level='stabilize')
sg = '[dot(DimShuffle{x,0}(a), DimShuffle{1,0}(b))]'
sg = '[dot(InplaceDimShuffle{x,0}(a), InplaceDimShuffle{1,0}(b))]'
assert str(g) == sg, (str(g), sg)
# Check stacktrace was copied over correctly after opt was applied
self.assertTrue(check_stack_trace(g, ops_to_check='all'))
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论