diff --git a/paddle/fluid/framework/new_executor/pir_adaptor/pir_adaptor_util.h b/paddle/fluid/framework/new_executor/pir_adaptor/pir_adaptor_util.h index cd1ca07bbe23d3..6bac089335b8ee 100644 --- a/paddle/fluid/framework/new_executor/pir_adaptor/pir_adaptor_util.h +++ b/paddle/fluid/framework/new_executor/pir_adaptor/pir_adaptor_util.h @@ -213,9 +213,13 @@ void BuildPhiContext(pir::Operation* op, } else if (variable_array[i]->IsType()) { inputs.emplace_back(InType(const_cast( &(variable_array[i]->Get())))); + } else if (variable_array[i]->IsType()) { + inputs.emplace_back(InType(const_cast( + &(variable_array[i]->Get())))); } else { PADDLE_THROW(phi::errors::Unimplemented( - "Only support Vector and vector now, " + "Only support Vector and vector " + "and vector now " "not support vector<%d>.", variable_array[i]->Type())); } diff --git a/paddle/fluid/pir/dialect/operator/ir/manual_api.cc b/paddle/fluid/pir/dialect/operator/ir/manual_api.cc index 33fecafdbb0258..b4edb817521e06 100644 --- a/paddle/fluid/pir/dialect/operator/ir/manual_api.cc +++ b/paddle/fluid/pir/dialect/operator/ir/manual_api.cc @@ -133,6 +133,14 @@ pir::OpResult create_array(phi::DataType dtype) { return create_array_op.out(); } +pir::OpResult create_array_like(pir::Value input, float value) { + auto create_array_like_op = + ApiBuilder::Instance() + .GetBuilder() + ->Build(input, value); + return create_array_like_op.out(); +} + pir::OpResult array_length(pir::Value x) { auto array_length_op = ApiBuilder::Instance() .GetBuilder() @@ -165,6 +173,15 @@ std::tuple array_to_tensor(pir::Value x, return std::make_tuple(array_to_tensor.result(0), array_to_tensor.result(1)); } +pir::OpResult add_n_array(const std::vector& inputs) { + auto inputs_combine_op = + ApiBuilder::Instance().GetBuilder()->Build(inputs); + paddle::dialect::AddNArrayOp add_n_array_op = + ApiBuilder::Instance().GetBuilder()->Build( + inputs_combine_op.out()); + return add_n_array_op.result(0); +} + pir::OpResult slice_array_dense(pir::Value input, pir::Value starts) { auto op = ApiBuilder::Instance() .GetBuilder() diff --git a/paddle/fluid/pir/dialect/operator/ir/manual_api.h b/paddle/fluid/pir/dialect/operator/ir/manual_api.h index 347e10494696c0..587554ab2c3c81 100644 --- a/paddle/fluid/pir/dialect/operator/ir/manual_api.h +++ b/paddle/fluid/pir/dialect/operator/ir/manual_api.h @@ -62,6 +62,8 @@ pir::OpResult zeros(const std::vector& shape, pir::OpResult create_array(phi::DataType dtype); +pir::OpResult create_array_like(pir::Value input, float value); + pir::OpResult array_length(pir::Value x); pir::OpResult array_read(pir::Value array, pir::Value i); @@ -72,6 +74,8 @@ std::tuple array_to_tensor(pir::Value x, int axis, bool use_stack); +pir::OpResult add_n_array(const std::vector& inputs); + pir::OpResult slice_array_dense(pir::Value input, pir::Value starts); } // namespace dialect diff --git a/paddle/fluid/pir/dialect/operator/ir/manual_op.cc b/paddle/fluid/pir/dialect/operator/ir/manual_op.cc index 0a60b4c7d7d819..4c07132cfaa1f0 100644 --- a/paddle/fluid/pir/dialect/operator/ir/manual_op.cc +++ b/paddle/fluid/pir/dialect/operator/ir/manual_op.cc @@ -14,14 +14,16 @@ #ifdef GET_OP_LIST #undef GET_OP_LIST paddle::dialect::AddNOp, paddle::dialect::AddN_Op, - paddle::dialect::AddNWithKernelOp, paddle::dialect::FusedGemmEpilogueOp, + paddle::dialect::AddNWithKernelOp, paddle::dialect::AddNArrayOp, + paddle::dialect::FusedGemmEpilogueOp, paddle::dialect::FusedGemmEpilogueGradOp, paddle::dialect::SplitGradOp, paddle::dialect::ExpandOp, paddle::dialect::CreateArrayOp, - paddle::dialect::ArrayLengthOp, paddle::dialect::ArrayReadOp, - paddle::dialect::ArrayWrite_Op, paddle::dialect::SliceArrayOp, - paddle::dialect::SliceArrayDenseOp, paddle::dialect::AssignArray_Op, - paddle::dialect::ArrayToTensorOp, paddle::dialect::SelectInputOp, - paddle::dialect::IncrementOp, paddle::dialect::Increment_Op + paddle::dialect::CreateArrayLikeOp, paddle::dialect::ArrayLengthOp, + paddle::dialect::ArrayReadOp, paddle::dialect::ArrayWrite_Op, + paddle::dialect::SliceArrayOp, paddle::dialect::SliceArrayDenseOp, + paddle::dialect::AssignArray_Op, paddle::dialect::ArrayToTensorOp, + paddle::dialect::SelectInputOp, paddle::dialect::IncrementOp, + paddle::dialect::Increment_Op #else #include "paddle/fluid/pir/dialect/operator/ir/manual_op.h" @@ -421,6 +423,136 @@ void AddNWithKernelOp::InferMeta(phi::InferMetaContext *infer_meta) { fn(infer_meta); } +OpInfoTuple AddNArrayOp::GetOpInfo() { + std::vector inputs = { + OpInputInfo("inputs", + "pir::VectorType", + false, + false, + false, + true)}; + std::vector attributes = {}; + std::vector outputs = {OpOutputInfo( + "out", "paddle::dialect::DenseTensorArrayType", false, false)}; + paddle::dialect::OpRunTimeInfo run_time_info = + OpRunTimeInfo("AddNTensorArrayInferMeta", + {"inputs"}, + "add_n_array", + {"inputs"}, + {}, + {}, + {}, + {}); + + return std::make_tuple( + inputs, attributes, outputs, run_time_info, "add_n_array"); +} + +void AddNArrayOp::VerifySig() { + VLOG(4) << "Start Verifying inputs, outputs and attributes for: AddNArrayOp."; + VLOG(4) << "Verifying inputs:"; + { + auto input_size = num_operands(); + PADDLE_ENFORCE_EQ( + input_size, + 1u, + phi::errors::PreconditionNotMet( + "The size %d of inputs must be equal to 1.", input_size)); + if (auto vec_type = + (*this)->operand(0).type().dyn_cast()) { + for (size_t i = 0; i < vec_type.size(); ++i) { + PADDLE_ENFORCE(vec_type[i].isa(), + phi::errors::PreconditionNotMet( + "Type validation failed for the 0th input.")); + } + } else { + PADDLE_ENFORCE((*this) + ->operand(0) + .type() + .isa(), + phi::errors::PreconditionNotMet( + "Type validation failed for the 0th input.")); + } + } + VLOG(4) << "Verifying attributes:"; + { + // Attributes num is 0, not need to check attributes type. + } + VLOG(4) << "Verifying outputs:"; + { + auto output_size = num_results(); + PADDLE_ENFORCE_EQ( + output_size, + 1u, + phi::errors::PreconditionNotMet( + "The size %d of outputs must be equal to 1.", output_size)); + PADDLE_ENFORCE( + (*this)->result(0).type().isa(), + phi::errors::PreconditionNotMet( + "Type validation failed for the 0th output.")); + } + VLOG(4) << "End Verifying for: AddNArrayOp."; +} + +void AddNArrayOp::Build(pir::Builder &builder, // NOLINT + pir::OperationArgument &argument, // NOLINT + pir::Value inputs_) { + VLOG(4) << "Start build AddNArrayOp"; + + VLOG(4) << "Builder construction inputs"; + argument.AddInput(inputs_); + + VLOG(4) << "Builder construction attributes"; + + VLOG(4) << "Builder construction outputs"; + pir::VectorType inputs = inputs_.type().dyn_cast(); + + std::vector vec_dense_inputs; + for (size_t i = 0; i < inputs.size(); i++) { + vec_dense_inputs.push_back(paddle::dialect::IrTensor( + TransToPhiDataType( + inputs[i] + .dyn_cast() + .dtype()), + {}, + inputs[i] + .dyn_cast() + .data_layout(), + {})); + } + + std::vector vec_meta_inputs; + for (size_t i = 0; i < vec_dense_inputs.size(); i++) { + vec_meta_inputs.push_back( + paddle::dialect::IrMetaTensor(&vec_dense_inputs[i])); + } + + std::vector meta_inputs; + for (size_t i = 0; i < static_cast(vec_meta_inputs.size()); i++) { + meta_inputs.push_back(&vec_meta_inputs[i]); + } + + paddle::dialect::IrTensor dense_out; + paddle::dialect::IrMetaTensor meta_out(&dense_out); + + phi::AddNTensorArrayInferMeta( + meta_inputs, &meta_out, phi::MetaConfig(false, false)); + std::vector argument_outputs; + pir::Type out_dense_tensor_type = paddle::dialect::DenseTensorArrayType::get( + pir::IrContext::Instance(), + TransToIrDataType(dense_out.dtype()), + dense_out.layout()); + + argument_outputs.push_back(out_dense_tensor_type); + argument.AddOutputs(argument_outputs.begin(), argument_outputs.end()); + ::pir::PassStopGradientsDefaultly(argument); +} + +void AddNArrayOp::InferMeta(phi::InferMetaContext *infer_meta) { + auto fn = PD_INFER_META(phi::AddNTensorArrayInferMeta); + fn(infer_meta); +} + const char *FusedGemmEpilogueOp::attributes_name[3] = { "trans_x", "trans_y", "activation"}; @@ -1156,6 +1288,114 @@ void CreateArrayOp::InferMeta(phi::InferMetaContext *infer_meta) { fn(infer_meta); } +const char *CreateArrayLikeOp::attributes_name[1] = {"val"}; + +OpInfoTuple CreateArrayLikeOp::GetOpInfo() { + std::vector inputs = { + paddle::dialect::OpInputInfo("input", + "paddle::dialect::DenseTensorArrayType", + false, + false, + false, + false)}; + + std::vector attributes = { + paddle::dialect::OpAttributeInfo("val", "pir::FloatAttribute", "")}; + + std::vector outputs = {OpOutputInfo( + "out", "paddle::dialect::DenseTensorArrayType", false, false)}; + + paddle::dialect::OpRunTimeInfo run_time_info = + OpRunTimeInfo("CreateArrayLikeInferMeta", + {"input"}, + "create_array_like", + {"input", "val"}, + {}, + {}, + {}, + {}); + + return std::make_tuple( + inputs, attributes, outputs, run_time_info, "create_array_like"); +} + +void CreateArrayLikeOp::Build(pir::Builder &builder, // NOLINT + pir::OperationArgument &argument, // NOLINT + pir::Value &input_, // NOLINT + float &val) { + VLOG(4) << "Start build CreateArrayLikeOp"; + VLOG(4) << "Builder construction inputs"; + std::vector argument_inputs = {input_}; + argument.AddInputs(argument_inputs); + + VLOG(4) << "Builder construction attributes"; + pir::Attribute attr_val = + pir::FloatAttribute::get(pir::IrContext::Instance(), val); + argument.AddAttribute("val", attr_val); + VLOG(4) << "Builder construction outputs"; + paddle::dialect::DenseTensorArrayType input_type = + input_.type().dyn_cast(); + paddle::dialect::IrTensor dense_input( + paddle::dialect::TransToPhiDataType(input_type.dtype()), + {}, + input_type.data_layout(), + {}); + + paddle::dialect::IrMetaTensor meta_input(&dense_input); + + paddle::dialect::IrTensor dense_out; + paddle::dialect::IrMetaTensor meta_out(&dense_out); + + phi::CreateArrayLikeInferMeta(meta_input, &meta_out); + + std::vector argument_outputs; + pir::Type out_dense_tensor_type = paddle::dialect::DenseTensorArrayType::get( + pir::IrContext::Instance(), + paddle::dialect::TransToIrDataType(dense_out.dtype()), + dense_out.layout()); + argument_outputs.push_back(out_dense_tensor_type); + argument.AddOutputs(argument_outputs.begin(), argument_outputs.end()); + ::pir::PassStopGradientsDefaultly(argument); +} + +void CreateArrayLikeOp::VerifySig() { + VLOG(4) << "Start Verifying inputs, outputs and attributes for: " + "CreateArrayLikeOp."; + VLOG(4) << "Verifying inputs:"; + { + auto input_size = num_operands(); + PADDLE_ENFORCE_EQ( + input_size, + 1u, + phi::errors::PreconditionNotMet( + "The size %d of inputs must be equal to 1.", input_size)); + } + VLOG(4) << "Verifying attributes:"; + { + auto &attributes = this->attributes(); + PADDLE_ENFORCE(attributes.count("val") > 0, "val does not exist."); + } + VLOG(4) << "Verifying outputs:"; + { + auto output_size = num_results(); + PADDLE_ENFORCE_EQ( + output_size, + 1u, + phi::errors::PreconditionNotMet( + "The size %d of outputs must be equal to 1.", output_size)); + PADDLE_ENFORCE( + (*this)->result(0).type().isa(), + phi::errors::PreconditionNotMet( + "Type validation failed for the 0th output.")); + } + VLOG(4) << "End Verifying for: CreateArrayLikeOp."; +} + +void CreateArrayLikeOp::InferMeta(phi::InferMetaContext *infer_meta) { + auto fn = PD_INFER_META(phi::CreateArrayLikeInferMeta); + fn(infer_meta); +} + OpInfoTuple ArrayLengthOp::GetOpInfo() { std::vector inputs = { OpInputInfo("x", @@ -1319,6 +1559,7 @@ void ArrayReadOp::Build(pir::Builder &builder, dense_out.lod()); argument_outputs.push_back(out_type); argument.AddOutputs(argument_outputs.begin(), argument_outputs.end()); + ::pir::PassStopGradientsDefaultly(argument); } void ArrayReadOp::Build(pir::Builder &builder, @@ -2691,9 +2932,11 @@ IR_DEFINE_EXPLICIT_TYPE_ID(paddle::dialect::AddNOp) IR_DEFINE_EXPLICIT_TYPE_ID(paddle::dialect::SplitGradOp) IR_DEFINE_EXPLICIT_TYPE_ID(paddle::dialect::AddN_Op) IR_DEFINE_EXPLICIT_TYPE_ID(paddle::dialect::AddNWithKernelOp) +IR_DEFINE_EXPLICIT_TYPE_ID(paddle::dialect::AddNArrayOp) IR_DEFINE_EXPLICIT_TYPE_ID(paddle::dialect::FusedGemmEpilogueOp) IR_DEFINE_EXPLICIT_TYPE_ID(paddle::dialect::FusedGemmEpilogueGradOp) IR_DEFINE_EXPLICIT_TYPE_ID(paddle::dialect::CreateArrayOp) +IR_DEFINE_EXPLICIT_TYPE_ID(paddle::dialect::CreateArrayLikeOp) IR_DEFINE_EXPLICIT_TYPE_ID(paddle::dialect::ArrayLengthOp) IR_DEFINE_EXPLICIT_TYPE_ID(paddle::dialect::ArrayReadOp) IR_DEFINE_EXPLICIT_TYPE_ID(paddle::dialect::ArrayWrite_Op) diff --git a/paddle/fluid/pir/dialect/operator/ir/manual_op.h b/paddle/fluid/pir/dialect/operator/ir/manual_op.h index 121c95dee169aa..cbfadb24b97e6d 100644 --- a/paddle/fluid/pir/dialect/operator/ir/manual_op.h +++ b/paddle/fluid/pir/dialect/operator/ir/manual_op.h @@ -102,6 +102,26 @@ class AddNWithKernelOp : public pir::Op { + public: + using Op::Op; + static const char *name() { return "pd_op.add_n_array"; } + static constexpr const char **attributes_name = nullptr; + static constexpr uint32_t attributes_num = 0; + static OpInfoTuple GetOpInfo(); + static void Build(pir::Builder &builder, // NOLINT + pir::OperationArgument &argument, // NOLINT + pir::Value inputs_); + + void VerifySig(); + pir::Value inputs() { return operand_source(0); } + pir::OpResult out() { return result(0); } + + static void InferMeta(phi::InferMetaContext *infer_meta); +}; + class FusedGemmEpilogueOp : public pir::Op { + public: + using Op::Op; + static const char *name() { return "pd_op.create_array_like"; } + static constexpr uint32_t attributes_num = 1; + static const char *attributes_name[attributes_num]; + static OpInfoTuple GetOpInfo(); + static void Build(pir::Builder &builder, // NOLINT + pir::OperationArgument &argument, // NOLINT + pir::Value &input_, // NOLINT + float &val); // NOLINT + void VerifySig(); + pir::Value input() { return operand_source(0); } + pir::OpResult out() { return result(0); } + static void InferMeta(phi::InferMetaContext *infer_meta); +}; + class ArrayLengthOp : public pir::Op { public: @@ -522,9 +561,11 @@ IR_DECLARE_EXPLICIT_TYPE_ID(paddle::dialect::AddNOp) IR_DECLARE_EXPLICIT_TYPE_ID(paddle::dialect::SplitGradOp) IR_DECLARE_EXPLICIT_TYPE_ID(paddle::dialect::AddN_Op) IR_DECLARE_EXPLICIT_TYPE_ID(paddle::dialect::AddNWithKernelOp) +IR_DECLARE_EXPLICIT_TYPE_ID(paddle::dialect::AddNArrayOp) IR_DECLARE_EXPLICIT_TYPE_ID(paddle::dialect::FusedGemmEpilogueOp) IR_DECLARE_EXPLICIT_TYPE_ID(paddle::dialect::FusedGemmEpilogueGradOp) IR_DECLARE_EXPLICIT_TYPE_ID(paddle::dialect::CreateArrayOp) +IR_DECLARE_EXPLICIT_TYPE_ID(paddle::dialect::CreateArrayLikeOp) IR_DECLARE_EXPLICIT_TYPE_ID(paddle::dialect::ArrayLengthOp) IR_DECLARE_EXPLICIT_TYPE_ID(paddle::dialect::ArrayReadOp) IR_DECLARE_EXPLICIT_TYPE_ID(paddle::dialect::ArrayWrite_Op) diff --git a/paddle/fluid/pir/transforms/pd_op_to_kernel_pass.cc b/paddle/fluid/pir/transforms/pd_op_to_kernel_pass.cc index 165a1d3fde4fc7..10bc81ea6eac99 100644 --- a/paddle/fluid/pir/transforms/pd_op_to_kernel_pass.cc +++ b/paddle/fluid/pir/transforms/pd_op_to_kernel_pass.cc @@ -292,6 +292,9 @@ static std::vector> PrepareFakeTensors( } else if (inner_types[i].isa()) { res.push_back( fake_sr(inner_types[i].dyn_cast())); + } else if (inner_types[i].isa()) { + res.push_back(fake_tensor_array( + inner_types[i].dyn_cast())); } } } else if (in_type.isa()) { @@ -942,6 +945,7 @@ phi::KernelKey GetKernelKey( if (!combine_op_res) { continue; } + if (combine_op_res.owner()->isa()) { auto data_op = combine_op_res.owner(); auto data_place = @@ -1807,11 +1811,15 @@ std::vector BuildInputs( place = in_i_type.dyn_cast().place(); } else if (in_i_type.isa()) { place = in_i_type.dyn_cast().place(); + } else if (in_i_type.isa()) { + place = + in_i_type.dyn_cast().place(); } else { PADDLE_THROW(phi::errors::Unimplemented( "builtin.combine Input type only support " "VectorType and " - "VectorType")); + "VectorType and" + "VectorType")); } // get input args def type @@ -1844,11 +1852,19 @@ std::vector BuildInputs( pre_define_op->operand_source(j) .type() .dyn_cast()); + } else if (in_i_type.isa()) { + out_type = AllocatedDenseTensorArrayType::get( + ctx, + out_place, + pre_define_op->operand_source(j) + .type() + .dyn_cast()); } else { PADDLE_THROW(phi::errors::Unimplemented( "builtin.combine Input type only support " "VectorType and " - "VectorType")); + "VectorType and" + "VectorType")); } in_i = AddPlaceTransferOp( in_i, out_type, place, out_place, kernel_key, block); diff --git a/paddle/fluid/pybind/manual_static_op_function.h b/paddle/fluid/pybind/manual_static_op_function.h index dc09d539f39ffb..af733ecbce53f8 100644 --- a/paddle/fluid/pybind/manual_static_op_function.h +++ b/paddle/fluid/pybind/manual_static_op_function.h @@ -147,6 +147,31 @@ static PyObject *static_api_create_array(PyObject *self, } } +static PyObject *static_api_create_array_like(PyObject *self, + PyObject *args, + PyObject *kwargs) { + try { + VLOG(6) << "Add create_array_like op into program"; + VLOG(8) << "args count: " << (PyTuple_Size(args) / 2); + + // Get Value from args + PyObject *input_obj = PyTuple_GET_ITEM(args, 0); + auto input = CastPyArg2Value(input_obj, "create_array_like", 0); + + // Parse Attributes + PyObject *value_obj = PyTuple_GET_ITEM(args, 1); + float value = CastPyArg2Float(value_obj, "create_array_like", 1); + + // Call ir static api + auto static_api_out = paddle::dialect::create_array_like(input, value); + + return ToPyObject(static_api_out); + } catch (...) { + ThrowExceptionToPython(std::current_exception()); + return nullptr; + } +} + static PyObject *static_api_array_length(PyObject *self, PyObject *args, PyObject *kwargs) { @@ -274,6 +299,28 @@ static PyObject *static_api_array_to_tensor(PyObject *self, } } +PyObject *static_api_add_n_array(PyObject *self, + PyObject *args, + PyObject *kwargs) { + try { + VLOG(6) << "Add add_n_array op into program"; + VLOG(8) << "args count: " << (PyTuple_Size(args) / 2); + + // Get Value from args + PyObject *inputs_obj = PyTuple_GET_ITEM(args, 0); + auto inputs = CastPyArg2VectorOfValue(inputs_obj, "add_n", 0); + + // Parse Attributes + + // Call ir static api + auto static_api_out = paddle::dialect::add_n_array(inputs); + + return ToPyObject(static_api_out); + } catch (...) { + ThrowExceptionToPython(std::current_exception()); + return nullptr; + } +} static PyObject *static_api_slice_array_dense(PyObject *self, PyObject *args, PyObject *kwargs) { @@ -324,6 +371,10 @@ static PyMethodDef ManualOpsAPI[] = { (PyCFunction)(void (*)(void))static_api_create_array, METH_VARARGS | METH_KEYWORDS, "C++ interface function for create_array."}, + {"create_array_like", + (PyCFunction)(void (*)(void))static_api_create_array_like, + METH_VARARGS | METH_KEYWORDS, + "C++ interface function for create_array_like."}, {"array_length", (PyCFunction)(void (*)(void))static_api_array_length, METH_VARARGS | METH_KEYWORDS, @@ -340,6 +391,10 @@ static PyMethodDef ManualOpsAPI[] = { (PyCFunction)(void (*)(void))static_api_array_to_tensor, METH_VARARGS | METH_KEYWORDS, "C++ interface function for array_to_tensor."}, + {"add_n_array", + (PyCFunction)(void (*)(void))static_api_add_n_array, + METH_VARARGS | METH_KEYWORDS, + "C++ interface function for add_n_array."}, {"slice_array_dense", (PyCFunction)(void (*)(void))static_api_slice_array_dense, METH_VARARGS | METH_KEYWORDS, diff --git a/paddle/fluid/pybind/pir.cc b/paddle/fluid/pybind/pir.cc index 1c398cf7cdf975..a477f42e40c485 100644 --- a/paddle/fluid/pybind/pir.cc +++ b/paddle/fluid/pybind/pir.cc @@ -665,6 +665,14 @@ void BindValue(py::module *m) { "is persistable")); } }) + .def("is_tensorarray", + [](Value self) { + if (self.type().isa()) { + return true; + } else { + return false; + } + }) .def_property( "shape", [](Value self) { return phi::vectorize(GetValueDims(self)); }, diff --git a/paddle/phi/infermeta/multiary.cc b/paddle/phi/infermeta/multiary.cc index 6250b3a3b23c81..5b9708b38a17e1 100644 --- a/paddle/phi/infermeta/multiary.cc +++ b/paddle/phi/infermeta/multiary.cc @@ -464,22 +464,19 @@ void AddNInferMeta(const std::vector& x, void AddNTensorArrayInferMeta(const std::vector& x, MetaTensor* out, MetaConfig config) { - int64_t max_length = 0; bool has_tensor_array = false; for (auto input : x) { if (input->is_tensor_array()) { + if (out->is_tensor_array()) { + out->set_dtype(input->dtype()); + out->set_layout(input->layout()); + } has_tensor_array = true; - // if input is lod_tensor_array, dims() will return its size (one element) - max_length = - input->dims()[0] > max_length ? input->dims()[0] : max_length; + break; } } - if (has_tensor_array) { - if (out->is_tensor_array()) { - out->set_dims(common::make_ddim({max_length})); - } - } else { + if (!has_tensor_array) { AddNInferMeta(x, out, config); } } diff --git a/paddle/phi/infermeta/unary.cc b/paddle/phi/infermeta/unary.cc index a75cd4170e2785..b1b06fdbfed715 100644 --- a/paddle/phi/infermeta/unary.cc +++ b/paddle/phi/infermeta/unary.cc @@ -524,6 +524,11 @@ void CreateLikeInferMeta(const MetaTensor& x, DataType dtype, MetaTensor* out) { out->set_layout(x.layout()); } +void CreateArrayLikeInferMeta(const MetaTensor& x, MetaTensor* out) { + out->set_dtype(x.dtype()); + out->set_layout(x.layout()); +} + void CumInferMeta(const MetaTensor& x, int axis, bool flatten, diff --git a/paddle/phi/infermeta/unary.h b/paddle/phi/infermeta/unary.h index eae4614a8eb5c9..0126b76754fef2 100644 --- a/paddle/phi/infermeta/unary.h +++ b/paddle/phi/infermeta/unary.h @@ -124,6 +124,8 @@ void CIdentityInferMeta(const MetaTensor& x, void CreateLikeInferMeta(const MetaTensor& x, DataType dtype, MetaTensor* out); +void CreateArrayLikeInferMeta(const MetaTensor& x, MetaTensor* out); + void CropInferMeta(const MetaTensor& x, const IntArray& shape, const IntArray& offsets, diff --git a/paddle/phi/kernels/array_kernel.cc b/paddle/phi/kernels/array_kernel.cc index 8a599dcf9d80d8..9f794be3f42721 100644 --- a/paddle/phi/kernels/array_kernel.cc +++ b/paddle/phi/kernels/array_kernel.cc @@ -27,6 +27,20 @@ void CreateArrayKernel(const Context& dev_ctx, DataType dtype, TensorArray* out) {} +template +void CreateArrayLikeKernel(const Context& dev_ctx, + const TensorArray& input, + float val, + TensorArray* out) { + out->resize(input.size()); + for (size_t i = 0; i < input.size(); i++) { + DenseTensor input_i = input[i]; + out->at(i).Resize(input_i.dims()); + FullLikeKernel( + dev_ctx, input_i, val, input_i.dtype(), &out->at(i)); + } +} + template void ArrayLengthKernel(const Context& dev_ctx, const TensorArray& x, @@ -150,6 +164,36 @@ PD_REGISTER_KERNEL(create_array, phi::dtype::complex) {} #endif +PD_REGISTER_KERNEL(create_array_like, + CPU, + ALL_LAYOUT, + phi::CreateArrayLikeKernel, + bool, + int, + int64_t, + float, + double, + phi::dtype::float16, + phi::dtype::bfloat16, + phi::dtype::complex, + phi::dtype::complex) {} + +#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP) +PD_REGISTER_KERNEL(create_array_like, + GPU, + ALL_LAYOUT, + phi::CreateArrayLikeKernel, + bool, + int, + int64_t, + float, + double, + phi::dtype::float16, + phi::dtype::bfloat16, + phi::dtype::complex, + phi::dtype::complex) {} +#endif + PD_REGISTER_KERNEL(array_length, CPU, ALL_LAYOUT, diff --git a/paddle/phi/kernels/array_kernel.h b/paddle/phi/kernels/array_kernel.h index 0c8436501371da..d41fc36d1057f6 100644 --- a/paddle/phi/kernels/array_kernel.h +++ b/paddle/phi/kernels/array_kernel.h @@ -25,6 +25,12 @@ void CreateArrayKernel(const Context& dev_ctx, DataType dtype, TensorArray* out); +template +void CreateArrayLikeKernel(const Context& dev_ctx, + const TensorArray& input, + float val, + TensorArray* out); + template void ArrayLengthKernel(const Context& dev_ctx, const TensorArray& x, diff --git a/test/legacy_test/test_array_read_write_op.py b/test/legacy_test/test_array_read_write_op.py index 5125ec16cf70d5..dbdcb7707c3939 100644 --- a/test/legacy_test/test_array_read_write_op.py +++ b/test/legacy_test/test_array_read_write_op.py @@ -242,6 +242,49 @@ def test_array_backward(self): np.testing.assert_allclose(res[0], mean, rtol=1e-05) np.testing.assert_allclose(res[1], x_grad, rtol=1e-05) + def test_create_array_like_add_n(self): + paddle.enable_static() + np.random.seed(2013) + with paddle.pir_utils.IrGuard(): + main_program = paddle.static.Program() + startup_program = paddle.static.Program() + with paddle.static.program_guard(main_program, startup_program): + d0 = paddle.static.data(name='d0', shape=[10], dtype='float32') + d1 = paddle.static.data(name='d1', shape=[10], dtype='float32') + i = paddle.zeros(shape=[1], dtype='int64') + mem_array = paddle.tensor.array_write(x=d0, i=i) + i = paddle.increment(i) + paddle.tensor.array_write(x=d1, i=i, array=mem_array) + copy_array = paddle._pir_ops.create_array_like(mem_array, 0.0) + out = paddle.tensor.array_read(array=copy_array, i=i) + + paddle.tensor.array_write(x=d0, i=i, array=copy_array) + i = paddle.increment(i, -1) + paddle.tensor.array_write(x=d1, i=i, array=copy_array) + + add_array = paddle._pir_ops.add_n_array([mem_array, copy_array]) + out_1 = paddle.tensor.array_read(array=add_array, i=i) + i = paddle.increment(i, 1) + out_2 = paddle.tensor.array_read(array=add_array, i=i) + + place = ( + base.CUDAPlace(0) + if core.is_compiled_with_cuda() + else base.CPUPlace() + ) + d0 = np.random.random(size=[10]).astype('float32') + d1 = np.random.random(size=[10]).astype('float32') + exe = base.Executor(place) + res = exe.run( + main_program, + feed={'d0': d0, 'd1': d1}, + fetch_list=[out, out_1, out_2], + ) + out = [0.0] * 10 + np.testing.assert_allclose(res[0], out, rtol=1e-05) + np.testing.assert_allclose(res[1], d0 + d1, rtol=1e-05) + np.testing.assert_allclose(res[2], d0 + d1, rtol=1e-05) + if __name__ == '__main__': unittest.main() diff --git a/test/legacy_test/test_while_loop_op.py b/test/legacy_test/test_while_loop_op.py index 83fecc6b5ad7f5..44ee6383fa6abc 100644 --- a/test/legacy_test/test_while_loop_op.py +++ b/test/legacy_test/test_while_loop_op.py @@ -353,7 +353,6 @@ def body(i, x): fetch_list = [out[1]] for p, g in grad_list: fetch_list.append(g) - res = exe.run( main_program, feed={'i': feed_i, 'x': feed_x}, @@ -409,10 +408,14 @@ def internal_body(j, x, mem_array): d1 = paddle.static.data(name='d1', shape=[10], dtype='float32') d2 = paddle.static.data(name='d2', shape=[10], dtype='float32') x = paddle.static.data(name='x', shape=[10], dtype='float32') + d0.persistable = True + d1.persistable = True + d2.persistable = True x.stop_gradient = False x.persistable = True i = paddle.zeros(shape=[1], dtype='int64') i.stop_gradient = True + i.persistable = True init = paddle.zeros(shape=[10], dtype='float32') mem_array = paddle.tensor.array_write(x=init, i=i) data_array = paddle.tensor.array_write(x=d0, i=i) @@ -440,6 +443,7 @@ def internal_body(j, x, mem_array): sum_result = paddle.tensor.array_read(array=out[3], i=j) mean = paddle.mean(sum_result) grad_list = append_backward(mean) + place = ( base.CUDAPlace(0) if core.is_compiled_with_cuda()