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

inplace optimization

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