Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ paddle/phi/kernels/fusion/cutlass/gemm_epilogue/build
paddle/phi/kernels/fusion/cutlass/gemm_epilogue/cutlass
python/paddle/_typing/libs/**/*.pyi
third_party.tar.gz

python/paddle/base/dygraph/generated_tensor_methods_patch.py
#fp8
paddle/fluid/fp8/deep_gemm/include/cute/*
paddle/fluid/fp8/deep_gemm/include/cutlass/*
20 changes: 20 additions & 0 deletions paddle/fluid/eager/auto_code_generator/generator/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,23 @@ add_custom_target(
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${tmp_python_c_header_path}
${python_c_header_path}
VERBATIM)

set(ops_yaml_path "${PADDLE_SOURCE_DIR}/paddle/phi/ops/yaml/ops.yaml")
set(monkey_patch_tensor_methods_path
"${PADDLE_SOURCE_DIR}/python/paddle/base/dygraph/generated_tensor_methods_patch.py"
)
set(tmp_monkey_patch_tensor_methods_path
"${PADDLE_SOURCE_DIR}/python/paddle/base/dygraph/generated_tensor_methods_patch.py.tmp"
)
message("Eager monkey path tensor methods CodeGen")
add_custom_target(
eager_monkey_patch_codegen
COMMAND
"${PYTHON_EXECUTABLE}"
"${PADDLE_SOURCE_DIR}/paddle/fluid/eager/auto_code_generator/generator/monkey_patch_gen.py"
"--api_yaml_path=${ops_yaml_path}"
"--output_path=${tmp_monkey_patch_tensor_methods_path}"
COMMAND
${CMAKE_COMMAND} -E copy_if_different
${tmp_monkey_patch_tensor_methods_path} ${monkey_patch_tensor_methods_path}
VERBATIM)
46 changes: 46 additions & 0 deletions paddle/fluid/eager/auto_code_generator/generator/codegen_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,7 @@ def __init__(self, forward_api_contents, namespace):
)

self.forward_api_name = ""
self.python_api_info = {}

self.orig_forward_inputs_list = (
[]
Expand Down Expand Up @@ -506,6 +507,15 @@ def __init__(self, forward_api_contents, namespace):
) # {name: func_name, args: [input_name, ...]}
self.intermediate_outputs = [] # [name, ...]
self.forward_inplace_map = {} # {name : name, ...}
self.args_alias_map = {} # {arg_name: alias_vector, ...}
self.dygraph_pre_process = (
"" # The pre_process function calling code for dygraph
)
self.static_pre_process = (
"" # The pre_process function calling code for static graph
)
self.args_parser_func_name = "" # The custom args parser function
self.python_api_names = ""

def ParseForwardInplaceInfo(self):
forward_api_contents = self.forward_api_contents
Expand All @@ -515,6 +525,40 @@ def ParseForwardInplaceInfo(self):
inplace_map_str = forward_api_contents['inplace']
self.forward_inplace_map = ParseYamlInplaceInfo(inplace_map_str)

# Function for parameters parse
def ParsePythonAPIInfo(self):
python_api_info = self.python_api_info
args_alias = {}
if 'name' in python_api_info.keys():
self.python_api_names = python_api_info['name']
if 'args_alias' in python_api_info.keys():
for arg, alias in python_api_info['args_alias'].items():
alias_set = set(alias)
# Add the original argument name to the alias set
alias_set.add(arg)
# Convert to C++ vector format
alias_vector = (
"{" + ",".join(f'"{name}"' for name in alias_set) + "}"
)
args_alias.update({arg: alias_vector})
self.args_alias_map = args_alias
if 'pre_process' in python_api_info.keys():
pre_process = python_api_info['pre_process']
if 'func' in pre_process.keys():
self.dygraph_pre_process = pre_process['func']
self.static_pre_process = pre_process['func']
# TODO check len(pre_process) > 1

if 'dygraph_func' in pre_process.keys():
self.dygraph_pre_process = pre_process['dygraph_func']
if 'static_func' in pre_process.keys():
self.static_pre_process = pre_process['static_func']
if (
'args_parser' in python_api_info.keys()
and 'func' in python_api_info['args_parser']
):
self.args_parser_func_name = python_api_info['args_parser']['func']

def ParseNoNeedBuffer(self):
grad_api_contents = self.grad_api_contents

Expand Down Expand Up @@ -575,6 +619,8 @@ def CollectOriginalForwardInfo(self):
), 'Unable to find "output" in forward_api_contents keys'

forward_returns_str = forward_api_contents['output']
if 'python_api' in forward_api_contents.keys():
self.python_api_info = forward_api_contents['python_api']

# Collect Original Forward Inputs/Outputs and then perform validation checks
(
Expand Down
143 changes: 143 additions & 0 deletions paddle/fluid/eager/auto_code_generator/generator/monkey_patch_gen.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import argparse

from codegen_utils import (
FunctionGeneratorBase,
GeneratorBase,
)

IMPORT_TEMPLATE = """
import paddle
from paddle import _C_ops
from .. import core
"""

FUNCTION_NAME_TEMPLATE = """
def {func_name}():
"""

NAME_METHOD_MAPPING_TEMPLATE = """ ('{api_name}',_{api_name})"""

METHODS_MAP_TEMPLATE = """
methods_map = [
{}
]
"""

METHOD_TEMPLATE = """
def _{name}(self,*args, **kwargs):
return _C_ops.{name}(self,*args, **kwargs)
"""
SET_METHOD_TEMPLATE = """
# set methods for Tensor in dygraph
local_tensor = core.eager.Tensor
for method_name, method in methods_map:
setattr(local_tensor, method_name, method)

"""


class MethodGenerator(FunctionGeneratorBase):
def __init__(self, forward_api_contents, namespace):
FunctionGeneratorBase.__init__(self, forward_api_contents, namespace)
self.need_parse_python_api_args = False
# Generated Results
self.Method_str = ""

def GenerateMethod(self, name):
self.Method_str = METHOD_TEMPLATE.format(name=name)

def run(self):
# Initialized orig_forward_inputs_list, orig_forward_returns_list, orig_forward_attrs_list
self.CollectOriginalForwardInfo()

if len(self.python_api_info) > 0:
self.need_parse_python_api_args = True
self.ParsePythonAPIInfo()
for name in self.python_api_names:
if "Tensor." in name:
api_name = name.split(".")[-1]
self.GenerateMethod(api_name)
self.api_name = api_name
break


class MonkeyPatchTensorMethodsGenerator(GeneratorBase):
def __init__(self, path):
# Parent members:
# self.namespace
# self.api_yaml_path
# self.forward_api_list
GeneratorBase.__init__(self, path)

# Generated Result
self.MonkeyPatchTensorMethods_str = ""

def GenerateMonkeyPatchTensorMethods(self):
self.MonkeyPatchTensorMethods_str += IMPORT_TEMPLATE

forward_api_list = self.forward_api_list
methods_map = [] # [("method_name",method),]
for forward_api_content in forward_api_list:
f_generator = MethodGenerator(forward_api_content, None)
status = f_generator.run()
method_str = f_generator.Method_str
if method_str != "":
methods_map.append(
NAME_METHOD_MAPPING_TEMPLATE.format(
api_name=f_generator.api_name
)
)
self.MonkeyPatchTensorMethods_str += method_str
result = ',\n '.join(methods_map)
self.MonkeyPatchTensorMethods_str += METHODS_MAP_TEMPLATE.format(result)
self.MonkeyPatchTensorMethods_str += FUNCTION_NAME_TEMPLATE.format(
func_name="monkey_patch_generated_methods_for_tensor"
)
self.MonkeyPatchTensorMethods_str += SET_METHOD_TEMPLATE

def run(self):
# Read Yaml file
self.ParseForwardYamlContents()
self.GenerateMonkeyPatchTensorMethods()


##########################
# Code Generation Helper #
##########################
def ParseArguments():
parser = argparse.ArgumentParser(
description='Eager Code Generator Args Parser for Monkey patch methods '
)
parser.add_argument('--api_yaml_path', type=str)
parser.add_argument('--output_path', type=str)

args = parser.parse_args()
return args


def GenerateMonkeyPathFile(filepath, python_c_str):
with open(filepath, 'w') as f:
f.write(python_c_str)


if __name__ == "__main__":
args = ParseArguments()
api_yaml_path = args.api_yaml_path
output_path = args.output_path
gen = MonkeyPatchTensorMethodsGenerator(api_yaml_path)
gen.run()
GenerateMonkeyPathFile(output_path, gen.MonkeyPatchTensorMethods_str)
Loading