| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329 |
- # Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- from paddle import _C_ops, _legacy_C_ops
- from paddle.base import core, framework
- name_mapping = {
- "graph_send_recv": {
- "final_op_name": "graph_send_recv",
- "x": "X",
- "src_index": "Src_index",
- "dst_index": "Dst_index",
- "out": "Out",
- "dst_count": "Dst_count",
- },
- "matmul_v2": {
- "final_op_name": "matmul",
- "transpose_x": "trans_x",
- "transpose_y": "trans_y",
- "x": "X",
- "y": "Y",
- "out": "Out",
- },
- # "elementwise_add": {
- # "final_op_name": "add",
- # "x": "X",
- # "y": "Y",
- # },
- "trunc": {
- "final_op_name": "trunc",
- "x": "X",
- "out": "Out",
- },
- # "pool2d": {
- # "final_op_name": "pool2d",
- # "x": "X",
- # "kernel_size": "ksize",
- # "out": "Out",
- # },
- "abs": {
- "final_op_name": "abs",
- "x": "X",
- "out": "Out",
- },
- "digamma": {
- "final_op_name": "digamma",
- "x": "X",
- "out": "Out",
- },
- "diagonal": {
- "final_op_name": "diagonal",
- "x": "Input",
- "offset": "offset",
- "axis1": "axis1",
- "axis2": "axis2",
- "out": "Out",
- },
- "roi_align": {
- "final_op_name": "roi_align",
- "x": "X",
- "boxes": "ROIs",
- "boxes_num": "RoisNum",
- "pooled_height": "pooled_height",
- "pooled_width": "pooled_width",
- "spatial_scale": "spatial_scale",
- "sampling_ratio": "sampling_ratio",
- "aligned": "aligned",
- },
- # "one_hot": {
- # "final_op_name": "one_hot",
- # "x": "X",
- # "num_class": "depth",
- # "out": "Out",
- # }
- }
- core_ops_args_info = _legacy_C_ops.get_core_ops_args_info()
- core_ops_args_type_info = _legacy_C_ops.get_core_ops_args_type_info()
- core_ops_returns_info = _legacy_C_ops.get_core_ops_returns_info()
- class Tracer(core.Tracer):
- """
- :api_attr: imperative
- Tracer is used to execute and record the operators executed, to construct the
- computation graph in dygraph model. Tracer has two mode, :code:`train_mode`
- and :code:`eval_mode`. In :code:`train_mode`, Tracer would add backward network
- automatically and perform AutoGrad by method :code:`loss.backward()`.
- In :code:`eval_mode`, Tracer would not add backward network.
- This is a low level API, users don't need to use it directly.
- """
- def __init__(self):
- super().__init__()
- self._train_mode = True
- def eager_legacy_trace_op(
- self,
- op_type,
- inputs,
- outputs,
- attrs,
- stop_gradient=False,
- inplace_map=None,
- ):
- function_ptr = _legacy_C_ops.__dict__[op_type]
- op_args = core_ops_args_info[op_type]
- op_args_type = core_ops_args_type_info[op_type]
- op_returns = core_ops_returns_info[op_type]
- arg_list = []
- for i in range(len(op_args)):
- # initialized with None
- arg_to_append = None
- arg_name = op_args[i]
- arg_type = op_args_type[i]
- if arg_name in inputs.keys():
- arg_to_append = inputs[arg_name]
- elif arg_name in outputs.keys():
- arg_to_append = outputs[arg_name]
- else:
- if "Num" in arg_name[-3:]:
- # Remove "Num" suffix to get out_name
- out_name = arg_name[:-3]
- assert out_name in outputs.keys()
- num_outs = len(outputs[out_name])
- arg_to_append = num_outs
- # NOTE(dev): For MasterParam/MasterParamOut in optimizer op
- elif "Var" in arg_name[-3:]:
- out_name = arg_name[:-3]
- print(out_name)
- if out_name in outputs.keys():
- arg_to_append = outputs[out_name]
- elif out_name in inputs.keys():
- arg_to_append = inputs[out_name]
- if arg_to_append is None:
- arg_list.append(arg_to_append)
- elif arg_type == "tensor":
- if isinstance(arg_to_append, list):
- arg_list.append(arg_to_append[0])
- else:
- arg_list.append(arg_to_append)
- elif arg_type == "list":
- assert isinstance(arg_to_append, list)
- arg_list.append(arg_to_append)
- else:
- assert arg_type == "int"
- assert isinstance(arg_to_append, int)
- arg_list.append(arg_to_append)
- attrs_list = []
- for k, v in attrs.items():
- attrs_list.append(k)
- attrs_list.append(v)
- returns = function_ptr(*arg_list, *attrs_list)
- if op_type == 'load_combine':
- assert len(outputs.keys()) == 1
- key = list(outputs.keys())[0]
- for j in range(len(returns)):
- returns[j]._share_underline_tensor_to(outputs[key][j])
- return
- if isinstance(returns, tuple):
- for i in range(len(op_returns)):
- retname = op_returns[i]
- if retname in outputs.keys():
- # Replaced outputs by function returns
- if isinstance(returns[i], list):
- for j in range(len(returns[i])):
- outputs[retname][j].reconstruct_from_(
- returns[i][j], False
- )
- else:
- if isinstance(outputs[retname], list):
- outputs[retname][0].reconstruct_from_(
- returns[i], False
- )
- else:
- outputs[retname].reconstruct_from_(
- returns[i], False
- )
- elif isinstance(returns, list):
- assert len(outputs.keys()) == 1
- key = list(outputs.keys())[0]
- for j in range(len(returns)):
- outputs[key][j].reconstruct_from_(returns[j], False)
- else:
- assert len(outputs.keys()) == 1
- key = list(outputs.keys())[0]
- if isinstance(outputs[key], list):
- outputs[key][0].reconstruct_from_(returns, False)
- else:
- outputs[key].reconstruct_from_(returns, False)
- def eager_trace_op(
- self,
- op_type,
- inputs,
- outputs,
- attrs,
- stop_gradient=False,
- inplace_map=None,
- ):
- assert op_type in name_mapping.keys()
- op_type = name_mapping[op_type]["final_op_name"]
- function_ptr = _C_ops.__dict__[op_type]
- core_ops_args_info = _C_ops.get_core_ops_args_info()
- core_ops_args_type_info = _C_ops.get_core_ops_args_type_info()
- core_ops_returns_info = _C_ops.get_core_ops_returns_info()
- op_args = core_ops_args_info[op_type]
- op_args_type = core_ops_args_type_info[op_type]
- op_returns = core_ops_returns_info[op_type]
- arg_list = []
- for i in range(len(op_args)):
- eager_arg_name = op_args[i]
- arg_type = op_args_type[i]
- assert eager_arg_name in name_mapping[op_type].keys()
- arg_name = name_mapping[op_type][eager_arg_name]
- if arg_name in inputs.keys():
- arg_to_append = inputs[arg_name]
- elif arg_name in outputs.keys():
- arg_to_append = outputs[arg_name]
- elif arg_name in attrs.keys() and arg_type == "":
- arg_to_append = attrs[arg_name]
- else:
- # dispensable
- arg_to_append = None
- if arg_type == "":
- # attribute
- arg_list.append(arg_to_append)
- elif arg_type == "tensor":
- if isinstance(arg_to_append, list):
- arg_list.append(arg_to_append[0])
- else:
- arg_list.append(arg_to_append)
- elif arg_type == "list":
- assert isinstance(arg_to_append, list)
- arg_list.append(arg_to_append)
- else:
- assert arg_to_append is None
- arg_list.append(arg_to_append)
- returns = function_ptr(*arg_list)
- if isinstance(returns, tuple):
- for i in range(len(op_returns)):
- eager_retname = op_returns[i]
- assert eager_retname in name_mapping[op_type].keys()
- retname = name_mapping[op_type][eager_retname]
- if retname in outputs.keys():
- # Replaced outputs by function returns
- if isinstance(returns[i], list):
- for j in range(len(returns[i])):
- outputs[retname][j].reconstruct_from_(
- returns[i][j], False
- )
- else:
- outputs[retname][0].reconstruct_from_(returns[i], False)
- elif isinstance(returns, list):
- assert len(outputs.keys()) == 1
- key = list(outputs.keys())[0]
- for j in range(len(returns)):
- outputs[key][j].reconstruct_from_(returns[j], False)
- else:
- assert len(outputs.keys()) == 1
- key = list(outputs.keys())[0]
- if isinstance(outputs[key], list):
- outputs[key][0].reconstruct_from_(returns, False)
- else:
- outputs[key].reconstruct_from_(returns, False)
- def trace_op(
- self,
- type,
- inputs,
- outputs,
- attrs,
- stop_gradient=False,
- inplace_map=None,
- ):
- if framework.in_dygraph_mode():
- # inputs : {"sum": [tensor], ...}
- # outputs : {"sum": [tensor], ...}
- if type in name_mapping.keys():
- type = name_mapping[type]["final_op_name"]
- assert type in _legacy_C_ops.__dict__
- self.eager_trace_op(
- type, inputs, outputs, attrs, stop_gradient, inplace_map
- )
- else:
- self.eager_legacy_trace_op(
- type, inputs, outputs, attrs, stop_gradient, inplace_map
- )
- else:
- raise ValueError("trace_op only work in dygraph mode")
- def train_mode(self):
- self._train_mode = True
- def eval_mode(self):
- self._train_mode = False
|