提交 ad4e2a09 authored 作者: Frédéric Bastien's avatar Frédéric Bastien

Merge pull request #3521 from carriepl/scan_speedup_cgt

Scan replace Allocs with AllocEmpty
...@@ -627,7 +627,7 @@ def scan(fn, ...@@ -627,7 +627,7 @@ def scan(fn,
# the initial state over. We do this using the expand function # the initial state over. We do this using the expand function
# defined in scan utils # defined in scan utils
sit_sot_scan_inputs.append( sit_sot_scan_inputs.append(
scan_utils.expand( scan_utils.expand_empty(
tensor.unbroadcast( tensor.unbroadcast(
tensor.shape_padleft(actual_arg), 0), tensor.shape_padleft(actual_arg), 0),
actual_n_steps actual_n_steps
...@@ -653,8 +653,8 @@ def scan(fn, ...@@ -653,8 +653,8 @@ def scan(fn,
idx_offset = abs(numpy.min(init_out['taps'])) idx_offset = abs(numpy.min(init_out['taps']))
# Sequence # Sequence
mit_sot_scan_inputs.append( mit_sot_scan_inputs.append(
scan_utils.expand(init_out['initial'][:mintap], scan_utils.expand_empty(init_out['initial'][:mintap],
actual_n_steps)) actual_n_steps))
if i in return_steps: if i in return_steps:
mit_sot_return_steps[n_mit_sot] = return_steps[i] mit_sot_return_steps[n_mit_sot] = return_steps[i]
...@@ -866,7 +866,7 @@ def scan(fn, ...@@ -866,7 +866,7 @@ def scan(fn,
if isinstance(new_var.type, ops.expandable_types): if isinstance(new_var.type, ops.expandable_types):
sit_sot_inner_inputs.append(new_var) sit_sot_inner_inputs.append(new_var)
sit_sot_scan_inputs.append( sit_sot_scan_inputs.append(
scan_utils.expand( scan_utils.expand_empty(
tensor.unbroadcast( tensor.unbroadcast(
tensor.shape_padleft(input.variable), 0), tensor.shape_padleft(input.variable), 0),
actual_n_steps)) actual_n_steps))
......
...@@ -1499,7 +1499,7 @@ class ScanSaveMem(gof.Optimizer): ...@@ -1499,7 +1499,7 @@ class ScanSaveMem(gof.Optimizer):
tmp_idx) tmp_idx)
tmp = pre_constant_merge([tmp])[0] tmp = pre_constant_merge([tmp])[0]
nw_input = scan_utils.expand(_nw_input, tmp) nw_input = scan_utils.expand_empty(_nw_input, tmp)
else: else:
tmp = tensor.as_tensor_variable(val) tmp = tensor.as_tensor_variable(val)
initl = tensor.as_tensor_variable(init_l[i]) initl = tensor.as_tensor_variable(init_l[i])
...@@ -1550,8 +1550,8 @@ class ScanSaveMem(gof.Optimizer): ...@@ -1550,8 +1550,8 @@ class ScanSaveMem(gof.Optimizer):
nw_inputs[in_idx].owner.op.idx_list[0], nw_inputs[in_idx].owner.op.idx_list[0],
slice))): slice))):
_nw_input = nw_inputs[in_idx].owner.inputs[1] _nw_input = nw_inputs[in_idx].owner.inputs[1]
nw_input = scan_utils.expand(_nw_input, nw_input = scan_utils.expand_empty(_nw_input,
nw_steps) nw_steps)
nw_inputs[in_idx] = nw_input nw_inputs[in_idx] = nw_input
else: else:
nw_input = nw_inputs[in_idx][:(initl+nw_steps)] nw_input = nw_inputs[in_idx][:(initl+nw_steps)]
......
...@@ -607,19 +607,18 @@ def isNaN_or_Inf_or_None(x): ...@@ -607,19 +607,18 @@ def isNaN_or_Inf_or_None(x):
return isNone or isNaN or isInf or isStr return isNone or isNaN or isInf or isStr
def expand(tensor_var, size): def expand_empty(tensor_var, size):
""" """
Transoforms the shape of a tensor from (d1, d2 ... ) to ( d1+size, d2, ..) Transforms the shape of a tensor from (d1, d2 ... ) to ( d1+size, d2, ..)
by adding 0s at the end of the tensor. by adding uninitialized memory at the end of the tensor.
""" """
# Corner case that I might use in an optimization
if size == 0: if size == 0:
return tensor_var return tensor_var
shapes = [tensor_var.shape[x] for x in xrange(tensor_var.ndim)] shapes = [tensor_var.shape[x] for x in xrange(tensor_var.ndim)]
zeros_shape = [size + shapes[0]] + shapes[1:] new_shape = [size + shapes[0]] + shapes[1:]
empty = tensor.zeros(zeros_shape, empty = tensor.AllocEmpty(tensor_var.dtype)(*new_shape)
dtype=tensor_var.dtype)
return tensor.set_subtensor(empty[:shapes[0]], tensor_var) return tensor.set_subtensor(empty[:shapes[0]], tensor_var)
......
...@@ -6099,3 +6099,12 @@ class AllocEmpty(gof.Op): ...@@ -6099,3 +6099,12 @@ class AllocEmpty(gof.Op):
def do_constant_folding(self, node): def do_constant_folding(self, node):
return False return False
def connection_pattern(self, node):
return [[False] for i in node.inputs]
def grad(self, inputs, grads):
return [DisconnectedType()() for i in inputs]
def R_op(self, inputs, eval_points):
return [zeros(inputs, self.dtype)]
...@@ -291,36 +291,35 @@ def test_scan_debugprint1(): ...@@ -291,36 +291,35 @@ def test_scan_debugprint1():
| |for{cpu,scan_fn} [@C] '' | |for{cpu,scan_fn} [@C] ''
| | |k [@D] | | |k [@D]
| | |IncSubtensor{Set;:int64:} [@E] '' | | |IncSubtensor{Set;:int64:} [@E] ''
| | | |Alloc [@F] '' | | | |AllocEmpty{dtype='float64'} [@F] ''
| | | | |TensorConstant{0.0} [@G] | | | | |Elemwise{add,no_inplace} [@G] ''
| | | | |Elemwise{add,no_inplace} [@H] ''
| | | | | |k [@D] | | | | | |k [@D]
| | | | | |Subtensor{int64} [@I] '' | | | | | |Subtensor{int64} [@H] ''
| | | | | |Shape [@J] '' | | | | | |Shape [@I] ''
| | | | | | |Rebroadcast{0} [@K] '' | | | | | | |Rebroadcast{0} [@J] ''
| | | | | | |DimShuffle{x,0} [@L] '' | | | | | | |DimShuffle{x,0} [@K] ''
| | | | | | |Elemwise{second,no_inplace} [@M] '' | | | | | | |Elemwise{second,no_inplace} [@L] ''
| | | | | | |A [@N] | | | | | | |A [@M]
| | | | | | |DimShuffle{x} [@O] '' | | | | | | |DimShuffle{x} [@N] ''
| | | | | | |TensorConstant{1.0} [@P] | | | | | | |TensorConstant{1.0} [@O]
| | | | | |Constant{0} [@Q] | | | | | |Constant{0} [@P]
| | | | |Subtensor{int64} [@R] '' | | | | |Subtensor{int64} [@Q] ''
| | | | |Shape [@S] '' | | | | |Shape [@R] ''
| | | | | |Rebroadcast{0} [@K] '' | | | | | |Rebroadcast{0} [@J] ''
| | | | |Constant{1} [@T] | | | | |Constant{1} [@S]
| | | |Rebroadcast{0} [@K] '' | | | |Rebroadcast{0} [@J] ''
| | | |ScalarFromTensor [@U] '' | | | |ScalarFromTensor [@T] ''
| | | |Subtensor{int64} [@I] '' | | | |Subtensor{int64} [@H] ''
| | |A [@N] | | |A [@M]
| |Constant{1} [@V] | |Constant{1} [@U]
|Constant{-1} [@W] |Constant{-1} [@V]
Inner graphs of the scan ops: Inner graphs of the scan ops:
for{cpu,scan_fn} [@C] '' for{cpu,scan_fn} [@C] ''
>Elemwise{mul,no_inplace} [@X] '' >Elemwise{mul,no_inplace} [@W] ''
> |<TensorType(float64, vector)> [@Y] -> [@E] > |<TensorType(float64, vector)> [@X] -> [@E]
> |A_copy [@Z] -> [@N]""" > |A_copy [@Y] -> [@M]"""
for truth, out in zip(expected_output.split("\n"), lines): for truth, out in zip(expected_output.split("\n"), lines):
assert truth.strip() == out.strip() assert truth.strip() == out.strip()
...@@ -475,36 +474,35 @@ def test_scan_debugprint3(): ...@@ -475,36 +474,35 @@ def test_scan_debugprint3():
> | | |for{cpu,scan_fn} [@BE] '' > | | |for{cpu,scan_fn} [@BE] ''
> | | | |k_copy [@BF] -> [@X] > | | | |k_copy [@BF] -> [@X]
> | | | |IncSubtensor{Set;:int64:} [@BG] '' > | | | |IncSubtensor{Set;:int64:} [@BG] ''
> | | | | |Alloc [@BH] '' > | | | | |AllocEmpty{dtype='float64'} [@BH] ''
> | | | | | |TensorConstant{0.0} [@BI] > | | | | | |Elemwise{add,no_inplace} [@BI] ''
> | | | | | |Elemwise{add,no_inplace} [@BJ] ''
> | | | | | | |k_copy [@BF] -> [@X] > | | | | | | |k_copy [@BF] -> [@X]
> | | | | | | |Subtensor{int64} [@BK] '' > | | | | | | |Subtensor{int64} [@BJ] ''
> | | | | | | |Shape [@BL] '' > | | | | | | |Shape [@BK] ''
> | | | | | | | |Rebroadcast{0} [@BM] '' > | | | | | | | |Rebroadcast{0} [@BL] ''
> | | | | | | | |DimShuffle{x,0} [@BN] '' > | | | | | | | |DimShuffle{x,0} [@BM] ''
> | | | | | | | |Elemwise{second,no_inplace} [@BO] '' > | | | | | | | |Elemwise{second,no_inplace} [@BN] ''
> | | | | | | | |A_copy [@BP] -> [@W] > | | | | | | | |A_copy [@BO] -> [@W]
> | | | | | | | |DimShuffle{x} [@BQ] '' > | | | | | | | |DimShuffle{x} [@BP] ''
> | | | | | | | |TensorConstant{1.0} [@BR] > | | | | | | | |TensorConstant{1.0} [@BQ]
> | | | | | | |Constant{0} [@BS] > | | | | | | |Constant{0} [@BR]
> | | | | | |Subtensor{int64} [@BT] '' > | | | | | |Subtensor{int64} [@BS] ''
> | | | | | |Shape [@BU] '' > | | | | | |Shape [@BT] ''
> | | | | | | |Rebroadcast{0} [@BM] '' > | | | | | | |Rebroadcast{0} [@BL] ''
> | | | | | |Constant{1} [@BV] > | | | | | |Constant{1} [@BU]
> | | | | |Rebroadcast{0} [@BM] '' > | | | | |Rebroadcast{0} [@BL] ''
> | | | | |ScalarFromTensor [@BW] '' > | | | | |ScalarFromTensor [@BV] ''
> | | | | |Subtensor{int64} [@BK] '' > | | | | |Subtensor{int64} [@BJ] ''
> | | | |A_copy [@BP] -> [@W] > | | | |A_copy [@BO] -> [@W]
> | | |Constant{1} [@BX] > | | |Constant{1} [@BW]
> | |Constant{-1} [@BY] > | |Constant{-1} [@BX]
> |DimShuffle{x} [@BZ] '' > |DimShuffle{x} [@BY] ''
> |<TensorType(int64, scalar)> [@CA] -> [@U] > |<TensorType(int64, scalar)> [@BZ] -> [@U]
for{cpu,scan_fn} [@BE] '' for{cpu,scan_fn} [@BE] ''
>Elemwise{mul,no_inplace} [@CB] '' >Elemwise{mul,no_inplace} [@CA] ''
> |<TensorType(float64, vector)> [@CC] -> [@BG] > |<TensorType(float64, vector)> [@CB] -> [@BG]
> |A_copy [@CD] -> [@BP]""" > |A_copy [@CC] -> [@BO]"""
for truth, out in zip(expected_output.split("\n"), lines): for truth, out in zip(expected_output.split("\n"), lines):
assert truth.strip() == out.strip() assert truth.strip() == out.strip()
...@@ -534,51 +532,49 @@ def test_scan_debugprint4(): ...@@ -534,51 +532,49 @@ def test_scan_debugprint4():
| |for{cpu,scan_fn}.0 [@C] '' | |for{cpu,scan_fn}.0 [@C] ''
| | |TensorConstant{5} [@D] | | |TensorConstant{5} [@D]
| | |IncSubtensor{Set;:int64:} [@E] '' | | |IncSubtensor{Set;:int64:} [@E] ''
| | | |Alloc [@F] '' | | | |AllocEmpty{dtype='int64'} [@F] ''
| | | | |TensorConstant{0} [@G] | | | | |Elemwise{add,no_inplace} [@G] ''
| | | | |Elemwise{add,no_inplace} [@H] ''
| | | | |TensorConstant{5} [@D] | | | | |TensorConstant{5} [@D]
| | | | |Subtensor{int64} [@I] '' | | | | |Subtensor{int64} [@H] ''
| | | | |Shape [@J] '' | | | | |Shape [@I] ''
| | | | | |Subtensor{:int64:} [@K] '' | | | | | |Subtensor{:int64:} [@J] ''
| | | | | |<TensorType(int64, vector)> [@L] | | | | | |<TensorType(int64, vector)> [@K]
| | | | | |Constant{2} [@M] | | | | | |Constant{2} [@L]
| | | | |Constant{0} [@N] | | | | |Constant{0} [@M]
| | | |Subtensor{:int64:} [@K] '' | | | |Subtensor{:int64:} [@J] ''
| | | |ScalarFromTensor [@O] '' | | | |ScalarFromTensor [@N] ''
| | | |Subtensor{int64} [@I] '' | | | |Subtensor{int64} [@H] ''
| | |IncSubtensor{Set;:int64:} [@P] '' | | |IncSubtensor{Set;:int64:} [@O] ''
| | |Alloc [@Q] '' | | |AllocEmpty{dtype='int64'} [@P] ''
| | | |TensorConstant{0} [@G] | | | |Elemwise{add,no_inplace} [@Q] ''
| | | |Elemwise{add,no_inplace} [@R] ''
| | | |TensorConstant{5} [@D] | | | |TensorConstant{5} [@D]
| | | |Subtensor{int64} [@S] '' | | | |Subtensor{int64} [@R] ''
| | | |Shape [@T] '' | | | |Shape [@S] ''
| | | | |Subtensor{:int64:} [@U] '' | | | | |Subtensor{:int64:} [@T] ''
| | | | |<TensorType(int64, vector)> [@V] | | | | |<TensorType(int64, vector)> [@U]
| | | | |Constant{2} [@W] | | | | |Constant{2} [@V]
| | | |Constant{0} [@X] | | | |Constant{0} [@W]
| | |Subtensor{:int64:} [@U] '' | | |Subtensor{:int64:} [@T] ''
| | |ScalarFromTensor [@Y] '' | | |ScalarFromTensor [@X] ''
| | |Subtensor{int64} [@S] '' | | |Subtensor{int64} [@R] ''
| |Constant{2} [@Z] | |Constant{2} [@Y]
|Subtensor{int64::} [@BA] '' |Subtensor{int64::} [@Z] ''
|for{cpu,scan_fn}.1 [@C] '' |for{cpu,scan_fn}.1 [@C] ''
|Constant{2} [@BB] |Constant{2} [@BA]
Inner graphs of the scan ops: Inner graphs of the scan ops:
for{cpu,scan_fn}.0 [@C] '' for{cpu,scan_fn}.0 [@C] ''
>Elemwise{add,no_inplace} [@BC] '' >Elemwise{add,no_inplace} [@BB] ''
> |<TensorType(int64, scalar)> [@BC] -> [@E]
> |<TensorType(int64, scalar)> [@BD] -> [@E] > |<TensorType(int64, scalar)> [@BD] -> [@E]
> |<TensorType(int64, scalar)> [@BE] -> [@E] >Elemwise{add,no_inplace} [@BE] ''
>Elemwise{add,no_inplace} [@BF] '' > |<TensorType(int64, scalar)> [@BF] -> [@O]
> |<TensorType(int64, scalar)> [@BG] -> [@P] > |<TensorType(int64, scalar)> [@BG] -> [@O]
> |<TensorType(int64, scalar)> [@BH] -> [@P]
for{cpu,scan_fn}.1 [@C] '' for{cpu,scan_fn}.1 [@C] ''
>Elemwise{add,no_inplace} [@BC] '' >Elemwise{add,no_inplace} [@BB] ''
>Elemwise{add,no_inplace} [@BF] ''""" >Elemwise{add,no_inplace} [@BE] ''"""
for truth, out in zip(expected_output.split("\n"), lines): for truth, out in zip(expected_output.split("\n"), lines):
assert truth.strip() == out.strip() assert truth.strip() == out.strip()
...@@ -603,122 +599,121 @@ def test_scan_debugprint5(): ...@@ -603,122 +599,121 @@ def test_scan_debugprint5():
lines += [line] lines += [line]
expected_output = """Subtensor{int64} [@A] '' expected_output = """Subtensor{int64} [@A] ''
|for{cpu,grad_of_scan_fn}.1 [@B] '' |for{cpu,grad_of_scan_fn}.1 [@B] ''
| |Elemwise{sub,no_inplace} [@C] '' | |Elemwise{sub,no_inplace} [@C] ''
| | |Subtensor{int64} [@D] '' | | |Subtensor{int64} [@D] ''
| | | |Shape [@E] '' | | | |Shape [@E] ''
| | | | |for{cpu,scan_fn} [@F] '' | | | | |for{cpu,scan_fn} [@F] ''
| | | | |k [@G] | | | | |k [@G]
| | | | |IncSubtensor{Set;:int64:} [@H] '' | | | | |IncSubtensor{Set;:int64:} [@H] ''
| | | | | |Alloc [@I] '' | | | | | |AllocEmpty{dtype='float64'} [@I] ''
| | | | | | |TensorConstant{0.0} [@J] | | | | | | |Elemwise{add,no_inplace} [@J] ''
| | | | | | |Elemwise{add,no_inplace} [@K] '' | | | | | | | |k [@G]
| | | | | | | |k [@G] | | | | | | | |Subtensor{int64} [@K] ''
| | | | | | | |Subtensor{int64} [@L] '' | | | | | | | |Shape [@L] ''
| | | | | | | |Shape [@M] '' | | | | | | | | |Rebroadcast{0} [@M] ''
| | | | | | | | |Rebroadcast{0} [@N] '' | | | | | | | | |DimShuffle{x,0} [@N] ''
| | | | | | | | |DimShuffle{x,0} [@O] '' | | | | | | | | |Elemwise{second,no_inplace} [@O] ''
| | | | | | | | |Elemwise{second,no_inplace} [@P] '' | | | | | | | | |A [@P]
| | | | | | | | |A [@Q] | | | | | | | | |DimShuffle{x} [@Q] ''
| | | | | | | | |DimShuffle{x} [@R] '' | | | | | | | | |TensorConstant{1.0} [@R]
| | | | | | | | |TensorConstant{1.0} [@S] | | | | | | | |Constant{0} [@S]
| | | | | | | |Constant{0} [@T] | | | | | | |Subtensor{int64} [@T] ''
| | | | | | |Subtensor{int64} [@U] '' | | | | | | |Shape [@U] ''
| | | | | | |Shape [@V] '' | | | | | | | |Rebroadcast{0} [@M] ''
| | | | | | | |Rebroadcast{0} [@N] '' | | | | | | |Constant{1} [@V]
| | | | | | |Constant{1} [@W] | | | | | |Rebroadcast{0} [@M] ''
| | | | | |Rebroadcast{0} [@N] '' | | | | | |ScalarFromTensor [@W] ''
| | | | | |ScalarFromTensor [@X] '' | | | | | |Subtensor{int64} [@K] ''
| | | | | |Subtensor{int64} [@L] '' | | | | |A [@P]
| | | | |A [@Q] | | | |Constant{0} [@X]
| | | |Constant{0} [@Y] | | |TensorConstant{1} [@Y]
| | |TensorConstant{1} [@Z] | |Subtensor{:int64:} [@Z] ''
| |Subtensor{:int64:} [@BA] '' | | |Subtensor{::int64} [@BA] ''
| | |Subtensor{::int64} [@BB] '' | | | |Subtensor{:int64:} [@BB] ''
| | | |Subtensor{:int64:} [@BC] '' | | | | |for{cpu,scan_fn} [@F] ''
| | | | |for{cpu,scan_fn} [@F] '' | | | | |Constant{-1} [@BC]
| | | | |Constant{-1} [@BD] | | | |Constant{-1} [@BD]
| | | |Constant{-1} [@BE] | | |ScalarFromTensor [@BE] ''
| | |ScalarFromTensor [@BF] '' | | |Elemwise{sub,no_inplace} [@C] ''
| | |Elemwise{sub,no_inplace} [@C] '' | |Subtensor{:int64:} [@BF] ''
| |Subtensor{:int64:} [@BG] '' | | |Subtensor{:int64:} [@BG] ''
| | |Subtensor{:int64:} [@BH] '' | | | |Subtensor{::int64} [@BH] ''
| | | |Subtensor{::int64} [@BI] '' | | | | |for{cpu,scan_fn} [@F] ''
| | | | |for{cpu,scan_fn} [@F] '' | | | | |Constant{-1} [@BI]
| | | | |Constant{-1} [@BJ] | | | |Constant{-1} [@BJ]
| | | |Constant{-1} [@BK] | | |ScalarFromTensor [@BK] ''
| | |ScalarFromTensor [@BL] '' | | |Elemwise{sub,no_inplace} [@C] ''
| | |Elemwise{sub,no_inplace} [@C] '' | |Subtensor{::int64} [@BL] ''
| |Subtensor{::int64} [@BM] '' | | |IncSubtensor{Inc;int64::} [@BM] ''
| | |IncSubtensor{Inc;int64::} [@BN] '' | | | |Elemwise{second,no_inplace} [@BN] ''
| | | |Elemwise{second,no_inplace} [@BO] '' | | | | |for{cpu,scan_fn} [@BO] ''
| | | | |for{cpu,scan_fn} [@BP] '' | | | | | |k [@G]
| | | | | |k [@G] | | | | | |IncSubtensor{Set;:int64:} [@H] ''
| | | | | |IncSubtensor{Set;:int64:} [@H] '' | | | | | |A [@P]
| | | | | |A [@Q] | | | | |DimShuffle{x,x} [@BP] ''
| | | | |DimShuffle{x,x} [@BQ] '' | | | | |TensorConstant{0.0} [@BQ]
| | | | |TensorConstant{0.0} [@J] | | | |IncSubtensor{Inc;int64} [@BR] ''
| | | |IncSubtensor{Inc;int64} [@BR] '' | | | | |Elemwise{second,no_inplace} [@BS] ''
| | | | |Elemwise{second,no_inplace} [@BS] '' | | | | | |Subtensor{int64::} [@BT] ''
| | | | | |Subtensor{int64::} [@BT] '' | | | | | | |for{cpu,scan_fn} [@BO] ''
| | | | | | |for{cpu,scan_fn} [@BP] '' | | | | | | |Constant{1} [@BU]
| | | | | | |Constant{1} [@BU] | | | | | |DimShuffle{x,x} [@BV] ''
| | | | | |DimShuffle{x,x} [@BV] '' | | | | | |TensorConstant{0.0} [@BQ]
| | | | | |TensorConstant{0.0} [@J] | | | | |Elemwise{second} [@BW] ''
| | | | |Elemwise{second} [@BW] '' | | | | | |Subtensor{int64} [@BX] ''
| | | | | |Subtensor{int64} [@BX] '' | | | | | | |Subtensor{int64::} [@BT] ''
| | | | | | |Subtensor{int64::} [@BT] '' | | | | | | |Constant{-1} [@BY]
| | | | | | |Constant{-1} [@BY] | | | | | |DimShuffle{x} [@BZ] ''
| | | | | |DimShuffle{x} [@BZ] '' | | | | | |Elemwise{second,no_inplace} [@CA] ''
| | | | | |Elemwise{second,no_inplace} [@CA] '' | | | | | |Sum{acc_dtype=float64} [@CB] ''
| | | | | |Sum{acc_dtype=float64} [@CB] '' | | | | | | |Subtensor{int64} [@BX] ''
| | | | | | |Subtensor{int64} [@BX] '' | | | | | |TensorConstant{1.0} [@R]
| | | | | |TensorConstant{1.0} [@S] | | | | |Constant{-1} [@BY]
| | | | |Constant{-1} [@BY] | | | |Constant{1} [@BU]
| | | |Constant{1} [@BU] | | |Constant{-1} [@CC]
| | |Constant{-1} [@CC] | |Alloc [@CD] ''
| |Alloc [@CD] '' | | |TensorConstant{0.0} [@BQ]
| | |TensorConstant{0.0} [@J] | | |Elemwise{add,no_inplace} [@CE] ''
| | |Elemwise{add,no_inplace} [@CE] '' | | | |Elemwise{sub,no_inplace} [@C] ''
| | | |Elemwise{sub,no_inplace} [@C] '' | | | |TensorConstant{1} [@Y]
| | | |TensorConstant{1} [@Z] | | |Subtensor{int64} [@CF] ''
| | |Subtensor{int64} [@CF] '' | | |Shape [@CG] ''
| | |Shape [@CG] '' | | | |A [@P]
| | | |A [@Q] | | |Constant{0} [@CH]
| | |Constant{0} [@CH] | |A [@P]
| |A [@Q] |Constant{-1} [@CI]
|Constant{-1} [@CI]
Inner graphs of the scan ops: Inner graphs of the scan ops:
for{cpu,grad_of_scan_fn}.1 [@B] '' for{cpu,grad_of_scan_fn}.1 [@B] ''
>Elemwise{add,no_inplace} [@CJ] '' >Elemwise{add,no_inplace} [@CJ] ''
> |Elemwise{mul} [@CK] '' > |Elemwise{mul} [@CK] ''
> | |<TensorType(float64, vector)> [@CL] -> [@BM] > | |<TensorType(float64, vector)> [@CL] -> [@BL]
> | |A_copy [@CM] -> [@Q] > | |A_copy [@CM] -> [@P]
> |<TensorType(float64, vector)> [@CN] -> [@BM] > |<TensorType(float64, vector)> [@CN] -> [@BL]
>Elemwise{add,no_inplace} [@CO] '' >Elemwise{add,no_inplace} [@CO] ''
> |Elemwise{mul} [@CP] '' > |Elemwise{mul} [@CP] ''
> | |<TensorType(float64, vector)> [@CL] -> [@BM] > | |<TensorType(float64, vector)> [@CL] -> [@BL]
> | |<TensorType(float64, vector)> [@CQ] -> [@BA] > | |<TensorType(float64, vector)> [@CQ] -> [@Z]
> |<TensorType(float64, vector)> [@CR] -> [@CD] > |<TensorType(float64, vector)> [@CR] -> [@CD]
for{cpu,scan_fn} [@F] '' for{cpu,scan_fn} [@F] ''
>Elemwise{mul,no_inplace} [@CS] '' >Elemwise{mul,no_inplace} [@CS] ''
> |<TensorType(float64, vector)> [@CT] -> [@H] > |<TensorType(float64, vector)> [@CT] -> [@H]
> |A_copy [@CU] -> [@Q] > |A_copy [@CU] -> [@P]
for{cpu,scan_fn} [@F] '' for{cpu,scan_fn} [@F] ''
>Elemwise{mul,no_inplace} [@CS] '' >Elemwise{mul,no_inplace} [@CS] ''
for{cpu,scan_fn} [@F] '' for{cpu,scan_fn} [@F] ''
>Elemwise{mul,no_inplace} [@CS] '' >Elemwise{mul,no_inplace} [@CS] ''
for{cpu,scan_fn} [@BP] '' for{cpu,scan_fn} [@BO] ''
>Elemwise{mul,no_inplace} [@CS] '' >Elemwise{mul,no_inplace} [@CS] ''
for{cpu,scan_fn} [@BP] '' for{cpu,scan_fn} [@BO] ''
>Elemwise{mul,no_inplace} [@CS] ''""" >Elemwise{mul,no_inplace} [@CS] ''"""
for truth, out in zip(expected_output.split("\n"), lines): for truth, out in zip(expected_output.split("\n"), lines):
assert truth.strip() == out.strip() assert truth.strip() == out.strip()
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论