未验证 提交 68f99b78 编写于 作者: Y YuanRisheng 提交者: GitHub

[PHI]Add TensorArray for PHI (#45479)

* add tensor array

* fix ci bugs

* fix ci bugs

* fix ci bugs

* fix ci bugs

* update by comment

* update code
上级 3f3f923b
...@@ -190,7 +190,7 @@ cc_test( ...@@ -190,7 +190,7 @@ cc_test(
cc_library( cc_library(
var_type_traits var_type_traits
SRCS var_type_traits.cc SRCS var_type_traits.cc
DEPS framework_proto scope) DEPS framework_proto scope tensor_array)
if(WITH_GPU) if(WITH_GPU)
target_link_libraries(var_type_traits dynload_cuda) target_link_libraries(var_type_traits dynload_cuda)
endif() endif()
......
...@@ -13,14 +13,14 @@ See the License for the specific language governing permissions and ...@@ -13,14 +13,14 @@ See the License for the specific language governing permissions and
limitations under the License. */ limitations under the License. */
#pragma once #pragma once
#include <vector>
#include "paddle/fluid/framework/lod_tensor.h" #include "paddle/fluid/framework/lod_tensor.h"
#include "paddle/phi/core/tensor_array.h"
namespace paddle { namespace paddle {
namespace framework { namespace framework {
using LoDTensorArray = std::vector<LoDTensor>; using LoDTensorArray = phi::TensorArray;
} // namespace framework } // namespace framework
} // namespace paddle } // namespace paddle
...@@ -2665,13 +2665,8 @@ void OperatorWithKernel::BuildPhiKernelContext( ...@@ -2665,13 +2665,8 @@ void OperatorWithKernel::BuildPhiKernelContext(
phi_kernel_context->EmplaceBackInputWithoutSetRange(tensor_in); phi_kernel_context->EmplaceBackInputWithoutSetRange(tensor_in);
} else if (var->IsType<framework::LoDTensorArray>()) { } else if (var->IsType<framework::LoDTensorArray>()) {
need_prepare_phi_data_ = true; need_prepare_phi_data_ = true;
paddle::small_vector<const phi::TensorBase*> tensor_vector; tensor_in = &(var->Get<framework::LoDTensorArray>());
auto& tensor_array = var->Get<framework::LoDTensorArray>(); phi_kernel_context->EmplaceBackInputWithoutSetRange(tensor_in);
for (auto& t : tensor_array) {
tensor_vector.emplace_back(&t);
}
phi_kernel_context->EmplaceBackInputsWithoutSetRange(tensor_vector);
end_idx += tensor_array.size() - 1;
} else { } else {
PADDLE_THROW(platform::errors::Unimplemented( PADDLE_THROW(platform::errors::Unimplemented(
"Unsupported input `%s` type when call pt kernel.", "Unsupported input `%s` type when call pt kernel.",
...@@ -2714,16 +2709,10 @@ void OperatorWithKernel::BuildPhiKernelContext( ...@@ -2714,16 +2709,10 @@ void OperatorWithKernel::BuildPhiKernelContext(
tensor_out = var->template GetMutable<phi::SelectedRows>(); tensor_out = var->template GetMutable<phi::SelectedRows>();
phi_kernel_context->EmplaceBackOutputWithoutSetRange(tensor_out); phi_kernel_context->EmplaceBackOutputWithoutSetRange(tensor_out);
} else if (var->template IsType<framework::LoDTensorArray>()) { } else if (var->template IsType<framework::LoDTensorArray>()) {
paddle::small_vector<phi::TensorBase*> tensor_vector; tensor_out = var->template GetMutable<framework::LoDTensorArray>();
auto* tensor_array =
var->template GetMutable<framework::LoDTensorArray>();
// Note: If the input LoDTensorArray size is 0, the output // Note: If the input LoDTensorArray size is 0, the output
// LoDTensorArray is also 0 // LoDTensorArray is also 0
for (auto& t : *tensor_array) { phi_kernel_context->EmplaceBackOutputWithoutSetRange(tensor_out);
tensor_vector.emplace_back(&t);
}
phi_kernel_context->EmplaceBackOutputsWithoutSetRange(tensor_vector);
end_idx += tensor_array->size() - 1;
} else { } else {
PADDLE_THROW(platform::errors::Unimplemented( PADDLE_THROW(platform::errors::Unimplemented(
"Unsupported output `%s` type when call pt kernel.", "Unsupported output `%s` type when call pt kernel.",
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
namespace paddle { namespace paddle {
namespace framework { namespace framework {
void ReaderBase::ReadNext(std::vector<LoDTensor> *out) { void ReaderBase::ReadNext(paddle::framework::LoDTensorArray *out) {
std::lock_guard<std::mutex> lock(mu_); std::lock_guard<std::mutex> lock(mu_);
PADDLE_ENFORCE_EQ(status_, PADDLE_ENFORCE_EQ(status_,
ReaderStatus::kRunning, ReaderStatus::kRunning,
......
...@@ -48,7 +48,7 @@ class ReaderBase { ...@@ -48,7 +48,7 @@ class ReaderBase {
"and need_check_feed")); "and need_check_feed"));
} }
virtual void ReadNext(std::vector<LoDTensor>* out); virtual void ReadNext(paddle::framework::LoDTensorArray* out);
virtual void Shutdown(); virtual void Shutdown();
...@@ -73,7 +73,7 @@ class ReaderBase { ...@@ -73,7 +73,7 @@ class ReaderBase {
virtual ~ReaderBase(); virtual ~ReaderBase();
protected: protected:
virtual void ReadNextImpl(std::vector<LoDTensor>* out) {} virtual void ReadNextImpl(paddle::framework::LoDTensorArray* out) {}
virtual void ShutdownImpl() {} virtual void ShutdownImpl() {}
...@@ -167,7 +167,7 @@ class ReaderHolder { ...@@ -167,7 +167,7 @@ class ReaderHolder {
const std::shared_ptr<ReaderBase>& Get() const { return reader_; } const std::shared_ptr<ReaderBase>& Get() const { return reader_; }
void ReadNext(std::vector<LoDTensor>* out) { void ReadNext(paddle::framework::LoDTensorArray* out) {
PADDLE_ENFORCE_NOT_NULL( PADDLE_ENFORCE_NOT_NULL(
reader_, reader_,
platform::errors::InvalidArgument( platform::errors::InvalidArgument(
......
...@@ -24,7 +24,7 @@ class StubDecoratedReader : public paddle::framework::DecoratedReader { ...@@ -24,7 +24,7 @@ class StubDecoratedReader : public paddle::framework::DecoratedReader {
explicit StubDecoratedReader(const std::shared_ptr<ReaderBase> &reader) explicit StubDecoratedReader(const std::shared_ptr<ReaderBase> &reader)
: DecoratedReader(reader) {} : DecoratedReader(reader) {}
void ReadNextImpl(std::vector<paddle::framework::LoDTensor> *out) override {} void ReadNextImpl(paddle::framework::LoDTensorArray *out) override {}
}; };
class StubRootReader : public paddle::framework::ReaderBase { class StubRootReader : public paddle::framework::ReaderBase {
...@@ -34,7 +34,7 @@ class StubRootReader : public paddle::framework::ReaderBase { ...@@ -34,7 +34,7 @@ class StubRootReader : public paddle::framework::ReaderBase {
const std::vector<paddle::framework::proto::VarType::Type> &var_types, const std::vector<paddle::framework::proto::VarType::Type> &var_types,
const std::vector<bool> &need_check_feed) const std::vector<bool> &need_check_feed)
: paddle::framework::ReaderBase(dims, var_types, need_check_feed) {} : paddle::framework::ReaderBase(dims, var_types, need_check_feed) {}
void ReadNextImpl(std::vector<paddle::framework::LoDTensor> *out) override {} void ReadNextImpl(paddle::framework::LoDTensorArray *out) override {}
}; };
TEST(READER, decorate_chain) { TEST(READER, decorate_chain) {
......
...@@ -330,13 +330,8 @@ void BuildDygraphPhiKernelContext(const phi::KernelSignature& kernel_signature, ...@@ -330,13 +330,8 @@ void BuildDygraphPhiKernelContext(const phi::KernelSignature& kernel_signature,
tensor_in = &(var.template Get<phi::SelectedRows>()); tensor_in = &(var.template Get<phi::SelectedRows>());
kernel_ctx->EmplaceBackInputWithoutSetRange(tensor_in); kernel_ctx->EmplaceBackInputWithoutSetRange(tensor_in);
} else if (var.template IsType<framework::LoDTensorArray>()) { } else if (var.template IsType<framework::LoDTensorArray>()) {
paddle::small_vector<const phi::TensorBase*> tensor_vector; tensor_in = &(var.template Get<framework::LoDTensorArray>());
auto& tensor_array = var.template Get<framework::LoDTensorArray>(); kernel_ctx->EmplaceBackInputWithoutSetRange(tensor_in);
for (auto& t : tensor_array) {
tensor_vector.emplace_back(&t);
}
kernel_ctx->EmplaceBackInputsWithoutSetRange(tensor_vector);
end_idx += tensor_array.size() - 1;
} else { } else {
PADDLE_THROW(platform::errors::Unimplemented( PADDLE_THROW(platform::errors::Unimplemented(
"Unsupported input `%s` type when call pt kernel.", "Unsupported input `%s` type when call pt kernel.",
...@@ -377,14 +372,8 @@ void BuildDygraphPhiKernelContext(const phi::KernelSignature& kernel_signature, ...@@ -377,14 +372,8 @@ void BuildDygraphPhiKernelContext(const phi::KernelSignature& kernel_signature,
tensor_out = var->template GetMutable<phi::SelectedRows>(); tensor_out = var->template GetMutable<phi::SelectedRows>();
kernel_ctx->EmplaceBackOutputWithoutSetRange(tensor_out); kernel_ctx->EmplaceBackOutputWithoutSetRange(tensor_out);
} else if (var->template IsType<framework::LoDTensorArray>()) { } else if (var->template IsType<framework::LoDTensorArray>()) {
paddle::small_vector<phi::TensorBase*> tensor_vector; tensor_out = var->template GetMutable<framework::LoDTensorArray>();
auto* tensor_array = kernel_ctx->EmplaceBackOutputWithoutSetRange(tensor_out);
var->template GetMutable<framework::LoDTensorArray>();
for (auto& t : *tensor_array) {
tensor_vector.emplace_back(&t);
}
kernel_ctx->EmplaceBackOutputsWithoutSetRange(tensor_vector);
end_idx += tensor_array->size() - 1;
} else { } else {
PADDLE_THROW(platform::errors::Unimplemented( PADDLE_THROW(platform::errors::Unimplemented(
"Unsupported output `%s` type when call pt kernel.", "Unsupported output `%s` type when call pt kernel.",
......
...@@ -65,7 +65,7 @@ class DequeueOp : public framework::OperatorBase { ...@@ -65,7 +65,7 @@ class DequeueOp : public framework::OperatorBase {
platform::errors::InvalidArgument( platform::errors::InvalidArgument(
"Variable with name %s has not been initialized.", out_names[i])); "Variable with name %s has not been initialized.", out_names[i]));
std::vector<LoDTensor> lod_tensor_vec; paddle::framework::LoDTensorArray lod_tensor_vec;
bool success = false; bool success = false;
lod_tensor_vec = queue_holder->GetQueue()->Pop(&success); lod_tensor_vec = queue_holder->GetQueue()->Pop(&success);
PADDLE_ENFORCE_EQ(lod_tensor_vec.size(), PADDLE_ENFORCE_EQ(lod_tensor_vec.size(),
......
...@@ -65,7 +65,7 @@ class EnqueueOp : public framework::OperatorBase { ...@@ -65,7 +65,7 @@ class EnqueueOp : public framework::OperatorBase {
auto* queue_holder = auto* queue_holder =
queue_holder_var->template GetMutable<LoDTensorBlockingQueueHolder>(); queue_holder_var->template GetMutable<LoDTensorBlockingQueueHolder>();
std::vector<LoDTensor> lod_tensor_vec; paddle::framework::LoDTensorArray lod_tensor_vec;
lod_tensor_vec.emplace_back(*in_tensor); lod_tensor_vec.emplace_back(*in_tensor);
queue_holder->GetQueue()->Push(lod_tensor_vec); queue_holder->GetQueue()->Push(lod_tensor_vec);
} }
......
...@@ -502,7 +502,7 @@ void BufferedReader::StartImpl() { ...@@ -502,7 +502,7 @@ void BufferedReader::StartImpl() {
ReadTillBufferFullAsync(); ReadTillBufferFullAsync();
} }
void BufferedReader::ReadNextImpl(std::vector<framework::LoDTensor> *out) { void BufferedReader::ReadNextImpl(paddle::framework::LoDTensorArray *out) {
if (position_.empty()) { if (position_.empty()) {
out->clear(); out->clear();
return; return;
......
...@@ -46,7 +46,7 @@ namespace operators { ...@@ -46,7 +46,7 @@ namespace operators {
namespace reader { namespace reader {
class BufferedReader : public framework::DecoratedReader { class BufferedReader : public framework::DecoratedReader {
using TensorVec = std::vector<framework::LoDTensor>; using TensorVec = paddle::framework::LoDTensorArray;
using VecFuture = std::future<TensorVec>; using VecFuture = std::future<TensorVec>;
public: public:
...@@ -65,7 +65,7 @@ class BufferedReader : public framework::DecoratedReader { ...@@ -65,7 +65,7 @@ class BufferedReader : public framework::DecoratedReader {
protected: protected:
void ShutdownImpl() override; void ShutdownImpl() override;
void StartImpl() override; void StartImpl() override;
void ReadNextImpl(std::vector<framework::LoDTensor>* out) override; void ReadNextImpl(paddle::framework::LoDTensorArray* out) override;
private: private:
ThreadPool thread_pool_; ThreadPool thread_pool_;
......
...@@ -156,9 +156,9 @@ class CustomReaderInferVarType : public framework::VarTypeInference { ...@@ -156,9 +156,9 @@ class CustomReaderInferVarType : public framework::VarTypeInference {
} }
}; };
void CustomReader::ReadNextImpl(std::vector<framework::LoDTensor>* out) { void CustomReader::ReadNextImpl(paddle::framework::LoDTensorArray* out) {
out->clear(); out->clear();
std::vector<framework::LoDTensor> underlying_outs; paddle::framework::LoDTensorArray underlying_outs;
reader_->ReadNext(&underlying_outs); reader_->ReadNext(&underlying_outs);
if (underlying_outs.empty()) { if (underlying_outs.empty()) {
// There is not next data. // There is not next data.
......
...@@ -34,16 +34,16 @@ class LoDTensorBlockingQueue { ...@@ -34,16 +34,16 @@ class LoDTensorBlockingQueue {
~LoDTensorBlockingQueue() { VLOG(10) << "Destruct LoDTensorBlockingQueue"; } ~LoDTensorBlockingQueue() { VLOG(10) << "Destruct LoDTensorBlockingQueue"; }
bool Push(const std::vector<framework::LoDTensor>& lod_tensor_vec) { bool Push(const paddle::framework::LoDTensorArray& lod_tensor_vec) {
return queue_.Send(lod_tensor_vec); return queue_.Send(lod_tensor_vec);
} }
bool Push(std::vector<framework::LoDTensor>&& lod_tensor_vec) { bool Push(paddle::framework::LoDTensorArray&& lod_tensor_vec) {
return queue_.Send(std::move(lod_tensor_vec)); return queue_.Send(std::move(lod_tensor_vec));
} }
std::vector<framework::LoDTensor> Pop(bool* ok = nullptr) { paddle::framework::LoDTensorArray Pop(bool* ok = nullptr) {
std::vector<framework::LoDTensor> lod_tensor_vec; paddle::framework::LoDTensorArray lod_tensor_vec;
bool success = queue_.Receive(&lod_tensor_vec); bool success = queue_.Receive(&lod_tensor_vec);
if (ok != nullptr) *ok = success; if (ok != nullptr) *ok = success;
return lod_tensor_vec; return lod_tensor_vec;
...@@ -67,7 +67,7 @@ class LoDTensorBlockingQueue { ...@@ -67,7 +67,7 @@ class LoDTensorBlockingQueue {
inline bool WaitForInited(size_t) { return true; } inline bool WaitForInited(size_t) { return true; }
private: private:
BlockingQueue<std::vector<framework::LoDTensor>> queue_; BlockingQueue<paddle::framework::LoDTensorArray> queue_;
}; };
class OrderedMultiDeviceLoDTensorBlockingQueue { class OrderedMultiDeviceLoDTensorBlockingQueue {
...@@ -123,7 +123,7 @@ class OrderedMultiDeviceLoDTensorBlockingQueue { ...@@ -123,7 +123,7 @@ class OrderedMultiDeviceLoDTensorBlockingQueue {
return queues_[idx]; return queues_[idx];
} }
bool Push(const std::vector<framework::LoDTensor>& lod_tensor_vec) { bool Push(const paddle::framework::LoDTensorArray& lod_tensor_vec) {
return CurQueue()->Push(lod_tensor_vec); return CurQueue()->Push(lod_tensor_vec);
} }
......
...@@ -30,7 +30,7 @@ PyReader::PyReader( ...@@ -30,7 +30,7 @@ PyReader::PyReader(
queue_ = queue; queue_ = queue;
} }
void PyReader::ReadNext(std::vector<framework::LoDTensor>* out) { void PyReader::ReadNext(paddle::framework::LoDTensorArray* out) {
bool success; bool success;
*out = queue_->Pop(&success); *out = queue_->Pop(&success);
if (!success) out->clear(); if (!success) out->clear();
......
...@@ -35,7 +35,7 @@ class PyReader : public framework::FileReader { ...@@ -35,7 +35,7 @@ class PyReader : public framework::FileReader {
const std::vector<framework::proto::VarType::Type>& var_types, const std::vector<framework::proto::VarType::Type>& var_types,
const std::vector<bool>& need_check_feed); const std::vector<bool>& need_check_feed);
void ReadNext(std::vector<framework::LoDTensor>* out) override; void ReadNext(paddle::framework::LoDTensorArray* out) override;
~PyReader(); ~PyReader();
......
...@@ -106,7 +106,7 @@ class ReadOp : public framework::OperatorBase { ...@@ -106,7 +106,7 @@ class ReadOp : public framework::OperatorBase {
scope.FindVar(Input("Reader")), "Input", "Reader", "Read") scope.FindVar(Input("Reader")), "Input", "Reader", "Read")
.GetMutable<framework::ReaderHolder>(); .GetMutable<framework::ReaderHolder>();
std::vector<std::string> out_arg_names = Outputs("Out"); std::vector<std::string> out_arg_names = Outputs("Out");
std::vector<framework::LoDTensor> ins; paddle::framework::LoDTensorArray ins;
// For profiling // For profiling
platform::RecordEvent record_event( platform::RecordEvent record_event(
......
...@@ -483,7 +483,10 @@ std::vector<framework::Tensor> CastPyArg2VectorOfTensorBase(PyObject* obj, ...@@ -483,7 +483,10 @@ std::vector<framework::Tensor> CastPyArg2VectorOfTensorBase(PyObject* obj,
} else if (PyObject_IsInstance(obj, } else if (PyObject_IsInstance(obj,
reinterpret_cast<PyObject*>( reinterpret_cast<PyObject*>(
g_framework_lodtensorarray_pytype))) { g_framework_lodtensorarray_pytype))) {
return ::pybind11::handle(obj).cast<framework::LoDTensorArray>(); for (auto& tensor :
(::pybind11::handle(obj).cast<framework::LoDTensorArray>())) {
result.emplace_back(tensor);
}
} else if (obj == Py_None) { } else if (obj == Py_None) {
return {}; return {};
} else { } else {
......
...@@ -19,6 +19,7 @@ typedef SSIZE_T ssize_t; ...@@ -19,6 +19,7 @@ typedef SSIZE_T ssize_t;
#include "paddle/fluid/eager/hooks.h" #include "paddle/fluid/eager/hooks.h"
#include "paddle/fluid/framework/lod_tensor.h" #include "paddle/fluid/framework/lod_tensor.h"
#include "paddle/fluid/framework/lod_tensor_array.h"
#include "paddle/fluid/framework/tensor.h" #include "paddle/fluid/framework/tensor.h"
#include "paddle/fluid/jit/function.h" #include "paddle/fluid/jit/function.h"
#include "paddle/fluid/platform/place.h" #include "paddle/fluid/platform/place.h"
......
...@@ -118,7 +118,7 @@ class MultiDeviceFeedReader { ...@@ -118,7 +118,7 @@ class MultiDeviceFeedReader {
public: public:
using ResultDictList = using ResultDictList =
std::vector<std::unordered_map<std::string, framework::LoDTensor>>; std::vector<std::unordered_map<std::string, framework::LoDTensor>>;
using ResultList = std::vector<std::vector<framework::LoDTensor>>; using ResultList = std::vector<paddle::framework::LoDTensorArray>;
static constexpr bool kKeepOrder = static constexpr bool kKeepOrder =
std::is_same<QueueType, std::is_same<QueueType,
...@@ -332,7 +332,7 @@ class MultiDeviceFeedReader { ...@@ -332,7 +332,7 @@ class MultiDeviceFeedReader {
std::vector<std::future<Status>> futures_; std::vector<std::future<Status>> futures_;
std::vector<std::exception_ptr> exceptions_; std::vector<std::exception_ptr> exceptions_;
std::vector<std::vector<framework::LoDTensor>> ret_; std::vector<paddle::framework::LoDTensorArray> ret_;
bool drop_last_; bool drop_last_;
bool pin_memory_; bool pin_memory_;
}; };
...@@ -427,7 +427,7 @@ void BindReader(py::module *module) { ...@@ -427,7 +427,7 @@ void BindReader(py::module *module) {
.def( .def(
"push", "push",
[](reader::LoDTensorBlockingQueue &self, [](reader::LoDTensorBlockingQueue &self,
const std::vector<framework::LoDTensor> &lod_tensor_vec) { const paddle::framework::LoDTensorArray &lod_tensor_vec) {
return self.Push(lod_tensor_vec); return self.Push(lod_tensor_vec);
}, },
py::call_guard<py::gil_scoped_release>()) py::call_guard<py::gil_scoped_release>())
...@@ -445,7 +445,7 @@ void BindReader(py::module *module) { ...@@ -445,7 +445,7 @@ void BindReader(py::module *module) {
.def( .def(
"push", "push",
[](reader::OrderedMultiDeviceLoDTensorBlockingQueue &self, [](reader::OrderedMultiDeviceLoDTensorBlockingQueue &self,
const std::vector<framework::LoDTensor> &lod_tensor_vec) { const paddle::framework::LoDTensorArray &lod_tensor_vec) {
return self.Push(lod_tensor_vec); return self.Push(lod_tensor_vec);
}, },
py::call_guard<py::gil_scoped_release>()) py::call_guard<py::gil_scoped_release>())
......
...@@ -2193,15 +2193,6 @@ ...@@ -2193,15 +2193,6 @@
func : reverse func : reverse
backward : reverse_grad backward : reverse_grad
- api : reverse_array
args : (Tensor[] x, IntArray axis)
output : Tensor[]{x.size()}
infer_meta :
func : ReverseArrayInferMeta
kernel :
func : reverse_array
backward : reverse_array_grad
- api : rmsprop_ - api : rmsprop_
args : (Tensor param, Tensor mean_square, Tensor grad, Tensor moment, Tensor learning_rate, Tensor mean_grad, float epsilon, float decay, float momentum, bool centered) args : (Tensor param, Tensor mean_square, Tensor grad, Tensor moment, Tensor learning_rate, Tensor mean_grad, float epsilon, float decay, float momentum, bool centered)
output : Tensor(param_out), Tensor(moment_out), Tensor(mean_square_out), Tensor(mean_grad_out) output : Tensor(param_out), Tensor(moment_out), Tensor(mean_square_out), Tensor(mean_grad_out)
......
...@@ -57,6 +57,11 @@ cc_library( ...@@ -57,6 +57,11 @@ cc_library(
SRCS string_tensor.cc SRCS string_tensor.cc
DEPS convert_utils tensor_meta tensor_base) DEPS convert_utils tensor_meta tensor_base)
cc_library(
tensor_array
SRCS tensor_array.cc
DEPS dense_tensor tensor_base)
cc_library( cc_library(
meta_tensor meta_tensor
SRCS meta_tensor.cc SRCS meta_tensor.cc
......
...@@ -132,6 +132,11 @@ struct KernelArgsParseFunctor<Return_ (*)(Args_...)> { ...@@ -132,6 +132,11 @@ struct KernelArgsParseFunctor<Return_ (*)(Args_...)> {
default_tensor_layout, default_tensor_layout,
default_key.dtype(), default_key.dtype(),
arg_type); arg_type);
} else if (arg_type == std::type_index(typeid(const TensorArray&))) {
args_def->AppendInput(default_key.backend(),
default_tensor_layout,
default_key.dtype(),
arg_type);
} else if (arg_type == std::type_index(typeid(DenseTensor*))) { } else if (arg_type == std::type_index(typeid(DenseTensor*))) {
args_def->AppendOutput(default_key.backend(), args_def->AppendOutput(default_key.backend(),
default_tensor_layout, default_tensor_layout,
...@@ -148,6 +153,11 @@ struct KernelArgsParseFunctor<Return_ (*)(Args_...)> { ...@@ -148,6 +153,11 @@ struct KernelArgsParseFunctor<Return_ (*)(Args_...)> {
default_tensor_layout, default_tensor_layout,
default_key.dtype(), default_key.dtype(),
arg_type); arg_type);
} else if (arg_type == std::type_index(typeid(TensorArray*))) {
args_def->AppendOutput(default_key.backend(),
default_tensor_layout,
default_key.dtype(),
arg_type);
} else if (arg_type == std::type_index(typeid(SparseCooTensor*))) { } else if (arg_type == std::type_index(typeid(SparseCooTensor*))) {
args_def->AppendOutput(default_key.backend(), args_def->AppendOutput(default_key.backend(),
default_tensor_layout, default_tensor_layout,
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "paddle/phi/core/sparse_coo_tensor.h" #include "paddle/phi/core/sparse_coo_tensor.h"
#include "paddle/phi/core/sparse_csr_tensor.h" #include "paddle/phi/core/sparse_csr_tensor.h"
#include "paddle/phi/core/string_tensor.h" #include "paddle/phi/core/string_tensor.h"
#include "paddle/phi/core/tensor_array.h"
#include "paddle/phi/core/type_defs.h" #include "paddle/phi/core/type_defs.h"
namespace phi { namespace phi {
...@@ -284,6 +285,9 @@ struct KernelImpl<Return (*)(DevCtx, Args...), kernel_fn> { ...@@ -284,6 +285,9 @@ struct KernelImpl<Return (*)(DevCtx, Args...), kernel_fn> {
PD_SPECIALIZE_KernelCallHelper_FOR_OPTIONAL_INPUT(StringTensor); PD_SPECIALIZE_KernelCallHelper_FOR_OPTIONAL_INPUT(StringTensor);
PD_SPECIALIZE_KernelCallHelper_FOR_MULTI_INPUT(StringTensor); PD_SPECIALIZE_KernelCallHelper_FOR_MULTI_INPUT(StringTensor);
PD_SPECIALIZE_KernelCallHelper_FOR_INPUT(TensorArray);
PD_SPECIALIZE_KernelCallHelper_FOR_MULTI_INPUT(TensorArray);
/* Attribute Helpers */ /* Attribute Helpers */
PD_SPECIALIZE_KernelCallHelper_FOR_ATTRIBUTE(bool); PD_SPECIALIZE_KernelCallHelper_FOR_ATTRIBUTE(bool);
...@@ -322,6 +326,8 @@ struct KernelImpl<Return (*)(DevCtx, Args...), kernel_fn> { ...@@ -322,6 +326,8 @@ struct KernelImpl<Return (*)(DevCtx, Args...), kernel_fn> {
PD_SPECIALIZE_KernelCallHelper_FOR_OUTPUT(StringTensor); PD_SPECIALIZE_KernelCallHelper_FOR_OUTPUT(StringTensor);
PD_SPECIALIZE_KernelCallHelper_FOR_MULTI_OUTPUT(StringTensor); PD_SPECIALIZE_KernelCallHelper_FOR_MULTI_OUTPUT(StringTensor);
PD_SPECIALIZE_KernelCallHelper_FOR_OUTPUT(TensorArray);
template <typename... Tail> template <typename... Tail>
struct KernelCallHelper<const RuntimeAttrs&, Tail...> { struct KernelCallHelper<const RuntimeAttrs&, Tail...> {
template <int dev_ctx_idx, template <int dev_ctx_idx,
......
/* 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. */
#include "paddle/phi/core/tensor_array.h"
namespace phi {
TensorArray::TensorArray(const std::vector<DenseTensor>& vec) {
tensors_ = vec;
}
/// \brief Test whether the tensor's storage in TensorArray is allocated.
/// return Whether all tensors in TensorArray is allocated.
bool TensorArray::initialized() const {
bool init = true;
for (auto tensor : tensors_) {
if (!tensor.IsInitialized()) {
init = false;
}
}
return init;
}
int64_t TensorArray::numel() const {
PADDLE_THROW(errors::Unavailable("numel() can't be used in TensorArray"));
return -1;
}
const DDim& TensorArray::dims() const {
PADDLE_THROW(errors::Unavailable("dims() can't be used in TensorArray"));
return tensors_[0].dims();
}
const Place& TensorArray::place() const {
PADDLE_THROW(errors::Unavailable("place() can't be used in TensorArray"));
return tensors_[0].place();
}
DataType TensorArray::dtype() const {
PADDLE_THROW(errors::Unavailable("dtype() can't be used in TensorArray"));
return DataType::UNDEFINED;
}
DataLayout TensorArray::layout() const {
PADDLE_THROW(errors::Unavailable("layout() can't be used in TensorArray"));
return DataLayout::UNDEFINED;
}
bool TensorArray::valid() const {
PADDLE_THROW(errors::Unavailable("valid() can't be used in TensorArray"));
return false;
}
/// \brief Allocate memory with requested size for all tensors from allocator.
/// \return Void pointer
void* TensorArray::AllocateFrom(Allocator* allocator,
DataType dtype,
size_t requested_size) {
for (size_t i = 0; i < tensors_.size(); i++) {
tensors_[i].AllocateFrom(allocator, tensors_[i].dtype(), requested_size);
}
return nullptr;
}
void TensorArray::push_back(const DenseTensor& tensor) {
tensors_.push_back(tensor);
}
void TensorArray::emplace_back(const DenseTensor& tensor) {
tensors_.emplace_back(tensor);
}
void TensorArray::emplace_back() {
DenseTensor t;
tensors_.emplace_back(t);
}
} // namespace phi
/* 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. */
#pragma once
#include "paddle/phi/core/dense_tensor.h"
namespace phi {
/// \brief The TensorArray store a list of tensor and it is designed for
/// compatible with LodTensorArray in Fluid. It shouldn't be used widely
/// in PHI. If you want to store a list of tensor in PHI, please use std::vector
/// when ever possible.
class TensorArray : public TensorBase,
public TypeInfoTraits<TensorBase, TensorArray> {
public:
/// \brief Construct a TensorArray.
/// \param vec The vector DenseTensor used to init TensorArray.
explicit TensorArray(const std::vector<DenseTensor>& vec);
explicit TensorArray(size_t n) {
for (size_t i = 0; i < n; i++) {
tensors_.emplace_back();
}
}
TensorArray() = default;
TensorArray(TensorArray&& other) = default;
TensorArray(const TensorArray& other) = default;
/// \brief TensorArray shallow copy assignment.
TensorArray& operator=(const TensorArray& other) = default;
TensorArray& operator=(TensorArray&& other) = default;
/// \brief Destroy the tensor object and release exclusive resources.
virtual ~TensorArray() = default;
public:
/// \brief Returns the name of the class for type traits.
/// \return The name of the class.
static const char* name() { return "TensorArray"; }
/// \brief This overrided function is not used in TensorArray.
int64_t numel() const override;
/// \brief This overrided function is not used in TensorArray.
const DDim& dims() const override;
/// \brief This overrided function is not used in TensorArray.
const Place& place() const override;
/// \brief This overrided function is not used in TensorArray.
DataType dtype() const override;
/// \brief This overrided function is not used in TensorArray.
DataLayout layout() const override;
/// \brief This overrided function is not used in TensorArray.
bool valid() const override;
/// \brief Test whether the tensor's storage in TensorArray is allocated.
/// return Whether all tensors in TensorArray is allocated.
bool initialized() const override;
/// \brief Clear all tensors in TensorArray.
void clear() { tensors_.clear(); }
/// \brief Allocate memory with requested size for all tensors from allocator.
/// \return Void pointer
void* AllocateFrom(Allocator* allocator,
DataType dtype,
size_t requested_size = 0);
bool empty() const { return tensors_.empty(); }
/// \brief Returns the number of tensors in TensorArray.
size_t size() const { return tensors_.size(); }
/// \brief Resizes the TensorArray so that it contains n tensors.
void resize(size_t n) { tensors_.resize(n); }
/// \brief Requests that the TensorArray capacity be at least enough to
/// contain n tensors.
void reserve(size_t n) { tensors_.reserve(n); }
/// \brief Add the tensor to the end of TensorArray
void push_back(const DenseTensor& tensor);
void emplace_back();
void emplace_back(const DenseTensor& tensor);
/// \brief Return the last tensor in TensorArray
DenseTensor& back() { return tensors_.back(); }
DenseTensor& at(size_t index) { return tensors_.at(index); }
const DenseTensor& at(size_t index) const { return tensors_.at(index); }
const DenseTensor& operator[](size_t index) const { return tensors_[index]; }
DenseTensor& operator[](size_t index) { return tensors_[index]; }
std::vector<DenseTensor>::iterator begin() { return tensors_.begin(); }
std::vector<DenseTensor>::const_iterator begin() const {
return tensors_.begin();
}
std::vector<DenseTensor>::iterator end() { return tensors_.end(); }
std::vector<DenseTensor>::const_iterator end() const {
return tensors_.end();
}
private:
std::vector<DenseTensor> tensors_;
};
} // namespace phi
...@@ -25,6 +25,7 @@ set(COMMON_KERNEL_DEPS ...@@ -25,6 +25,7 @@ set(COMMON_KERNEL_DEPS
string_tensor string_tensor
sparse_coo_tensor sparse_coo_tensor
sparse_csr_tensor sparse_csr_tensor
tensor_array
kernel_context kernel_context
kernel_factory kernel_factory
arg_map_context arg_map_context
......
...@@ -45,10 +45,10 @@ void AssignRawKernel(const Context& dev_ctx, ...@@ -45,10 +45,10 @@ void AssignRawKernel(const Context& dev_ctx,
// as input if needed // as input if needed
template <typename Context> template <typename Context>
void AssignArrayKernel(const Context& dev_ctx, void AssignArrayKernel(const Context& dev_ctx,
const std::vector<const DenseTensor*>& x, const TensorArray& x,
std::vector<DenseTensor*> out) { TensorArray* out) {
for (size_t i = 0; i < x.size(); ++i) { for (size_t i = 0; i < x.size(); ++i) {
AssignKernel<Context>(dev_ctx, *x[i], out.at(i)); AssignKernel<Context>(dev_ctx, x[i], &out->at(i));
} }
} }
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "paddle/phi/common/scalar.h" #include "paddle/phi/common/scalar.h"
#include "paddle/phi/core/dense_tensor.h" #include "paddle/phi/core/dense_tensor.h"
#include "paddle/phi/core/tensor_array.h"
#include "paddle/phi/infermeta/unary.h" #include "paddle/phi/infermeta/unary.h"
namespace phi { namespace phi {
...@@ -47,8 +48,8 @@ void AssignRawKernel(const Context& dev_ctx, ...@@ -47,8 +48,8 @@ void AssignRawKernel(const Context& dev_ctx,
template <typename Context> template <typename Context>
void AssignArrayKernel(const Context& dev_ctx, void AssignArrayKernel(const Context& dev_ctx,
const std::vector<const DenseTensor*>& x, const TensorArray& x,
std::vector<DenseTensor*> out); TensorArray* out);
template <typename T, typename Context> template <typename T, typename Context>
void AssignValueKernel(const Context& dev_ctx, void AssignValueKernel(const Context& dev_ctx,
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "paddle/phi/core/ddim.h" #include "paddle/phi/core/ddim.h"
#include "paddle/phi/core/dense_tensor.h" #include "paddle/phi/core/dense_tensor.h"
#include "paddle/phi/core/enforce.h" #include "paddle/phi/core/enforce.h"
#include "paddle/phi/core/tensor_array.h"
#include "paddle/phi/core/tensor_utils.h" #include "paddle/phi/core/tensor_utils.h"
#include "paddle/phi/kernels/funcs/eigen/common.h" #include "paddle/phi/kernels/funcs/eigen/common.h"
#include "paddle/phi/kernels/funcs/eigen/eigen_function.h" #include "paddle/phi/kernels/funcs/eigen/eigen_function.h"
...@@ -297,14 +298,14 @@ void StridedSliceCompute(const Context& dev_ctx, ...@@ -297,14 +298,14 @@ void StridedSliceCompute(const Context& dev_ctx,
template <typename Context, typename T, size_t D> template <typename Context, typename T, size_t D>
void StridedSliceCompute(const Context& dev_ctx, void StridedSliceCompute(const Context& dev_ctx,
const std::vector<const DenseTensor*>& x, const TensorArray& x,
const std::vector<int>& axes, const std::vector<int>& axes,
const IntArray& starts, const IntArray& starts,
const IntArray& ends, const IntArray& ends,
const IntArray& strides, const IntArray& strides,
const std::vector<int>& infer_flags, const std::vector<int>& infer_flags,
const std::vector<int>& decrease_axis, const std::vector<int>& decrease_axis,
std::vector<DenseTensor*> out) { TensorArray* out) {
const int64_t size = x.size(); const int64_t size = x.size();
auto in_dims = phi::make_ddim({size}); auto in_dims = phi::make_ddim({size});
...@@ -419,29 +420,29 @@ void StridedSliceCompute(const Context& dev_ctx, ...@@ -419,29 +420,29 @@ void StridedSliceCompute(const Context& dev_ctx,
"dimension of Output should be 1, but received %d", "dimension of Output should be 1, but received %d",
out_dims_origin.size())); out_dims_origin.size()));
out.resize(out_dims_origin[0]); out->resize(out_dims_origin[0]);
size_t const in_array_size = x.size(); size_t const in_array_size = x.size();
for (size_t i = 0; i < out.size(); i++) { for (size_t i = 0; i < out->size(); i++) {
size_t in_offset = size_t in_offset =
(starts_indices[0] % in_array_size) + i * strides_indices[0]; (starts_indices[0] % in_array_size) + i * strides_indices[0];
int64_t out_offset = i; int64_t out_offset = i;
if (need_reverse) { if (need_reverse) {
out_offset = out.size() - i - 1; out_offset = out->size() - i - 1;
} }
auto* in_tensor = x.at(in_offset); auto& in_tensor = x.at(in_offset);
PADDLE_ENFORCE_GT( PADDLE_ENFORCE_GT(
in_tensor->memory_size(), in_tensor.memory_size(),
0, 0,
errors::PreconditionNotMet( errors::PreconditionNotMet(
"The input LoDTensorArray Input[%d] holds no memory.", in_offset)); "The input LoDTensorArray Input[%d] holds no memory.", in_offset));
auto* out_tensor = out.at(out_offset); auto& out_tensor = out->at(out_offset);
out_tensor->Resize(in_tensor->dims()); out_tensor.Resize(in_tensor.dims());
phi::Copy<Context>( phi::Copy<Context>(
dev_ctx, *in_tensor, dev_ctx.GetPlace(), false, out_tensor); dev_ctx, in_tensor, dev_ctx.GetPlace(), false, &out_tensor);
out_tensor->set_lod(in_tensor->lod()); out_tensor.set_lod(in_tensor.lod());
} }
} }
...@@ -531,15 +532,15 @@ void StridedSliceGradCompute(const Context& dev_ctx, ...@@ -531,15 +532,15 @@ void StridedSliceGradCompute(const Context& dev_ctx,
template <typename Context, typename T, size_t D> template <typename Context, typename T, size_t D>
void StridedSliceGradCompute(const Context& dev_ctx, void StridedSliceGradCompute(const Context& dev_ctx,
const std::vector<const DenseTensor*>& x, const TensorArray& x,
const std::vector<const DenseTensor*>& out_grad, const TensorArray& out_grad,
const std::vector<int>& axes, const std::vector<int>& axes,
const IntArray& starts, const IntArray& starts,
const IntArray& ends, const IntArray& ends,
const IntArray& strides, const IntArray& strides,
const std::vector<int>& infer_flags, const std::vector<int>& infer_flags,
const std::vector<int>& decrease_axis, const std::vector<int>& decrease_axis,
std::vector<DenseTensor*> x_grad) { TensorArray* x_grad) {
// Note(weixin):Since the shape of `framework::GradVarName("Input")` of // Note(weixin):Since the shape of `framework::GradVarName("Input")` of
// StridedSliceGrad cannot be calculated by // StridedSliceGrad cannot be calculated by
// `framework::GradVarName("Output")`, the dim of "Input" is used to // `framework::GradVarName("Output")`, the dim of "Input" is used to
...@@ -619,11 +620,11 @@ void StridedSliceGradCompute(const Context& dev_ctx, ...@@ -619,11 +620,11 @@ void StridedSliceGradCompute(const Context& dev_ctx,
"the dimension of output should be 1, but received %d.", "the dimension of output should be 1, but received %d.",
out_dims.size())); out_dims.size()));
auto const d_out_array_size = x_grad.size(); auto const d_out_array_size = x_grad->size();
for (size_t j = 0; j < d_out_array_size; j++) { for (size_t j = 0; j < d_out_array_size; j++) {
auto& dim = x.at(j)->dims(); auto& dim = x.at(j).dims();
auto* d_out_tensor = x_grad.at(j); auto& d_out_tensor = x_grad->at(j);
int64_t sub = j - starts_indices[0]; int64_t sub = j - starts_indices[0];
...@@ -635,26 +636,26 @@ void StridedSliceGradCompute(const Context& dev_ctx, ...@@ -635,26 +636,26 @@ void StridedSliceGradCompute(const Context& dev_ctx,
if ((sub % strides_indices[0] == 0) && (0 <= in_offset) && if ((sub % strides_indices[0] == 0) && (0 <= in_offset) &&
(static_cast<size_t>(in_offset) < out_grad.size())) { (static_cast<size_t>(in_offset) < out_grad.size())) {
auto* in_tensor = out_grad.at(in_offset); auto& in_tensor = out_grad.at(in_offset);
PADDLE_ENFORCE_GT( PADDLE_ENFORCE_GT(
in_tensor->memory_size(), in_tensor.memory_size(),
0, 0,
errors::PreconditionNotMet( errors::PreconditionNotMet(
"The input LoDTensorArray Input[%d] holds no memory.", "The input LoDTensorArray Input[%d] holds no memory.",
in_offset)); in_offset));
phi::Copy<Context>( phi::Copy<Context>(
dev_ctx, *in_tensor, dev_ctx.GetPlace(), false, d_out_tensor); dev_ctx, in_tensor, dev_ctx.GetPlace(), false, &d_out_tensor);
d_out_tensor->set_lod(in_tensor->lod()); d_out_tensor.set_lod(in_tensor.lod());
} else { } else {
d_out_tensor->Resize(dim); d_out_tensor.Resize(dim);
if (!d_out_tensor->IsInitialized()) { if (!d_out_tensor.IsInitialized()) {
dev_ctx.template Alloc<T>(d_out_tensor); dev_ctx.template Alloc<T>(&d_out_tensor);
} }
phi::funcs::SetConstant<Context, T> set_zero; phi::funcs::SetConstant<Context, T> set_zero;
set_zero(dev_ctx, d_out_tensor, static_cast<T>(0)); set_zero(dev_ctx, &d_out_tensor, static_cast<T>(0));
} }
} }
} }
......
...@@ -56,17 +56,16 @@ void StridedSliceRawGradKernel(const Context& dev_ctx, ...@@ -56,17 +56,16 @@ void StridedSliceRawGradKernel(const Context& dev_ctx,
} }
template <typename T, typename Context> template <typename T, typename Context>
void StridedSliceArrayGradKernel( void StridedSliceArrayGradKernel(const Context& dev_ctx,
const Context& dev_ctx, const TensorArray& x,
const std::vector<const DenseTensor*>& x, const TensorArray& out_grad,
const std::vector<const DenseTensor*>& out_grad, const std::vector<int>& axes,
const std::vector<int>& axes, const IntArray& starts,
const IntArray& starts, const IntArray& ends,
const IntArray& ends, const IntArray& strides,
const IntArray& strides, const std::vector<int>& infer_flags,
const std::vector<int>& infer_flags, const std::vector<int>& decrease_axis,
const std::vector<int>& decrease_axis, TensorArray* x_grad) {
std::vector<DenseTensor*> x_grad) {
funcs::StridedSliceGradCompute<Context, T, 1>(dev_ctx, funcs::StridedSliceGradCompute<Context, T, 1>(dev_ctx,
x, x,
out_grad, out_grad,
......
...@@ -55,14 +55,14 @@ void StridedSliceRawKernel(const Context& dev_ctx, ...@@ -55,14 +55,14 @@ void StridedSliceRawKernel(const Context& dev_ctx,
template <typename T, typename Context> template <typename T, typename Context>
void StridedSliceArrayKernel(const Context& dev_ctx, void StridedSliceArrayKernel(const Context& dev_ctx,
const std::vector<const DenseTensor*>& x, const TensorArray& x,
const std::vector<int>& axes, const std::vector<int>& axes,
const IntArray& starts, const IntArray& starts,
const IntArray& ends, const IntArray& ends,
const IntArray& strides, const IntArray& strides,
const std::vector<int>& infer_flags, const std::vector<int>& infer_flags,
const std::vector<int>& decrease_axis, const std::vector<int>& decrease_axis,
std::vector<DenseTensor*> out) { TensorArray* out) {
funcs::StridedSliceCompute<Context, T, 1>( funcs::StridedSliceCompute<Context, T, 1>(
dev_ctx, x, axes, starts, ends, strides, infer_flags, decrease_axis, out); dev_ctx, x, axes, starts, ends, strides, infer_flags, decrease_axis, out);
} }
......
...@@ -110,25 +110,21 @@ void MemcpyD2HKernel(const Context& dev_ctx, ...@@ -110,25 +110,21 @@ void MemcpyD2HKernel(const Context& dev_ctx,
template <typename Context> template <typename Context>
void MemcpyD2HMultiIOKernel(const Context& dev_ctx, void MemcpyD2HMultiIOKernel(const Context& dev_ctx,
const std::vector<const DenseTensor*>& array, const TensorArray& array,
int dst_place_type, int dst_place_type,
std::vector<DenseTensor*> out_array) { TensorArray* out_array) {
PADDLE_ENFORCE_NOT_NULL(
out_array,
errors::PreconditionNotMet("output tesnor_array should not be nullptr"));
PADDLE_ENFORCE_EQ( PADDLE_ENFORCE_EQ(
array.size(), array.size(),
out_array.size(), out_array->size(),
errors::PreconditionNotMet( errors::PreconditionNotMet(
"input size %d != output size %d", array.size(), out_array.size())); "input size %d != output size %d", array.size(), out_array->size()));
for (size_t i = 0; i < array.size(); i++) { for (size_t i = 0; i < array.size(); i++) {
PADDLE_ENFORCE_NOT_NULL( const auto& x = array[i];
array[i], MemcpyD2HKernel<Context>(dev_ctx, x, dst_place_type, &(out_array->at(i)));
errors::PreconditionNotMet("input tesnor %d should not be nullptr", i));
PADDLE_ENFORCE_NOT_NULL(out_array[i],
errors::PreconditionNotMet(
"output tesnor %d should not be nullptr", i));
const auto& x = *(array[i]);
MemcpyD2HKernel<Context>(dev_ctx, x, dst_place_type, out_array[i]);
} }
} }
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <vector> #include <vector>
#include "paddle/phi/core/dense_tensor.h" #include "paddle/phi/core/dense_tensor.h"
#include "paddle/phi/core/tensor_array.h"
namespace phi { namespace phi {
...@@ -36,9 +37,9 @@ void MemcpyD2HKernel(const Context& dev_ctx, ...@@ -36,9 +37,9 @@ void MemcpyD2HKernel(const Context& dev_ctx,
template <typename Context> template <typename Context>
void MemcpyD2HMultiIOKernel(const Context& dev_ctx, void MemcpyD2HMultiIOKernel(const Context& dev_ctx,
const std::vector<const DenseTensor*>& array, const TensorArray& array,
int dst_place_type, int dst_place_type,
std::vector<DenseTensor*> out_array); TensorArray* out_array);
template <typename Context> template <typename Context>
void MemcpyKernel(const Context& dev_ctx, void MemcpyKernel(const Context& dev_ctx,
......
...@@ -22,29 +22,29 @@ namespace phi { ...@@ -22,29 +22,29 @@ namespace phi {
template <typename T, typename Context> template <typename T, typename Context>
void ReverseArrayKernel(const Context& dev_ctx, void ReverseArrayKernel(const Context& dev_ctx,
const std::vector<const DenseTensor*>& x, const TensorArray& x,
const IntArray& axis, const IntArray& axis,
std::vector<DenseTensor*> out) { TensorArray* out) {
PADDLE_ENFORCE_EQ( PADDLE_ENFORCE_EQ(
x.size(), x.size(),
out.size(), out->size(),
phi::errors::InvalidArgument("The input size(%d) and output size(%d) of " phi::errors::InvalidArgument("The input size(%d) and output size(%d) of "
"ReverseArrayKernel is different.", "ReverseArrayKernel is different.",
x.size(), x.size(),
out.size())); out->size()));
for (size_t offset = 0; offset < x.size(); ++offset) { for (size_t offset = 0; offset < x.size(); ++offset) {
auto* x_tensor = x.at(offset); auto& x_tensor = x.at(offset);
PADDLE_ENFORCE_GT( PADDLE_ENFORCE_GT(
x_tensor->memory_size(), x_tensor.memory_size(),
0, 0,
phi::errors::PreconditionNotMet( phi::errors::PreconditionNotMet(
"The input LoDTensorArray X[%d] holds no memory.", offset)); "The input LoDTensorArray X[%d] holds no memory.", offset));
auto out_offset = x.size() - offset - 1; auto out_offset = x.size() - offset - 1;
auto* out_tensor = out.at(out_offset); auto& out_tensor = out->at(out_offset);
out_tensor->set_lod(x_tensor->lod()); out_tensor.set_lod(x_tensor.lod());
phi::Copy<Context>( phi::Copy<Context>(
dev_ctx, *x_tensor, dev_ctx.GetPlace(), false, out_tensor); dev_ctx, x_tensor, dev_ctx.GetPlace(), false, &out_tensor);
} }
} }
...@@ -60,7 +60,9 @@ PD_REGISTER_KERNEL(reverse_array, ...@@ -60,7 +60,9 @@ PD_REGISTER_KERNEL(reverse_array,
bool, bool,
float, float,
double) {} double) {}
#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP) #if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP)
PD_REGISTER_KERNEL(reverse_array, PD_REGISTER_KERNEL(reverse_array,
GPU, GPU,
ALL_LAYOUT, ALL_LAYOUT,
...@@ -71,4 +73,5 @@ PD_REGISTER_KERNEL(reverse_array, ...@@ -71,4 +73,5 @@ PD_REGISTER_KERNEL(reverse_array,
bool, bool,
float, float,
double) {} double) {}
#endif #endif
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "paddle/phi/common/int_array.h" #include "paddle/phi/common/int_array.h"
#include "paddle/phi/core/dense_tensor.h" #include "paddle/phi/core/dense_tensor.h"
#include "paddle/phi/core/tensor_array.h"
namespace phi { namespace phi {
...@@ -29,8 +30,8 @@ void ReverseKernel(const Context& dev_ctx, ...@@ -29,8 +30,8 @@ void ReverseKernel(const Context& dev_ctx,
template <typename T, typename Context> template <typename T, typename Context>
void ReverseArrayKernel(const Context& dev_ctx, void ReverseArrayKernel(const Context& dev_ctx,
const std::vector<const DenseTensor*>& x, const TensorArray& x,
const IntArray& axis, const IntArray& axis,
std::vector<DenseTensor*> out); TensorArray* out);
} // namespace phi } // namespace phi
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "paddle/phi/common/int_array.h" #include "paddle/phi/common/int_array.h"
#include "paddle/phi/core/dense_tensor.h" #include "paddle/phi/core/dense_tensor.h"
#include "paddle/phi/core/tensor_array.h"
namespace phi { namespace phi {
...@@ -42,15 +43,14 @@ void StridedSliceGradKernel(const Context& dev_ctx, ...@@ -42,15 +43,14 @@ void StridedSliceGradKernel(const Context& dev_ctx,
DenseTensor* x_grad); DenseTensor* x_grad);
template <typename T, typename Context> template <typename T, typename Context>
void StridedSliceArrayGradKernel( void StridedSliceArrayGradKernel(const Context& dev_ctx,
const Context& dev_ctx, const TensorArray& x,
const std::vector<const DenseTensor*>& x, const TensorArray& out_grad,
const std::vector<const DenseTensor*>& out_grad, const std::vector<int>& axes,
const std::vector<int>& axes, const IntArray& starts,
const IntArray& starts, const IntArray& ends,
const IntArray& ends, const IntArray& strides,
const IntArray& strides, const std::vector<int>& infer_flags,
const std::vector<int>& infer_flags, const std::vector<int>& decrease_axis,
const std::vector<int>& decrease_axis, TensorArray* x_grad);
std::vector<DenseTensor*> x_grad);
} // namespace phi } // namespace phi
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "paddle/phi/common/int_array.h" #include "paddle/phi/common/int_array.h"
#include "paddle/phi/core/dense_tensor.h" #include "paddle/phi/core/dense_tensor.h"
#include "paddle/phi/core/tensor_array.h"
namespace phi { namespace phi {
...@@ -41,12 +42,12 @@ void StridedSliceKernel(const Context& dev_ctx, ...@@ -41,12 +42,12 @@ void StridedSliceKernel(const Context& dev_ctx,
template <typename T, typename Context> template <typename T, typename Context>
void StridedSliceArrayKernel(const Context& dev_ctx, void StridedSliceArrayKernel(const Context& dev_ctx,
const std::vector<const DenseTensor*>& x, const TensorArray& x,
const std::vector<int>& axes, const std::vector<int>& axes,
const IntArray& starts, const IntArray& starts,
const IntArray& ends, const IntArray& ends,
const IntArray& strides, const IntArray& strides,
const std::vector<int>& infer_flags, const std::vector<int>& infer_flags,
const std::vector<int>& decrease_axis, const std::vector<int>& decrease_axis,
std::vector<DenseTensor*> out); TensorArray* out);
} // namespace phi } // namespace phi
...@@ -60,3 +60,8 @@ cc_test( ...@@ -60,3 +60,8 @@ cc_test(
SRCS test_string_tensor.cc SRCS test_string_tensor.cc
DEPS string_tensor) DEPS string_tensor)
cc_test(unroll_array_ops_test SRCS unroll_array_ops_test.cc) cc_test(unroll_array_ops_test SRCS unroll_array_ops_test.cc)
cc_test(
test_tensor_array
SRCS test_tensor_array.cc
DEPS tensor_array)
/* 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. */
#include <sstream>
#include <string>
#include <utility>
#include "gtest/gtest.h"
#include "paddle/phi/backends/all_context.h"
#include "paddle/phi/core/enforce.h"
#include "paddle/phi/core/errors.h"
#include "paddle/phi/core/tensor_array.h"
#include "paddle/phi/tests/core/allocator.h"
namespace phi {
namespace tests {
using pstring = ::phi::dtype::pstring;
TEST(tensor_array, tensor_array_not_init) {
const DDim dims({1, 2});
const DataType dtype{DataType::INT8};
const DataLayout layout{DataLayout::NHWC};
const LoD lod{};
DenseTensorMeta meta(dtype, dims, layout, lod);
DenseTensor tensor_0;
tensor_0.set_meta(meta);
std::vector<DenseTensor> tensors;
tensors.push_back(tensor_0);
tensors.push_back(tensor_0);
tensors.push_back(tensor_0);
TensorArray tensor_array(tensors);
try {
tensor_array.dims();
} catch (const phi::enforce::EnforceNotMet& error) {
std::string ex_msg = error.what();
EXPECT_TRUE(ex_msg.find("dims") != std::string::npos);
}
try {
tensor_array.place();
} catch (const phi::enforce::EnforceNotMet& error) {
std::string ex_msg = error.what();
EXPECT_TRUE(ex_msg.find("place") != std::string::npos);
}
try {
tensor_array.dtype();
} catch (const phi::enforce::EnforceNotMet& error) {
std::string ex_msg = error.what();
EXPECT_TRUE(ex_msg.find("dtype") != std::string::npos);
}
try {
tensor_array.layout();
} catch (const phi::enforce::EnforceNotMet& error) {
std::string ex_msg = error.what();
EXPECT_TRUE(ex_msg.find("layout") != std::string::npos);
}
try {
tensor_array.numel();
} catch (const phi::enforce::EnforceNotMet& error) {
std::string ex_msg = error.what();
EXPECT_TRUE(ex_msg.find("numel") != std::string::npos);
}
try {
tensor_array.valid();
} catch (const phi::enforce::EnforceNotMet& error) {
std::string ex_msg = error.what();
EXPECT_TRUE(ex_msg.find("valid") != std::string::npos);
}
CHECK_EQ(tensor_array.initialized(), false);
}
TEST(tensor_array, tensor_array_init) {
const DDim dims1({1, 2});
const DDim dims2({1, 2, 3});
const DataType dtype{DataType::INT8};
const DataLayout layout{DataLayout::NHWC};
const LoD lod{};
DenseTensorMeta meta1(dtype, dims1, layout, lod);
DenseTensorMeta meta2(dtype, dims2, layout, lod);
auto fancy_allocator = std::unique_ptr<Allocator>(new FancyAllocator);
auto* alloc = fancy_allocator.get();
DenseTensor tensor_0;
tensor_0.set_meta(meta1);
DenseTensor tensor_1;
tensor_1.set_meta(meta2);
std::vector<DenseTensor> tensors;
tensors.push_back(tensor_0);
tensors.push_back(tensor_1);
tensors.push_back(tensor_0);
TensorArray tensor_array(tensors);
tensor_array.AllocateFrom(alloc, DataType::INT8);
CHECK_EQ(tensor_array.initialized(), true);
}
} // namespace tests
} // namespace phi
...@@ -1284,10 +1284,7 @@ def reverse(x, axis): ...@@ -1284,10 +1284,7 @@ def reverse(x, axis):
if isinstance(axis, int): if isinstance(axis, int):
axis = [axis] axis = [axis]
if in_dygraph_mode(): if in_dygraph_mode():
if x.type == core.VarDesc.VarType.LOD_TENSOR_ARRAY: return _C_ops.reverse(x, axis)
return _C_ops.reverse_array(x, axis)
else:
return _C_ops.reverse(x, axis)
helper = LayerHelper("reverse", **locals()) helper = LayerHelper("reverse", **locals())
out = helper.create_variable_for_type_inference(dtype=x.dtype) out = helper.create_variable_for_type_inference(dtype=x.dtype)
helper.append_op(type='reverse', helper.append_op(type='reverse',
......
...@@ -267,68 +267,6 @@ class TestReverseAxisListTensor(TestReverseAxisTensor): ...@@ -267,68 +267,6 @@ class TestReverseAxisListTensor(TestReverseAxisTensor):
return out return out
class TestAReverseEagerAPI(UnittestBase):
def test_api(self):
paddle.disable_static()
x = paddle.randn([4, 10])
y = paddle.randn([4, 10])
out = paddle._C_ops.reverse_array([x, y], [0])
np.testing.assert_allclose(x.numpy(), out[1].numpy())
np.testing.assert_allclose(y.numpy(), out[0].numpy())
paddle.enable_static()
class TestReverseTensorArrayAxisTensor(UnittestBase):
def init_info(self):
self.shapes = [[2, 3, 4]]
self.save_path = os.path.join(self.temp_dir.name,
'reverse_tensor_array')
def test_static(self):
main_prog = Program()
starup_prog = Program()
with program_guard(main_prog, starup_prog):
fc = paddle.nn.Linear(4, 2)
x = paddle.randn([2, 3, 4])
x.stop_gradient = False
feat = fc(x) # [2,3,10]
# tensor_array.shape: [[2,3,10], [2,3,10]]
tensor_array = paddle.fluid.layers.create_array(dtype='float32')
idx0 = paddle.full(shape=[1], fill_value=0, dtype="int64")
val0 = paddle.randn([2, 3, 2])
paddle.fluid.layers.array_write(val0, idx0, tensor_array)
idx1 = paddle.full(shape=[1], fill_value=1, dtype="int64")
paddle.fluid.layers.array_write(feat, idx1, tensor_array)
# axes is a Variable
axes = paddle.assign([0])
# tensor_array.shape: [[2,3,10], [2,3,10]]
reverse_array = paddle.fluid.layers.reverse(tensor_array, axes)
out, _ = paddle.fluid.layers.tensor_array_to_tensor(reverse_array,
axis=0)
sgd = paddle.optimizer.SGD()
sgd.minimize(paddle.mean(out))
self.assertTrue("Var[" in str(main_prog))
exe = paddle.static.Executor()
exe.run(starup_prog)
res = exe.run(fetch_list=[val0, feat, out])
np.testing.assert_allclose(res[1], res[-1][0:2])
np.testing.assert_allclose(res[0], res[-1][2:4])
paddle.static.save_inference_model(self.save_path, [x],
[val0, feat, out], exe)
# Test for Inference Predictor
infer_outs = self.infer_prog()
np.testing.assert_allclose(infer_outs[1], infer_outs[-1][0:2])
np.testing.assert_allclose(infer_outs[0], infer_outs[-1][2:4])
if __name__ == '__main__': if __name__ == '__main__':
paddle.enable_static() paddle.enable_static()
unittest.main() unittest.main()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册