diff --git a/.gitignore b/.gitignore index ffb44db5f7181..eef92a0488cd2 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ paddle/phi/api/lib/operants_manager.cc paddle/phi/api/lib/sparse_api.cc paddle/phi/api/lib/strings_api.cc paddle/phi/api/lib/sparse_bw_api.cc +paddle/phi/api/lib/tensor_api.cc paddle/phi/api/lib/tensor_operants.cc paddle/phi/extension.h paddle/phi/include/* diff --git a/paddle/phi/api/include/tensor.h b/paddle/phi/api/include/tensor.h index 4924ff3f1a2a3..0cef41d5259a0 100644 --- a/paddle/phi/api/include/tensor.h +++ b/paddle/phi/api/include/tensor.h @@ -645,6 +645,13 @@ class PADDLE_API Tensor final { * in the development of new dygraph. It may be removed in the future. */ std::string name_{""}; + + // Tensor C++ APIs + // Example: Tensor add(const Tensor& other) const; + Tensor add(const Tensor& y) const; + Tensor divide(const Tensor& y) const; + Tensor multiply(const Tensor& y) const; + Tensor subtract(const Tensor& y) const; }; } // namespace experimental diff --git a/paddle/phi/api/lib/CMakeLists.txt b/paddle/phi/api/lib/CMakeLists.txt index 2212b7e51e443..1fb9c147ffec4 100644 --- a/paddle/phi/api/lib/CMakeLists.txt +++ b/paddle/phi/api/lib/CMakeLists.txt @@ -102,6 +102,7 @@ set(tensor_gen_file ${CMAKE_SOURCE_DIR}/paddle/phi/api/yaml/generator/tensor_gen.py) set(operants_base_file ${CMAKE_SOURCE_DIR}/paddle/phi/api/include/operants_base.h) +set(tensor_api_source_file ${CMAKE_SOURCE_DIR}/paddle/phi/api/lib/tensor_api.cc) set(phi_tensor_operants_header_file ${CMAKE_SOURCE_DIR}/paddle/phi/api/include/tensor_operants.h) set(phi_tensor_operants_source_file @@ -111,6 +112,7 @@ set(operants_manager_header_file set(operants_manager_source_file ${CMAKE_SOURCE_DIR}/paddle/phi/api/lib/operants_manager.cc) set(operants_base_file_tmp ${operants_base_file}.tmp) +set(tensor_api_source_file_tmp ${tensor_api_source_file}.tmp) set(phi_tensor_operants_header_file_tmp ${phi_tensor_operants_header_file}.tmp) set(phi_tensor_operants_source_file_tmp ${phi_tensor_operants_source_file}.tmp) set(operants_manager_header_file_tmp ${operants_manager_header_file}.tmp) @@ -235,35 +237,43 @@ add_custom_command( VERBATIM) # generate tensor and tensor operants file -add_custom_command( - OUTPUT ${operants_base_file} ${phi_tensor_operants_header_file} - ${phi_tensor_operants_source_file} ${operants_manager_header_file} - ${operants_manager_source_file} - COMMAND ${PYTHON_EXECUTABLE} -m pip install pyyaml +message("create or copy auto-geneated tensor files") +execute_process(COMMAND ${PYTHON_EXECUTABLE} -m pip install pyyaml) +execute_process( + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/paddle/phi/api/yaml/generator COMMAND ${PYTHON_EXECUTABLE} ${tensor_gen_file} --api_yaml_path ${api_yaml_file} ${legacy_api_yaml_file} --operants_base_path ${operants_base_file_tmp} + --tensor_api_source_path ${tensor_api_source_file_tmp} --phi_tensor_operants_header_path ${phi_tensor_operants_header_file_tmp} --phi_tensor_operants_source_path ${phi_tensor_operants_source_file_tmp} --operants_manager_header_path ${operants_manager_header_file_tmp} --operants_manager_source_path ${operants_manager_source_file_tmp} - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${operants_base_file_tmp} - ${operants_base_file} - COMMAND - ${CMAKE_COMMAND} -E copy_if_different ${phi_tensor_operants_header_file_tmp} - ${phi_tensor_operants_header_file} - COMMAND - ${CMAKE_COMMAND} -E copy_if_different ${phi_tensor_operants_source_file_tmp} - ${phi_tensor_operants_source_file} - COMMAND ${CMAKE_COMMAND} -E copy_if_different - ${operants_manager_header_file_tmp} ${operants_manager_header_file} - COMMAND ${CMAKE_COMMAND} -E copy_if_different - ${operants_manager_source_file_tmp} ${operants_manager_source_file} - COMMENT - "copy_if_different ${phi_tensor_operants_header_file} ${phi_tensor_operants_source_file}" - DEPENDS ${api_yaml_file} ${legacy_api_yaml_file} ${tensor_gen_file} - ${api_gen_base} ${api_gen_file} - VERBATIM) + RESULT_VARIABLE _result) +if(${_result}) + message(FATAL_ERROR "tensor codegen failed, exiting.") +endif() + +set(generated_tensor_files + "${operants_base_file}" "${tensor_api_source_file}" + "${phi_tensor_operants_header_file}" "${phi_tensor_operants_source_file}" + "${operants_manager_header_file}" "${operants_manager_source_file}") + +foreach(generated_tensor_file ${generated_tensor_files}) + if(EXISTS "${generated_tensor_file}.tmp" AND EXISTS + "${generated_tensor_file}") + execute_process( + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${generated_tensor_file}.tmp" "${generated_tensor_file}") + message( + "copy if different ${generated_tensor_file}.tmp ${generated_tensor_file}") + elseif(EXISTS "${generated_tensor_file}.tmp") + execute_process( + COMMAND ${CMAKE_COMMAND} -E copy "${generated_tensor_file}.tmp" + "${generated_tensor_file}") + message("copy ${generated_tensor_file}.tmp ${generated_tensor_file}") + endif() +endforeach() cc_library( op_meta_info @@ -388,5 +398,5 @@ cc_library( DEPS phi_enforce) cc_library( tensor_api - SRCS tensor_api.cc + SRCS ${tensor_api_source_file} DEPS operants_manager) diff --git a/paddle/phi/api/lib/tensor_api.cc b/paddle/phi/api/lib/tensor_api.cc deleted file mode 100644 index c063730155e8a..0000000000000 --- a/paddle/phi/api/lib/tensor_api.cc +++ /dev/null @@ -1,43 +0,0 @@ -/* 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. */ - -#include "paddle/phi/api/include/tensor.h" - -#include "paddle/phi/api/include/operants_manager.h" - -namespace paddle { -namespace experimental { - -Tensor Tensor::operator+(const Tensor &other) const { - return paddle::OperantsManager::Instance().add( - static_cast(*this), other); -} - -Tensor Tensor::operator-(const Tensor &other) const { - return paddle::OperantsManager::Instance().subtract( - static_cast(*this), other); -} - -Tensor Tensor::operator*(const Tensor &other) const { - return paddle::OperantsManager::Instance().multiply( - static_cast(*this), other); -} - -Tensor Tensor::operator/(const Tensor &other) const { - return paddle::OperantsManager::Instance().divide( - static_cast(*this), other); -} - -} // namespace experimental -} // namespace paddle diff --git a/paddle/phi/api/yaml/generator/tensor_gen.py b/paddle/phi/api/yaml/generator/tensor_gen.py index f894713ceb7a4..19f1919edbb33 100644 --- a/paddle/phi/api/yaml/generator/tensor_gen.py +++ b/paddle/phi/api/yaml/generator/tensor_gen.py @@ -58,6 +58,43 @@ class TensorOperantsBase { """ +tensor_api_source_include = """// Generated by paddle/phi/api/yaml/generator/tensor_gen.py + +#include "paddle/phi/api/include/tensor.h" + +#include "paddle/phi/api/include/operants_manager.h" + +""" + +tensor_api_source_start = """ +namespace paddle { + +namespace experimental { + +Tensor Tensor::operator+(const Tensor &other) const { + return add(other); +} + +Tensor Tensor::operator-(const Tensor &other) const { + return subtract(other); +} + +Tensor Tensor::operator*(const Tensor &other) const { + return multiply(other); +} + +Tensor Tensor::operator/(const Tensor &other) const { + return divide(other); +} +""" + + +tensor_api_source_end = """ +} // namespace experimental +} // namespace paddle + +""" + operants_header_include = """// Generated by paddle/phi/api/yaml/generator/tensor_gen.py @@ -231,6 +268,40 @@ def gene_operants_base(self): else: return f""" {indent}virtual {self.get_return_type(inplace_flag=True)} {api_func_name}({self.get_declare_args(inplace_flag=True)}) = 0; +""" + + def get_define_args_without_first_tensor(self, inplace_flag=False): + # NOTE(HongyuJia): consider vector becomes first input argument. + define_args = self.get_input_tensor_args(inplace_flag) + assert ( + len(define_args) > 1 + ), "Can't use tensor api without Tensor inputs" + for name in self.attrs['names']: + define_args.append(self.attrs['attr_info'][name][0] + ' ' + name) + # remove first Tensor argument + return ", ".join(define_args[1:]) + + def gene_tensor_api_implementation(self): + func_name = self.get_api_func_name() + assert ( + len(self.inputs['names']) > 1 + ), "Can't use tensor api without Tensor inputs" + # remove first Tensor argument + func_args = self.inputs['names'][1:] + self.attrs['names'] + func_args_code = ", ".join(func_args) + # func decalaration + if func_name[-1] != '_': + return f""" +{self.get_return_type()} Tensor::{func_name}({self.get_define_args_without_first_tensor()}) const {{ +{indent}return paddle::OperantsManager::Instance().{func_name}(static_cast(*this), {func_args_code}); +}} +""" + else: + return f""" +{self.get_return_type(inplace_flag=True)} Tensor::{func_name}({self.get_define_args_without_first_tensor(inplace_flag=True)}) const {{ +{indent}return paddle::OperantsManager::Instance().{func_name}(static_cast(*this), {func_args_code}); +}} + """ def gene_operants_declaration(self): @@ -318,6 +389,7 @@ def gene_operants_manager_implementation(self): def generate_tensor_operants_api( api_yaml_path, operants_base_path, + tensor_api_source_path, operants_header_path, operants_source_path, operants_manager_header_path, @@ -332,6 +404,7 @@ def generate_tensor_operants_api( apis.extend(api_list) operants_base_file = open(operants_base_path, 'w') + tensor_api_source_file = open(tensor_api_source_path, 'w') operants_header_file = open(operants_header_path, 'w') operants_source_file = open(operants_source_path, 'w') operants_manager_header_file = open(operants_manager_header_path, 'w') @@ -339,6 +412,8 @@ def generate_tensor_operants_api( operants_base_file.write(operants_base_include) operants_base_file.write(operants_base_start) + tensor_api_source_file.write(tensor_api_source_include) + tensor_api_source_file.write(tensor_api_source_start) operants_header_file.write(operants_header_include) operants_header_file.write(operants_header_start) operants_source_file.write(operants_source_include) @@ -355,6 +430,9 @@ def generate_tensor_operants_api( operants_api = OperantsAPI(api, api_prims) if operants_api.is_prim_api: operants_base_file.write(operants_api.gene_operants_base()) + tensor_api_source_file.write( + operants_api.gene_tensor_api_implementation() + ) operants_header_file.write(operants_api.gene_operants_declaration()) operants_source_file.write( operants_api.gene_operants_implementation() @@ -367,12 +445,14 @@ def generate_tensor_operants_api( ) operants_base_file.write(operants_base_end) + tensor_api_source_file.write(tensor_api_source_end) operants_header_file.write(operants_header_end) operants_source_file.write(operants_source_end) operants_manager_header_file.write(operants_manager_header_end) operants_manager_source_file.write(operants_manager_source_end) operants_base_file.close() + tensor_api_source_file.close() operants_header_file.close() operants_source_file.close() operants_manager_header_file.close() @@ -396,6 +476,12 @@ def main(): default='paddle/phi/api/include/operants_base.h', ) + parser.add_argument( + '--tensor_api_source_path', + help='output of generated tensor_api source code file', + default='paddle/phi/api/lib/tensor_api.cc', + ) + parser.add_argument( '--phi_tensor_operants_header_path', help='output of generated phi_tensor_operants header code file', @@ -424,6 +510,7 @@ def main(): api_yaml_path = options.api_yaml_path operants_base_path = options.operants_base_path + tensor_api_source_path = options.tensor_api_source_path operants_header_path = options.phi_tensor_operants_header_path operants_source_path = options.phi_tensor_operants_source_path operants_manager_header_path = options.operants_manager_header_path @@ -432,6 +519,7 @@ def main(): generate_tensor_operants_api( api_yaml_path, operants_base_path, + tensor_api_source_path, operants_header_path, operants_source_path, operants_manager_header_path,