chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
set(api_yaml_path "${PADDLE_BINARY_DIR}/paddle/phi/ops/yaml/ops.parsed.yaml")
|
||||
set(legacy_api_yaml_path
|
||||
"${PADDLE_BINARY_DIR}/paddle/phi/ops/yaml/inconsistent/dygraph_ops.parsed.yaml"
|
||||
)
|
||||
set(api_compat_yaml_path
|
||||
"${PADDLE_SOURCE_DIR}/paddle/phi/ops/yaml/op_compat.yaml")
|
||||
set(api_prim_yaml_path "${PADDLE_SOURCE_DIR}/paddle/fluid/prim/api/api.yaml")
|
||||
set(api_version_yaml_path
|
||||
"${PADDLE_SOURCE_DIR}/paddle/phi/ops/yaml/op_version.yaml")
|
||||
set(tmp_eager_prim_api_cc_path
|
||||
"${PADDLE_SOURCE_DIR}/paddle/fluid/prim/api/generated_prim/eager_prim_api.cc.tmp"
|
||||
)
|
||||
set(tmp_static_prim_api_cc_path
|
||||
"${PADDLE_SOURCE_DIR}/paddle/fluid/prim/api/generated_prim/static_prim_api.cc.tmp"
|
||||
)
|
||||
set(tmp_prim_api_h_path
|
||||
"${PADDLE_SOURCE_DIR}/paddle/fluid/prim/api/generated_prim/prim_generated_api.h.tmp"
|
||||
)
|
||||
set(eager_prim_api_cc_path
|
||||
"${PADDLE_SOURCE_DIR}/paddle/fluid/prim/api/generated_prim/eager_prim_api.cc"
|
||||
)
|
||||
set(static_prim_api_cc_path
|
||||
"${PADDLE_SOURCE_DIR}/paddle/fluid/prim/api/generated_prim/static_prim_api.cc"
|
||||
)
|
||||
set(prim_api_h_path
|
||||
"${PADDLE_SOURCE_DIR}/paddle/fluid/prim/api/generated_prim/prim_generated_api.h"
|
||||
)
|
||||
set(static_prim_api_template_path
|
||||
"${PADDLE_SOURCE_DIR}/paddle/fluid/prim/api/auto_code_generated/template/static_prim_api.cc.j2"
|
||||
)
|
||||
set(eager_prim_api_gen_file
|
||||
${PADDLE_SOURCE_DIR}/paddle/fluid/prim/api/auto_code_generated/eager_gen.py)
|
||||
set(static_prim_api_gen_file
|
||||
${PADDLE_SOURCE_DIR}/paddle/fluid/prim/api/auto_code_generated/static_gen.py
|
||||
)
|
||||
set(prim_tensor_operants_gen_file
|
||||
${PADDLE_SOURCE_DIR}/paddle/fluid/prim/api/auto_code_generated/tensor_operants_gen.py
|
||||
)
|
||||
|
||||
message("Eager prim api code generator")
|
||||
execute_process(
|
||||
WORKING_DIRECTORY
|
||||
${CMAKE_SOURCE_DIR}/paddle/fluid/prim/api/auto_code_generated
|
||||
COMMAND
|
||||
${PYTHON_EXECUTABLE} ${eager_prim_api_gen_file} --api_yaml_path
|
||||
${legacy_api_yaml_path} ${api_yaml_path} --prim_api_header_path
|
||||
${tmp_prim_api_h_path} --eager_prim_api_source_path
|
||||
${tmp_eager_prim_api_cc_path} --api_prim_yaml_path ${api_prim_yaml_path}
|
||||
RESULT_VARIABLE _result)
|
||||
if(${_result})
|
||||
message(FATAL_ERROR "Eager prim api generate failed, exiting.")
|
||||
endif()
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${tmp_prim_api_h_path} ${prim_api_h_path})
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${tmp_eager_prim_api_cc_path} ${eager_prim_api_cc_path})
|
||||
message("copy tmp_xxx_prim_api to xxx_prim_api")
|
||||
|
||||
message("Static prim api code generator")
|
||||
execute_process(
|
||||
WORKING_DIRECTORY
|
||||
${CMAKE_SOURCE_DIR}/paddle/fluid/prim/api/auto_code_generated
|
||||
COMMAND
|
||||
${PYTHON_EXECUTABLE} ${static_prim_api_gen_file} --api_phi_yaml_path
|
||||
${api_yaml_path} --api_phi_legacy_yaml_path ${legacy_api_yaml_path}
|
||||
--api_compat_yaml_path ${api_compat_yaml_path} --api_version_yaml_path
|
||||
${api_version_yaml_path} --api_prim_yaml_path ${api_prim_yaml_path}
|
||||
--template_path ${static_prim_api_template_path} --output_path
|
||||
${tmp_static_prim_api_cc_path}
|
||||
RESULT_VARIABLE _result)
|
||||
if(${_result})
|
||||
message(FATAL_ERROR "Static prim api generate failed, exiting.")
|
||||
endif()
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${tmp_static_prim_api_cc_path}
|
||||
${static_prim_api_cc_path})
|
||||
message("copy tmp_xxx_prim_api to xxx_prim_api")
|
||||
|
||||
set(eager_tensor_operants_cc_path
|
||||
${PADDLE_SOURCE_DIR}/paddle/fluid/prim/utils/eager/eager_tensor_operants.cc)
|
||||
set(eager_tensor_operants_h_path
|
||||
${PADDLE_SOURCE_DIR}/paddle/fluid/prim/utils/eager/eager_tensor_operants.h)
|
||||
set(static_tensor_operants_cc_path
|
||||
${PADDLE_SOURCE_DIR}/paddle/fluid/prim/utils/static/static_tensor_operants.cc
|
||||
)
|
||||
set(static_tensor_operants_h_path
|
||||
${PADDLE_SOURCE_DIR}/paddle/fluid/prim/utils/static/static_tensor_operants.h
|
||||
)
|
||||
set(tmp_eager_tensor_operants_cc_path ${eager_tensor_operants_cc_path}.tmp)
|
||||
set(tmp_eager_tensor_operants_h_path ${eager_tensor_operants_h_path}.tmp)
|
||||
set(tmp_static_tensor_operants_cc_path ${static_tensor_operants_cc_path}.tmp)
|
||||
set(tmp_static_tensor_operants_h_path ${static_tensor_operants_h_path}.tmp)
|
||||
set(tensor_api_yaml_path
|
||||
${PADDLE_SOURCE_DIR}/paddle/phi/api/lib/tensor_operants.yaml)
|
||||
|
||||
message("Prim tensor operants code generator")
|
||||
execute_process(
|
||||
WORKING_DIRECTORY
|
||||
${CMAKE_SOURCE_DIR}/paddle/fluid/prim/api/auto_code_generated
|
||||
COMMAND
|
||||
${PYTHON_EXECUTABLE} ${prim_tensor_operants_gen_file} --api_yaml_path
|
||||
${legacy_api_yaml_path} ${api_yaml_path} --eager_tensor_operants_header_path
|
||||
${tmp_eager_tensor_operants_h_path} --eager_tensor_operants_source_path
|
||||
${tmp_eager_tensor_operants_cc_path} --static_tensor_operants_header_path
|
||||
${tmp_static_tensor_operants_h_path} --static_tensor_operants_source_path
|
||||
${tmp_static_tensor_operants_cc_path} --api_prim_yaml_path
|
||||
${tensor_api_yaml_path}
|
||||
RESULT_VARIABLE _result)
|
||||
if(${_result})
|
||||
message(FATAL_ERROR "Prim tensor operants generate failed, exiting.")
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${tmp_eager_tensor_operants_h_path} ${eager_tensor_operants_h_path})
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${tmp_eager_tensor_operants_cc_path} ${eager_tensor_operants_cc_path})
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${tmp_static_tensor_operants_h_path} ${static_tensor_operants_h_path})
|
||||
execute_process(
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E copy_if_different ${tmp_static_tensor_operants_cc_path}
|
||||
${static_tensor_operants_cc_path})
|
||||
message("copy prim xxx_tensor_operants.tmp to xxx_tensor_operants")
|
||||
@@ -0,0 +1,460 @@
|
||||
# Copyright (c) 2022 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
|
||||
|
||||
import yaml
|
||||
|
||||
inplace_out_type_map = {
|
||||
"Tensor": "Tensor&",
|
||||
"std::vector<Tensor>": "std::vector<Tensor>&",
|
||||
}
|
||||
|
||||
inplace_optional_out_type_map = {
|
||||
"Tensor": "paddle::optional<Tensor>&",
|
||||
"std::vector<Tensor>": "paddle::optional<std::vector<Tensor>>&",
|
||||
}
|
||||
|
||||
|
||||
class BaseAPI:
|
||||
def __init__(self, api_item_yaml, prims=()):
|
||||
# self.api = api_item_yaml['op']
|
||||
self.api = api_item_yaml['name']
|
||||
|
||||
self.is_prim_api = False
|
||||
if api_item_yaml['name'] in prims:
|
||||
self.is_prim_api = True
|
||||
|
||||
#######################################
|
||||
# inputs:
|
||||
# names : [], list of input names
|
||||
# input_info : {input_name : type}
|
||||
# attrs:
|
||||
# names : [], list of attribute names
|
||||
# attr_info : { attr_name : (type, default_values)}
|
||||
# outputs:
|
||||
# names : [], list of output names
|
||||
# types : [], list of output types
|
||||
# out_size_expr : [], expression for getting size of vector<Tensor>
|
||||
########################################
|
||||
if self.is_prim_api:
|
||||
(
|
||||
self.inputs,
|
||||
self.attrs,
|
||||
self.outputs,
|
||||
self.optional_vars,
|
||||
) = self.parse_args(self.api, api_item_yaml)
|
||||
|
||||
self.inplace_map = api_item_yaml['inplace']
|
||||
|
||||
def get_api_func_name(self):
|
||||
return self.api
|
||||
|
||||
# def is_inplace(self):
|
||||
# if self.inplace_map
|
||||
# return True
|
||||
# return False
|
||||
|
||||
def get_input_tensor_args(self, inplace_flag=False):
|
||||
input_args = []
|
||||
inplace_type_map = {
|
||||
"const Tensor&": "Tensor&",
|
||||
"const paddle::optional<Tensor>&": "paddle::optional<Tensor>&",
|
||||
"const std::vector<Tensor>&": "std::vector<Tensor>&",
|
||||
"const paddle::optional<std::vector<Tensor>>&": "paddle::optional<std::vector<Tensor>>&",
|
||||
}
|
||||
for name in self.inputs['names']:
|
||||
name = name.split('@')[0]
|
||||
if inplace_flag and name in self.inplace_map.values():
|
||||
input_args.append(
|
||||
inplace_type_map[self.inputs['input_info'][name]]
|
||||
+ ' '
|
||||
+ name
|
||||
)
|
||||
else:
|
||||
input_args.append(self.inputs['input_info'][name] + ' ' + name)
|
||||
return input_args
|
||||
|
||||
def get_declare_args(self, inplace_flag=False):
|
||||
declare_args = self.get_input_tensor_args(inplace_flag)
|
||||
for name in self.attrs['names']:
|
||||
default_value = ''
|
||||
if self.attrs['attr_info'][name][1] is not None:
|
||||
default_value = ' = ' + self.attrs['attr_info'][name][1]
|
||||
declare_args.append(
|
||||
self.attrs['attr_info'][name][0] + ' ' + name + default_value
|
||||
)
|
||||
|
||||
return ", ".join(declare_args)
|
||||
|
||||
def get_declare_args_nodefault(self, inplace_flag=False):
|
||||
declare_args = self.get_input_tensor_args(inplace_flag)
|
||||
for name in self.attrs['names']:
|
||||
declare_args.append(self.attrs['attr_info'][name][0] + ' ' + name)
|
||||
|
||||
return ", ".join(declare_args)
|
||||
|
||||
def get_return_type(self, inplace_flag=False):
|
||||
out_type_list = []
|
||||
for i, out_type in enumerate(self.outputs['types']):
|
||||
out_name = self.outputs['names'][i].split('@')[0]
|
||||
if inplace_flag and out_name in self.inplace_map:
|
||||
if self.inplace_map[out_name] in self.optional_vars:
|
||||
out_type_list.append(
|
||||
inplace_optional_out_type_map[out_type]
|
||||
)
|
||||
else:
|
||||
out_type_list.append(inplace_out_type_map[out_type])
|
||||
else:
|
||||
out_type_list.append(out_type)
|
||||
if len(out_type_list) == 1:
|
||||
return out_type_list[0]
|
||||
else:
|
||||
return "std::tuple<" + ", ".join(out_type_list) + ">"
|
||||
|
||||
def parse_args(self, api_name, api_item_yaml):
|
||||
optional_vars = []
|
||||
for input_dict in api_item_yaml['inputs']:
|
||||
if input_dict['optional']:
|
||||
optional_vars.append(input_dict['name'])
|
||||
|
||||
inputs, attrs = self.parse_input_and_attr(
|
||||
api_item_yaml['inputs'], api_item_yaml['attrs']
|
||||
)
|
||||
|
||||
output_type_list, output_names, out_size_expr = self.parse_output(
|
||||
api_item_yaml['outputs']
|
||||
)
|
||||
return (
|
||||
inputs,
|
||||
attrs,
|
||||
{
|
||||
'names': output_names,
|
||||
'types': output_type_list,
|
||||
'out_size_expr': out_size_expr,
|
||||
},
|
||||
optional_vars,
|
||||
)
|
||||
|
||||
def parse_input_and_attr(self, inputs_list, attrs_list):
|
||||
input_types_map = {
|
||||
'Tensor': 'const Tensor&',
|
||||
'Tensor[]': 'const std::vector<Tensor>&',
|
||||
}
|
||||
attr_types_map = {
|
||||
'IntArray': 'const IntArray&',
|
||||
'Scalar': 'const Scalar&',
|
||||
'Scalar(int)': 'const Scalar&',
|
||||
'Scalar(int64_t)': 'const Scalar&',
|
||||
'Scalar(float)': 'const Scalar&',
|
||||
'Scalar(double)': 'const Scalar&',
|
||||
'Scalar[]': 'const std::vector<phi::Scalar>&',
|
||||
'int': 'int',
|
||||
'int32_t': 'int32_t',
|
||||
'int64_t': 'int64_t',
|
||||
'long': 'long',
|
||||
'size_t': 'size_t',
|
||||
'float': 'float',
|
||||
'float[]': 'const std::vector<float>&',
|
||||
'double': 'double',
|
||||
'double[]': 'const std::vector<double>&',
|
||||
'bool': 'bool',
|
||||
'bool[]': 'const std::vector<bool>&',
|
||||
'str': 'const std::string&',
|
||||
'str[]': 'const std::vector<std::string>&',
|
||||
'Place': 'const Place&',
|
||||
'DataLayout': 'DataLayout',
|
||||
'DataType': 'DataType',
|
||||
'int64_t[]': 'const std::vector<int64_t>&',
|
||||
'int[]': 'const std::vector<int>&',
|
||||
}
|
||||
optional_types_trans = {
|
||||
'Tensor': 'const paddle::optional<Tensor>&',
|
||||
'Tensor[]': 'const paddle::optional<std::vector<Tensor>>&',
|
||||
'int': 'paddle::optional<int>',
|
||||
'int32_t': 'paddle::optional<int32_t>',
|
||||
'int64_t': 'paddle::optional<int64_t>',
|
||||
'float': 'paddle::optional<float>',
|
||||
'double': 'paddle::optional<double>',
|
||||
'bool': 'paddle::optional<bool>',
|
||||
'Place': 'paddle::optional<const Place&>',
|
||||
'DataLayout': 'paddle::optional<DataLayout>',
|
||||
'DataType': 'paddle::optional<DataType>',
|
||||
}
|
||||
|
||||
inputs = {'names': [], 'input_info': {}}
|
||||
for input_dict in inputs_list:
|
||||
inputs['names'].append(input_dict['name'])
|
||||
if input_dict['optional']:
|
||||
inputs['input_info'][input_dict['name']] = optional_types_trans[
|
||||
input_dict['typename']
|
||||
]
|
||||
else:
|
||||
inputs['input_info'][input_dict['name']] = input_types_map[
|
||||
input_dict['typename']
|
||||
]
|
||||
|
||||
attrs = {'names': [], 'attr_info': {}}
|
||||
for attr_dict in attrs_list:
|
||||
attrs['names'].append(attr_dict['name'])
|
||||
if 'default_value' in attr_dict.keys():
|
||||
default_value = attr_dict['default_value']
|
||||
else:
|
||||
default_value = None
|
||||
|
||||
if 'optional' in attr_dict.keys():
|
||||
attrs['attr_info'][attr_dict['name']] = (
|
||||
optional_types_trans[attr_dict['typename']],
|
||||
default_value,
|
||||
)
|
||||
else:
|
||||
attrs['attr_info'][attr_dict['name']] = (
|
||||
attr_types_map[attr_dict['typename']],
|
||||
default_value,
|
||||
)
|
||||
return inputs, attrs
|
||||
|
||||
def parse_output(self, outputs_list):
|
||||
output_types_map = {
|
||||
'Tensor[]': 'std::vector<Tensor>',
|
||||
}
|
||||
out_type_list = []
|
||||
out_name_list = []
|
||||
out_size_expr_list = []
|
||||
for output_dict in outputs_list:
|
||||
if output_dict['intermediate']:
|
||||
continue
|
||||
out_type_list.append(
|
||||
output_types_map.get(
|
||||
output_dict['typename'], output_dict['typename']
|
||||
)
|
||||
)
|
||||
out_name_list.append(output_dict['name'])
|
||||
if 'size' in output_dict.keys():
|
||||
out_size_expr_list.append(output_dict['size'])
|
||||
else:
|
||||
out_size_expr_list.append(None)
|
||||
return out_type_list, out_name_list, out_size_expr_list
|
||||
|
||||
|
||||
class EagerPrimAPI(BaseAPI):
|
||||
def __init__(self, api_item_yaml, prims=()):
|
||||
super().__init__(api_item_yaml, prims)
|
||||
|
||||
def get_api__func_name(self):
|
||||
api_func_name = self.api
|
||||
# if self.is_inplace:
|
||||
# if api_func_name[-1] != '_':
|
||||
# api_func_name += '_'
|
||||
# print("after api name", api_func_name)
|
||||
return api_func_name
|
||||
|
||||
def gene_prim_api_declaration(self):
|
||||
api_declaration = ""
|
||||
api_func_name = self.get_api__func_name()
|
||||
if api_func_name[-1] != '_':
|
||||
api_declaration = f"""
|
||||
template <typename T>
|
||||
{self.get_return_type()} {api_func_name}({self.get_declare_args()});
|
||||
"""
|
||||
else:
|
||||
api_declaration = (
|
||||
api_declaration
|
||||
+ f"""
|
||||
template <typename T>
|
||||
{self.get_return_type(inplace_flag=True)} {api_func_name}({self.get_declare_args(inplace_flag=True)});
|
||||
"""
|
||||
)
|
||||
|
||||
return api_declaration
|
||||
|
||||
def get_ad_func_input_args(self, inplace_flag=False):
|
||||
input_args = []
|
||||
for name in self.inputs['names']:
|
||||
name = name.split('@')[0]
|
||||
input_args.append(name)
|
||||
return input_args
|
||||
|
||||
def get_ad_func_args(self, inplace_flag=False):
|
||||
ad_func_args = self.get_ad_func_input_args(inplace_flag)
|
||||
for name in self.attrs['names']:
|
||||
default_value = ''
|
||||
if self.attrs['attr_info'][name][1] is not None:
|
||||
default_value = ' = ' + self.attrs['attr_info'][name][1]
|
||||
ad_func_args.append(name)
|
||||
|
||||
ad_func_args_str = ", ".join(ad_func_args)
|
||||
return ad_func_args_str
|
||||
|
||||
def gene_ad_func_call(self):
|
||||
api_func_name = self.get_api__func_name()
|
||||
|
||||
dygraph_ad_func_name = '::' + api_func_name + '_ad_func'
|
||||
dygraph_ad_func_parameters = self.get_ad_func_args()
|
||||
|
||||
ad_func_call_str = f"""
|
||||
VLOG(4) << "Eager Prim API {api_func_name}_ad_func call";
|
||||
return {dygraph_ad_func_name}({dygraph_ad_func_parameters});
|
||||
"""
|
||||
# print("ad_func_call_str: ", ad_func_call_str)
|
||||
return ad_func_call_str
|
||||
|
||||
def gene_eager_prim_api_code(self):
|
||||
api_code = ""
|
||||
indent = " "
|
||||
api_func_name = self.get_api__func_name()
|
||||
template = '<Tensor>'
|
||||
# func declaration
|
||||
if api_func_name[-1] != '_':
|
||||
api_code = f"""
|
||||
template <>
|
||||
{self.get_return_type()} {api_func_name}{template}({self.get_declare_args_nodefault()})
|
||||
"""
|
||||
else:
|
||||
api_code = f"""
|
||||
template <>
|
||||
{self.get_return_type(inplace_flag=True)} {api_func_name}{template}({self.get_declare_args_nodefault(inplace_flag=True)})
|
||||
"""
|
||||
# func code
|
||||
|
||||
api_code = api_code + '{'
|
||||
api_code += f"""{self.gene_ad_func_call()}"""
|
||||
api_code += '}' + '\n'
|
||||
|
||||
return api_code
|
||||
|
||||
|
||||
def header_include():
|
||||
return """
|
||||
#include "paddle/phi/common/int_array.h"
|
||||
#include "paddle/phi/common/data_type.h"
|
||||
#include "paddle/phi/common/scalar.h"
|
||||
#include "paddle/phi/common/place.h"
|
||||
#include "paddle/utils/optional.h"
|
||||
"""
|
||||
|
||||
|
||||
def eager_source_include():
|
||||
return """
|
||||
#include "paddle/fluid/eager/api/all.h"
|
||||
#include "paddle/fluid/eager/api/generated/eager_generated/forwards/dygraph_functions.h"
|
||||
#include "paddle/fluid/eager/api/manual/eager_manual/dygraph_forward_api.h"
|
||||
#include "paddle/fluid/prim/api/generated_prim/prim_generated_api.h"
|
||||
"""
|
||||
|
||||
|
||||
def api_namespace():
|
||||
return (
|
||||
"""
|
||||
namespace paddle {
|
||||
namespace prim {
|
||||
""",
|
||||
"""
|
||||
using Tensor = paddle::Tensor;
|
||||
using Scalar = paddle::experimental::Scalar;
|
||||
using IntArray = paddle::experimental::IntArray;
|
||||
using DataType = phi::DataType;
|
||||
""",
|
||||
"""
|
||||
} // namespace prim
|
||||
} // namespace paddle
|
||||
""",
|
||||
)
|
||||
|
||||
|
||||
def generate_api(
|
||||
api_yaml_path, header_file_path, eager_prim_source_file_path, api_prim_path
|
||||
):
|
||||
apis = []
|
||||
|
||||
for each_api_yaml in api_yaml_path:
|
||||
with open(each_api_yaml, 'r') as f:
|
||||
api_list = yaml.load(f, Loader=yaml.FullLoader)
|
||||
if api_list:
|
||||
apis.extend(api_list)
|
||||
|
||||
header_file = open(header_file_path, 'w')
|
||||
eager_prim_source_file = open(eager_prim_source_file_path, 'w')
|
||||
|
||||
namespace = api_namespace()
|
||||
|
||||
header_file.write("#pragma once\n")
|
||||
header_file.write(header_include())
|
||||
header_file.write(namespace[0])
|
||||
header_file.write(namespace[1])
|
||||
eager_prim_source_file.write(eager_source_include())
|
||||
eager_prim_source_file.write(namespace[0])
|
||||
|
||||
with open(api_prim_path, 'rt') as f:
|
||||
api_prims = yaml.safe_load(f)
|
||||
|
||||
for api in apis:
|
||||
prim_api = EagerPrimAPI(api, api_prims)
|
||||
if prim_api.is_prim_api:
|
||||
header_file.write(prim_api.gene_prim_api_declaration())
|
||||
eager_prim_source_file.write(prim_api.gene_eager_prim_api_code())
|
||||
|
||||
header_file.write(namespace[2])
|
||||
eager_prim_source_file.write(namespace[2])
|
||||
|
||||
header_file.close()
|
||||
eager_prim_source_file.close()
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Generate PaddlePaddle C++ API files'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--api_yaml_path',
|
||||
help='path to api yaml file',
|
||||
nargs='+',
|
||||
default=['paddle/phi/ops/yaml/ops.yaml'],
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--prim_api_header_path',
|
||||
help='output of generated prim_api header code file',
|
||||
default='paddle/fluid/prim/api/generated_prim/prim_generated_api.h',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--eager_prim_api_source_path',
|
||||
help='output of generated eager_prim_api source code file',
|
||||
default='paddle/fluid/prim/api/generated_prim/eager_prim_api.cc',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--api_prim_yaml_path',
|
||||
help='Primitive API list yaml file.',
|
||||
default='paddle/fluid/prim/api/api.yaml',
|
||||
)
|
||||
|
||||
options = parser.parse_args()
|
||||
|
||||
api_yaml_path = options.api_yaml_path
|
||||
prim_api_header_file_path = options.prim_api_header_path
|
||||
eager_prim_api_source_file_path = options.eager_prim_api_source_path
|
||||
api_prim_yaml_path = options.api_prim_yaml_path
|
||||
|
||||
generate_api(
|
||||
api_yaml_path,
|
||||
prim_api_header_file_path,
|
||||
eager_prim_api_source_file_path,
|
||||
api_prim_yaml_path,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,156 @@
|
||||
# Copyright (c) 2023 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
|
||||
import copy
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
import jinja2
|
||||
import yaml
|
||||
|
||||
# import from paddle/fluid/operators/generator
|
||||
sys.path.append(
|
||||
str(pathlib.Path(__file__).parents[3].joinpath('operators/generator'))
|
||||
)
|
||||
import filters as op_gen_filters
|
||||
import generate_op as op_gen_utils
|
||||
import parse_utils as op_gen_parse_utils
|
||||
import tests_utils as op_gen_tests
|
||||
|
||||
# fmt: on
|
||||
|
||||
|
||||
def load_yaml(path, mode="rt"):
|
||||
with open(path, mode) as f:
|
||||
return yaml.safe_load(f)
|
||||
|
||||
|
||||
def render(tpl, *args, **kwargs):
|
||||
env = jinja2.Environment(
|
||||
loader=jinja2.FileSystemLoader(pathlib.Path(tpl).parent),
|
||||
keep_trailing_newline=True,
|
||||
trim_blocks=True,
|
||||
lstrip_blocks=True,
|
||||
undefined=jinja2.StrictUndefined,
|
||||
extensions=['jinja2.ext.do'],
|
||||
)
|
||||
env.filters.update(
|
||||
{
|
||||
'to_paddle_attr_type': op_gen_filters.to_paddle_attr_type,
|
||||
'to_paddle_input_type': op_gen_filters.to_paddle_input_type,
|
||||
'to_paddle_output_type': op_gen_filters.to_paddle_output_type,
|
||||
'to_pascal': op_gen_filters.to_pascal_case,
|
||||
"trip_intermediate": op_gen_filters.filter_intermediate,
|
||||
}
|
||||
)
|
||||
env.tests.update(
|
||||
{
|
||||
'scalar': op_gen_tests.is_scalar,
|
||||
'intarray': op_gen_tests.is_intarray,
|
||||
'datatype': op_gen_tests.is_datatype,
|
||||
'tensor_sequence': op_gen_tests.is_tensor_list,
|
||||
}
|
||||
)
|
||||
return env.get_template(pathlib.Path(tpl).name).render(*args, **kwargs)
|
||||
|
||||
|
||||
def filter_prim(apis, prims):
|
||||
return [api for api in apis if api.get('name') in prims]
|
||||
|
||||
|
||||
def extend_compat(apis, compats):
|
||||
dicts = op_gen_parse_utils.to_named_dict(copy.deepcopy(apis))
|
||||
for api in dicts.values():
|
||||
op_gen_utils.restruct_io(api)
|
||||
api['op_name'] = api['name']
|
||||
op_gen_utils.add_fluid_name(api['inputs'])
|
||||
op_gen_utils.add_fluid_name(api['attrs'])
|
||||
op_gen_utils.add_fluid_name(api['outputs'])
|
||||
api['backward'] = None
|
||||
op_gen_utils.add_compat_name(compats, dicts, {})
|
||||
return tuple(dicts.values())
|
||||
|
||||
|
||||
def extend_version(apis, versions):
|
||||
apis = copy.deepcopy(apis)
|
||||
for api in apis:
|
||||
for version in versions:
|
||||
if version.get('op') == api.get('name'):
|
||||
api['version'] = version['version']
|
||||
return apis
|
||||
|
||||
|
||||
def generate(
|
||||
api_prim_yaml_path,
|
||||
api_phi_yaml_path,
|
||||
api_phi_legacy_yaml_path,
|
||||
api_compat_yaml_path,
|
||||
api_version_yaml_path,
|
||||
template_path,
|
||||
output_op_path,
|
||||
):
|
||||
prims, phis, legacy_phis, compats, versions = (
|
||||
load_yaml(api_prim_yaml_path),
|
||||
load_yaml(api_phi_yaml_path),
|
||||
load_yaml(api_phi_legacy_yaml_path),
|
||||
load_yaml(api_compat_yaml_path),
|
||||
load_yaml(api_version_yaml_path),
|
||||
)
|
||||
|
||||
apis = phis + legacy_phis
|
||||
apis = filter_prim(apis, prims)
|
||||
apis = extend_version(apis, versions)
|
||||
apis = extend_compat(apis, compats)
|
||||
|
||||
if len(apis) > 0:
|
||||
with open(output_op_path, "wt") as f:
|
||||
msg = render(template_path, apis=apis)
|
||||
f.write(msg)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Generate Static Primitive API"
|
||||
)
|
||||
parser.add_argument(
|
||||
'--api_prim_yaml_path', type=str, help="Primitive API yaml file.."
|
||||
)
|
||||
parser.add_argument(
|
||||
'--api_phi_yaml_path', type=str, help="Parsed ops yaml file."
|
||||
)
|
||||
parser.add_argument(
|
||||
'--api_phi_legacy_yaml_path', type=str, help="Parsed ops yaml file."
|
||||
)
|
||||
parser.add_argument(
|
||||
'--api_compat_yaml_path', type=str, help="Ops args compat yaml file."
|
||||
)
|
||||
parser.add_argument(
|
||||
'--api_version_yaml_path', type=str, help="Ops version yaml file."
|
||||
)
|
||||
parser.add_argument(
|
||||
"--template_path", type=str, help="JinJa2 template file Path."
|
||||
)
|
||||
parser.add_argument("--output_path", type=str, help="Output path.")
|
||||
|
||||
args = parser.parse_args()
|
||||
generate(
|
||||
args.api_prim_yaml_path,
|
||||
args.api_phi_yaml_path,
|
||||
args.api_phi_legacy_yaml_path,
|
||||
args.api_compat_yaml_path,
|
||||
args.api_version_yaml_path,
|
||||
args.template_path,
|
||||
args.output_path,
|
||||
)
|
||||
@@ -0,0 +1,39 @@
|
||||
{% from "utils.cc.j2" import static_prim_api %}
|
||||
// Generated by /paddle/fluid/prim/api/auto_code_generated/static_gen.py.
|
||||
// DO NOT EDIT!
|
||||
|
||||
#include <string.h>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <tuple>
|
||||
|
||||
#include "paddle/fluid/framework/block_desc.h"
|
||||
#include "paddle/fluid/framework/op_desc.h"
|
||||
#include "paddle/fluid/framework/op_proto_maker.h"
|
||||
#include "paddle/fluid/framework/operator.h"
|
||||
#include "paddle/fluid/framework/program_desc.h"
|
||||
|
||||
#include "paddle/fluid/framework/convert_utils.h"
|
||||
#include "paddle/fluid/prim/api/generated_prim/prim_generated_api.h"
|
||||
#include "paddle/fluid/prim/api/manual_prim/utils/utils.h"
|
||||
#include "paddle/fluid/prim/utils/static/composite_grad_desc_maker.h"
|
||||
#include "paddle/fluid/prim/utils/static/desc_tensor.h"
|
||||
#include "paddle/phi/api/include/tensor.h"
|
||||
#include "paddle/phi/common/data_type.h"
|
||||
#include "paddle/phi/common/float16.h"
|
||||
#include "paddle/phi/core/enforce.h"
|
||||
|
||||
|
||||
namespace paddle {
|
||||
namespace prim {
|
||||
|
||||
{% for api in apis %}
|
||||
{{static_prim_api(api)}}
|
||||
{% endfor %}
|
||||
|
||||
} // namespace prim
|
||||
} // namespace paddle
|
||||
@@ -0,0 +1,200 @@
|
||||
|
||||
{% macro static_prim_api(api) %}
|
||||
{%- set fluid_name = api.op_name -%}
|
||||
{%- set phi_name = api.name -%}
|
||||
{%- set inputs = api.inputs -%}
|
||||
{%- set outputs = api.outputs|trip_intermediate -%} {#- ignore intermediate output -#}
|
||||
{%- set attrs = api.attrs -%}
|
||||
{%- set output_names = [] -%}
|
||||
{%- for o in outputs -%} {%- do output_names.append(o.name) -%} {%-endfor-%}
|
||||
{%- set output_dtype = static_prim_api_output_dtype(api.inputs, api.attrs) -%}
|
||||
{{static_prim_api_sig(phi_name, inputs, outputs, attrs)}} {
|
||||
framework::BlockDesc* block = StaticCompositeContext::Instance().GetBlock();
|
||||
framework::OpDesc* op = block->AppendOp();
|
||||
op->SetType("{{fluid_name}}");
|
||||
{% filter indent(2, True) %}
|
||||
{% for input in inputs %}
|
||||
{{static_prim_api_input(input)}}
|
||||
{% endfor %}
|
||||
{% for output in outputs %}
|
||||
{{static_prim_api_output(output, output_dtype)}}
|
||||
{% endfor %}
|
||||
{% for attr in attrs %}
|
||||
{{static_prim_api_attr(attr)}}
|
||||
{% endfor %}
|
||||
{% endfilter %}
|
||||
op->CheckAttrs();
|
||||
op->InferVarType(block);
|
||||
op->InferShape(*block);
|
||||
{% if outputs|length > 1 %}
|
||||
return std::make_tuple{{sequence('(', ')', ', ', output_names)}};
|
||||
{% elif outputs|length == 1 %}
|
||||
return {{outputs[0].name}};
|
||||
{% else %} {#- render nothing -#}
|
||||
{% endif %}
|
||||
}
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
{%- macro static_prim_api_sig(name, inputs, outputs, attrs) -%}
|
||||
template <>
|
||||
{{static_prim_api_sig_ret(outputs)}} {{name}}<DescTensor>({{static_prim_api_sig_params(inputs, attrs)}})
|
||||
{%- endmacro %}
|
||||
|
||||
|
||||
{%- macro static_prim_api_sig_params(inputs, attrs) -%}
|
||||
{%- set input_params = [] -%}
|
||||
{%- for i in inputs -%} {%- do input_params.append(i.typename|to_paddle_input_type(i.optional)~' '~i.name) -%} {%- endfor -%}
|
||||
{%- set attr_params = [] -%}
|
||||
{%- for i in attrs -%} {%- do attr_params.append(i.typename|to_paddle_attr_type~' '~i.name) -%} {%- endfor -%}
|
||||
{{sequence('', '', ', ', input_params)}}
|
||||
{%- if attr_params|length > 0 -%} {{", "}} {%- endif -%} {#- append comma between inputs and attrs -#}
|
||||
{{sequence('', '', ', ', attr_params)}}
|
||||
{%- endmacro -%}
|
||||
|
||||
|
||||
{%- macro static_prim_api_sig_ret(outputs) -%}
|
||||
{%- set names = [] -%}
|
||||
{%- for i in outputs -%} {%- do names.append(i.typename|to_paddle_output_type) -%} {%- endfor -%}
|
||||
{%- if names|length > 1 -%}
|
||||
std::tuple<{{sequence('', '', ', ', names)}}>
|
||||
{%- else -%}
|
||||
{{names[0]}}
|
||||
{%- endif -%}
|
||||
{%- endmacro -%}
|
||||
|
||||
|
||||
{% macro static_prim_api_input(input) %}
|
||||
{%- if input.optional -%}
|
||||
{{static_prim_api_input_optional(input)}}
|
||||
{%- else -%}
|
||||
{{static_prim_api_input_without_optional(input)}}
|
||||
{%- endif -%}
|
||||
{%- endmacro -%}
|
||||
|
||||
|
||||
{%- macro static_prim_api_input_optional(input) -%}
|
||||
{%- if input.typename=='Tensor[]' -%} {#- render the input of type paddle::optional<std::Vector<Tensor>> -#}
|
||||
if ({{input.name}}) {
|
||||
std::vector<std::string> {{input.name}}_names({{input.name}}.get().size());
|
||||
std::transform({{input.name}}.get().begin(), {{input.name}}.get().end(), {{input.name}}_names.begin(), [](const Tensor& t) {
|
||||
return std::static_pointer_cast<prim::DescTensor>(t.impl())->Name();
|
||||
});
|
||||
op->SetInput("{{input.fluid_name | to_pascal}}", {{input.name}}_names);
|
||||
}
|
||||
{%- else -%}
|
||||
if ({{input.name}}) {
|
||||
op->SetInput("{{input.fluid_name | to_pascal}}", {std::static_pointer_cast<prim::DescTensor>({{input.name}}->impl())->Name()});
|
||||
}
|
||||
{%- endif -%}
|
||||
{%- endmacro -%}
|
||||
|
||||
|
||||
{%- macro static_prim_api_input_without_optional(input) -%}
|
||||
{%- if input.typename is tensor_sequence -%} {#- render the input of type std::Vector<Tensor> -#}
|
||||
std::vector<std::string> {{input.name}}_names({{input.name}}.size());;
|
||||
std::transform({{input.name}}.begin(), {{input.name}}.end(), {{input.name}}_names.begin(), [](const Tensor& t) {
|
||||
return std::static_pointer_cast<prim::DescTensor>(t.impl())->Name();
|
||||
});
|
||||
op->SetInput("{{input.fluid_name | to_pascal}}", {{input.name}}_names);
|
||||
{%- else -%}
|
||||
op->SetInput("{{input.fluid_name | to_pascal}}", {std::static_pointer_cast<prim::DescTensor>({{input.name}}.impl())->Name()});
|
||||
{%- endif -%}
|
||||
{%- endmacro -%}
|
||||
|
||||
|
||||
{% macro static_prim_api_output(output, dtype) %}
|
||||
{%- if output.optional -%}
|
||||
{{static_prim_api_output_optional(output, dtype)}}
|
||||
{%- else -%}
|
||||
{{static_prim_api_output_without_optional(output, dtype)}}
|
||||
{%- endif -%}
|
||||
{%- endmacro -%}
|
||||
|
||||
|
||||
{%- macro static_prim_api_output_without_optional(output, dtype) -%}
|
||||
{%- if output.typename is tensor_sequence -%} {#- render the output of type std::Vector<Tensor> -#}
|
||||
std::vector<Tensor> {{output.name}};
|
||||
std::vector<std::string> {{output.name}}_names;
|
||||
for (size_t i=0; i<{{output.size}}; i++) {
|
||||
auto tmp = empty<DescTensor>({}, {{dtype}}, paddle::Place());
|
||||
{{output.name}}.push_back(tmp);
|
||||
{{output.name}}_names.push_back(std::static_pointer_cast<prim::DescTensor>(tmp.impl())->Name());
|
||||
}
|
||||
op->SetOutput("{{output.fluid_name | to_pascal}}", {{output.name}}_names);
|
||||
{%- else -%}
|
||||
auto {{output.name}} = empty<DescTensor>({}, {{dtype}}, paddle::Place());
|
||||
op->SetOutput("{{output.fluid_name | to_pascal}}", {std::static_pointer_cast<prim::DescTensor>({{output.name}}.impl())->Name()});
|
||||
{%- endif -%}
|
||||
{%- endmacro -%}
|
||||
|
||||
|
||||
{%- macro static_prim_api_output_optional(output, dtype) -%}
|
||||
// TODO(cxxly): Render optional output
|
||||
{%- endmacro -%}
|
||||
|
||||
|
||||
{% macro static_prim_api_attr(attr) %}
|
||||
op->SetAttr("{{attr.fluid_name}}", {{phi_attr_to_fluid(attr)}});
|
||||
{%- endmacro %}
|
||||
|
||||
|
||||
{%- macro phi_attr_to_fluid(attr) -%}
|
||||
{%- if attr.typename is intarray -%}
|
||||
{{int_array_to_fluid(attr.name, attr.typename, attr.fluid_name, attr.data_type)}}
|
||||
{%- elif attr.typename is scalar -%}
|
||||
{{scalar_to_fluid(attr.name, attr.typename, attr.fluid_name, attr.data_type)}}
|
||||
{%- elif attr.typename is datatype -%}
|
||||
{{datatype_to_fluid(attr.name, attr.typename, attr.fluid_name, attr.data_type)}}
|
||||
{%- else -%}
|
||||
{{attr.name}}
|
||||
{%- endif -%}
|
||||
{%- endmacro %}
|
||||
|
||||
|
||||
{%- macro int_array_to_fluid(src_name, src_type, dst_name, dst_type) -%}
|
||||
{%- if dst_type=='std::vector<int>' -%}
|
||||
unsafe_vector_cast<int64_t, int>({{src_name}}.GetData())
|
||||
{%- else -%}
|
||||
{{src_name}}.GetData()
|
||||
{%- endif -%}
|
||||
{%- endmacro -%}
|
||||
|
||||
|
||||
{%- macro scalar_to_fluid(src_name, src_type, dst_name, dst_type) -%}
|
||||
{{src_name}}.to<{{dst_type}}>()
|
||||
{%- endmacro -%}
|
||||
|
||||
|
||||
{%- macro datatype_to_fluid(src_name, src_type, dst_name, dst_type) -%}
|
||||
paddle::framework::TransToProtoVarType({{src_name}})
|
||||
{%- endmacro -%}
|
||||
|
||||
|
||||
{%- macro sequence(lsymbol, rsymbol, delimiter, items) -%}
|
||||
{{lsymbol}}{%- for item in items -%}{{item}}{{delimiter if not loop.last else "" }}{%- endfor -%}{{rsymbol}}
|
||||
{%- endmacro -%}
|
||||
|
||||
|
||||
{%- macro static_prim_api_output_dtype(inputs, attrs) -%}
|
||||
{%- set is_set = [] -%} {#- why not use boolean, ref: https://stackoverflow.com/questions/17925674/jinja2-local-global-variable -#}
|
||||
{%- if not is_set -%} {#- use DataType attr as default output dtype -#}
|
||||
{%- for attr in attrs -%}
|
||||
{%- if attr.typename is datatype -%}
|
||||
{{attr.name}}
|
||||
{%- do is_set.append(1) -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- endif -%}
|
||||
{%- if not is_set -%} {#- use first input named x dtype as default output dtype -#}
|
||||
{%- for input in inputs -%}
|
||||
{%- if input.typename == 'Tensor' and input.name == 'x' -%}
|
||||
{{input.name}}.dtype()
|
||||
{%- do is_set.append(1) -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- endif -%}
|
||||
{%- if not is_set -%} {#- use fp32 as default output dtype -#}
|
||||
phi::DataType::FLOAT32
|
||||
{%- endif -%}
|
||||
{%- endmacro -%}
|
||||
@@ -0,0 +1,551 @@
|
||||
# Copyright (c) 2023 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
|
||||
|
||||
import yaml
|
||||
from eager_gen import BaseAPI
|
||||
|
||||
indent = " "
|
||||
|
||||
eager_header_include = """// Generated by paddle/fluid/prim/api/auto_code_generated/tensor_operants_gen.py
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "paddle/phi/api/include/operants_base.h"
|
||||
#include "paddle/phi/api/include/tensor.h"
|
||||
#include "paddle/phi/common/scalar.h"
|
||||
#include "paddle/phi/common/int_array.h"
|
||||
#include "paddle/common/macros.h"
|
||||
#include "paddle/utils/test_macros.h"
|
||||
|
||||
"""
|
||||
|
||||
eager_header_start = """
|
||||
namespace paddle {
|
||||
|
||||
namespace prim {
|
||||
|
||||
using Tensor = paddle::Tensor;
|
||||
using Scalar = paddle::experimental::Scalar;
|
||||
using IntArray = paddle::experimental::IntArray;
|
||||
using TensorOperantsBase = paddle::operants::TensorOperantsBase;
|
||||
|
||||
class TEST_API EagerTensorOperants : public TensorOperantsBase {
|
||||
private:
|
||||
DISABLE_COPY_AND_ASSIGN(EagerTensorOperants);
|
||||
|
||||
public:
|
||||
EagerTensorOperants() = default;
|
||||
|
||||
Tensor add(const Tensor& x, const Scalar& y);
|
||||
|
||||
Tensor subtract(const Tensor& x, const Scalar& y);
|
||||
|
||||
Tensor multiply(const Tensor& x, const Scalar& y);
|
||||
|
||||
Tensor divide(const Tensor& x, const Scalar& y);
|
||||
|
||||
Tensor add(const Scalar& x, const Tensor& y);
|
||||
|
||||
Tensor subtract(const Scalar& x, const Tensor& y);
|
||||
|
||||
Tensor multiply(const Scalar& x, const Tensor& y);
|
||||
|
||||
Tensor divide(const Scalar& x, const Tensor& y);
|
||||
|
||||
Tensor pow(const Tensor& x, const Tensor& y);
|
||||
|
||||
Tensor pow(const Tensor& x, const Scalar& y);
|
||||
|
||||
"""
|
||||
|
||||
|
||||
eager_header_end = """};
|
||||
|
||||
} // namespace prim
|
||||
} // namespace paddle
|
||||
|
||||
"""
|
||||
|
||||
|
||||
eager_source_include = """// Generated by paddle/fluid/prim/api/auto_code_generated/tensor_operants_gen.py
|
||||
|
||||
#include "paddle/fluid/prim/utils/eager/eager_tensor_operants.h"
|
||||
|
||||
#include "paddle/fluid/eager/api/generated/eager_generated/forwards/dygraph_functions.h"
|
||||
|
||||
"""
|
||||
|
||||
|
||||
eager_source_start = """
|
||||
namespace paddle {
|
||||
|
||||
namespace prim {
|
||||
|
||||
Tensor EagerTensorOperants::add(const Tensor& x, const Scalar& y) {
|
||||
return ::scale_ad_func(x, 1.0f, y, true);
|
||||
}
|
||||
|
||||
Tensor EagerTensorOperants::subtract(const Tensor& x, const Scalar& y) {
|
||||
return ::scale_ad_func(x, 1.0f, -y, true);
|
||||
}
|
||||
|
||||
Tensor EagerTensorOperants::multiply(const Tensor& x, const Scalar& y) {
|
||||
return ::scale_ad_func(x, y, 0.0f, true);
|
||||
}
|
||||
|
||||
Tensor EagerTensorOperants::divide(const Tensor& x, const Scalar& y) {
|
||||
return ::divide_ad_func(x, ::full_like_ad_func(x, y));
|
||||
}
|
||||
|
||||
Tensor EagerTensorOperants::add(const Scalar& x, const Tensor& y) {
|
||||
return ::scale_ad_func(y, 1.0f, x, true);
|
||||
}
|
||||
|
||||
Tensor EagerTensorOperants::subtract(const Scalar& x, const Tensor& y) {
|
||||
return ::scale_ad_func(y, -1.0f, x, true);
|
||||
}
|
||||
|
||||
Tensor EagerTensorOperants::multiply(const Scalar& x, const Tensor& y) {
|
||||
return ::scale_ad_func(y, x, 0.0f, true);
|
||||
}
|
||||
|
||||
Tensor EagerTensorOperants::divide(const Scalar& x, const Tensor& y) {
|
||||
return ::divide_ad_func(::full_like_ad_func(y, x), y);
|
||||
}
|
||||
|
||||
Tensor EagerTensorOperants::pow(const Tensor& x, const Tensor& y) {
|
||||
return ::elementwise_pow_ad_func(x, y);
|
||||
}
|
||||
|
||||
Tensor EagerTensorOperants::pow(const Tensor& x, const Scalar& y) {
|
||||
return ::pow_ad_func(x, y);
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
|
||||
eager_source_end = """
|
||||
} // namespace prim
|
||||
} // namespace paddle
|
||||
|
||||
"""
|
||||
|
||||
|
||||
static_header_include = """// Generated by paddle/fluid/prim/api/auto_code_generated/tensor_operants_gen.py
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "paddle/phi/api/include/operants_base.h"
|
||||
#include "paddle/phi/api/include/tensor.h"
|
||||
#include "paddle/phi/common/scalar.h"
|
||||
#include "paddle/phi/common/int_array.h"
|
||||
#include "paddle/common/macros.h"
|
||||
#include "paddle/utils/test_macros.h"
|
||||
"""
|
||||
|
||||
static_header_start = """
|
||||
namespace paddle {
|
||||
|
||||
namespace prim {
|
||||
|
||||
using Tensor = paddle::Tensor;
|
||||
using Scalar = paddle::experimental::Scalar;
|
||||
using IntArray = paddle::experimental::IntArray;
|
||||
using TensorOperantsBase = paddle::operants::TensorOperantsBase;
|
||||
|
||||
class TEST_API StaticTensorOperants : public TensorOperantsBase {
|
||||
private:
|
||||
DISABLE_COPY_AND_ASSIGN(StaticTensorOperants);
|
||||
|
||||
public:
|
||||
StaticTensorOperants() = default;
|
||||
|
||||
Tensor add(const Tensor& x, const Scalar& y);
|
||||
|
||||
Tensor subtract(const Tensor& x, const Scalar& y);
|
||||
|
||||
Tensor multiply(const Tensor& x, const Scalar& y);
|
||||
|
||||
Tensor divide(const Tensor& x, const Scalar& y);
|
||||
|
||||
Tensor add(const Scalar& x, const Tensor& y);
|
||||
|
||||
Tensor subtract(const Scalar& x, const Tensor& y);
|
||||
|
||||
Tensor multiply(const Scalar& x, const Tensor& y);
|
||||
|
||||
Tensor divide(const Scalar& x, const Tensor& y);
|
||||
|
||||
Tensor pow(const Tensor& x, const Tensor& y);
|
||||
|
||||
Tensor pow(const Tensor& x, const Scalar& y);
|
||||
|
||||
"""
|
||||
|
||||
|
||||
static_header_end = """};
|
||||
|
||||
} // namespace prim
|
||||
} // namespace paddle
|
||||
|
||||
"""
|
||||
|
||||
|
||||
static_source_include = """// Generated by paddle/fluid/prim/api/auto_code_generated/tensor_operants_gen.py
|
||||
|
||||
#include "paddle/fluid/prim/utils/static/static_tensor_operants.h"
|
||||
|
||||
#include "paddle/fluid/prim/api/generated_prim/prim_generated_api.h"
|
||||
#include "paddle/fluid/prim/api/manual_prim/prim_manual_api.h"
|
||||
#include "paddle/fluid/prim/utils/static/desc_tensor.h"
|
||||
|
||||
#include "paddle/fluid/primitive/backend/backend.h"
|
||||
#include "paddle/fluid/primitive/base/lazy_tensor.h"
|
||||
|
||||
COMMON_DECLARE_bool(enable_pir_api);
|
||||
COMMON_DECLARE_bool(enable_pir_in_executor);
|
||||
|
||||
"""
|
||||
|
||||
|
||||
static_source_start = """
|
||||
namespace paddle {
|
||||
|
||||
namespace prim {
|
||||
using DescTensor = paddle::prim::DescTensor;
|
||||
using LazyTensor = paddle::primitive::LazyTensor;
|
||||
|
||||
Tensor StaticTensorOperants::add(const Tensor& x, const Scalar& y) {
|
||||
if (FLAGS_enable_pir_api || FLAGS_enable_pir_in_executor) {
|
||||
return paddle::primitive::backend::add<LazyTensor>(x, paddle::primitive::backend::full<LazyTensor>(x.shape(), y, x.dtype(), x.place()));
|
||||
} else {
|
||||
return paddle::prim::add<DescTensor>(x, paddle::prim::full<DescTensor>(x.shape(), y, x.dtype(), x.place()));
|
||||
}
|
||||
}
|
||||
|
||||
Tensor StaticTensorOperants::subtract(const Tensor& x, const Scalar& y) {
|
||||
if (FLAGS_enable_pir_api || FLAGS_enable_pir_in_executor) {
|
||||
return paddle::primitive::backend::subtract<LazyTensor>(x, paddle::primitive::backend::full<LazyTensor>(x.shape(), y, x.dtype(), x.place()));
|
||||
} else {
|
||||
return paddle::prim::subtract<DescTensor>(x, paddle::prim::full<DescTensor>(x.shape(), y, x.dtype(), x.place()));
|
||||
}
|
||||
}
|
||||
|
||||
Tensor StaticTensorOperants::multiply(const Tensor& x, const Scalar& y) {
|
||||
if (FLAGS_enable_pir_api || FLAGS_enable_pir_in_executor) {
|
||||
return paddle::primitive::backend::scale<LazyTensor>(x, y, 0.0f, true);
|
||||
} else {
|
||||
return paddle::prim::scale<DescTensor>(x, y, 0.0f, true);
|
||||
}
|
||||
}
|
||||
|
||||
Tensor StaticTensorOperants::divide(const Tensor& x, const Scalar& y) {
|
||||
if (FLAGS_enable_pir_api || FLAGS_enable_pir_in_executor) {
|
||||
return paddle::primitive::backend::divide<LazyTensor>(x, paddle::primitive::backend::full<LazyTensor>(x.shape(), y, x.dtype(), x.place()));
|
||||
} else {
|
||||
return paddle::prim::divide<DescTensor>(x, paddle::prim::full<DescTensor>(x.shape(), y, x.dtype(), x.place()));
|
||||
}
|
||||
}
|
||||
|
||||
Tensor StaticTensorOperants::add(const Scalar& x, const Tensor& y) {
|
||||
if (FLAGS_enable_pir_api || FLAGS_enable_pir_in_executor) {
|
||||
return paddle::primitive::backend::add<LazyTensor>(paddle::primitive::backend::full<LazyTensor>(y.shape(), x, y.dtype(), y.place()), y);
|
||||
} else {
|
||||
return paddle::prim::add<DescTensor>(paddle::prim::full<DescTensor>(y.shape(), x, y.dtype(), y.place()), y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Tensor StaticTensorOperants::subtract(const Scalar& x, const Tensor& y) {
|
||||
if (FLAGS_enable_pir_api || FLAGS_enable_pir_in_executor) {
|
||||
return paddle::primitive::backend::subtract<LazyTensor>(paddle::primitive::backend::full<LazyTensor>(y.shape(), x, y.dtype(), y.place()), y);
|
||||
} else {
|
||||
return paddle::prim::subtract<DescTensor>(paddle::prim::full<DescTensor>(y.shape(), x, y.dtype(), y.place()), y);
|
||||
}
|
||||
}
|
||||
|
||||
Tensor StaticTensorOperants::multiply(const Scalar& x, const Tensor& y) {
|
||||
if (FLAGS_enable_pir_api || FLAGS_enable_pir_in_executor) {
|
||||
return paddle::primitive::backend::scale<LazyTensor>(y, x, 0.0f, true);
|
||||
} else {
|
||||
return paddle::prim::scale<DescTensor>(y, x, 0.0f, true);
|
||||
}
|
||||
}
|
||||
|
||||
Tensor StaticTensorOperants::divide(const Scalar& x, const Tensor& y) {
|
||||
if (FLAGS_enable_pir_api || FLAGS_enable_pir_in_executor) {
|
||||
return paddle::primitive::backend::divide<LazyTensor>(paddle::primitive::backend::full<LazyTensor>(y.shape(), x, y.dtype(), y.place()), y);
|
||||
} else {
|
||||
return paddle::prim::divide<DescTensor>(paddle::prim::full<DescTensor>(y.shape(), x, y.dtype(), y.place()), y);
|
||||
}
|
||||
}
|
||||
|
||||
Tensor StaticTensorOperants::pow(const Tensor& x, const Tensor& y) {
|
||||
if (FLAGS_enable_pir_api || FLAGS_enable_pir_in_executor) {
|
||||
return paddle::primitive::backend::elementwise_pow<LazyTensor>(x, y);
|
||||
} else {
|
||||
return paddle::prim::elementwise_pow<DescTensor>(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
Tensor StaticTensorOperants::pow(const Tensor& x, const Scalar& y) {
|
||||
if (FLAGS_enable_pir_api || FLAGS_enable_pir_in_executor) {
|
||||
return paddle::primitive::backend::pow<LazyTensor>(x, y);
|
||||
} else {
|
||||
return paddle::prim::pow<DescTensor>(x, y);
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
static_source_end = """
|
||||
} // namespace prim
|
||||
} // namespace paddle
|
||||
|
||||
"""
|
||||
|
||||
|
||||
class PrimTensorAPI(BaseAPI):
|
||||
def __init__(self, api_item_yaml, prims=()):
|
||||
super().__init__(api_item_yaml, prims)
|
||||
|
||||
def get_api_func_name(self):
|
||||
return self.api
|
||||
|
||||
# def is_inplace(self):
|
||||
# if self.inplace_map
|
||||
# return True
|
||||
# return False
|
||||
|
||||
def gene_tensor_operants_declaration(self):
|
||||
api_func_name = self.get_api_func_name()
|
||||
|
||||
if api_func_name[-1] != '_':
|
||||
return f"""{indent}{self.get_return_type()} {api_func_name}({self.get_declare_args()});\n
|
||||
"""
|
||||
else:
|
||||
return f"""{indent}{self.get_return_type(inplace_flag=True)} {api_func_name}({self.get_declare_args(inplace_flag=True)});\n
|
||||
"""
|
||||
|
||||
def get_func_input_args(self, inplace_flag=False):
|
||||
input_args = []
|
||||
for name in self.inputs['names']:
|
||||
name = name.split('@')[0]
|
||||
input_args.append(name)
|
||||
return input_args
|
||||
|
||||
def get_func_args(self, inplace_flag=False):
|
||||
ad_func_args = self.get_func_input_args(inplace_flag)
|
||||
for name in self.attrs['names']:
|
||||
default_value = ''
|
||||
if self.attrs['attr_info'][name][1] is not None:
|
||||
default_value = ' = ' + self.attrs['attr_info'][name][1]
|
||||
ad_func_args.append(name)
|
||||
|
||||
ad_func_args_str = ", ".join(ad_func_args)
|
||||
return ad_func_args_str
|
||||
|
||||
def gene_eager_tensor_func_call(self):
|
||||
api_func_name = self.get_api_func_name()
|
||||
|
||||
dygraph_ad_func_name = '::' + api_func_name + '_ad_func'
|
||||
dygraph_ad_func_parameters = self.get_func_args()
|
||||
|
||||
return (
|
||||
f"""return {dygraph_ad_func_name}({dygraph_ad_func_parameters});"""
|
||||
)
|
||||
|
||||
def gene_eager_tensor_operants_implementation(self):
|
||||
api_func_name = self.get_api_func_name()
|
||||
# func declaration
|
||||
if api_func_name[-1] != '_':
|
||||
api_code = f"""{self.get_return_type()} EagerTensorOperants::{api_func_name}({self.get_declare_args_nodefault()}) {{"""
|
||||
else:
|
||||
api_code = f"""{self.get_return_type(inplace_flag=True)} EagerTensorOperants::{api_func_name}({self.get_declare_args_nodefault(inplace_flag=True)}) {{"""
|
||||
|
||||
# func code
|
||||
api_code += f"""
|
||||
{indent}{self.gene_eager_tensor_func_call()}\n}}\n
|
||||
"""
|
||||
return api_code
|
||||
|
||||
def gene_static_tensor_func_call(self):
|
||||
api_func_name = self.get_api_func_name()
|
||||
backend_static_func_name = (
|
||||
'paddle::primitive::backend::' + api_func_name + '<LazyTensor>'
|
||||
)
|
||||
prim_static_func_name = (
|
||||
'paddle::prim::' + api_func_name + '<DescTensor>'
|
||||
)
|
||||
static_func_parameters = self.get_func_args()
|
||||
|
||||
static_tensor_func_call = f"""if (FLAGS_enable_pir_api || FLAGS_enable_pir_in_executor) {{
|
||||
return {backend_static_func_name}({static_func_parameters});
|
||||
}} else {{
|
||||
return {prim_static_func_name}({static_func_parameters});
|
||||
}}"""
|
||||
|
||||
return static_tensor_func_call
|
||||
|
||||
def gene_static_tensor_operants_implementation(self):
|
||||
api_code = ""
|
||||
indent = " "
|
||||
api_func_name = self.get_api_func_name()
|
||||
# func declaration
|
||||
if api_func_name[-1] != '_':
|
||||
api_code = f"""{self.get_return_type()} StaticTensorOperants::{api_func_name}({self.get_declare_args_nodefault()}) {{"""
|
||||
else:
|
||||
api_code = f"""{self.get_return_type(inplace_flag=True)} StaticTensorOperants::{api_func_name}({self.get_declare_args_nodefault(inplace_flag=True)}) {{"""
|
||||
|
||||
function_call = self.gene_static_tensor_func_call()
|
||||
# func code
|
||||
api_code += f"""
|
||||
{indent}{function_call}\n}}\n
|
||||
"""
|
||||
|
||||
return api_code
|
||||
|
||||
|
||||
def generate_tensor_operants_api(
|
||||
api_yaml_path,
|
||||
eager_header_path,
|
||||
eager_source_path,
|
||||
static_header_path,
|
||||
static_source_path,
|
||||
api_prim_path,
|
||||
):
|
||||
apis = []
|
||||
|
||||
for each_api_yaml in api_yaml_path:
|
||||
with open(each_api_yaml, 'r') as f:
|
||||
api_list = yaml.load(f, Loader=yaml.FullLoader)
|
||||
if api_list:
|
||||
apis.extend(api_list)
|
||||
|
||||
eager_header_file = open(eager_header_path, 'w')
|
||||
eager_source_file = open(eager_source_path, 'w')
|
||||
static_header_file = open(static_header_path, 'w')
|
||||
static_source_file = open(static_source_path, 'w')
|
||||
|
||||
eager_header_file.write(eager_header_include)
|
||||
eager_header_file.write(eager_header_start)
|
||||
eager_source_file.write(eager_source_include)
|
||||
eager_source_file.write(eager_source_start)
|
||||
static_header_file.write(static_header_include)
|
||||
static_header_file.write(static_header_start)
|
||||
static_source_file.write(static_source_include)
|
||||
static_source_file.write(static_source_start)
|
||||
|
||||
with open(api_prim_path, 'rt') as f:
|
||||
api_prims = yaml.safe_load(f)
|
||||
|
||||
for api in apis:
|
||||
eager_api = PrimTensorAPI(api, api_prims)
|
||||
if eager_api.is_prim_api:
|
||||
eager_header_file.write(
|
||||
eager_api.gene_tensor_operants_declaration()
|
||||
)
|
||||
eager_source_file.write(
|
||||
eager_api.gene_eager_tensor_operants_implementation()
|
||||
)
|
||||
static_header_file.write(
|
||||
eager_api.gene_tensor_operants_declaration()
|
||||
)
|
||||
static_source_file.write(
|
||||
eager_api.gene_static_tensor_operants_implementation()
|
||||
)
|
||||
|
||||
eager_header_file.write(eager_header_end)
|
||||
eager_source_file.write(eager_source_end)
|
||||
static_header_file.write(static_header_end)
|
||||
static_source_file.write(static_source_end)
|
||||
|
||||
eager_header_file.close()
|
||||
eager_source_file.close()
|
||||
static_header_file.close()
|
||||
static_source_file.close()
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Generate PaddlePaddle C++ API files'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--api_yaml_path',
|
||||
help='path to api yaml file',
|
||||
nargs='+',
|
||||
default=['paddle/phi/ops/yaml/ops.yaml'],
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--eager_tensor_operants_header_path',
|
||||
help='output of generated eager_tensor_operants header code file',
|
||||
default='paddle/fluid/prim/utils/eager/eager_tensor_operants.h.tmp',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--eager_tensor_operants_source_path',
|
||||
help='output of generated eager_tensor_operants source code file',
|
||||
default='paddle/fluid/prim/utils/eager/eager_tensor_operants.cc.tmp',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--static_tensor_operants_header_path',
|
||||
help='output of generated eager_tensor_operants header code file',
|
||||
default='paddle/fluid/prim/utils/static/static_tensor_operants.h.tmp',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--static_tensor_operants_source_path',
|
||||
help='output of generated eager_tensor_operants source code file',
|
||||
default='paddle/fluid/prim/utils/static/static_tensor_operants.cc.tmp',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--api_prim_yaml_path',
|
||||
help='Primitive API list yaml file.',
|
||||
default='paddle/fluid/prim/api/auto_code_generated/api.yaml',
|
||||
)
|
||||
|
||||
options = parser.parse_args()
|
||||
|
||||
api_yaml_path = options.api_yaml_path
|
||||
api_prim_yaml_path = options.api_prim_yaml_path
|
||||
eager_tensor_operants_header_path = (
|
||||
options.eager_tensor_operants_header_path
|
||||
)
|
||||
eager_tensor_operants_source_path = (
|
||||
options.eager_tensor_operants_source_path
|
||||
)
|
||||
static_tensor_operants_header_path = (
|
||||
options.static_tensor_operants_header_path
|
||||
)
|
||||
static_tensor_operants_source_path = (
|
||||
options.static_tensor_operants_source_path
|
||||
)
|
||||
|
||||
generate_tensor_operants_api(
|
||||
api_yaml_path,
|
||||
eager_tensor_operants_header_path,
|
||||
eager_tensor_operants_source_path,
|
||||
static_tensor_operants_header_path,
|
||||
static_tensor_operants_source_path,
|
||||
api_prim_yaml_path,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user