From 5e95fd1f1888bd2bdada5ad22e8575823486084b Mon Sep 17 00:00:00 2001 From: jim19930609 Date: Thu, 24 Mar 2022 09:28:08 +0000 Subject: [PATCH 01/12] [Refactor] refactored eager_gen.py PR #2 --- .../final_state_generator/codegen_utils.py | 10 +- .../final_state_generator/eager_gen.py | 109 ++++++++++++------ 2 files changed, 78 insertions(+), 41 deletions(-) diff --git a/paddle/fluid/eager/auto_code_generator/final_state_generator/codegen_utils.py b/paddle/fluid/eager/auto_code_generator/final_state_generator/codegen_utils.py index 6e1bee37a4e59..f5e41a6ae340a 100644 --- a/paddle/fluid/eager/auto_code_generator/final_state_generator/codegen_utils.py +++ b/paddle/fluid/eager/auto_code_generator/final_state_generator/codegen_utils.py @@ -46,6 +46,10 @@ ############################# ### File Reader Helpers ### ############################# +def AssertMessage(lhs_str, rhs_str): + return f"lhs: {lhs_str}, rhs: {rhs_str}" + + def ReadFwdFile(filepath): f = open(filepath, 'r') contents = yaml.load(f, Loader=yaml.FullLoader) @@ -58,10 +62,10 @@ def ReadBwdFile(filepath): contents = yaml.load(f, Loader=yaml.FullLoader) ret = {} for content in contents: + assert 'backward_api' in content.keys(), AssertMessage('backward_api', + content.keys()) if 'backward_api' in content.keys(): api_name = content['backward_api'] - else: - assert False ret[api_name] = content f.close() @@ -221,7 +225,7 @@ def ParseYamlReturns(string): ), f"The return type {ret_type} in yaml config is not supported in yaml_types_mapping." ret_type = yaml_types_mapping[ret_type] - assert "Tensor" in ret_type + assert "Tensor" in ret_type, AssertMessage("Tensor", ret_type) ret_name = RemoveSpecialSymbolsInName(ret_name) returns_list.append([ret_name, ret_type, i]) diff --git a/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py b/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py index fd750c0d07369..cd59211f02f3b 100644 --- a/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py +++ b/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py @@ -16,6 +16,7 @@ import re import argparse import os +import logging from codegen_utils import core_ops_returns_info, core_ops_args_info, core_ops_args_type_info from codegen_utils import yaml_types_mapping from codegen_utils import ReadFwdFile, ReadBwdFile @@ -30,6 +31,7 @@ from codegen_utils import ParseYamlForward, ParseYamlBackward from codegen_utils import FunctionGeneratorBase, YamlGeneratorBase from codegen_utils import ops_to_fill_zero_for_empty_grads +from codegen_utils import AssertMessage ########### @@ -398,14 +400,21 @@ def DygraphYamlValidationCheck(self): forward_api_contents = self.forward_api_contents grad_api_contents = self.grad_api_contents - assert 'api' in forward_api_contents.keys() - assert 'args' in forward_api_contents.keys() - assert 'output' in forward_api_contents.keys() - assert 'backward' in forward_api_contents.keys() - - assert 'args' in grad_api_contents.keys() - assert 'output' in grad_api_contents.keys() - assert 'forward' in grad_api_contents.keys() + assert 'api' in forward_api_contents.keys( + ), "Unable to find \"api\" in api.yaml" + assert 'args' in forward_api_contents.keys( + ), "Unable to find \"args\" in api.yaml" + assert 'output' in forward_api_contents.keys( + ), "Unable to find \"output\" in api.yaml" + assert 'backward' in forward_api_contents.keys( + ), "Unable to find \"backward\" in api.yaml" + + assert 'args' in grad_api_contents.keys( + ), "Unable to find \"args\" in backward.yaml" + assert 'output' in grad_api_contents.keys( + ), "Unable to find \"output\" in backward.yaml" + assert 'forward' in grad_api_contents.keys( + ), "Unable to find \"forward\" in backward.yaml" def ForwardsValidationCheck(self): forward_inputs_list = self.forward_inputs_list @@ -424,8 +433,10 @@ def ForwardsValidationCheck(self): orig_input_type = orig_forward_inputs_list[i][1] orig_input_pos = orig_forward_inputs_list[i][2] - assert forward_input_type == orig_input_type - assert forward_input_pos == orig_input_pos + assert forward_input_type == orig_input_type, AssertMessage( + forward_input_type, orig_input_type) + assert forward_input_pos == orig_input_pos, AssertMessage( + forward_input_pos, orig_input_pos) for i in range(len(forward_attrs_list)): orig_attr_name = orig_forward_attrs_list[i][0] @@ -436,9 +447,12 @@ def ForwardsValidationCheck(self): forward_attr_type = forward_attrs_list[i][1] forward_attr_default = forward_attrs_list[i][2] forward_attr_pos = forward_attrs_list[i][3] - assert orig_attr_type == forward_attr_type - assert orig_attr_default == forward_attr_default - assert orig_attr_pos == forward_attr_pos + assert orig_attr_type == forward_attr_type, AssertMessage( + orig_attr_type, forward_attr_type) + assert orig_attr_default == forward_attr_default, AssertMessage( + orig_attr_default, forward_attr_default) + assert orig_attr_pos == forward_attr_pos, AssertMessage( + orig_attr_pos, forward_attr_pos) for i in range(len(forward_returns_list)): orig_return_type = orig_forward_returns_list[i][1] @@ -446,8 +460,10 @@ def ForwardsValidationCheck(self): forward_return_type = forward_returns_list[i][1] forward_return_pos = forward_returns_list[i][2] - assert orig_return_type == forward_return_type - assert orig_return_pos == forward_return_pos + assert orig_return_type == forward_return_type, AssertMessage( + orig_return_type, forward_return_type) + assert orig_return_pos == forward_return_pos, AssertMessage( + orig_return_pos, forward_return_pos) # Check Order: Inputs, Attributes max_input_position = -1 @@ -456,7 +472,8 @@ def ForwardsValidationCheck(self): max_attr_position = -1 for _, _, _, pos in forward_attrs_list: - assert pos > max_input_position + assert pos > max_input_position, AssertMessage(pos, + max_input_position) max_attr_position = max(max_attr_position, pos) def BackwardValidationCheck(self): @@ -471,12 +488,14 @@ def BackwardValidationCheck(self): max_grad_tensor_position = -1 for _, (_, _, pos) in backward_grad_inputs_map.items(): - assert pos > max_fwd_input_position + assert pos > max_fwd_input_position, AssertMessage( + pos, max_grad_tensor_position) max_grad_tensor_position = max(max_grad_tensor_position, pos) max_attr_position = -1 for _, _, _, pos in backward_attrs_list: - assert pos > max_grad_tensor_position + assert pos > max_grad_tensor_position, AssertMessage( + pos, max_grad_tensor_position) max_attr_position = max(max_attr_position, pos) def IntermediateValidationCheck(self): @@ -491,7 +510,8 @@ def IntermediateValidationCheck(self): len(forward_returns_list)) for ret_name, _, pos in forward_returns_list: if ret_name in intermediate_outputs: - assert pos in intermediate_positions + assert pos in intermediate_positions, AssertMessage( + pos, intermediate_positions) def CollectBackwardInfo(self): forward_api_contents = self.forward_api_contents @@ -505,9 +525,12 @@ def CollectBackwardInfo(self): self.backward_inputs_list, self.backward_attrs_list, self.backward_returns_list = ParseYamlBackward( backward_args_str, backward_returns_str) - print("Parsed Backward Inputs List: ", self.backward_inputs_list) - print("Prased Backward Attrs List: ", self.backward_attrs_list) - print("Parsed Backward Returns List: ", self.backward_returns_list) + + logging.info( + f"Parsed Backward Inputs List: {self.backward_inputs_list}") + logging.info(f"Prased Backward Attrs List: {self.backward_attrs_list}") + logging.info( + f"Parsed Backward Returns List: {self.backward_returns_list}") def CollectForwardInfoFromBackwardContents(self): @@ -530,7 +553,9 @@ def SlotNameMatching(self): backward_fwd_name = FindForwardName(backward_input_name) if backward_fwd_name: # Grad Input - assert backward_fwd_name in forward_outputs_position_map.keys() + assert backward_fwd_name in forward_outputs_position_map.keys( + ), AssertMessage(backward_fwd_name, + forward_outputs_position_map.keys()) matched_forward_output_type = forward_outputs_position_map[ backward_fwd_name][0] matched_forward_output_pos = forward_outputs_position_map[ @@ -556,7 +581,7 @@ def SlotNameMatching(self): backward_input_type, False, backward_input_pos ] else: - assert False, backward_input_name + assert False, f"Cannot find {backward_input_name} in forward position map" for backward_output in backward_returns_list: backward_output_name = backward_output[0] @@ -564,9 +589,10 @@ def SlotNameMatching(self): backward_output_pos = backward_output[2] backward_fwd_name = FindForwardName(backward_output_name) - assert backward_fwd_name is not None + assert backward_fwd_name is not None, f"Detected {backward_fwd_name} = None" assert backward_fwd_name in forward_inputs_position_map.keys( - ), f"Unable to find {backward_fwd_name} in forward inputs" + ), AssertMessage(backward_fwd_name, + forward_inputs_position_map.keys()) matched_forward_input_type = forward_inputs_position_map[ backward_fwd_name][0] @@ -577,12 +603,15 @@ def SlotNameMatching(self): backward_output_type, matched_forward_input_pos, backward_output_pos ] - print("Generated Backward Fwd Input Map: ", - self.backward_forward_inputs_map) - print("Generated Backward Grad Input Map: ", - self.backward_grad_inputs_map) - print("Generated Backward Grad Output Map: ", - self.backward_grad_outputs_map) + logging.info( + f"Generated Backward Fwd Input Map: {self.backward_forward_inputs_map}" + ) + logging.info( + f"Generated Backward Grad Input Map: {self.backward_grad_inputs_map}" + ) + logging.info( + f"Generated Backward Grad Output Map: {self.backward_grad_outputs_map}" + ) def GenerateNodeDeclaration(self): forward_op_name = self.forward_api_name @@ -642,7 +671,7 @@ def GenerateNodeDeclaration(self): set_tensor_wrapper_methods_str, set_attribute_methods_str, tensor_wrapper_members_str, attribute_members_str) - print("Generated Node Declaration: ", self.node_declaration_str) + logging.info(f"Generated Node Declaration: {self.node_declaration_str}") def GenerateNodeDefinition(self): namespace = self.namespace @@ -710,7 +739,7 @@ def GenerateNodeDefinition(self): grad_node_name, fill_zero_str, grad_node_name, grad_api_namespace, backward_api_name, grad_api_args_str, returns_str) - print("Generated Node Definition: ", self.node_definition_str) + logging.info(f"Generated Node Definition: {self.node_definition_str}") def GenerateForwardDefinition(self, is_inplaced): namespace = self.namespace @@ -813,8 +842,10 @@ def GenerateForwardDefinition(self, is_inplaced): dygraph_event_str, node_creation_str, returns_str) self.forward_declaration_str += f"{returns_type_str} {forward_function_name}({inputs_args_declaration_str});\n" - print("Generated Forward Definition: ", self.forward_definition_str) - print("Generated Forward Declaration: ", self.forward_declaration_str) + logging.info( + f"Generated Forward Definition: {self.forward_definition_str}") + logging.info( + f"Generated Forward Declaration: {self.forward_declaration_str}") def GenerateNodeCreationCodes(self, forward_call_str): forward_api_name = self.forward_api_name @@ -921,7 +952,8 @@ def GenerateNodeCreationCodes(self, forward_call_str): else: if num_fwd_outputs > 1: # Aligned with forward output position - assert name in forward_outputs_position_map.keys() + assert name in forward_outputs_position_map.keys( + ), AssertMessage(name, forward_outputs_position_map.keys()) fwd_output_pos = forward_outputs_position_map[name][1] tw_name = f"std::get<{fwd_output_pos}>(api_result)" else: @@ -1114,7 +1146,8 @@ def GetBackwardAPIContents(self, forward_api_contents): if 'backward' not in forward_api_contents.keys(): return None backward_api_name = forward_api_contents['backward'] - assert backward_api_name in grad_api_dict.keys() + assert backward_api_name in grad_api_dict.keys(), AssertMessage( + backward_api_name, grad_api_dict.keys()) backward_api_contents = grad_api_dict[backward_api_name] return backward_api_contents From 214ad3626b7b63b9a11871fa25d79c1f51c20a66 Mon Sep 17 00:00:00 2001 From: jim19930609 Date: Fri, 25 Mar 2022 05:54:46 +0000 Subject: [PATCH 02/12] [DoubleGrad PR #1] Decoupled code generation logics for Dygraph ForwardFunctions and GradNodes --- .../final_state_generator/eager_gen.py | 624 +++++++++--------- 1 file changed, 326 insertions(+), 298 deletions(-) diff --git a/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py b/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py index cd59211f02f3b..e6e829ffd44f2 100644 --- a/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py +++ b/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py @@ -172,7 +172,7 @@ class {} : public egr::GradNodeBase {{ """ -NODE_CREATION_TEMPLATE = \ +FORWARD_BODY_TEMPLATE = \ """ // Get AutoGradMeta {} @@ -344,7 +344,7 @@ def GenerateCoreOpInfoDefinition(): ##################### ## Generator Class ## ##################### -class DygraphSingleFunctionGenerator(FunctionGeneratorBase): +class DygraphFunctionGeneratorBase(FunctionGeneratorBase): def __init__(self, forward_api_contents, grad_api_contents, namespace): self.forward_api_contents = forward_api_contents # Members from Parent: @@ -390,12 +390,6 @@ def __init__(self, forward_api_contents, grad_api_contents, namespace): self.backward_grad_outputs_map = { } #{ "name" : [type, fwd_position, orig_position] ...} - # Generated Results - self.forward_definition_str = "" - self.forward_declaration_str = "" - self.node_declaration_str = "" - self.node_definition_str = "" - def DygraphYamlValidationCheck(self): forward_api_contents = self.forward_api_contents grad_api_contents = self.grad_api_contents @@ -613,241 +607,7 @@ def SlotNameMatching(self): f"Generated Backward Grad Output Map: {self.backward_grad_outputs_map}" ) - def GenerateNodeDeclaration(self): - forward_op_name = self.forward_api_name - backward_forward_inputs_map = self.backward_forward_inputs_map - backward_attrs_list = self.backward_attrs_list - no_need_buffers = self.no_need_buffers - - # SetTensorWrapper Methods & TensorWrapper Members - set_tensor_wrapper_methods_str = "" - tensor_wrapper_members_str = "" - clear_tensor_wrapper_str = "" - for tname, (ttype, is_fwd_input, - _) in backward_forward_inputs_map.items(): - no_need_buffer = "true" if tname in no_need_buffers else "false" - tensor_wrapper_name = GetSavedName(tname) - if IsPlainTensorType(ttype): - set_tensor_wrapper_methods_str += SET_PLAIN_TENSOR_WRAPPER_TEMPLATE.format( - tname, tname, tensor_wrapper_name, tname, no_need_buffer) - - tensor_wrapper_members_str += PLAIN_TENSOR_MEMBER_TEMPLATE.format( - tensor_wrapper_name) - - clear_tensor_wrapper_str += CLEAR_TENSOR_WRAPPER_TEMPLATE.format( - tensor_wrapper_name) - - else: - assert IsVectorTensorType(ttype) - set_tensor_wrapper_methods_str += SET_VECTOR_TENSOR_WRAPPER_TEMPLATE.format( - tname, tname, tname, tensor_wrapper_name, no_need_buffer) - - tensor_wrapper_members_str += VECTOR_TENSOR_MEMBER_TEMPLATE.format( - tensor_wrapper_name) - - clear_tensor_wrapper_str += CLEAR_VECTOR_TENSOR_WRAPPERS_TEMPLATE.format( - tensor_wrapper_name) - - # SetAttributes & Attribute Members - set_attribute_methods_str = "" - attribute_members_str = "" - for aname, atype, default_val, _ in backward_attrs_list: - saved_attr_name = GetSavedName(aname) - set_attribute_methods_str += SET_ATTR_METHOD_TEMPLATE.format( - aname, GetConstReference(atype), aname, saved_attr_name, aname) - - if default_val: - attribute_members_str += ATTRIBUTE_MEMBER_WITH_DEFAULT_TEMPLATE.format( - RemoveConstAndReference(atype), saved_attr_name, - default_val) - else: - attribute_members_str += ATTRIBUTE_MEMBER_TEMPLATE.format( - RemoveConstAndReference(atype), saved_attr_name) - - grad_node_name = GetGradNodeName(forward_op_name) - self.node_declaration_str = NODE_DECLARATION_TEMPLATE.format( - grad_node_name, grad_node_name, grad_node_name, grad_node_name, - grad_node_name, clear_tensor_wrapper_str, - set_tensor_wrapper_methods_str, set_attribute_methods_str, - tensor_wrapper_members_str, attribute_members_str) - - logging.info(f"Generated Node Declaration: {self.node_declaration_str}") - - def GenerateNodeDefinition(self): - namespace = self.namespace - forward_api_name = self.forward_api_name - backward_api_name = self.backward_api_name - backward_forward_inputs_map = self.backward_forward_inputs_map - backward_grad_inputs_map = self.backward_grad_inputs_map - backward_grad_outputs_map = self.backward_grad_outputs_map - backward_attrs_list = self.backward_attrs_list - - # Construct grad_api function args - # Order: TensorWrappers, GradTensors, Attributes - grad_api_args_len = len(backward_forward_inputs_map.keys()) + len( - backward_grad_inputs_map.keys()) + len(backward_attrs_list) - grad_api_args = ["" for i in range(grad_api_args_len)] - for name, (_, is_fwd_input, - grad_api_position), in backward_forward_inputs_map.items(): - tensor_wrapper_name = GetSavedName(name) - grad_api_args[ - grad_api_position] = f"egr::EagerUtils::RecoverTensorWrapper(&this->{tensor_wrapper_name}, nullptr)" - - for _, (ttype, fwd_position, - grad_api_position) in backward_grad_inputs_map.items(): - if IsPlainTensorType(ttype): - grad_api_args[ - grad_api_position] = f"hooked_grads[{fwd_position}][0]" - else: - assert IsVectorTensorType(ttype) - grad_api_args[ - grad_api_position] = f"hooked_grads[{fwd_position}]" - - for name, _, _, grad_api_position in backward_attrs_list: - saved_attribute_name = GetSavedName(name) - grad_api_args[grad_api_position] = f"this->{saved_attribute_name}" - grad_api_args_str = ", ".join(grad_api_args) - - # Construct grad_api returns - num_bwd_outputs = len(backward_grad_outputs_map.keys()) - returns_str = f"std::vector> returns({num_bwd_outputs});\n" - for _, (ttype, fwd_position, - grad_api_position) in backward_grad_outputs_map.items(): - # Infer Grad API Return Type - if num_bwd_outputs == 1: - # Single tensor output, return as is - if IsPlainTensorType(ttype): - returns_str += "returns[0] = { grad_api_returns };\n" - else: - assert IsVectorTensorType(ttype) - returns_str += "returns[0] = grad_api_returns;\n" - else: - # Rearrange output order accordingly - returns_str += f"returns[{fwd_position}] = grad_api_returns[{grad_api_position}];\n" - returns_str += f"if(NeedComplexToRealConversion()) HandleComplexGradToRealGrad(&returns);\n" - returns_str += f"return returns;\n" - - grad_node_name = GetGradNodeName(forward_api_name) - - fill_zero_str = "" - if forward_api_name in ops_to_fill_zero_for_empty_grads: - fill_zero_str = "egr::EagerUtils::FillZeroForEmptyGradInputs(&grads, this->InputMeta());\n" - - grad_api_namespace = f"paddle::experimental::{namespace}" - - self.node_definition_str = FUNCTION_TEMPLATE.format( - grad_node_name, fill_zero_str, grad_node_name, grad_api_namespace, - backward_api_name, grad_api_args_str, returns_str) - - logging.info(f"Generated Node Definition: {self.node_definition_str}") - - def GenerateForwardDefinition(self, is_inplaced): - namespace = self.namespace - forward_api_name = GetInplacedFunctionName( - self.forward_api_name) if is_inplaced else self.forward_api_name - backward_api_name = self.backward_api_name - forward_inputs_position_map = self.forward_inputs_position_map - forward_outputs_position_map = self.forward_outputs_position_map - forward_attrs_list = self.forward_attrs_list - backward_forward_inputs_map = self.backward_forward_inputs_map - backward_grad_inputs_map = self.backward_grad_inputs_map - backward_grad_outputs_map = self.backward_grad_outputs_map - backward_attrs_list = self.backward_attrs_list - optional_inputs = self.optional_inputs - intermediate_outputs = self.intermediate_outputs - inplace_map = self.inplace_map - - # Get Function Args - num_inputs = len(forward_attrs_list) + len( - forward_inputs_position_map.keys()) - inputs_args_definition_list = ["" for i in range(num_inputs)] - inputs_args_declaration_list = ["" for i in range(num_inputs)] - inputs_call_list = ["" for i in range(num_inputs)] - for name, (ttype, pos) in forward_inputs_position_map.items(): - inputs_call_list[pos] = f"{name}" - is_optional = (name in optional_inputs) - if IsPlainTensorType(ttype): - if is_optional: - arg_str = f"const paddle::optional& {name}" - else: - if inplace_map and name in inplace_map.keys(): - arg_str = f"paddle::experimental::Tensor& {name}" - else: - arg_str = f"const paddle::experimental::Tensor& {name}" - else: - assert IsVectorTensorType(ttype) - arg_str = f"const std::vector& {name}" - - inputs_args_definition_list[pos] = arg_str - inputs_args_declaration_list[pos] = arg_str - - for name, atype, default_val, pos in forward_attrs_list: - inputs_call_list[pos] = name - if default_val is not None: - inputs_args_declaration_list[ - pos] = f"{atype} {name} = {default_val}" - else: - inputs_args_declaration_list[pos] = f"{atype} {name}" - inputs_args_definition_list[pos] = f"{atype} {name}" - - inputs_args_declaration_str = ", ".join(inputs_args_declaration_list) - inputs_args_definition_str = ", ".join(inputs_args_definition_list) - inputs_call_args_str = ", ".join(inputs_call_list) - - # Forward Full Logic - function_name = forward_api_name - if len(intermediate_outputs) > 0: - function_name = GetIntermediateAPIFunctionName(function_name) - - forward_call_str = f"auto api_result = paddle::experimental::{namespace}{function_name}({inputs_call_args_str});" - - # Get return type list & outputs - num_outputs = len(forward_outputs_position_map.keys()) - len( - intermediate_outputs) - returns_type_list = ["" for i in range(num_outputs)] - returns_list = ["" for i in range(num_outputs)] - for name, (rtype, pos) in forward_outputs_position_map.items(): - if name in intermediate_outputs: - continue - if num_outputs == 1: - returns_list[0] = f"api_result" - else: - # Tuple api_result - returns_list[pos] = f"std::get<{pos}>(api_result)" - - if IsPlainTensorType(rtype): - returns_type_list[pos] = "paddle::experimental::Tensor" - else: - assert IsVectorTensorType(rtype) - returns_type_list[ - pos] = "std::vector" - - if num_outputs == 1: - returns_str = returns_list[0] - returns_type_str = returns_type_list[0] - else: - returns_type_str = ", ".join(returns_type_list) - returns_type_str = f"std::tuple<{returns_type_str}>" - returns_str = ", ".join(returns_list) - returns_str = f"std::make_tuple({returns_str})" - - self.GenerateNodeCreationCodes(forward_call_str) - - node_creation_str = self.node_creation_str - dygraph_event_str = f"paddle::platform::RecordEvent dygraph_entrance_record_event(\"{forward_api_name} dygraph\", paddle::platform::TracerEventType::Operator, 1);" - forward_function_name = GetDygraphForwardFunctionName(forward_api_name) - - self.forward_definition_str += FORWARD_FUNCTION_TEMPLATE.format( - returns_type_str, forward_function_name, inputs_args_definition_str, - dygraph_event_str, node_creation_str, returns_str) - self.forward_declaration_str += f"{returns_type_str} {forward_function_name}({inputs_args_declaration_str});\n" - - logging.info( - f"Generated Forward Definition: {self.forward_definition_str}") - logging.info( - f"Generated Forward Declaration: {self.forward_declaration_str}") - - def GenerateNodeCreationCodes(self, forward_call_str): + def GenerateForwardFunctionBody(self, forward_call_str, is_inplaced): forward_api_name = self.forward_api_name forward_inputs_position_map = self.forward_inputs_position_map forward_outputs_position_map = self.forward_outputs_position_map @@ -857,7 +617,7 @@ def GenerateNodeCreationCodes(self, forward_call_str): backward_grad_outputs_map = self.backward_grad_outputs_map backward_attrs_list = self.backward_attrs_list optional_inputs = self.optional_inputs - inplace_map = self.inplace_map + inplace_map = self.inplace_map if is_inplaced else {} # Get Input AutoGradMeta inputs_autograd_meta_list = [] @@ -1008,7 +768,7 @@ def GenerateNodeCreationCodes(self, forward_call_str): node_event_name = forward_api_name + " node_creation" node_creation_event_str = f"paddle::platform::RecordEvent node_creation_record_event(\"{node_event_name}\", paddle::platform::TracerEventType::Operator, 1);\n" - self.node_creation_str = NODE_CREATION_TEMPLATE.format( + self.node_creation_str = FORWARD_BODY_TEMPLATE.format( inputs_autograd_meta_str, compute_require_grad_args_str, check_inplace_str, forward_call_str, bump_inplace_version_str, node_creation_event_str, outputs_autograd_meta_str, @@ -1017,18 +777,179 @@ def GenerateNodeCreationCodes(self, forward_call_str): set_edges_str, set_out_rank_str, set_history_str, set_grad_in_meta_str, set_retain_grad_str) - def GenerateInplacedForwardDygraphFunctions(self): - # Inplaced Version Dygraph Function Generation - forward_api_name = self.forward_api_name - forward_api_contents = self.forward_api_contents + def run(self): + # Basic Validation Check + self.DygraphYamlValidationCheck() - if forward_api_name != "sum" and "inplace" in forward_api_contents.keys( - ): - # Node Definition Generation - self.GenerateForwardDefinition(is_inplaced=True) - self.UpdateCoreOpsInformation(is_inplaced=True) + ########################## + ## Parsing Raw Contents ## + ########################## + # Parse inplace_map + self.ParseInplaceInfo() - def UpdateCoreOpsInformation(self, is_inplaced): + # Parse no_need_buffer + self.ParseNoNeedBuffer() + + # Parse optional_inputs + self.ParseDispensable() + + # Parse intermediate_outputs + self.ParseIntermediate() + self.IntermediateValidationCheck() + + # Initialize backward_forward_str, backward_inputs_list, backward_attrs_list, backward_returns_list + self.CollectBackwardInfo() + + # Initialize forward_inputs_list, forward_attrs_list, forward_returns_list + self.CollectForwardInfoFromBackwardContents() + + # Initialize orig_forward_inputs_list, orig_forward_attrs_list, orig_forward_returns_list + self.CollectOriginalForwardInfo() + + # Forwards Validation Check + self.ForwardsValidationCheck() + + ############################# + ## Process Parsed Contents ## + ############################# + # Initialize forward_inputs_position_map, forward_outputs_position_map + self.DetermineForwardPositionMap(self.forward_inputs_list, + self.forward_returns_list) + + # Initialize forward_inputs_position_map, forward_outputs_position_map + self.SlotNameMatching() + + # Backward Validation Check + self.BackwardValidationCheck() + + +class DygraphForwardFunctionGenerator(DygraphFunctionGeneratorBase): + def __init__(self, forward_api_contents, grad_api_contents, namespace): + DygraphFunctionGeneratorBase.__init__(self, forward_api_contents, + grad_api_contents, namespace) + + # Generated Results + self.forward_definition_str = "" + self.forward_declaration_str = "" + + def GenerateForwardDefinition(self, is_inplaced): + namespace = self.namespace + forward_api_name = GetInplacedFunctionName( + self.forward_api_name) if is_inplaced else self.forward_api_name + backward_api_name = self.backward_api_name + forward_inputs_position_map = self.forward_inputs_position_map + forward_outputs_position_map = self.forward_outputs_position_map + forward_attrs_list = self.forward_attrs_list + backward_forward_inputs_map = self.backward_forward_inputs_map + backward_grad_inputs_map = self.backward_grad_inputs_map + backward_grad_outputs_map = self.backward_grad_outputs_map + backward_attrs_list = self.backward_attrs_list + optional_inputs = self.optional_inputs + intermediate_outputs = self.intermediate_outputs + inplace_map = self.inplace_map if is_inplaced else {} + + # Get Function Args + num_inputs = len(forward_attrs_list) + len( + forward_inputs_position_map.keys()) + inputs_args_definition_list = ["" for i in range(num_inputs)] + inputs_args_declaration_list = ["" for i in range(num_inputs)] + inputs_call_list = ["" for i in range(num_inputs)] + for name, (ttype, pos) in forward_inputs_position_map.items(): + inputs_call_list[pos] = f"{name}" + is_optional = (name in optional_inputs) + if IsPlainTensorType(ttype): + if is_optional: + arg_str = f"const paddle::optional& {name}" + else: + if inplace_map and name in inplace_map.keys(): + arg_str = f"paddle::experimental::Tensor& {name}" + else: + arg_str = f"const paddle::experimental::Tensor& {name}" + else: + assert IsVectorTensorType(ttype) + arg_str = f"const std::vector& {name}" + + inputs_args_definition_list[pos] = arg_str + inputs_args_declaration_list[pos] = arg_str + + for name, atype, default_val, pos in forward_attrs_list: + inputs_call_list[pos] = name + if default_val is not None: + inputs_args_declaration_list[ + pos] = f"{atype} {name} = {default_val}" + else: + inputs_args_declaration_list[pos] = f"{atype} {name}" + inputs_args_definition_list[pos] = f"{atype} {name}" + + inputs_args_declaration_str = ", ".join(inputs_args_declaration_list) + inputs_args_definition_str = ", ".join(inputs_args_definition_list) + inputs_call_args_str = ", ".join(inputs_call_list) + + # Forward Full Logic + function_name = forward_api_name + if len(intermediate_outputs) > 0: + function_name = GetIntermediateAPIFunctionName(function_name) + + forward_call_str = f"auto api_result = paddle::experimental::{namespace}{function_name}({inputs_call_args_str});" + + # Get return type list & outputs + num_outputs = len(forward_outputs_position_map.keys()) - len( + intermediate_outputs) + returns_type_list = ["" for i in range(num_outputs)] + returns_list = ["" for i in range(num_outputs)] + for name, (rtype, pos) in forward_outputs_position_map.items(): + if name in intermediate_outputs: + continue + if num_outputs == 1: + returns_list[0] = f"api_result" + else: + # Tuple api_result + returns_list[pos] = f"std::get<{pos}>(api_result)" + + if IsPlainTensorType(rtype): + returns_type_list[pos] = "paddle::experimental::Tensor" + else: + assert IsVectorTensorType(rtype) + returns_type_list[ + pos] = "std::vector" + + if num_outputs == 1: + returns_str = returns_list[0] + returns_type_str = returns_type_list[0] + else: + returns_type_str = ", ".join(returns_type_list) + returns_type_str = f"std::tuple<{returns_type_str}>" + returns_str = ", ".join(returns_list) + returns_str = f"std::make_tuple({returns_str})" + + self.GenerateForwardFunctionBody(forward_call_str, is_inplaced) + + node_creation_str = self.node_creation_str + dygraph_event_str = f"paddle::platform::RecordEvent dygraph_entrance_record_event(\"{forward_api_name} dygraph\", paddle::platform::TracerEventType::Operator, 1);" + forward_function_name = GetDygraphForwardFunctionName(forward_api_name) + + self.forward_definition_str += FORWARD_FUNCTION_TEMPLATE.format( + returns_type_str, forward_function_name, inputs_args_definition_str, + dygraph_event_str, node_creation_str, returns_str) + self.forward_declaration_str += f"{returns_type_str} {forward_function_name}({inputs_args_declaration_str});\n" + + logging.info( + f"Generated Forward Definition: {self.forward_definition_str}") + logging.info( + f"Generated Forward Declaration: {self.forward_declaration_str}") + + def GenerateInplacedForwardDygraphFunctions(self): + # Inplaced Version Dygraph Function Generation + forward_api_name = self.forward_api_name + forward_api_contents = self.forward_api_contents + + if forward_api_name != "sum" and "inplace" in forward_api_contents.keys( + ): + # Node Definition Generation + self.GenerateForwardDefinition(is_inplaced=True) + self.UpdateCoreOpsInformation(is_inplaced=True) + + def UpdateCoreOpsInformation(self, is_inplaced): forward_api_name = GetInplacedFunctionName( self.forward_api_name) if is_inplaced else self.forward_api_name forward_inputs_position_map = self.forward_inputs_position_map @@ -1062,60 +983,163 @@ def UpdateCoreOpsInformation(self, is_inplaced): core_ops_returns_info[final_state_fwd_api_name][pos] = name def run(self): - # Basic Validation Check - self.DygraphYamlValidationCheck() + super().run() - ########################## - ## Parsing Raw Contents ## - ########################## - # Parse inplace_map - self.ParseInplaceInfo() + ##################### + ## Code Generation ## + ##################### + self.GenerateForwardDefinition(is_inplaced=False) - # Parse no_need_buffer - self.ParseNoNeedBuffer() + self.UpdateCoreOpsInformation(is_inplaced=False) - # Parse optional_inputs - self.ParseDispensable() + self.GenerateInplacedForwardDygraphFunctions() - # Parse intermediate_outputs - self.ParseIntermediate() - self.IntermediateValidationCheck() - # Initialize backward_forward_str, backward_inputs_list, backward_attrs_list, backward_returns_list - self.CollectBackwardInfo() +class DygraphNodeGenerator(DygraphFunctionGeneratorBase): + def __init__(self, forward_api_contents, grad_api_contents, namespace): + DygraphFunctionGeneratorBase.__init__(self, forward_api_contents, + grad_api_contents, namespace) - # Initialize forward_inputs_list, forward_attrs_list, forward_returns_list - self.CollectForwardInfoFromBackwardContents() + # Generated Results + self.node_declaration_str = "" + self.node_definition_str = "" - # Initialize orig_forward_inputs_list, orig_forward_attrs_list, orig_forward_returns_list - self.CollectOriginalForwardInfo() + def GenerateNodeDeclaration(self): + forward_op_name = self.forward_api_name + backward_forward_inputs_map = self.backward_forward_inputs_map + backward_attrs_list = self.backward_attrs_list + no_need_buffers = self.no_need_buffers - # Forwards Validation Check - self.ForwardsValidationCheck() + # SetTensorWrapper Methods & TensorWrapper Members + set_tensor_wrapper_methods_str = "" + tensor_wrapper_members_str = "" + clear_tensor_wrapper_str = "" + for tname, (ttype, is_fwd_input, + _) in backward_forward_inputs_map.items(): + no_need_buffer = "true" if tname in no_need_buffers else "false" + tensor_wrapper_name = GetSavedName(tname) + if IsPlainTensorType(ttype): + set_tensor_wrapper_methods_str += SET_PLAIN_TENSOR_WRAPPER_TEMPLATE.format( + tname, tname, tensor_wrapper_name, tname, no_need_buffer) - ############################# - ## Process Parsed Contents ## - ############################# - # Initialize forward_inputs_position_map, forward_outputs_position_map - self.DetermineForwardPositionMap(self.forward_inputs_list, - self.forward_returns_list) + tensor_wrapper_members_str += PLAIN_TENSOR_MEMBER_TEMPLATE.format( + tensor_wrapper_name) - # Initialize forward_inputs_position_map, forward_outputs_position_map - self.SlotNameMatching() + clear_tensor_wrapper_str += CLEAR_TENSOR_WRAPPER_TEMPLATE.format( + tensor_wrapper_name) - # Backward Validation Check - self.BackwardValidationCheck() + else: + assert IsVectorTensorType(ttype) + set_tensor_wrapper_methods_str += SET_VECTOR_TENSOR_WRAPPER_TEMPLATE.format( + tname, tname, tname, tensor_wrapper_name, no_need_buffer) + + tensor_wrapper_members_str += VECTOR_TENSOR_MEMBER_TEMPLATE.format( + tensor_wrapper_name) + + clear_tensor_wrapper_str += CLEAR_VECTOR_TENSOR_WRAPPERS_TEMPLATE.format( + tensor_wrapper_name) + + # SetAttributes & Attribute Members + set_attribute_methods_str = "" + attribute_members_str = "" + for aname, atype, default_val, _ in backward_attrs_list: + saved_attr_name = GetSavedName(aname) + set_attribute_methods_str += SET_ATTR_METHOD_TEMPLATE.format( + aname, GetConstReference(atype), aname, saved_attr_name, aname) + + if default_val: + attribute_members_str += ATTRIBUTE_MEMBER_WITH_DEFAULT_TEMPLATE.format( + RemoveConstAndReference(atype), saved_attr_name, + default_val) + else: + attribute_members_str += ATTRIBUTE_MEMBER_TEMPLATE.format( + RemoveConstAndReference(atype), saved_attr_name) + + grad_node_name = GetGradNodeName(forward_op_name) + self.node_declaration_str = NODE_DECLARATION_TEMPLATE.format( + grad_node_name, grad_node_name, grad_node_name, grad_node_name, + grad_node_name, clear_tensor_wrapper_str, + set_tensor_wrapper_methods_str, set_attribute_methods_str, + tensor_wrapper_members_str, attribute_members_str) + + logging.info(f"Generated Node Declaration: {self.node_declaration_str}") + + def GenerateNodeDefinition(self): + namespace = self.namespace + forward_api_name = self.forward_api_name + backward_api_name = self.backward_api_name + backward_forward_inputs_map = self.backward_forward_inputs_map + backward_grad_inputs_map = self.backward_grad_inputs_map + backward_grad_outputs_map = self.backward_grad_outputs_map + backward_attrs_list = self.backward_attrs_list + + # Construct grad_api function args + # Order: TensorWrappers, GradTensors, Attributes + grad_api_args_len = len(backward_forward_inputs_map.keys()) + len( + backward_grad_inputs_map.keys()) + len(backward_attrs_list) + grad_api_args = ["" for i in range(grad_api_args_len)] + for name, (_, is_fwd_input, + grad_api_position), in backward_forward_inputs_map.items(): + tensor_wrapper_name = GetSavedName(name) + grad_api_args[ + grad_api_position] = f"egr::EagerUtils::RecoverTensorWrapper(&this->{tensor_wrapper_name}, nullptr)" + + for _, (ttype, fwd_position, + grad_api_position) in backward_grad_inputs_map.items(): + if IsPlainTensorType(ttype): + grad_api_args[ + grad_api_position] = f"hooked_grads[{fwd_position}][0]" + else: + assert IsVectorTensorType(ttype) + grad_api_args[ + grad_api_position] = f"hooked_grads[{fwd_position}]" + + for name, _, _, grad_api_position in backward_attrs_list: + saved_attribute_name = GetSavedName(name) + grad_api_args[grad_api_position] = f"this->{saved_attribute_name}" + grad_api_args_str = ", ".join(grad_api_args) + + # Construct grad_api returns + num_bwd_outputs = len(backward_grad_outputs_map.keys()) + returns_str = f"std::vector> returns({num_bwd_outputs});\n" + for _, (ttype, fwd_position, + grad_api_position) in backward_grad_outputs_map.items(): + # Infer Grad API Return Type + if num_bwd_outputs == 1: + # Single tensor output, return as is + if IsPlainTensorType(ttype): + returns_str += "returns[0] = { grad_api_returns };\n" + else: + assert IsVectorTensorType(ttype) + returns_str += "returns[0] = grad_api_returns;\n" + else: + # Rearrange output order accordingly + returns_str += f"returns[{fwd_position}] = grad_api_returns[{grad_api_position}];\n" + returns_str += f"if(NeedComplexToRealConversion()) HandleComplexGradToRealGrad(&returns);\n" + returns_str += f"return returns;\n" + + grad_node_name = GetGradNodeName(forward_api_name) + + fill_zero_str = "" + if forward_api_name in ops_to_fill_zero_for_empty_grads: + fill_zero_str = "egr::EagerUtils::FillZeroForEmptyGradInputs(&grads, this->InputMeta());\n" + + grad_api_namespace = f"paddle::experimental::{namespace}" + + self.node_definition_str = FUNCTION_TEMPLATE.format( + grad_node_name, fill_zero_str, grad_node_name, grad_api_namespace, + backward_api_name, grad_api_args_str, returns_str) + + logging.info(f"Generated Node Definition: {self.node_definition_str}") + + def run(self): + super().run() ##################### ## Code Generation ## ##################### self.GenerateNodeDeclaration() self.GenerateNodeDefinition() - self.GenerateForwardDefinition(is_inplaced=False) - - self.UpdateCoreOpsInformation(is_inplaced=False) - - self.GenerateInplacedForwardDygraphFunctions() class DygraphYamlGenerator(YamlGeneratorBase): @@ -1162,14 +1186,18 @@ def GenerateCode(self): forward_api_contents) if backward_api_contents is None: continue - d_generator = DygraphSingleFunctionGenerator( + function_generator = DygraphForwardFunctionGenerator( + forward_api_contents, backward_api_contents, namespace) + function_generator.run() + + node_generator = DygraphNodeGenerator( forward_api_contents, backward_api_contents, namespace) - d_generator.run() + node_generator.run() - self.forward_definition_str += d_generator.forward_definition_str + "\n" - self.forward_declaration_str += d_generator.forward_declaration_str + "\n" - self.node_declaration_str += d_generator.node_declaration_str + "\n" - self.node_definition_str += d_generator.node_definition_str + "\n" + self.forward_definition_str += function_generator.forward_definition_str + "\n" + self.forward_declaration_str += function_generator.forward_declaration_str + "\n" + self.node_declaration_str += node_generator.node_declaration_str + "\n" + self.node_definition_str += node_generator.node_definition_str + "\n" if len(namespace) > 0: if namespace.endswith("::"): From 14ebc19eed8844edae58950c4a93c5f36559f6c2 Mon Sep 17 00:00:00 2001 From: jim19930609 Date: Fri, 25 Mar 2022 08:01:21 +0000 Subject: [PATCH 03/12] Fixed minor issue --- .../final_state_generator/python_c_gen.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/paddle/fluid/eager/auto_code_generator/final_state_generator/python_c_gen.py b/paddle/fluid/eager/auto_code_generator/final_state_generator/python_c_gen.py index c7be9480f557d..0b45fee2de088 100644 --- a/paddle/fluid/eager/auto_code_generator/final_state_generator/python_c_gen.py +++ b/paddle/fluid/eager/auto_code_generator/final_state_generator/python_c_gen.py @@ -310,7 +310,7 @@ def GeneratePythonCFunction(self): dygraph_function_call_list[pos] = f"{name}" dygraph_function_call_str = ",".join(dygraph_function_call_list) - # Generate Python-C Function Definitions + # Generate Python-C Function Definitions if is_forward_only: fwd_function_name = FUNCTION_NAME_TEMPLATE.format( "paddle::experimental::", namespace, forward_api_name) @@ -332,9 +332,18 @@ def GeneratePythonCFunction(self): self.python_c_function_reg_str = PYTHON_C_FUNCTION_REG_TEMPLATE.format( forward_api_name, namespace, forward_api_name, forward_api_name) - if len(inplace_map) > 0: + if inplace_map: inplaced_forward_api_name = GetInplacedFunctionName( self.forward_api_name) + if is_forward_only: + inplaced_fwd_function_name = FUNCTION_NAME_TEMPLATE.format( + "paddle::experimental::", namespace, + inplaced_forward_api_name) + else: + inplaced_fwd_function_name = FUNCTION_NAME_TEMPLATE.format( + "::", namespace, + GetForwardFunctionName(inplaced_forward_api_name)) + assert len( inplace_map ) == 1, f"size of inplace_map must be 1, but inplace_map of \"{forward_api_name}\" op got {len(inplace_map)}" @@ -347,7 +356,7 @@ def GeneratePythonCFunction(self): self.python_c_function_str += PYTHON_C_FUNCTION_TEMPLATE.format( inplaced_forward_api_name, pythonc_record_event_str, inplaced_forward_api_name, get_eager_tensor_str, - parse_attributes_str, fwd_function_name, + parse_attributes_str, inplaced_fwd_function_name, dygraph_function_call_str, return_str) # Generate Python-C Function Registration From 9e7ecf689e8e678ccd8055f8e6358faf4d1c5e70 Mon Sep 17 00:00:00 2001 From: jim19930609 Date: Mon, 28 Mar 2022 06:31:35 +0000 Subject: [PATCH 04/12] Adjusted logics of GenerateNodeCreationCodes and GenerateForwardDefinition --- .../final_state_generator/eager_gen.py | 156 ++++++++++-------- 1 file changed, 85 insertions(+), 71 deletions(-) diff --git a/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py b/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py index 3bac4046909e4..119cea68fd8c6 100644 --- a/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py +++ b/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py @@ -162,9 +162,21 @@ class {} : public egr::GradNodeBase {{ FORWARD_FUNCTION_TEMPLATE = \ """ {} {}({}) {{ - {} - {} - {} + // Dygraph Record Event +{} + // AMP Logic +{} + + // Get Input AutoGradMeta +{} + // Check Inplace +{} + // Forward API Call +{} + // Get Output AutoGradMeta +{} + // Node Creation +{} // Returns return {}; @@ -174,18 +186,10 @@ class {} : public egr::GradNodeBase {{ FORWARD_BODY_TEMPLATE = \ """ - // Get AutoGradMeta -{} - bool trace_backward = egr::Controller::Instance().HasGrad(); - bool require_any_grad = egr::EagerUtils::ComputeRequireGrad({}); -{} - // Forward API Call - {} -{} - {{ -{} -{} + bool trace_backward = egr::Controller::Instance().HasGrad(); + bool require_any_grad = egr::EagerUtils::ComputeRequireGrad({}); if(require_any_grad) {{ +{} egr::EagerUtils::PassStopGradient({}); // Node Construction @@ -203,7 +207,6 @@ class {} : public egr::GradNodeBase {{ {} {} }} - }} """ NAMESPACE_WRAPPER_TEMPLATE = \ @@ -625,7 +628,7 @@ def SlotNameMatching(self): f"Generated Backward Grad Output Map: {self.backward_grad_outputs_map}" ) - def GenerateNodeCreationCodes(self, forward_call_str, is_inplaced): + def GenerateNodeCreationCodes(self): forward_api_name = self.forward_api_name forward_inputs_position_map = self.forward_inputs_position_map forward_outputs_position_map = self.forward_outputs_position_map @@ -635,67 +638,20 @@ def GenerateNodeCreationCodes(self, forward_call_str, is_inplaced): backward_grad_outputs_map = self.backward_grad_outputs_map backward_attrs_list = self.backward_attrs_list optional_inputs = self.optional_inputs - inplace_map = self.inplace_map if is_inplaced else {} - # Get Input AutoGradMeta - inputs_autograd_meta_list = [] compute_require_grad_args_list = ["trace_backward"] - for name, (ttype, pos) in forward_inputs_position_map.items(): + for name, (_, _) in forward_inputs_position_map.items(): input_autograd_meta_name = GetAutoGradMetaName(name) - if IsPlainTensorType(ttype): - input_autograd_meta = f" egr::AutogradMeta* {input_autograd_meta_name} = egr::EagerUtils::nullable_autograd_meta({name});" - else: - assert IsVectorTensorType(ttype) - input_autograd_meta_vec_name = GetAutoGradMetaVectorName(name) - input_autograd_meta = f" std::vector {input_autograd_meta_vec_name} = egr::EagerUtils::nullable_autograd_meta({name});\n" - input_autograd_meta += f" std::vector* {input_autograd_meta_name} = &{input_autograd_meta_vec_name};" - - inputs_autograd_meta_list.append(input_autograd_meta) compute_require_grad_args_list.append(input_autograd_meta_name) - inputs_autograd_meta_str = "\n".join(inputs_autograd_meta_list) compute_require_grad_args_str = ",".join(compute_require_grad_args_list) - # Get Output AutoGradMeta - outputs_autograd_meta_list = [] + # Pass Stop Gradient Args pass_stop_gradient_args_list = ["false"] - num_fwd_outputs = len(forward_outputs_position_map.keys()) - for name, (rtype, pos) in forward_outputs_position_map.items(): + for name, (_, _) in forward_outputs_position_map.items(): output_autograd_meta_name = GetAutoGradMetaName(name) - output_autograd_meta_vec_name = GetAutoGradMetaVectorName(name) - if num_fwd_outputs == 1: - if IsPlainTensorType(rtype): - output_autograd_meta = f" egr::AutogradMeta* {output_autograd_meta_name} = egr::EagerUtils::autograd_meta(&api_result);" - else: - assert IsVectorTensorType(rtype) - output_autograd_meta = f" std::vector {output_autograd_meta_vec_name} = egr::EagerUtils::autograd_meta(&api_result);\n" - output_autograd_meta += f" std::vector* {output_autograd_meta_name} = &{output_autograd_meta_vec_name};" - else: - # Tuple api_result - if IsPlainTensorType(rtype): - output_autograd_meta = f" egr::AutogradMeta* {output_autograd_meta_name} = egr::EagerUtils::autograd_meta(&std::get<{pos}>(api_result));" - else: - assert IsVectorTensorType(rtype) - output_autograd_meta = f" std::vector {output_autograd_meta_vec_name} = egr::EagerUtils::autograd_meta(&std::get<{pos}>(api_result));\n" - output_autograd_meta += f" std::vector* {output_autograd_meta_name} = &{output_autograd_meta_vec_name};" - - outputs_autograd_meta_list.append(output_autograd_meta) pass_stop_gradient_args_list.append(output_autograd_meta_name) - - # ComputeRequireGrad & PassStopGradient - outputs_autograd_meta_str = "\n".join(outputs_autograd_meta_list) pass_stop_gradient_args_str = ",".join(pass_stop_gradient_args_list) - # Check Inplace - check_inplace_str = "" - bump_inplace_version_str = "" - if is_inplaced: - for inplace_name in inplace_map.keys(): - inplace_autograd_meta_name = GetAutoGradMetaName(inplace_name) - check_inplace_str += CHECK_INPLACE_TEMPLATE.format( - inplace_name, inplace_autograd_meta_name) - bump_inplace_version_str += BUMP_INPLACE_VERSION_TEMPLATE.format( - inplace_name, inplace_name) - # Node Construction num_backward_inputs = len(forward_outputs_position_map.keys()) num_backward_outputs = len(forward_inputs_position_map.keys()) @@ -719,6 +675,7 @@ def GenerateNodeCreationCodes(self, forward_call_str, is_inplaced): # SetTensorWrappers set_tensor_wrappers_list = [] + num_fwd_outputs = len(forward_outputs_position_map.keys()) for name, (atype, is_fwd_input, pos) in backward_forward_inputs_map.items(): is_optional = (name in optional_inputs) @@ -794,9 +751,7 @@ def GenerateNodeCreationCodes(self, forward_call_str, is_inplaced): node_creation_event_str = f"paddle::platform::RecordEvent node_creation_record_event(\"{node_event_name}\", paddle::platform::TracerEventType::Operator, 1);\n" self.node_creation_str = FORWARD_BODY_TEMPLATE.format( - inputs_autograd_meta_str, compute_require_grad_args_str, - check_inplace_str, forward_call_str, bump_inplace_version_str, - node_creation_event_str, outputs_autograd_meta_str, + compute_require_grad_args_str, node_creation_event_str, pass_stop_gradient_args_str, node_construction_str, set_attributes_str, set_tensor_wrappers_str, set_grad_out_meta_str, set_edges_str, set_out_rank_str, set_history_str, @@ -973,7 +928,64 @@ def GenerateForwardDefinition(self, is_inplaced): returns_str = ", ".join(returns_list) returns_str = f"std::make_tuple({returns_str})" - self.GenerateNodeCreationCodes(forward_call_str, is_inplaced) + # Node Creation Pre-Processing + # 1. Get Input AutoGradMeta + inputs_autograd_meta_list = [] + compute_require_grad_args_list = ["trace_backward"] + for name, (ttype, pos) in forward_inputs_position_map.items(): + input_autograd_meta_name = GetAutoGradMetaName(name) + if IsPlainTensorType(ttype): + input_autograd_meta = f" egr::AutogradMeta* {input_autograd_meta_name} = egr::EagerUtils::nullable_autograd_meta({name});" + else: + assert IsVectorTensorType(ttype) + input_autograd_meta_vec_name = GetAutoGradMetaVectorName(name) + input_autograd_meta = f" std::vector {input_autograd_meta_vec_name} = egr::EagerUtils::nullable_autograd_meta({name});\n" + input_autograd_meta += f" std::vector* {input_autograd_meta_name} = &{input_autograd_meta_vec_name};" + + inputs_autograd_meta_list.append(input_autograd_meta) + compute_require_grad_args_list.append(input_autograd_meta_name) + inputs_autograd_meta_str = "\n".join(inputs_autograd_meta_list) + compute_require_grad_args_str = ",".join(compute_require_grad_args_list) + + # 2. Get Output AutoGradMeta + outputs_autograd_meta_list = [] + num_fwd_outputs = len(forward_outputs_position_map.keys()) + for name, (rtype, pos) in forward_outputs_position_map.items(): + output_autograd_meta_name = GetAutoGradMetaName(name) + output_autograd_meta_vec_name = GetAutoGradMetaVectorName(name) + if num_fwd_outputs == 1: + if IsPlainTensorType(rtype): + output_autograd_meta = f" egr::AutogradMeta* {output_autograd_meta_name} = egr::EagerUtils::autograd_meta(&api_result);" + else: + assert IsVectorTensorType(rtype) + output_autograd_meta = f" std::vector {output_autograd_meta_vec_name} = egr::EagerUtils::autograd_meta(&api_result);\n" + output_autograd_meta += f" std::vector* {output_autograd_meta_name} = &{output_autograd_meta_vec_name};" + else: + # Tuple api_result + if IsPlainTensorType(rtype): + output_autograd_meta = f" egr::AutogradMeta* {output_autograd_meta_name} = egr::EagerUtils::autograd_meta(&std::get<{pos}>(api_result));" + else: + assert IsVectorTensorType(rtype) + output_autograd_meta = f" std::vector {output_autograd_meta_vec_name} = egr::EagerUtils::autograd_meta(&std::get<{pos}>(api_result));\n" + output_autograd_meta += f" std::vector* {output_autograd_meta_name} = &{output_autograd_meta_vec_name};" + + outputs_autograd_meta_list.append(output_autograd_meta) + + # 3. ComputeRequireGrad & PassStopGradient + outputs_autograd_meta_str = "\n".join(outputs_autograd_meta_list) + + # 4. Check Inplace + check_inplace_str = "" + bump_inplace_version_str = "" + if is_inplaced: + for inplace_name in inplace_map.keys(): + inplace_autograd_meta_name = GetAutoGradMetaName(inplace_name) + check_inplace_str += CHECK_INPLACE_TEMPLATE.format( + inplace_name, inplace_autograd_meta_name) + bump_inplace_version_str += BUMP_INPLACE_VERSION_TEMPLATE.format( + inplace_name, inplace_name) + + self.GenerateNodeCreationCodes() node_creation_str = self.node_creation_str dygraph_event_str = f"paddle::platform::RecordEvent dygraph_entrance_record_event(\"{forward_api_name} dygraph\", paddle::platform::TracerEventType::Operator, 1);" @@ -1001,7 +1013,9 @@ def GenerateForwardDefinition(self, is_inplaced): self.forward_definition_str += FORWARD_FUNCTION_TEMPLATE.format( returns_type_str, forward_function_name, inputs_args_definition_str, - dygraph_event_str, amp_logic_str, node_creation_str, returns_str) + dygraph_event_str, amp_logic_str, inputs_autograd_meta_str, + check_inplace_str, forward_call_str, outputs_autograd_meta_str, + node_creation_str, returns_str) self.forward_declaration_str += f"{returns_type_str} {forward_function_name}({inputs_args_declaration_str});\n" logging.info( From b9454249ff85eb2cd419e1a5e478790f6e7c73a5 Mon Sep 17 00:00:00 2001 From: jim19930609 Date: Mon, 28 Mar 2022 07:41:49 +0000 Subject: [PATCH 05/12] Fixed issues --- .../final_state_generator/eager_gen.py | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py b/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py index 119cea68fd8c6..1abb47889c6ad 100644 --- a/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py +++ b/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py @@ -168,12 +168,14 @@ class {} : public egr::GradNodeBase {{ {} // Get Input AutoGradMeta -{} - // Check Inplace {} // Forward API Call {} // Get Output AutoGradMeta +{} + bool trace_backward = egr::Controller::Instance().HasGrad(); + bool require_any_grad = egr::EagerUtils::ComputeRequireGrad({}); + // Check Inplace {} // Node Creation {} @@ -186,8 +188,6 @@ class {} : public egr::GradNodeBase {{ FORWARD_BODY_TEMPLATE = \ """ - bool trace_backward = egr::Controller::Instance().HasGrad(); - bool require_any_grad = egr::EagerUtils::ComputeRequireGrad({}); if(require_any_grad) {{ {} egr::EagerUtils::PassStopGradient({}); @@ -297,7 +297,6 @@ class {} : public egr::GradNodeBase {{ CHECK_INPLACE_TEMPLATE = \ """ - // Check Inplace egr::EagerUtils::CheckInplace({}, {}, require_any_grad);\n """ @@ -639,12 +638,6 @@ def GenerateNodeCreationCodes(self): backward_attrs_list = self.backward_attrs_list optional_inputs = self.optional_inputs - compute_require_grad_args_list = ["trace_backward"] - for name, (_, _) in forward_inputs_position_map.items(): - input_autograd_meta_name = GetAutoGradMetaName(name) - compute_require_grad_args_list.append(input_autograd_meta_name) - compute_require_grad_args_str = ",".join(compute_require_grad_args_list) - # Pass Stop Gradient Args pass_stop_gradient_args_list = ["false"] for name, (_, _) in forward_outputs_position_map.items(): @@ -751,11 +744,10 @@ def GenerateNodeCreationCodes(self): node_creation_event_str = f"paddle::platform::RecordEvent node_creation_record_event(\"{node_event_name}\", paddle::platform::TracerEventType::Operator, 1);\n" self.node_creation_str = FORWARD_BODY_TEMPLATE.format( - compute_require_grad_args_str, node_creation_event_str, - pass_stop_gradient_args_str, node_construction_str, - set_attributes_str, set_tensor_wrappers_str, set_grad_out_meta_str, - set_edges_str, set_out_rank_str, set_history_str, - set_grad_in_meta_str, set_retain_grad_str) + node_creation_event_str, pass_stop_gradient_args_str, + node_construction_str, set_attributes_str, set_tensor_wrappers_str, + set_grad_out_meta_str, set_edges_str, set_out_rank_str, + set_history_str, set_grad_in_meta_str, set_retain_grad_str) def run(self): # Basic Validation Check @@ -1014,8 +1006,9 @@ def GenerateForwardDefinition(self, is_inplaced): self.forward_definition_str += FORWARD_FUNCTION_TEMPLATE.format( returns_type_str, forward_function_name, inputs_args_definition_str, dygraph_event_str, amp_logic_str, inputs_autograd_meta_str, - check_inplace_str, forward_call_str, outputs_autograd_meta_str, - node_creation_str, returns_str) + forward_call_str, outputs_autograd_meta_str, + compute_require_grad_args_str, check_inplace_str, node_creation_str, + returns_str) self.forward_declaration_str += f"{returns_type_str} {forward_function_name}({inputs_args_declaration_str});\n" logging.info( From 84ea03edc5eb5450f88224d2d5019dfe5a3f5cf3 Mon Sep 17 00:00:00 2001 From: jim19930609 Date: Mon, 28 Mar 2022 07:48:16 +0000 Subject: [PATCH 06/12] Supported higher-order grad node generation --- .../final_state_generator/eager_gen.py | 62 ++++++++++++++++--- python/paddle/utils/code_gen/backward.yaml | 29 ++++++--- 2 files changed, 72 insertions(+), 19 deletions(-) diff --git a/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py b/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py index 119cea68fd8c6..36dd62a92b963 100644 --- a/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py +++ b/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py @@ -155,6 +155,11 @@ class {} : public egr::GradNodeBase {{ // Call grad_api function VLOG(3) << \"Final State Running: \" << \"{}\"; auto grad_api_returns = {}{}({}); + + // Create Grad Node + {} + + // Return {} }} """ @@ -1081,13 +1086,18 @@ def run(self): class DygraphNodeGenerator(DygraphFunctionGeneratorBase): - def __init__(self, forward_api_contents, grad_api_contents, namespace): + def __init__(self, + forward_api_contents, + grad_api_contents, + namespace, + next_grad_api_contents=None): DygraphFunctionGeneratorBase.__init__(self, forward_api_contents, grad_api_contents, namespace) # Generated Results self.node_declaration_str = "" self.node_definition_str = "" + self.next_grad_api_contents = next_grad_api_contents def GenerateNodeDeclaration(self): forward_op_name = self.forward_api_name @@ -1149,7 +1159,7 @@ def GenerateNodeDeclaration(self): logging.info(f"Generated Node Declaration: {self.node_declaration_str}") - def GenerateNodeDefinition(self): + def GenerateNodeDefinition(self, grad_node_creation_str): namespace = self.namespace forward_api_name = self.forward_api_name backward_api_name = self.backward_api_name @@ -1218,7 +1228,8 @@ def GenerateNodeDefinition(self): self.node_definition_str = FUNCTION_TEMPLATE.format( grad_node_name, fill_zero_str, grad_node_name, grad_api_namespace, - backward_api_name, grad_api_args_str, returns_str) + backward_api_name, grad_api_args_str, grad_node_creation_str, + returns_str) logging.info(f"Generated Node Definition: {self.node_definition_str}") @@ -1229,7 +1240,22 @@ def run(self): ## Code Generation ## ##################### self.GenerateNodeDeclaration() - self.GenerateNodeDefinition() + + namespace = self.namespace + grad_node_creation_str = "" + next_grad_api_contents = self.next_grad_api_contents + if next_grad_api_contents: + forward_api_contents = self.grad_api_contents + forward_api_contents['api'] = forward_api_contents['backward_api'] + backward_api_contents = next_grad_api_contents + + next_node_generator = DygraphFunctionGeneratorBase( + forward_api_contents, backward_api_contents, namespace) + next_node_generator.run() + next_node_generator.GenerateNodeCreationCodes() + grad_node_creation_str = next_node_generator.node_creation_str + + self.GenerateNodeDefinition(grad_node_creation_str) class DygraphYamlGenerator(YamlGeneratorBase): @@ -1276,18 +1302,34 @@ def GenerateCode(self): forward_api_contents) if backward_api_contents is None: continue + # Generate Dygraph Forward Function function_generator = DygraphForwardFunctionGenerator( forward_api_contents, backward_api_contents, namespace) function_generator.run() - node_generator = DygraphNodeGenerator( - forward_api_contents, backward_api_contents, namespace) - node_generator.run() - self.forward_definition_str += function_generator.forward_definition_str + "\n" self.forward_declaration_str += function_generator.forward_declaration_str + "\n" - self.node_declaration_str += node_generator.node_declaration_str + "\n" - self.node_definition_str += node_generator.node_definition_str + "\n" + + while True: + next_grad_api_contents = self.GetBackwardAPIContents( + backward_api_contents) + + node_generator = DygraphNodeGenerator( + forward_api_contents, backward_api_contents, namespace, + next_grad_api_contents) + node_generator.run() + self.node_declaration_str += node_generator.node_declaration_str + "\n" + self.node_definition_str += node_generator.node_definition_str + "\n" + + if next_grad_api_contents is None: break + + # Detect if there exists higher-order GradNode + forward_api_contents = backward_api_contents + + # Fake forward_api_content + forward_api_contents['api'] = forward_api_contents[ + 'backward_api'] + backward_api_contents = next_grad_api_contents if len(namespace) > 0: if namespace.endswith("::"): diff --git a/python/paddle/utils/code_gen/backward.yaml b/python/paddle/utils/code_gen/backward.yaml index 56ee071626ed8..dd0bf2915d52e 100644 --- a/python/paddle/utils/code_gen/backward.yaml +++ b/python/paddle/utils/code_gen/backward.yaml @@ -85,16 +85,27 @@ param : [x] kernel : func : abs_grad - + - backward_api : relu_grad - forward : relu (Tensor x) -> Tensor(out) - args : (Tensor x, Tensor out_grad) - output : Tensor(x_grad) - infer_meta : - func : UnchangedInferMeta - param : [x] - kernel : - func : relu_grad + forward : relu (Tensor x) -> Tensor(out) + args : (Tensor out, Tensor out_grad) + output : Tensor(x_grad) + infer_meta : + func : UnchangedInferMeta + param : [out] + kernel : + func : relu_grad + backward: relu_double_grad + +- backward_api : relu_double_grad + forward : relu_grad (Tensor out, Tensor grad_out) -> Tensor(grad_x) + args : (Tensor out, Tensor grad_x_grad) + output : Tensor(out_grad), Tensor(grad_out_grad) + infer_meta : + func : UnchangedInferMeta + param : [out] + kernel : + func : relu_double_grad - backward_api : trunc_grad forward : trunc (Tensor x) -> Tensor(out) From 6117fd1b6ecda9669cb29ea68c702e252e274218 Mon Sep 17 00:00:00 2001 From: jim19930609 Date: Tue, 29 Mar 2022 02:44:08 +0000 Subject: [PATCH 07/12] [DoubleGrad PR #4] Supported higher-order GradNode generation --- .../final_state_generator/codegen_utils.py | 10 + .../final_state_generator/eager_gen.py | 246 ++++++++++++++---- python/paddle/utils/code_gen/backward.yaml | 34 +-- 3 files changed, 219 insertions(+), 71 deletions(-) diff --git a/paddle/fluid/eager/auto_code_generator/final_state_generator/codegen_utils.py b/paddle/fluid/eager/auto_code_generator/final_state_generator/codegen_utils.py index 89939a68f2abd..f8b53db2e0751 100644 --- a/paddle/fluid/eager/auto_code_generator/final_state_generator/codegen_utils.py +++ b/paddle/fluid/eager/auto_code_generator/final_state_generator/codegen_utils.py @@ -89,6 +89,10 @@ def FindForwardName(string): return string[:-5] +def IsGradName(string): + return string.endswith("_grad") + + def IsPlainTensorType(string): plain_tensor_types = ['Tensor&', 'Tensor', 'const Tensor&', 'const Tensor'] if string in plain_tensor_types: @@ -166,6 +170,12 @@ def GetForwardFunctionName(string): return f"{string}_final_state_dygraph_function" +def TransformGradVarNameForDoubleGradGeneration(string): + if IsGradName(string): + string = "grad_" + string[:-5] + return string + + ###################### ### Yaml Parsers ### ###################### diff --git a/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py b/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py index 4e59239b17f36..7777ee52796ad 100644 --- a/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py +++ b/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py @@ -31,6 +31,7 @@ from codegen_utils import ParseYamlForward, ParseYamlBackward from codegen_utils import FunctionGeneratorBase, YamlGeneratorBase from codegen_utils import ops_to_fill_zero_for_empty_grads +from codegen_utils import TransformGradVarNameForDoubleGradGeneration from codegen_utils import AssertMessage @@ -146,15 +147,33 @@ class {} : public egr::GradNodeBase {{ }}; """ -FUNCTION_TEMPLATE = \ +GRAD_FUNCTION_TEMPLATE = \ """ std::vector> {}::operator()(std::vector>& grads, bool create_graph) {{ + // Fill Zero For GradIn Tensors {} + + // Apply Gradient Hooks auto hooked_grads = ApplyGradientHooks(grads); + + // Collect GradIn Tensors, Attrs and Recovered TensorWrappers + {} // Call grad_api function VLOG(3) << \"Final State Running: \" << \"{}\"; - auto grad_api_returns = {}{}({}); + {} + + // Get Output + {} + + // Get GradIn autograd_meta + {} + + // Get GradOut autograd_meta + {} + + // Compute Require Grad + {} // Create Grad Node {} @@ -175,11 +194,14 @@ class {} : public egr::GradNodeBase {{ // Get Input AutoGradMeta {} // Forward API Call +{} + // Get Outputs {} // Get Output AutoGradMeta {} bool trace_backward = egr::Controller::Instance().HasGrad(); bool require_any_grad = egr::EagerUtils::ComputeRequireGrad({}); + // Check Inplace {} // Node Creation @@ -229,6 +251,7 @@ class {} : public egr::GradNodeBase {{ #include "paddle/phi/api/backward/sparse_bw_api.h" #include "paddle/fluid/imperative/tracer.h" #include "paddle/fluid/framework/op_registry.h" +#include "paddle/fluid/platform/profiler/event_tracing.h" #include "paddle/fluid/eager/utils.h" #include "paddle/fluid/eager/api/utils/global_utils.h" #include "paddle/fluid/eager/api/generated/eager_generated/backwards/nodes.h" @@ -689,14 +712,11 @@ def GenerateNodeCreationCodes(self): assert name in forward_outputs_position_map.keys( ), AssertMessage(name, forward_outputs_position_map.keys()) fwd_output_pos = forward_outputs_position_map[name][1] - tw_name = f"std::get<{fwd_output_pos}>(api_result)" - else: - tw_name = f"api_result" if is_optional: - set_tensor_wrappers = f" if({tw_name}.get_ptr() != nullptr) grad_node->SetTensorWrapper{name}(*({tw_name}.get_ptr()), false);" + set_tensor_wrappers = f" if({name}.get_ptr() != nullptr) grad_node->SetTensorWrapper{name}(*({name}.get_ptr()), false);" else: - set_tensor_wrappers = f" grad_node->SetTensorWrapper{name}({tw_name}, false);" + set_tensor_wrappers = f" grad_node->SetTensorWrapper{name}({name}, false);" set_tensor_wrappers_list.append(set_tensor_wrappers) set_tensor_wrappers_str = "\n".join(set_tensor_wrappers_list) @@ -729,12 +749,8 @@ def GenerateNodeCreationCodes(self): set_out_rank = f" egr::EagerUtils::SetOutRankWithSlot({output_autograd_meta_name}, {pos});" set_history = f" egr::EagerUtils::SetHistory({output_autograd_meta_name}, grad_node);" - if num_outputs == 1: - set_retain_grad = f" egr::EagerUtils::CheckAndRetainGrad(api_result);" - set_grad_in_meta = f" grad_node->SetGradInMeta(api_result, {pos});" - else: - set_retain_grad = f" egr::EagerUtils::CheckAndRetainGrad(std::get<{pos}>(api_result));" - set_grad_in_meta = f" grad_node->SetGradInMeta(std::get<{pos}>(api_result), {pos});" + set_retain_grad = f" egr::EagerUtils::CheckAndRetainGrad({name});" + set_grad_in_meta = f" grad_node->SetGradInMeta({name}, {pos});" set_out_rank_list.append(set_out_rank) set_history_list.append(set_history) set_grad_in_meta_list.append(set_grad_in_meta) @@ -894,20 +910,24 @@ def GenerateForwardDefinition(self, is_inplaced): function_name = GetIntermediateAPIFunctionName(function_name) forward_call_str = f"auto api_result = paddle::experimental::{namespace}{function_name}({inputs_call_args_str});" - - # Get return type list & outputs num_outputs = len(forward_outputs_position_map.keys()) - len( intermediate_outputs) + + # Get Outputs + get_outputs_str = "" + for name, (rtype, pos) in forward_outputs_position_map.items(): + if num_outputs == 1 and len(intermediate_outputs) == 0: + get_outputs_str += f"auto& {name} = api_result;\n" + else: + get_outputs_str += f"auto& {name} = std::get<{pos}>(api_result);\n" + + # Get return type list & outputs returns_type_list = ["" for i in range(num_outputs)] returns_list = ["" for i in range(num_outputs)] for name, (rtype, pos) in forward_outputs_position_map.items(): if name in intermediate_outputs: continue - if num_outputs == 1 and len(intermediate_outputs) == 0: - returns_list[0] = f"api_result" - else: - # Tuple api_result - returns_list[pos] = f"std::get<{pos}>(api_result)" + returns_list[pos] = f"{name}" if IsPlainTensorType(rtype): returns_type_list[pos] = "paddle::experimental::Tensor" @@ -952,26 +972,24 @@ def GenerateForwardDefinition(self, is_inplaced): output_autograd_meta_vec_name = GetAutoGradMetaVectorName(name) if num_fwd_outputs == 1: if IsPlainTensorType(rtype): - output_autograd_meta = f" egr::AutogradMeta* {output_autograd_meta_name} = egr::EagerUtils::autograd_meta(&api_result);" + output_autograd_meta = f" egr::AutogradMeta* {output_autograd_meta_name} = egr::EagerUtils::autograd_meta(&{name});" else: assert IsVectorTensorType(rtype) - output_autograd_meta = f" std::vector {output_autograd_meta_vec_name} = egr::EagerUtils::autograd_meta(&api_result);\n" + output_autograd_meta = f" std::vector {output_autograd_meta_vec_name} = egr::EagerUtils::autograd_meta(&{name});\n" output_autograd_meta += f" std::vector* {output_autograd_meta_name} = &{output_autograd_meta_vec_name};" else: # Tuple api_result if IsPlainTensorType(rtype): - output_autograd_meta = f" egr::AutogradMeta* {output_autograd_meta_name} = egr::EagerUtils::autograd_meta(&std::get<{pos}>(api_result));" + output_autograd_meta = f" egr::AutogradMeta* {output_autograd_meta_name} = egr::EagerUtils::autograd_meta(&{name});" else: assert IsVectorTensorType(rtype) - output_autograd_meta = f" std::vector {output_autograd_meta_vec_name} = egr::EagerUtils::autograd_meta(&std::get<{pos}>(api_result));\n" + output_autograd_meta = f" std::vector {output_autograd_meta_vec_name} = egr::EagerUtils::autograd_meta(&{name});\n" output_autograd_meta += f" std::vector* {output_autograd_meta_name} = &{output_autograd_meta_vec_name};" outputs_autograd_meta_list.append(output_autograd_meta) - - # 3. ComputeRequireGrad & PassStopGradient outputs_autograd_meta_str = "\n".join(outputs_autograd_meta_list) - # 4. Check Inplace + # 3. Check Inplace check_inplace_str = "" bump_inplace_version_str = "" if is_inplaced: @@ -1011,7 +1029,7 @@ def GenerateForwardDefinition(self, is_inplaced): self.forward_definition_str += FORWARD_FUNCTION_TEMPLATE.format( returns_type_str, forward_function_name, inputs_args_definition_str, dygraph_event_str, amp_logic_str, inputs_autograd_meta_str, - forward_call_str, outputs_autograd_meta_str, + forward_call_str, get_outputs_str, outputs_autograd_meta_str, compute_require_grad_args_str, check_inplace_str, node_creation_str, returns_str) self.forward_declaration_str += f"{returns_type_str} {forward_function_name}({inputs_args_declaration_str});\n" @@ -1166,63 +1184,183 @@ def GenerateNodeDefinition(self, grad_node_creation_str): grad_api_args_len = len(backward_forward_inputs_map.keys()) + len( backward_grad_inputs_map.keys()) + len(backward_attrs_list) grad_api_args = ["" for i in range(grad_api_args_len)] + get_grad_in_args_list = [] + + # Fill Grad Ins with Zero + fill_zero_str = "" + if forward_api_name in ops_to_fill_zero_for_empty_grads: + fill_zero_str = "egr::EagerUtils::FillZeroForEmptyGradInputs(&grads, this->InputMeta());\n" + + # Grad Ins from TensorWrappers for name, (_, is_fwd_input, grad_api_position), in backward_forward_inputs_map.items(): tensor_wrapper_name = GetSavedName(name) + transformed_tensor_name = TransformGradVarNameForDoubleGradGeneration( + name) + is_optional = (name in self.optional_inputs) if is_optional: - grad_api_args[ - grad_api_position] = f"egr::EagerUtils::RecoverOptionalTensorWrapper(&this->{tensor_wrapper_name}, nullptr)" + tensor_wrapper_recover_str = f"auto {transformed_tensor_name} = egr::EagerUtils::RecoverOptionalTensorWrapper(&this->{tensor_wrapper_name}, nullptr);" else: - grad_api_args[ - grad_api_position] = f"egr::EagerUtils::RecoverTensorWrapper(&this->{tensor_wrapper_name}, nullptr)" - for _, (ttype, fwd_position, - grad_api_position) in backward_grad_inputs_map.items(): + tensor_wrapper_recover_str = f"auto {transformed_tensor_name} = egr::EagerUtils::RecoverTensorWrapper(&this->{tensor_wrapper_name}, nullptr);" + grad_api_args[grad_api_position] = transformed_tensor_name + get_grad_in_args_list.append(tensor_wrapper_recover_str) + + # Grad Ins from grads + for name, (ttype, fwd_position, + grad_api_position) in backward_grad_inputs_map.items(): + transformed_tensor_name = TransformGradVarNameForDoubleGradGeneration( + name) + if IsPlainTensorType(ttype): - grad_api_args[ - grad_api_position] = f"hooked_grads[{fwd_position}][0]" + get_tensor_str = f"auto& {transformed_tensor_name} = hooked_grads[{fwd_position}][0];" else: assert IsVectorTensorType(ttype) - grad_api_args[ - grad_api_position] = f"hooked_grads[{fwd_position}]" + get_tensor_str = f"auto& {transformed_tensor_name} = hooked_grads[{fwd_position}];" + grad_api_args[grad_api_position] = transformed_tensor_name + get_grad_in_args_list.append(get_tensor_str) + # Grad Attrs for name, _, _, grad_api_position in backward_attrs_list: saved_attribute_name = GetSavedName(name) - grad_api_args[grad_api_position] = f"this->{saved_attribute_name}" + get_attr_str = f"auto& {name} = this->{saved_attribute_name};" + + grad_api_args[grad_api_position] = name + get_grad_in_args_list.append(get_attr_str) + + get_grad_in_args_str = "\n".join(get_grad_in_args_list) grad_api_args_str = ", ".join(grad_api_args) + # Grad Function Call String + grad_api_namespace = f"paddle::experimental::{namespace}" + grad_function_call_str = f"auto grad_api_result = {grad_api_namespace}{backward_api_name}({grad_api_args_str});" + + # Get Grad Outputs + get_outputs_str = "" + num_outputs = len(backward_grad_outputs_map.keys()) + for name, (ttype, fwd_position, + grad_api_position) in backward_grad_outputs_map.items(): + transformed_tensor_name = TransformGradVarNameForDoubleGradGeneration( + name) + + if num_outputs == 1: + get_tensor_str = f"auto& {transformed_tensor_name} = grad_api_result;" + else: + get_tensor_str = f"auto& {transformed_tensor_name} = grad_api_result[{fwd_position}];" + get_outputs_str += get_tensor_str + "\n" + + # Prepare for Node Creation if Necessary + inputs_autograd_meta_str = "" + outputs_autograd_meta_str = "" + compute_require_grad_str = "" + if len(grad_node_creation_str) > 0: + # 1. Get Input AutoGradMeta + inputs_autograd_meta_list = [] + compute_require_grad_args_list = ["trace_backward"] + for name, (ttype, pos, + grad_api_position) in backward_grad_inputs_map.items(): + transformed_tensor_name = TransformGradVarNameForDoubleGradGeneration( + name) + + input_autograd_meta_name = GetAutoGradMetaName( + transformed_tensor_name) + if IsPlainTensorType(ttype): + input_autograd_meta = f" egr::AutogradMeta* {input_autograd_meta_name} = egr::EagerUtils::nullable_autograd_meta({transformed_tensor_name});" + else: + assert IsVectorTensorType(ttype) + input_autograd_meta_vec_name = GetAutoGradMetaVectorName( + transformed_tensor_name) + input_autograd_meta = f" std::vector {input_autograd_meta_vec_name} = egr::EagerUtils::nullable_autograd_meta({transformed_tensor_name});\n" + input_autograd_meta += f" std::vector* {input_autograd_meta_name} = &{input_autograd_meta_vec_name};" + + inputs_autograd_meta_list.append(input_autograd_meta) + compute_require_grad_args_list.append(input_autograd_meta_name) + + # 2. Get TensorWrapper AutoGradMeta + for name, (ttype, _, pos), in backward_forward_inputs_map.items(): + transformed_tensor_name = TransformGradVarNameForDoubleGradGeneration( + name) + + input_autograd_meta_name = GetAutoGradMetaName( + transformed_tensor_name) + if IsPlainTensorType(ttype): + input_autograd_meta = f" egr::AutogradMeta* {input_autograd_meta_name} = egr::EagerUtils::nullable_autograd_meta({transformed_tensor_name});" + else: + assert IsVectorTensorType(ttype) + input_autograd_meta_vec_name = GetAutoGradMetaVectorName( + transformed_tensor_name) + input_autograd_meta = f" std::vector {input_autograd_meta_vec_name} = egr::EagerUtils::nullable_autograd_meta({transformed_tensor_name});\n" + input_autograd_meta += f" std::vector* {input_autograd_meta_name} = &{input_autograd_meta_vec_name};" + + inputs_autograd_meta_list.append(input_autograd_meta) + compute_require_grad_args_list.append(input_autograd_meta_name) + inputs_autograd_meta_str = "\n".join(inputs_autograd_meta_list) + compute_require_grad_args_str = ",".join( + compute_require_grad_args_list) + + # 3. Get Output AutoGradMeta + outputs_autograd_meta_list = [] + num_fwd_outputs = len(backward_grad_outputs_map.keys()) + for name, (rtype, pos, _) in backward_grad_outputs_map.items(): + transformed_tensor_name = TransformGradVarNameForDoubleGradGeneration( + name) + + output_autograd_meta_name = GetAutoGradMetaName( + transformed_tensor_name) + output_autograd_meta_vec_name = GetAutoGradMetaVectorName( + transformed_tensor_name) + if num_fwd_outputs == 1: + if IsPlainTensorType(rtype): + output_autograd_meta = f" egr::AutogradMeta* {output_autograd_meta_name} = egr::EagerUtils::autograd_meta(&{transformed_tensor_name});" + else: + assert IsVectorTensorType(rtype) + output_autograd_meta = f" std::vector {output_autograd_meta_vec_name} = egr::EagerUtils::autograd_meta(&{transformed_tensor_name});\n" + output_autograd_meta += f" std::vector* {output_autograd_meta_name} = &{output_autograd_meta_vec_name};" + else: + # Tuple api_result + if IsPlainTensorType(rtype): + output_autograd_meta = f" egr::AutogradMeta* {output_autograd_meta_name} = egr::EagerUtils::autograd_meta(&{transformed_tensor_name});" + else: + assert IsVectorTensorType(rtype) + output_autograd_meta = f" std::vector {output_autograd_meta_vec_name} = egr::EagerUtils::autograd_meta(&{transformed_tensor_name});\n" + output_autograd_meta += f" std::vector* {output_autograd_meta_name} = &{output_autograd_meta_vec_name};" + + outputs_autograd_meta_list.append(output_autograd_meta) + outputs_autograd_meta_str = "\n".join(outputs_autograd_meta_list) + + compute_require_grad_str = "bool trace_backward = egr::Controller::Instance().HasGrad() && create_graph;\n" + compute_require_grad_str += f"bool require_any_grad = egr::EagerUtils::ComputeRequireGrad({compute_require_grad_args_str});" + # Construct grad_api returns num_bwd_outputs = len(backward_grad_outputs_map.keys()) slot_num_bwd_outputs = len(self.forward_inputs_position_map.keys()) returns_str = f"std::vector> returns({slot_num_bwd_outputs});\n" - for _, (ttype, fwd_position, - grad_api_position) in backward_grad_outputs_map.items(): + for name, (ttype, fwd_position, + grad_api_position) in backward_grad_outputs_map.items(): + transformed_tensor_name = TransformGradVarNameForDoubleGradGeneration( + name) + # Infer Grad API Return Type if num_bwd_outputs == 1: # Single tensor output, return as is if IsPlainTensorType(ttype): - returns_str += "returns[0] = { grad_api_returns };\n" + returns_str += f"returns[0] = {{ {transformed_tensor_name} }};\n" else: assert IsVectorTensorType(ttype) - returns_str += "returns[0] = grad_api_returns;\n" + returns_str += f"returns[0] = {transformed_tensor_name};\n" else: # Rearrange output order accordingly - returns_str += f"returns[{fwd_position}] = grad_api_returns[{grad_api_position}];\n" + returns_str += f"returns[{fwd_position}] = {transformed_tensor_name};\n" returns_str += f"if(NeedComplexToRealConversion()) HandleComplexGradToRealGrad(&returns);\n" returns_str += f"return returns;\n" grad_node_name = GetGradNodeName(forward_api_name) - fill_zero_str = "" - if forward_api_name in ops_to_fill_zero_for_empty_grads: - fill_zero_str = "egr::EagerUtils::FillZeroForEmptyGradInputs(&grads, this->InputMeta());\n" - - grad_api_namespace = f"paddle::experimental::{namespace}" - - self.node_definition_str = FUNCTION_TEMPLATE.format( - grad_node_name, fill_zero_str, grad_node_name, grad_api_namespace, - backward_api_name, grad_api_args_str, grad_node_creation_str, - returns_str) + self.node_definition_str = GRAD_FUNCTION_TEMPLATE.format( + grad_node_name, fill_zero_str, get_grad_in_args_str, grad_node_name, + grad_function_call_str, get_outputs_str, inputs_autograd_meta_str, + outputs_autograd_meta_str, compute_require_grad_str, + grad_node_creation_str, returns_str) logging.info(f"Generated Node Definition: {self.node_definition_str}") diff --git a/python/paddle/utils/code_gen/backward.yaml b/python/paddle/utils/code_gen/backward.yaml index dd0bf2915d52e..6aa7d5c679716 100644 --- a/python/paddle/utils/code_gen/backward.yaml +++ b/python/paddle/utils/code_gen/backward.yaml @@ -87,25 +87,25 @@ func : abs_grad - backward_api : relu_grad - forward : relu (Tensor x) -> Tensor(out) - args : (Tensor out, Tensor out_grad) - output : Tensor(x_grad) - infer_meta : - func : UnchangedInferMeta - param : [out] - kernel : - func : relu_grad - backward: relu_double_grad + forward : relu (Tensor x) -> Tensor(out) + args : (Tensor out, Tensor out_grad) + output : Tensor(x_grad) + infer_meta : + func : UnchangedInferMeta + param : [out] + kernel : + func : relu_grad + backward: relu_double_grad - backward_api : relu_double_grad - forward : relu_grad (Tensor out, Tensor grad_out) -> Tensor(grad_x) - args : (Tensor out, Tensor grad_x_grad) - output : Tensor(out_grad), Tensor(grad_out_grad) - infer_meta : - func : UnchangedInferMeta - param : [out] - kernel : - func : relu_double_grad + forward : relu_grad (Tensor out, Tensor grad_out) -> Tensor(grad_x) + args : (Tensor out, Tensor grad_x_grad) + output : Tensor(out_grad), Tensor(grad_out_grad) + infer_meta : + func : GeneralBinaryGradInferMeta + param : [out, out] + kernel : + func : relu_double_grad - backward_api : trunc_grad forward : trunc (Tensor x) -> Tensor(out) From 244f6da1651636ca309b1be861b6983bf5752d91 Mon Sep 17 00:00:00 2001 From: jim19930609 Date: Wed, 30 Mar 2022 01:29:18 +0000 Subject: [PATCH 08/12] [DoubleGrad #4] Bug Fixes to Double Grad Node Generation --- .../final_state_generator/codegen_utils.py | 8 +- .../final_state_generator/eager_gen.py | 345 ++++++++++-------- paddle/fluid/eager/grad_node_info.h | 4 +- python/paddle/nn/functional/activation.py | 4 +- python/paddle/utils/code_gen/backward.yaml | 11 +- 5 files changed, 217 insertions(+), 155 deletions(-) diff --git a/paddle/fluid/eager/auto_code_generator/final_state_generator/codegen_utils.py b/paddle/fluid/eager/auto_code_generator/final_state_generator/codegen_utils.py index f8b53db2e0751..e65349c7036c7 100644 --- a/paddle/fluid/eager/auto_code_generator/final_state_generator/codegen_utils.py +++ b/paddle/fluid/eager/auto_code_generator/final_state_generator/codegen_utils.py @@ -21,7 +21,8 @@ ######################## ### Global Variables ### ######################## -ops_to_fill_zero_for_empty_grads = set(["split", "rnn"]) +ops_to_fill_zero_for_empty_grads = set( + ["split_grad", "rnn_grad", "matmul_double_grad"]) # For API dispatch used at python-level # { op_name : [arg_name, ...] } @@ -176,6 +177,11 @@ def TransformGradVarNameForDoubleGradGeneration(string): return string +def GetIndent(num): + tab = " " + return "".join([tab for i in range(num)]) + + ###################### ### Yaml Parsers ### ###################### diff --git a/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py b/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py index a2c5617c82ea4..547c2e2880d94 100644 --- a/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py +++ b/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py @@ -32,7 +32,7 @@ from codegen_utils import FunctionGeneratorBase, YamlGeneratorBase from codegen_utils import ops_to_fill_zero_for_empty_grads from codegen_utils import TransformGradVarNameForDoubleGradGeneration -from codegen_utils import AssertMessage +from codegen_utils import AssertMessage, GetIndent ########### @@ -112,80 +112,81 @@ def ParseArguments(): NODE_DECLARATION_TEMPLATE = \ """ - class {} : public egr::GradNodeBase {{ - public: - {}() : egr::GradNodeBase() {{}} - {}(size_t bwd_in_slot_num, size_t bwd_out_slot_num) : - egr::GradNodeBase(bwd_in_slot_num, bwd_out_slot_num) {{}} - ~{}() override = default; - - virtual std::vector> operator()( - std::vector>& grads, bool create_graph = false) override; - std::string name() override {{ return \" {} \"; }} - - void ClearTensorWrappers() override {{ - {} - is_tensor_wrappers_cleared = true; - }} - - // SetTensorWrapperX, SetTensorWrapperY, ... +class {} : public egr::GradNodeBase {{ + public: + {}() : egr::GradNodeBase() {{}} + {}(size_t bwd_in_slot_num, size_t bwd_out_slot_num) : + egr::GradNodeBase(bwd_in_slot_num, bwd_out_slot_num) {{}} + ~{}() override = default; + + virtual std::vector> operator()( + std::vector>& grads, bool create_graph = false) override; + std::string name() override {{ return \" {} \"; }} + + void ClearTensorWrappers() override {{ {} - // SetAttributes - {} - - bool IsTensorWrappersCleared() override {{ - return is_tensor_wrappers_cleared; - }} - private: - // TensorWrappers - {} - - bool is_tensor_wrappers_cleared = false; - - // Attributes - {} - }}; + is_tensor_wrappers_cleared = true; + }} + + // SetTensorWrapperX, SetTensorWrapperY, ... + {} + // SetAttributes + {} + + bool IsTensorWrappersCleared() override {{ + return is_tensor_wrappers_cleared; + }} + private: + // TensorWrappers + {} + + bool is_tensor_wrappers_cleared = false; + + // Attributes + {} +}}; """ GRAD_FUNCTION_TEMPLATE = \ """ - std::vector> {}::operator()(std::vector>& grads, bool create_graph) {{ - // Fill Zero For GradIn Tensors - {} +std::vector> {}::operator()(std::vector>& grads, bool create_graph) {{ + // Fill Zero For GradIn Tensors +{} - // Apply Gradient Hooks - auto hooked_grads = ApplyGradientHooks(grads); - - // Collect GradIn Tensors, Attrs and Recovered TensorWrappers - {} + // Apply Gradient Hooks + auto hooked_grads = ApplyGradientHooks(grads); + + // Collect GradIn Tensors, Attrs and Recovered TensorWrappers +{} - // Call grad_api function - VLOG(3) << \"Final State Running: \" << \"{}\"; - {} + // Call grad_api function + VLOG(3) << \"Final State Running: \" << \"{}\"; +{} - // Get Output - {} + // Get Output +{} - // Get GradIn autograd_meta - {} + // Get GradIn autograd_meta +{} - // Get GradOut autograd_meta - {} - - // Compute Require Grad - {} - - // Create Grad Node - {} + // Get GradOut autograd_meta +{} + + // Compute Require Grad +{} + + // Create Grad Node +{} - // Return - {} - }} + // Return +{} + +}} """ FORWARD_FUNCTION_TEMPLATE = \ """ - {} {}({}) {{ +{} {}({}) {{ // Dygraph Record Event {} // AMP Logic @@ -208,33 +209,33 @@ class {} : public egr::GradNodeBase {{ // Node Creation {} - // Returns - return {}; - }} + // Returns + return {}; +}} """ FORWARD_BODY_TEMPLATE = \ """ - if(require_any_grad) {{ + if(require_any_grad) {{ {} - egr::EagerUtils::PassStopGradient({}); + egr::EagerUtils::PassStopGradient({}); - // Node Construction + // Node Construction {} - // SetAttributes + // SetAttributes {} - // SetTensorWrappers + // SetTensorWrappers {} - // SetGradOutMeta & SetEdges + // SetGradOutMeta & SetEdges {} {} - // SetOutRank & SetHistory & SetGradInMeta & RetainGrad + // SetOutRank & SetHistory & SetGradInMeta & RetainGrad {} {} {} {} - }} + }} """ NAMESPACE_WRAPPER_TEMPLATE = \ @@ -318,9 +319,9 @@ class {} : public egr::GradNodeBase {{ CORE_OPS_DECLARATION_TEMPLATE = \ """ - extern std::unordered_map> core_ops_final_state_args_info; - extern std::unordered_map> core_ops_final_state_args_type_info; - extern std::unordered_map> core_ops_final_state_returns_info; +extern std::unordered_map> core_ops_final_state_args_info; +extern std::unordered_map> core_ops_final_state_args_type_info; +extern std::unordered_map> core_ops_final_state_returns_info; """ @@ -352,6 +353,12 @@ class {} : public egr::GradNodeBase {{ }} """ +CREATE_PLAIN_OPTIONAL_TENSOR_TEMPLATE = \ +""" + paddle::optional {}_optional = paddle::none; + if({}.initialized()) {}_optional = paddle::make_optional({}); +""" + ####################### ## Generator Helpers ## @@ -679,7 +686,10 @@ def GenerateNodeCreationCodes(self): num_backward_outputs = len(forward_inputs_position_map.keys()) grad_node_name = GetGradNodeName(forward_api_name) - node_construction_str = f" auto grad_node = std::make_shared<{grad_node_name}>({num_backward_inputs}, {num_backward_outputs});" + # Helper + indent = GetIndent(2) + + node_construction_str = f"{indent}auto grad_node = std::make_shared<{grad_node_name}>({num_backward_inputs}, {num_backward_outputs});" # SetAttributes set_attributes_list = [] @@ -689,9 +699,9 @@ def GenerateNodeCreationCodes(self): for name, _, default_val_attr, _ in backward_attrs_list: if name in forward_attrs_name_set: - set_attributes = f" grad_node->SetAttribute{name}({name});" + set_attributes = f"{indent}grad_node->SetAttribute{name}({name});" else: - set_attributes = f" grad_node->SetAttribute{name}({default_val_attr});" + set_attributes = f"{indent}grad_node->SetAttribute{name}({default_val_attr});" set_attributes_list.append(set_attributes) set_attributes_str = "\n".join(set_attributes_list) @@ -704,9 +714,9 @@ def GenerateNodeCreationCodes(self): if is_fwd_input: if is_optional: - set_tensor_wrappers = f" if({name}.get_ptr() != nullptr) grad_node->SetTensorWrapper{name}(*({name}.get_ptr()), true);" + set_tensor_wrappers = f"{indent}if({name}.get_ptr() != nullptr) grad_node->SetTensorWrapper{name}(*({name}.get_ptr()), true);" else: - set_tensor_wrappers = f" grad_node->SetTensorWrapper{name}({name}, true);" + set_tensor_wrappers = f"{indent}grad_node->SetTensorWrapper{name}({name}, true);" else: if num_fwd_outputs > 1: # Aligned with forward output position @@ -715,9 +725,9 @@ def GenerateNodeCreationCodes(self): fwd_output_pos = forward_outputs_position_map[name][1] if is_optional: - set_tensor_wrappers = f" if({name}.get_ptr() != nullptr) grad_node->SetTensorWrapper{name}(*({name}.get_ptr()), false);" + set_tensor_wrappers = f"{indent}if({name}.get_ptr() != nullptr) grad_node->SetTensorWrapper{name}(*({name}.get_ptr()), false);" else: - set_tensor_wrappers = f" grad_node->SetTensorWrapper{name}({name}, false);" + set_tensor_wrappers = f"{indent}grad_node->SetTensorWrapper{name}({name}, false);" set_tensor_wrappers_list.append(set_tensor_wrappers) set_tensor_wrappers_str = "\n".join(set_tensor_wrappers_list) @@ -728,11 +738,11 @@ def GenerateNodeCreationCodes(self): input_autograd_meta_name = GetAutoGradMetaName(name) is_optional = (name in self.optional_inputs) if is_optional: - set_grad_out_meta = f" if({name}.get_ptr() != nullptr) grad_node->SetGradOutMeta(*({name}.get_ptr()), {pos});" - set_edges = f" if({name}.get_ptr() != nullptr) grad_node->AddEdges({input_autograd_meta_name}, {pos});" + set_grad_out_meta = f"{indent}if({name}.get_ptr() != nullptr) grad_node->SetGradOutMeta(*({name}.get_ptr()), {pos});" + set_edges = f"{indent}if({name}.get_ptr() != nullptr) grad_node->AddEdges({input_autograd_meta_name}, {pos});" else: - set_grad_out_meta = f" grad_node->SetGradOutMeta({name}, {pos});" - set_edges = f" grad_node->AddEdges({input_autograd_meta_name}, {pos});" + set_grad_out_meta = f"{indent}grad_node->SetGradOutMeta({name}, {pos});" + set_edges = f"{indent}grad_node->AddEdges({input_autograd_meta_name}, {pos});" set_grad_out_meta_list.append(set_grad_out_meta) set_edges_list.append(set_edges) @@ -747,11 +757,11 @@ def GenerateNodeCreationCodes(self): num_outputs = len(forward_outputs_position_map.keys()) for name, (_, pos) in forward_outputs_position_map.items(): output_autograd_meta_name = GetAutoGradMetaName(name) - set_out_rank = f" egr::EagerUtils::SetOutRankWithSlot({output_autograd_meta_name}, {pos});" - set_history = f" egr::EagerUtils::SetHistory({output_autograd_meta_name}, grad_node);" + set_out_rank = f"{indent}egr::EagerUtils::SetOutRankWithSlot({output_autograd_meta_name}, {pos});" + set_history = f"{indent}egr::EagerUtils::SetHistory({output_autograd_meta_name}, grad_node);" - set_retain_grad = f" egr::EagerUtils::CheckAndRetainGrad({name});" - set_grad_in_meta = f" grad_node->SetGradInMeta({name}, {pos});" + set_retain_grad = f"{indent}egr::EagerUtils::CheckAndRetainGrad({name});" + set_grad_in_meta = f"{indent}grad_node->SetGradInMeta({name}, {pos});" set_out_rank_list.append(set_out_rank) set_history_list.append(set_history) set_grad_in_meta_list.append(set_grad_in_meta) @@ -763,7 +773,7 @@ def GenerateNodeCreationCodes(self): set_retain_grad_str = "\n".join(set_retain_grad_list) node_event_name = forward_api_name + " node_creation" - node_creation_event_str = f"paddle::platform::RecordEvent node_creation_record_event(\"{node_event_name}\", paddle::platform::TracerEventType::Operator, 1);\n" + node_creation_event_str = f"{indent}paddle::platform::RecordEvent node_creation_record_event(\"{node_event_name}\", paddle::platform::TracerEventType::Operator, 1);\n" self.node_creation_str = FORWARD_BODY_TEMPLATE.format( node_creation_event_str, pass_stop_gradient_args_str, @@ -841,6 +851,7 @@ def GenerateForwardDefinition(self, is_inplaced): optional_inputs = self.optional_inputs intermediate_outputs = self.intermediate_outputs inplace_map = self.inplace_map if is_inplaced else {} + indent = GetIndent(1) # Get Function Args num_inputs = len(forward_attrs_list) + len( @@ -910,7 +921,7 @@ def GenerateForwardDefinition(self, is_inplaced): if len(intermediate_outputs) > 0: function_name = GetIntermediateAPIFunctionName(function_name) - forward_call_str = f"auto api_result = paddle::experimental::{namespace}{function_name}({inputs_call_args_str});" + forward_call_str = f"{indent}auto api_result = paddle::experimental::{namespace}{function_name}({inputs_call_args_str});" num_outputs = len(forward_outputs_position_map.keys()) - len( intermediate_outputs) @@ -918,9 +929,9 @@ def GenerateForwardDefinition(self, is_inplaced): get_outputs_str = "" for name, (rtype, pos) in forward_outputs_position_map.items(): if num_outputs == 1 and len(intermediate_outputs) == 0: - get_outputs_str += f"auto& {name} = api_result;\n" + get_outputs_str += f"{indent}auto& {name} = api_result;\n" else: - get_outputs_str += f"auto& {name} = std::get<{pos}>(api_result);\n" + get_outputs_str += f"{indent}auto& {name} = std::get<{pos}>(api_result);\n" # Get return type list & outputs returns_type_list = ["" for i in range(num_outputs)] @@ -953,12 +964,12 @@ def GenerateForwardDefinition(self, is_inplaced): for name, (ttype, pos) in forward_inputs_position_map.items(): input_autograd_meta_name = GetAutoGradMetaName(name) if IsPlainTensorType(ttype): - input_autograd_meta = f" egr::AutogradMeta* {input_autograd_meta_name} = egr::EagerUtils::nullable_autograd_meta({name});" + input_autograd_meta = f"{indent}egr::AutogradMeta* {input_autograd_meta_name} = egr::EagerUtils::nullable_autograd_meta({name});" else: assert IsVectorTensorType(ttype) input_autograd_meta_vec_name = GetAutoGradMetaVectorName(name) - input_autograd_meta = f" std::vector {input_autograd_meta_vec_name} = egr::EagerUtils::nullable_autograd_meta({name});\n" - input_autograd_meta += f" std::vector* {input_autograd_meta_name} = &{input_autograd_meta_vec_name};" + input_autograd_meta = f"{indent}std::vector {input_autograd_meta_vec_name} = egr::EagerUtils::nullable_autograd_meta({name});\n" + input_autograd_meta += f"{indent}std::vector* {input_autograd_meta_name} = &{input_autograd_meta_vec_name};" inputs_autograd_meta_list.append(input_autograd_meta) compute_require_grad_args_list.append(input_autograd_meta_name) @@ -973,19 +984,19 @@ def GenerateForwardDefinition(self, is_inplaced): output_autograd_meta_vec_name = GetAutoGradMetaVectorName(name) if num_fwd_outputs == 1: if IsPlainTensorType(rtype): - output_autograd_meta = f" egr::AutogradMeta* {output_autograd_meta_name} = egr::EagerUtils::autograd_meta(&{name});" + output_autograd_meta = f"{indent}egr::AutogradMeta* {output_autograd_meta_name} = egr::EagerUtils::autograd_meta(&{name});" else: assert IsVectorTensorType(rtype) - output_autograd_meta = f" std::vector {output_autograd_meta_vec_name} = egr::EagerUtils::autograd_meta(&{name});\n" - output_autograd_meta += f" std::vector* {output_autograd_meta_name} = &{output_autograd_meta_vec_name};" + output_autograd_meta = f"{indent}std::vector {output_autograd_meta_vec_name} = egr::EagerUtils::autograd_meta(&{name});\n" + output_autograd_meta += f"{indent}std::vector* {output_autograd_meta_name} = &{output_autograd_meta_vec_name};" else: # Tuple api_result if IsPlainTensorType(rtype): - output_autograd_meta = f" egr::AutogradMeta* {output_autograd_meta_name} = egr::EagerUtils::autograd_meta(&{name});" + output_autograd_meta = f"{indent}egr::AutogradMeta* {output_autograd_meta_name} = egr::EagerUtils::autograd_meta(&{name});" else: assert IsVectorTensorType(rtype) - output_autograd_meta = f" std::vector {output_autograd_meta_vec_name} = egr::EagerUtils::autograd_meta(&{name});\n" - output_autograd_meta += f" std::vector* {output_autograd_meta_name} = &{output_autograd_meta_vec_name};" + output_autograd_meta = f"{indent}std::vector {output_autograd_meta_vec_name} = egr::EagerUtils::autograd_meta(&{name});\n" + output_autograd_meta += f"{indent}std::vector* {output_autograd_meta_name} = &{output_autograd_meta_vec_name};" outputs_autograd_meta_list.append(output_autograd_meta) outputs_autograd_meta_str = "\n".join(outputs_autograd_meta_list) @@ -1004,7 +1015,7 @@ def GenerateForwardDefinition(self, is_inplaced): self.GenerateNodeCreationCodes() node_creation_str = self.node_creation_str - dygraph_event_str = f"paddle::platform::RecordEvent dygraph_entrance_record_event(\"{forward_api_name} dygraph\", paddle::platform::TracerEventType::Operator, 1);" + dygraph_event_str = f"{indent}paddle::platform::RecordEvent dygraph_entrance_record_event(\"{forward_api_name} dygraph\", paddle::platform::TracerEventType::Operator, 1);" forward_function_name = GetDygraphForwardFunctionName(forward_api_name) # Forward amp logic @@ -1111,6 +1122,34 @@ def __init__(self, self.node_definition_str = "" self.next_grad_api_contents = next_grad_api_contents + def ResetOptionalInputs(self): + namespace = self.namespace + grad_api_contents = self.grad_api_contents + + base_generator = FunctionGeneratorBase(grad_api_contents, namespace) + base_generator.ParseDispensable() + + self.optional_inputs = base_generator.optional_inputs + + def GenerateHigherOrderNodeCreationCode(self): + namespace = self.namespace + grad_api_contents = self.grad_api_contents + next_grad_api_contents = self.next_grad_api_contents + + grad_node_creation_str = "" + if next_grad_api_contents: + forward_api_contents = grad_api_contents + forward_api_contents['api'] = forward_api_contents['backward_api'] + backward_api_contents = next_grad_api_contents + + next_node_generator = DygraphFunctionGeneratorBase( + forward_api_contents, backward_api_contents, namespace) + next_node_generator.run() + next_node_generator.GenerateNodeCreationCodes() + grad_node_creation_str = next_node_generator.node_creation_str + + return grad_node_creation_str + def GenerateNodeDeclaration(self): forward_op_name = self.forward_api_name backward_forward_inputs_map = self.backward_forward_inputs_map @@ -1179,6 +1218,7 @@ def GenerateNodeDefinition(self, grad_node_creation_str): backward_grad_inputs_map = self.backward_grad_inputs_map backward_grad_outputs_map = self.backward_grad_outputs_map backward_attrs_list = self.backward_attrs_list + indent = GetIndent(1) # Construct grad_api function args # Order: TensorWrappers, GradTensors, Attributes @@ -1189,8 +1229,8 @@ def GenerateNodeDefinition(self, grad_node_creation_str): # Fill Grad Ins with Zero fill_zero_str = "" - if forward_api_name in ops_to_fill_zero_for_empty_grads: - fill_zero_str = "egr::EagerUtils::FillZeroForEmptyGradInputs(&grads, this->InputMeta());\n" + if backward_api_name in ops_to_fill_zero_for_empty_grads: + fill_zero_str = f"{indent}egr::EagerUtils::FillZeroForEmptyGradInputs(&grads, this->InputMeta());\n" # Grad Ins from TensorWrappers for name, (_, is_fwd_input, @@ -1201,9 +1241,9 @@ def GenerateNodeDefinition(self, grad_node_creation_str): is_optional = (name in self.optional_inputs) if is_optional: - tensor_wrapper_recover_str = f"auto {transformed_tensor_name} = egr::EagerUtils::RecoverOptionalTensorWrapper(&this->{tensor_wrapper_name}, nullptr);" + tensor_wrapper_recover_str = f"{indent}auto {transformed_tensor_name} = egr::EagerUtils::RecoverOptionalTensorWrapper(&this->{tensor_wrapper_name}, this->shared_from_this());" else: - tensor_wrapper_recover_str = f"auto {transformed_tensor_name} = egr::EagerUtils::RecoverTensorWrapper(&this->{tensor_wrapper_name}, nullptr);" + tensor_wrapper_recover_str = f"{indent}auto {transformed_tensor_name} = egr::EagerUtils::RecoverTensorWrapper(&this->{tensor_wrapper_name}, this->shared_from_this());" grad_api_args[grad_api_position] = transformed_tensor_name get_grad_in_args_list.append(tensor_wrapper_recover_str) @@ -1213,18 +1253,29 @@ def GenerateNodeDefinition(self, grad_node_creation_str): transformed_tensor_name = TransformGradVarNameForDoubleGradGeneration( name) + is_optional = (name in self.optional_inputs) if IsPlainTensorType(ttype): - get_tensor_str = f"auto& {transformed_tensor_name} = hooked_grads[{fwd_position}][0];" + get_tensor_str = f"{indent}auto& {transformed_tensor_name} = hooked_grads[{fwd_position}][0];" + + if is_optional: + get_tensor_str += "\n" + CREATE_PLAIN_OPTIONAL_TENSOR_TEMPLATE.format( + transformed_tensor_name, transformed_tensor_name, + transformed_tensor_name, transformed_tensor_name) + grad_api_args[ + grad_api_position] = f"{transformed_tensor_name}_optional" + else: + grad_api_args[grad_api_position] = transformed_tensor_name else: assert IsVectorTensorType(ttype) - get_tensor_str = f"auto& {transformed_tensor_name} = hooked_grads[{fwd_position}];" - grad_api_args[grad_api_position] = transformed_tensor_name + get_tensor_str = f"{indent}auto& {transformed_tensor_name} = hooked_grads[{fwd_position}];" + grad_api_args[grad_api_position] = transformed_tensor_name + get_grad_in_args_list.append(get_tensor_str) # Grad Attrs for name, _, _, grad_api_position in backward_attrs_list: saved_attribute_name = GetSavedName(name) - get_attr_str = f"auto& {name} = this->{saved_attribute_name};" + get_attr_str = f"{indent}auto& {name} = this->{saved_attribute_name};" grad_api_args[grad_api_position] = name get_grad_in_args_list.append(get_attr_str) @@ -1234,7 +1285,7 @@ def GenerateNodeDefinition(self, grad_node_creation_str): # Grad Function Call String grad_api_namespace = f"paddle::experimental::{namespace}" - grad_function_call_str = f"auto grad_api_result = {grad_api_namespace}{backward_api_name}({grad_api_args_str});" + grad_function_call_str = f"{indent}auto grad_api_result = {grad_api_namespace}{backward_api_name}({grad_api_args_str});" # Get Grad Outputs get_outputs_str = "" @@ -1245,9 +1296,13 @@ def GenerateNodeDefinition(self, grad_node_creation_str): name) if num_outputs == 1: - get_tensor_str = f"auto& {transformed_tensor_name} = grad_api_result;" + get_tensor_str = f"{indent}auto& {transformed_tensor_name} = grad_api_result;" else: - get_tensor_str = f"auto& {transformed_tensor_name} = grad_api_result[{fwd_position}];" + if IsPlainTensorType(ttype): + get_tensor_str = f"{indent}auto& {transformed_tensor_name} = grad_api_result[{fwd_position}][0];" + else: + assert IsVectorTensorType(ttype) + get_tensor_str = f"{indent}auto& {transformed_tensor_name} = grad_api_result[{fwd_position}];" get_outputs_str += get_tensor_str + "\n" # Prepare for Node Creation if Necessary @@ -1266,13 +1321,13 @@ def GenerateNodeDefinition(self, grad_node_creation_str): input_autograd_meta_name = GetAutoGradMetaName( transformed_tensor_name) if IsPlainTensorType(ttype): - input_autograd_meta = f" egr::AutogradMeta* {input_autograd_meta_name} = egr::EagerUtils::nullable_autograd_meta({transformed_tensor_name});" + input_autograd_meta = f"{indent}egr::AutogradMeta* {input_autograd_meta_name} = egr::EagerUtils::nullable_autograd_meta({transformed_tensor_name});" else: assert IsVectorTensorType(ttype) input_autograd_meta_vec_name = GetAutoGradMetaVectorName( transformed_tensor_name) - input_autograd_meta = f" std::vector {input_autograd_meta_vec_name} = egr::EagerUtils::nullable_autograd_meta({transformed_tensor_name});\n" - input_autograd_meta += f" std::vector* {input_autograd_meta_name} = &{input_autograd_meta_vec_name};" + input_autograd_meta = f"{indent}std::vector {input_autograd_meta_vec_name} = egr::EagerUtils::nullable_autograd_meta({transformed_tensor_name});\n" + input_autograd_meta += f"{indent}std::vector* {input_autograd_meta_name} = &{input_autograd_meta_vec_name};" inputs_autograd_meta_list.append(input_autograd_meta) compute_require_grad_args_list.append(input_autograd_meta_name) @@ -1285,13 +1340,13 @@ def GenerateNodeDefinition(self, grad_node_creation_str): input_autograd_meta_name = GetAutoGradMetaName( transformed_tensor_name) if IsPlainTensorType(ttype): - input_autograd_meta = f" egr::AutogradMeta* {input_autograd_meta_name} = egr::EagerUtils::nullable_autograd_meta({transformed_tensor_name});" + input_autograd_meta = f"{indent}egr::AutogradMeta* {input_autograd_meta_name} = egr::EagerUtils::nullable_autograd_meta({transformed_tensor_name});" else: assert IsVectorTensorType(ttype) input_autograd_meta_vec_name = GetAutoGradMetaVectorName( transformed_tensor_name) - input_autograd_meta = f" std::vector {input_autograd_meta_vec_name} = egr::EagerUtils::nullable_autograd_meta({transformed_tensor_name});\n" - input_autograd_meta += f" std::vector* {input_autograd_meta_name} = &{input_autograd_meta_vec_name};" + input_autograd_meta = f"{indent}std::vector {input_autograd_meta_vec_name} = egr::EagerUtils::nullable_autograd_meta({transformed_tensor_name});\n" + input_autograd_meta += f"{indent}std::vector* {input_autograd_meta_name} = &{input_autograd_meta_vec_name};" inputs_autograd_meta_list.append(input_autograd_meta) compute_require_grad_args_list.append(input_autograd_meta_name) @@ -1312,30 +1367,30 @@ def GenerateNodeDefinition(self, grad_node_creation_str): transformed_tensor_name) if num_fwd_outputs == 1: if IsPlainTensorType(rtype): - output_autograd_meta = f" egr::AutogradMeta* {output_autograd_meta_name} = egr::EagerUtils::autograd_meta(&{transformed_tensor_name});" + output_autograd_meta = f"{indent}egr::AutogradMeta* {output_autograd_meta_name} = egr::EagerUtils::autograd_meta(&{transformed_tensor_name});" else: assert IsVectorTensorType(rtype) - output_autograd_meta = f" std::vector {output_autograd_meta_vec_name} = egr::EagerUtils::autograd_meta(&{transformed_tensor_name});\n" - output_autograd_meta += f" std::vector* {output_autograd_meta_name} = &{output_autograd_meta_vec_name};" + output_autograd_meta = f"{indent}std::vector {output_autograd_meta_vec_name} = egr::EagerUtils::autograd_meta(&{transformed_tensor_name});\n" + output_autograd_meta += f"{indent}std::vector* {output_autograd_meta_name} = &{output_autograd_meta_vec_name};" else: # Tuple api_result if IsPlainTensorType(rtype): - output_autograd_meta = f" egr::AutogradMeta* {output_autograd_meta_name} = egr::EagerUtils::autograd_meta(&{transformed_tensor_name});" + output_autograd_meta = f"{indent}egr::AutogradMeta* {output_autograd_meta_name} = egr::EagerUtils::autograd_meta(&{transformed_tensor_name});" else: assert IsVectorTensorType(rtype) - output_autograd_meta = f" std::vector {output_autograd_meta_vec_name} = egr::EagerUtils::autograd_meta(&{transformed_tensor_name});\n" - output_autograd_meta += f" std::vector* {output_autograd_meta_name} = &{output_autograd_meta_vec_name};" + output_autograd_meta = f"{indent}std::vector {output_autograd_meta_vec_name} = egr::EagerUtils::autograd_meta(&{transformed_tensor_name});\n" + output_autograd_meta += f"{indent}std::vector* {output_autograd_meta_name} = &{output_autograd_meta_vec_name};" outputs_autograd_meta_list.append(output_autograd_meta) outputs_autograd_meta_str = "\n".join(outputs_autograd_meta_list) - compute_require_grad_str = "bool trace_backward = egr::Controller::Instance().HasGrad() && create_graph;\n" - compute_require_grad_str += f"bool require_any_grad = egr::EagerUtils::ComputeRequireGrad({compute_require_grad_args_str});" + compute_require_grad_str = f"{indent}bool trace_backward = egr::Controller::Instance().HasGrad() && create_graph;\n" + compute_require_grad_str += f"{indent}bool require_any_grad = egr::EagerUtils::ComputeRequireGrad({compute_require_grad_args_str});" # Construct grad_api returns num_bwd_outputs = len(backward_grad_outputs_map.keys()) slot_num_bwd_outputs = len(self.forward_inputs_position_map.keys()) - returns_str = f"std::vector> returns({slot_num_bwd_outputs});\n" + returns_str = f"{indent}std::vector> returns({slot_num_bwd_outputs});\n" for name, (ttype, fwd_position, grad_api_position) in backward_grad_outputs_map.items(): transformed_tensor_name = TransformGradVarNameForDoubleGradGeneration( @@ -1345,15 +1400,20 @@ def GenerateNodeDefinition(self, grad_node_creation_str): if num_bwd_outputs == 1: # Single tensor output, return as is if IsPlainTensorType(ttype): - returns_str += f"returns[0] = {{ {transformed_tensor_name} }};\n" + returns_str += f"{indent}returns[0] = {{ {transformed_tensor_name} }};\n" else: assert IsVectorTensorType(ttype) - returns_str += f"returns[0] = {transformed_tensor_name};\n" + returns_str += f"{indent}returns[0] = {transformed_tensor_name};\n" else: # Rearrange output order accordingly - returns_str += f"returns[{fwd_position}] = {transformed_tensor_name};\n" - returns_str += f"if(NeedComplexToRealConversion()) HandleComplexGradToRealGrad(&returns);\n" - returns_str += f"return returns;\n" + if IsPlainTensorType(ttype): + returns_str += f"{indent}returns[{fwd_position}] = {{ {transformed_tensor_name} }};\n" + else: + assert IsVectorTensorType(ttype) + returns_str += f"{indent}returns[{fwd_position}] = {transformed_tensor_name};\n" + + returns_str += f"{indent}if(NeedComplexToRealConversion()) HandleComplexGradToRealGrad(&returns);\n" + returns_str += f"{indent}return returns;\n" grad_node_name = GetGradNodeName(forward_api_name) @@ -1368,24 +1428,15 @@ def GenerateNodeDefinition(self, grad_node_creation_str): def run(self): super().run() + self.ResetOptionalInputs() + ##################### ## Code Generation ## ##################### self.GenerateNodeDeclaration() - namespace = self.namespace - grad_node_creation_str = "" - next_grad_api_contents = self.next_grad_api_contents - if next_grad_api_contents: - forward_api_contents = self.grad_api_contents - forward_api_contents['api'] = forward_api_contents['backward_api'] - backward_api_contents = next_grad_api_contents - - next_node_generator = DygraphFunctionGeneratorBase( - forward_api_contents, backward_api_contents, namespace) - next_node_generator.run() - next_node_generator.GenerateNodeCreationCodes() - grad_node_creation_str = next_node_generator.node_creation_str + # Higher-order GradNode generation + grad_node_creation_str = self.GenerateHigherOrderNodeCreationCode() self.GenerateNodeDefinition(grad_node_creation_str) diff --git a/paddle/fluid/eager/grad_node_info.h b/paddle/fluid/eager/grad_node_info.h index 81470f38cc37b..2b90126098a7c 100644 --- a/paddle/fluid/eager/grad_node_info.h +++ b/paddle/fluid/eager/grad_node_info.h @@ -14,6 +14,8 @@ #pragma once +#include + #include "paddle/fluid/eager/eager_tensor.h" #include "paddle/fluid/eager/hooks.h" #include "paddle/phi/api/all.h" @@ -85,7 +87,7 @@ class GradSlotMeta { std::shared_ptr meta_ = nullptr; }; -class GradNodeBase { +class GradNodeBase : public std::enable_shared_from_this { public: GradNodeBase() { VLOG(6) << "Construct GradNodeBase"; } GradNodeBase(size_t bwd_in_slot_num, size_t bwd_out_slot_num); diff --git a/python/paddle/nn/functional/activation.py b/python/paddle/nn/functional/activation.py index 794e265930247..0f02b359f9540 100644 --- a/python/paddle/nn/functional/activation.py +++ b/python/paddle/nn/functional/activation.py @@ -23,6 +23,7 @@ import warnings from ...fluid.layer_helper import LayerHelper from ...fluid.framework import convert_np_dtype_to_dtype_ +from ...fluid.framework import _in_legacy_dygraph, in_dygraph_mode from ...fluid.data_feeder import check_variable_and_dtype, check_dtype import paddle from paddle import _C_ops, in_dynamic_mode @@ -561,8 +562,9 @@ def relu(x, name=None): """ if in_dynamic_mode(): + return _C_ops.final_state_relu(x) + if _in_legacy_dygraph(): return _C_ops.relu(x) - check_variable_and_dtype(x, 'x', ['float16', 'float32', 'float64'], 'relu') helper = LayerHelper('relu', **locals()) out = helper.create_variable_for_type_inference(x.dtype) diff --git a/python/paddle/utils/code_gen/backward.yaml b/python/paddle/utils/code_gen/backward.yaml index 6aa7d5c679716..a95cc108e5ff0 100644 --- a/python/paddle/utils/code_gen/backward.yaml +++ b/python/paddle/utils/code_gen/backward.yaml @@ -7,17 +7,18 @@ param : [x, y] kernel : func : matmul_grad + backward : matmul_double_grad - backward_api : matmul_double_grad - forward : matmul_grad (Tensor x, Tensor y, Tensor out_grad, bool transpose_x, bool transpose_y) -> Tensor(dx), Tensor(dy) - args : (Tensor x, Tensor y, Tensor out_grad, Tensor dx_grad, Tensor dy_grad, bool transpose_x, bool transpose_y) - output : Tensor(d2x), Tensor(d2y), Tensor(dout_grad) + forward : matmul_grad (Tensor x, Tensor y, Tensor grad_out, bool transpose_x=false, bool transpose_y=false) -> Tensor(grad_x), Tensor(grad_y) + args : (Tensor x, Tensor y, Tensor grad_out, Tensor grad_x_grad, Tensor grad_y_grad, bool transpose_x=false, bool transpose_y=false) + output : Tensor(x_grad), Tensor(y_grad), Tensor(grad_out_grad) infer_meta : func : GeneralTernaryGradInferMeta - param : [x, y, out_grad] + param : [x, y, grad_out] kernel : func : matmul_double_grad - optional : dx_grad, dy_grad + optional : grad_x_grad, grad_y_grad - backward_api : scale_grad forward : scale (Tensor x, Scalar scale, float bias, bool bias_after_scale) -> Tensor(out) From 4001488da7d9e638344672719b5fb5d0762e3c49 Mon Sep 17 00:00:00 2001 From: jim19930609 Date: Wed, 30 Mar 2022 01:35:09 +0000 Subject: [PATCH 09/12] Fixed yaml typo --- python/paddle/utils/code_gen/backward.yaml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/python/paddle/utils/code_gen/backward.yaml b/python/paddle/utils/code_gen/backward.yaml index 5a8051738003f..f65be3863a9da 100644 --- a/python/paddle/utils/code_gen/backward.yaml +++ b/python/paddle/utils/code_gen/backward.yaml @@ -650,21 +650,21 @@ func : put_along_axis_grad - backward_api : relu_double_grad - forward : relu_grad (tensor out, tensor grad_out) -> tensor(grad_x) - args : (tensor out, tensor grad_x_grad) - output : tensor(out_grad), tensor(grad_out_grad) + forward : relu_grad (Tensor out, Tensor grad_out) -> Tensor(grad_x) + args : (Tensor out, Tensor grad_x_grad) + output : Tensor(out_grad), Tensor(grad_out_grad) infer_meta : - func : generalbinarygradinfermeta + func : GeneralBinaryGradInferMeta param : [out, out] kernel : func : relu_double_grad - backward_api : relu_grad - forward : relu (tensor x) -> tensor(out) - args : (tensor out, tensor out_grad) - output : tensor(x_grad) + forward : relu (Tensor x) -> Tensor(out) + args : (Tensor out, Tensor out_grad) + output : Tensor(x_grad) infer_meta : - func : unchangedinfermeta + func : UnchangedInferMeta param : [out] kernel : func : relu_grad From e26b5721a9cf262fdbd88df38ef993189804a4ab Mon Sep 17 00:00:00 2001 From: jim19930609 Date: Wed, 30 Mar 2022 01:35:09 +0000 Subject: [PATCH 10/12] Fixed yaml typo --- python/paddle/utils/code_gen/backward.yaml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/python/paddle/utils/code_gen/backward.yaml b/python/paddle/utils/code_gen/backward.yaml index 5a8051738003f..cf4ffeba708b0 100644 --- a/python/paddle/utils/code_gen/backward.yaml +++ b/python/paddle/utils/code_gen/backward.yaml @@ -633,7 +633,7 @@ output : Tensor(x_grad) infer_meta : func : UnchangedInferMeta - param : [out] + param : [x] kernel : func : psroi_pool_grad optional : rois_num @@ -650,21 +650,21 @@ func : put_along_axis_grad - backward_api : relu_double_grad - forward : relu_grad (tensor out, tensor grad_out) -> tensor(grad_x) - args : (tensor out, tensor grad_x_grad) - output : tensor(out_grad), tensor(grad_out_grad) + forward : relu_grad (Tensor out, Tensor grad_out) -> Tensor(grad_x) + args : (Tensor out, Tensor grad_x_grad) + output : Tensor(out_grad), Tensor(grad_out_grad) infer_meta : - func : generalbinarygradinfermeta + func : GeneralBinaryGradInferMeta param : [out, out] kernel : func : relu_double_grad - backward_api : relu_grad - forward : relu (tensor x) -> tensor(out) - args : (tensor out, tensor out_grad) - output : tensor(x_grad) + forward : relu (Tensor x) -> Tensor(out) + args : (Tensor out, Tensor out_grad) + output : Tensor(x_grad) infer_meta : - func : unchangedinfermeta + func : UnchangedInferMeta param : [out] kernel : func : relu_grad From 1b5fdb5d13db61f381fede4f3ff38351eab9ff6f Mon Sep 17 00:00:00 2001 From: jim19930609 Date: Wed, 30 Mar 2022 09:34:49 +0000 Subject: [PATCH 11/12] fixed minor issues --- python/paddle/nn/functional/activation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/paddle/nn/functional/activation.py b/python/paddle/nn/functional/activation.py index 0f02b359f9540..9e59d79408b0d 100644 --- a/python/paddle/nn/functional/activation.py +++ b/python/paddle/nn/functional/activation.py @@ -561,7 +561,7 @@ def relu(x, name=None): out = F.relu(x) # [0., 0., 1.] """ - if in_dynamic_mode(): + if in_dygraph_mode(): return _C_ops.final_state_relu(x) if _in_legacy_dygraph(): return _C_ops.relu(x) From 1239f69fae75450669942cbe407c0968ac7b11d8 Mon Sep 17 00:00:00 2001 From: jim19930609 Date: Thu, 31 Mar 2022 08:39:37 +0000 Subject: [PATCH 12/12] Fixed minor issue --- .../auto_code_generator/final_state_generator/eager_gen.py | 4 ++-- paddle/fluid/eager/grad_node_info.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py b/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py index 0d1d3ab722522..fb86c5da6856c 100644 --- a/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py +++ b/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py @@ -1249,9 +1249,9 @@ def GenerateNodeDefinition(self, grad_node_creation_str): is_optional = (name in self.optional_inputs) if is_optional: - tensor_wrapper_recover_str = f"{indent}auto {transformed_tensor_name} = egr::EagerUtils::RecoverOptionalTensorWrapper(&this->{tensor_wrapper_name}, this->shared_from_this());" + tensor_wrapper_recover_str = f"{indent}auto {transformed_tensor_name} = egr::EagerUtils::RecoverOptionalTensorWrapper(&this->{tensor_wrapper_name}, nullptr);" else: - tensor_wrapper_recover_str = f"{indent}auto {transformed_tensor_name} = egr::EagerUtils::RecoverTensorWrapper(&this->{tensor_wrapper_name}, this->shared_from_this());" + tensor_wrapper_recover_str = f"{indent}auto {transformed_tensor_name} = egr::EagerUtils::RecoverTensorWrapper(&this->{tensor_wrapper_name}, nullptr);" grad_api_args[grad_api_position] = transformed_tensor_name get_grad_in_args_list.append(tensor_wrapper_recover_str) diff --git a/paddle/fluid/eager/grad_node_info.h b/paddle/fluid/eager/grad_node_info.h index 70fc4afa0ac71..0d07f780dda9d 100644 --- a/paddle/fluid/eager/grad_node_info.h +++ b/paddle/fluid/eager/grad_node_info.h @@ -87,7 +87,7 @@ class GradSlotMeta { std::shared_ptr meta_ = nullptr; }; -class GradNodeBase : public std::enable_shared_from_this { +class GradNodeBase { public: GradNodeBase() { VLOG(6) << "Construct GradNodeBase"; } GradNodeBase(size_t bwd_in_slot_num, size_t bwd_out_slot_num);