未验证 提交 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(
cc_library(
var_type_traits
SRCS var_type_traits.cc
DEPS framework_proto scope)
DEPS framework_proto scope tensor_array)
if(WITH_GPU)
target_link_libraries(var_type_traits dynload_cuda)
endif()
......
......@@ -13,14 +13,14 @@ See the License for the specific language governing permissions and
limitations under the License. */
#pragma once
#include <vector>
#include "paddle/fluid/framework/lod_tensor.h"
#include "paddle/phi/core/tensor_array.h"
namespace paddle {
namespace framework {
using LoDTensorArray = std::vector<LoDTensor>;
using LoDTensorArray = phi::TensorArray;
} // namespace framework
} // namespace paddle
......@@ -2665,13 +2665,8 @@ void OperatorWithKernel::BuildPhiKernelContext(
phi_kernel_context->EmplaceBackInputWithoutSetRange(tensor_in);
} else if (var->IsType<framework::LoDTensorArray>()) {
need_prepare_phi_data_ = true;
paddle::small_vector<const phi::TensorBase*> tensor_vector;
auto& tensor_array = var->Get<framework::LoDTensorArray>();
for (auto& t : tensor_array) {
tensor_vector.emplace_back(&t);
}
phi_kernel_context->EmplaceBackInputsWithoutSetRange(tensor_vector);
end_idx += tensor_array.size() - 1;
tensor_in = &(var->Get<framework::LoDTensorArray>());
phi_kernel_context->EmplaceBackInputWithoutSetRange(tensor_in);
} else {
PADDLE_THROW(platform::errors::Unimplemented(
"Unsupported input `%s` type when call pt kernel.",
......@@ -2714,16 +2709,10 @@ void OperatorWithKernel::BuildPhiKernelContext(
tensor_out = var->template GetMutable<phi::SelectedRows>();
phi_kernel_context->EmplaceBackOutputWithoutSetRange(tensor_out);
} else if (var->template IsType<framework::LoDTensorArray>()) {
paddle::small_vector<phi::TensorBase*> tensor_vector;
auto* tensor_array =
var->template GetMutable<framework::LoDTensorArray>();
tensor_out = var->template GetMutable<framework::LoDTensorArray>();
// Note: If the input LoDTensorArray size is 0, the output
// LoDTensorArray is also 0
for (auto& t : *tensor_array) {
tensor_vector.emplace_back(&t);
}
phi_kernel_context->EmplaceBackOutputsWithoutSetRange(tensor_vector);
end_idx += tensor_array->size() - 1;
phi_kernel_context->EmplaceBackOutputWithoutSetRange(tensor_out);
} else {
PADDLE_THROW(platform::errors::Unimplemented(
"Unsupported output `%s` type when call pt kernel.",
......
......@@ -19,7 +19,7 @@
namespace paddle {
namespace framework {
void ReaderBase::ReadNext(std::vector<LoDTensor> *out) {
void ReaderBase::ReadNext(paddle::framework::LoDTensorArray *out) {
std::lock_guard<std::mutex> lock(mu_);
PADDLE_ENFORCE_EQ(status_,
ReaderStatus::kRunning,
......
......@@ -48,7 +48,7 @@ class ReaderBase {
"and need_check_feed"));
}
virtual void ReadNext(std::vector<LoDTensor>* out);
virtual void ReadNext(paddle::framework::LoDTensorArray* out);
virtual void Shutdown();
......@@ -73,7 +73,7 @@ class ReaderBase {
virtual ~ReaderBase();
protected:
virtual void ReadNextImpl(std::vector<LoDTensor>* out) {}
virtual void ReadNextImpl(paddle::framework::LoDTensorArray* out) {}
virtual void ShutdownImpl() {}
......@@ -167,7 +167,7 @@ class ReaderHolder {
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(
reader_,
platform::errors::InvalidArgument(
......
......@@ -24,7 +24,7 @@ class StubDecoratedReader : public paddle::framework::DecoratedReader {
explicit StubDecoratedReader(const std::shared_ptr<ReaderBase> &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 {
......@@ -34,7 +34,7 @@ class StubRootReader : public paddle::framework::ReaderBase {
const std::vector<paddle::framework::proto::VarType::Type> &var_types,
const std::vector<bool> &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) {
......
......@@ -330,13 +330,8 @@ void BuildDygraphPhiKernelContext(const phi::KernelSignature& kernel_signature,
tensor_in = &(var.template Get<phi::SelectedRows>());
kernel_ctx->EmplaceBackInputWithoutSetRange(tensor_in);
} else if (var.template IsType<framework::LoDTensorArray>()) {
paddle::small_vector<const phi::TensorBase*> tensor_vector;
auto& tensor_array = var.template Get<framework::LoDTensorArray>();
for (auto& t : tensor_array) {
tensor_vector.emplace_back(&t);
}
kernel_ctx->EmplaceBackInputsWithoutSetRange(tensor_vector);
end_idx += tensor_array.size() - 1;
tensor_in = &(var.template Get<framework::LoDTensorArray>());
kernel_ctx->EmplaceBackInputWithoutSetRange(tensor_in);
} else {
PADDLE_THROW(platform::errors::Unimplemented(
"Unsupported input `%s` type when call pt kernel.",
......@@ -377,14 +372,8 @@ void BuildDygraphPhiKernelContext(const phi::KernelSignature& kernel_signature,
tensor_out = var->template GetMutable<phi::SelectedRows>();
kernel_ctx->EmplaceBackOutputWithoutSetRange(tensor_out);
} else if (var->template IsType<framework::LoDTensorArray>()) {
paddle::small_vector<phi::TensorBase*> tensor_vector;
auto* tensor_array =
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;
tensor_out = var->template GetMutable<framework::LoDTensorArray>();
kernel_ctx->EmplaceBackOutputWithoutSetRange(tensor_out);
} else {
PADDLE_THROW(platform::errors::Unimplemented(
"Unsupported output `%s` type when call pt kernel.",
......
......@@ -65,7 +65,7 @@ class DequeueOp : public framework::OperatorBase {
platform::errors::InvalidArgument(
"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;
lod_tensor_vec = queue_holder->GetQueue()->Pop(&success);
PADDLE_ENFORCE_EQ(lod_tensor_vec.size(),
......
......@@ -65,7 +65,7 @@ class EnqueueOp : public framework::OperatorBase {
auto* queue_holder =
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);
queue_holder->GetQueue()->Push(lod_tensor_vec);
}
......
......@@ -502,7 +502,7 @@ void BufferedReader::StartImpl() {
ReadTillBufferFullAsync();
}
void BufferedReader::ReadNextImpl(std::vector<framework::LoDTensor> *out) {
void BufferedReader::ReadNextImpl(paddle::framework::LoDTensorArray *out) {
if (position_.empty()) {
out->clear();
return;
......
......@@ -46,7 +46,7 @@ namespace operators {
namespace reader {
class BufferedReader : public framework::DecoratedReader {
using TensorVec = std::vector<framework::LoDTensor>;
using TensorVec = paddle::framework::LoDTensorArray;
using VecFuture = std::future<TensorVec>;
public:
......@@ -65,7 +65,7 @@ class BufferedReader : public framework::DecoratedReader {
protected:
void ShutdownImpl() override;
void StartImpl() override;
void ReadNextImpl(std::vector<framework::LoDTensor>* out) override;
void ReadNextImpl(paddle::framework::LoDTensorArray* out) override;
private:
ThreadPool thread_pool_;
......
......@@ -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();
std::vector<framework::LoDTensor> underlying_outs;
paddle::framework::LoDTensorArray underlying_outs;
reader_->ReadNext(&underlying_outs);
if (underlying_outs.empty()) {
// There is not next data.
......
......@@ -34,16 +34,16 @@ class 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);
}
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));
}
std::vector<framework::LoDTensor> Pop(bool* ok = nullptr) {
std::vector<framework::LoDTensor> lod_tensor_vec;
paddle::framework::LoDTensorArray Pop(bool* ok = nullptr) {
paddle::framework::LoDTensorArray lod_tensor_vec;
bool success = queue_.Receive(&lod_tensor_vec);
if (ok != nullptr) *ok = success;
return lod_tensor_vec;
......@@ -67,7 +67,7 @@ class LoDTensorBlockingQueue {
inline bool WaitForInited(size_t) { return true; }
private:
BlockingQueue<std::vector<framework::LoDTensor>> queue_;
BlockingQueue<paddle::framework::LoDTensorArray> queue_;
};
class OrderedMultiDeviceLoDTensorBlockingQueue {
......@@ -123,7 +123,7 @@ class OrderedMultiDeviceLoDTensorBlockingQueue {
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);
}
......
......@@ -30,7 +30,7 @@ PyReader::PyReader(
queue_ = queue;
}
void PyReader::ReadNext(std::vector<framework::LoDTensor>* out) {
void PyReader::ReadNext(paddle::framework::LoDTensorArray* out) {
bool success;
*out = queue_->Pop(&success);
if (!success) out->clear();
......
......@@ -35,7 +35,7 @@ class PyReader : public framework::FileReader {
const std::vector<framework::proto::VarType::Type>& var_types,
const std::vector<bool>& need_check_feed);
void ReadNext(std::vector<framework::LoDTensor>* out) override;
void ReadNext(paddle::framework::LoDTensorArray* out) override;
~PyReader();
......
......@@ -106,7 +106,7 @@ class ReadOp : public framework::OperatorBase {
scope.FindVar(Input("Reader")), "Input", "Reader", "Read")
.GetMutable<framework::ReaderHolder>();
std::vector<std::string> out_arg_names = Outputs("Out");
std::vector<framework::LoDTensor> ins;
paddle::framework::LoDTensorArray ins;
// For profiling
platform::RecordEvent record_event(
......
......@@ -483,7 +483,10 @@ std::vector<framework::Tensor> CastPyArg2VectorOfTensorBase(PyObject* obj,
} else if (PyObject_IsInstance(obj,
reinterpret_cast<PyObject*>(
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) {
return {};
} else {
......
......@@ -19,6 +19,7 @@ typedef SSIZE_T ssize_t;
#include "paddle/fluid/eager/hooks.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/jit/function.h"
#include "paddle/fluid/platform/place.h"
......
......@@ -118,7 +118,7 @@ class MultiDeviceFeedReader {
public:
using ResultDictList =
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 =
std::is_same<QueueType,
......@@ -332,7 +332,7 @@ class MultiDeviceFeedReader {
std::vector<std::future<Status>> futures_;
std::vector<std::exception_ptr> exceptions_;
std::vector<std::vector<framework::LoDTensor>> ret_;
std::vector<paddle::framework::LoDTensorArray> ret_;
bool drop_last_;
bool pin_memory_;
};
......@@ -427,7 +427,7 @@ void BindReader(py::module *module) {
.def(
"push",
[](reader::LoDTensorBlockingQueue &self,
const std::vector<framework::LoDTensor> &lod_tensor_vec) {
const paddle::framework::LoDTensorArray &lod_tensor_vec) {
return self.Push(lod_tensor_vec);
},
py::call_guard<py::gil_scoped_release>())
......@@ -445,7 +445,7 @@ void BindReader(py::module *module) {
.def(
"push",
[](reader::OrderedMultiDeviceLoDTensorBlockingQueue &self,
const std::vector<framework::LoDTensor> &lod_tensor_vec) {
const paddle::framework::LoDTensorArray &lod_tensor_vec) {
return self.Push(lod_tensor_vec);
},
py::call_guard<py::gil_scoped_release>())
......
......@@ -2193,15 +2193,6 @@
func : reverse
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_
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)
......
......@@ -57,6 +57,11 @@ cc_library(
SRCS string_tensor.cc
DEPS convert_utils tensor_meta tensor_base)
cc_library(
tensor_array
SRCS tensor_array.cc
DEPS dense_tensor tensor_base)
cc_library(
meta_tensor
SRCS meta_tensor.cc
......
......@@ -132,6 +132,11 @@ struct KernelArgsParseFunctor<Return_ (*)(Args_...)> {
default_tensor_layout,
default_key.dtype(),
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*))) {
args_def->AppendOutput(default_key.backend(),
default_tensor_layout,
......@@ -148,6 +153,11 @@ struct KernelArgsParseFunctor<Return_ (*)(Args_...)> {
default_tensor_layout,
default_key.dtype(),
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*))) {
args_def->AppendOutput(default_key.backend(),
default_tensor_layout,
......
......@@ -30,6 +30,7 @@
#include "paddle/phi/core/sparse_coo_tensor.h"
#include "paddle/phi/core/sparse_csr_tensor.h"
#include "paddle/phi/core/string_tensor.h"
#include "paddle/phi/core/tensor_array.h"
#include "paddle/phi/core/type_defs.h"
namespace phi {
......@@ -284,6 +285,9 @@ struct KernelImpl<Return (*)(DevCtx, Args...), kernel_fn> {
PD_SPECIALIZE_KernelCallHelper_FOR_OPTIONAL_INPUT(StringTensor);
PD_SPECIALIZE_KernelCallHelper_FOR_MULTI_INPUT(StringTensor);
PD_SPECIALIZE_KernelCallHelper_FOR_INPUT(TensorArray);
PD_SPECIALIZE_KernelCallHelper_FOR_MULTI_INPUT(TensorArray);
/* Attribute Helpers */
PD_SPECIALIZE_KernelCallHelper_FOR_ATTRIBUTE(bool);
......@@ -322,6 +326,8 @@ struct KernelImpl<Return (*)(DevCtx, Args...), kernel_fn> {
PD_SPECIALIZE_KernelCallHelper_FOR_OUTPUT(StringTensor);
PD_SPECIALIZE_KernelCallHelper_FOR_MULTI_OUTPUT(StringTensor);
PD_SPECIALIZE_KernelCallHelper_FOR_OUTPUT(TensorArray);
template <typename... Tail>
struct KernelCallHelper<const RuntimeAttrs&, Tail...> {
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
string_tensor
sparse_coo_tensor
sparse_csr_tensor
tensor_array
kernel_context
kernel_factory
arg_map_context
......
......@@ -45,10 +45,10 @@ void AssignRawKernel(const Context& dev_ctx,
// as input if needed
template <typename Context>
void AssignArrayKernel(const Context& dev_ctx,
const std::vector<const DenseTensor*>& x,
std::vector<DenseTensor*> out) {
const TensorArray& x,
TensorArray* out) {
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 @@
#include "paddle/phi/common/scalar.h"
#include "paddle/phi/core/dense_tensor.h"
#include "paddle/phi/core/tensor_array.h"
#include "paddle/phi/infermeta/unary.h"
namespace phi {
......@@ -47,8 +48,8 @@ void AssignRawKernel(const Context& dev_ctx,
template <typename Context>
void AssignArrayKernel(const Context& dev_ctx,
const std::vector<const DenseTensor*>& x,
std::vector<DenseTensor*> out);
const TensorArray& x,
TensorArray* out);
template <typename T, typename Context>
void AssignValueKernel(const Context& dev_ctx,
......
......@@ -20,6 +20,7 @@
#include "paddle/phi/core/ddim.h"
#include "paddle/phi/core/dense_tensor.h"
#include "paddle/phi/core/enforce.h"
#include "paddle/phi/core/tensor_array.h"
#include "paddle/phi/core/tensor_utils.h"
#include "paddle/phi/kernels/funcs/eigen/common.h"
#include "paddle/phi/kernels/funcs/eigen/eigen_function.h"
......@@ -297,14 +298,14 @@ void StridedSliceCompute(const Context& dev_ctx,
template <typename Context, typename T, size_t D>
void StridedSliceCompute(const Context& dev_ctx,
const std::vector<const DenseTensor*>& x,
const TensorArray& x,
const std::vector<int>& axes,
const IntArray& starts,
const IntArray& ends,
const IntArray& strides,
const std::vector<int>& infer_flags,
const std::vector<int>& decrease_axis,
std::vector<DenseTensor*> out) {
TensorArray* out) {
const int64_t size = x.size();
auto in_dims = phi::make_ddim({size});
......@@ -419,29 +420,29 @@ void StridedSliceCompute(const Context& dev_ctx,
"dimension of Output should be 1, but received %d",
out_dims_origin.size()));
out.resize(out_dims_origin[0]);
out->resize(out_dims_origin[0]);
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 =
(starts_indices[0] % in_array_size) + i * strides_indices[0];
int64_t out_offset = i;
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(
in_tensor->memory_size(),
in_tensor.memory_size(),
0,
errors::PreconditionNotMet(
"The input LoDTensorArray Input[%d] holds no memory.", in_offset));
auto* out_tensor = out.at(out_offset);
out_tensor->Resize(in_tensor->dims());
auto& out_tensor = out->at(out_offset);
out_tensor.Resize(in_tensor.dims());
phi::Copy<Context>(
dev_ctx, *in_tensor, dev_ctx.GetPlace(), false, out_tensor);
out_tensor->set_lod(in_tensor->lod());
dev_ctx, in_tensor, dev_ctx.GetPlace(), false, &out_tensor);
out_tensor.set_lod(in_tensor.lod());
}
}
......@@ -531,15 +532,15 @@ void StridedSliceGradCompute(const Context& dev_ctx,
template <typename Context, typename T, size_t D>
void StridedSliceGradCompute(const Context& dev_ctx,
const std::vector<const DenseTensor*>& x,
const std::vector<const DenseTensor*>& out_grad,
const TensorArray& x,
const TensorArray& out_grad,
const std::vector<int>& axes,
const IntArray& starts,
const IntArray& ends,
const IntArray& strides,
const std::vector<int>& infer_flags,
const std::vector<int>& decrease_axis,
std::vector<DenseTensor*> x_grad) {
TensorArray* x_grad) {
// Note(weixin):Since the shape of `framework::GradVarName("Input")` of
// StridedSliceGrad cannot be calculated by
// `framework::GradVarName("Output")`, the dim of "Input" is used to
......@@ -619,11 +620,11 @@ void StridedSliceGradCompute(const Context& dev_ctx,
"the dimension of output should be 1, but received %d.",
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++) {
auto& dim = x.at(j)->dims();
auto* d_out_tensor = x_grad.at(j);
auto& dim = x.at(j).dims();
auto& d_out_tensor = x_grad->at(j);
int64_t sub = j - starts_indices[0];
......@@ -635,26 +636,26 @@ void StridedSliceGradCompute(const Context& dev_ctx,
if ((sub % strides_indices[0] == 0) && (0 <= in_offset) &&
(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(
in_tensor->memory_size(),
in_tensor.memory_size(),
0,
errors::PreconditionNotMet(
"The input LoDTensorArray Input[%d] holds no memory.",
in_offset));
phi::Copy<Context>(
dev_ctx, *in_tensor, dev_ctx.GetPlace(), false, d_out_tensor);
d_out_tensor->set_lod(in_tensor->lod());
dev_ctx, in_tensor, dev_ctx.GetPlace(), false, &d_out_tensor);
d_out_tensor.set_lod(in_tensor.lod());
} else {
d_out_tensor->Resize(dim);
d_out_tensor.Resize(dim);
if (!d_out_tensor->IsInitialized()) {
dev_ctx.template Alloc<T>(d_out_tensor);
if (!d_out_tensor.IsInitialized()) {
dev_ctx.template Alloc<T>(&d_out_tensor);
}
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,
}
template <typename T, typename Context>
void StridedSliceArrayGradKernel(
const Context& dev_ctx,
const std::vector<const DenseTensor*>& x,
const std::vector<const DenseTensor*>& out_grad,
const std::vector<int>& axes,
const IntArray& starts,
const IntArray& ends,
const IntArray& strides,
const std::vector<int>& infer_flags,
const std::vector<int>& decrease_axis,
std::vector<DenseTensor*> x_grad) {
void StridedSliceArrayGradKernel(const Context& dev_ctx,
const TensorArray& x,
const TensorArray& out_grad,
const std::vector<int>& axes,
const IntArray& starts,
const IntArray& ends,
const IntArray& strides,
const std::vector<int>& infer_flags,
const std::vector<int>& decrease_axis,
TensorArray* x_grad) {
funcs::StridedSliceGradCompute<Context, T, 1>(dev_ctx,
x,
out_grad,
......
......@@ -55,14 +55,14 @@ void StridedSliceRawKernel(const Context& dev_ctx,
template <typename T, typename Context>
void StridedSliceArrayKernel(const Context& dev_ctx,
const std::vector<const DenseTensor*>& x,
const TensorArray& x,
const std::vector<int>& axes,
const IntArray& starts,
const IntArray& ends,
const IntArray& strides,
const std::vector<int>& infer_flags,
const std::vector<int>& decrease_axis,
std::vector<DenseTensor*> out) {
TensorArray* out) {
funcs::StridedSliceCompute<Context, T, 1>(
dev_ctx, x, axes, starts, ends, strides, infer_flags, decrease_axis, out);
}
......
......@@ -110,25 +110,21 @@ void MemcpyD2HKernel(const Context& dev_ctx,
template <typename Context>
void MemcpyD2HMultiIOKernel(const Context& dev_ctx,
const std::vector<const DenseTensor*>& array,
const TensorArray& array,
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(
array.size(),
out_array.size(),
out_array->size(),
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++) {
PADDLE_ENFORCE_NOT_NULL(
array[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]);
const auto& x = array[i];
MemcpyD2HKernel<Context>(dev_ctx, x, dst_place_type, &(out_array->at(i)));
}
}
......
......@@ -17,6 +17,7 @@
#include <vector>
#include "paddle/phi/core/dense_tensor.h"
#include "paddle/phi/core/tensor_array.h"
namespace phi {
......@@ -36,9 +37,9 @@ void MemcpyD2HKernel(const Context& dev_ctx,
template <typename Context>
void MemcpyD2HMultiIOKernel(const Context& dev_ctx,
const std::vector<const DenseTensor*>& array,
const TensorArray& array,
int dst_place_type,
std::vector<DenseTensor*> out_array);
TensorArray* out_array);
template <typename Context>
void MemcpyKernel(const Context& dev_ctx,
......
......@@ -22,29 +22,29 @@ namespace phi {
template <typename T, typename Context>
void ReverseArrayKernel(const Context& dev_ctx,
const std::vector<const DenseTensor*>& x,
const TensorArray& x,
const IntArray& axis,
std::vector<DenseTensor*> out) {
TensorArray* out) {
PADDLE_ENFORCE_EQ(
x.size(),
out.size(),
out->size(),
phi::errors::InvalidArgument("The input size(%d) and output size(%d) of "
"ReverseArrayKernel is different.",
x.size(),
out.size()));
out->size()));
for (size_t offset = 0; offset < x.size(); ++offset) {
auto* x_tensor = x.at(offset);
auto& x_tensor = x.at(offset);
PADDLE_ENFORCE_GT(
x_tensor->memory_size(),
x_tensor.memory_size(),
0,
phi::errors::PreconditionNotMet(
"The input LoDTensorArray X[%d] holds no memory.", offset));
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>(
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,
bool,
float,
double) {}
#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP)
PD_REGISTER_KERNEL(reverse_array,
GPU,
ALL_LAYOUT,
......@@ -71,4 +73,5 @@ PD_REGISTER_KERNEL(reverse_array,
bool,
float,
double) {}
#endif
......@@ -18,6 +18,7 @@
#include "paddle/phi/common/int_array.h"
#include "paddle/phi/core/dense_tensor.h"
#include "paddle/phi/core/tensor_array.h"
namespace phi {
......@@ -29,8 +30,8 @@ void ReverseKernel(const Context& dev_ctx,
template <typename T, typename Context>
void ReverseArrayKernel(const Context& dev_ctx,
const std::vector<const DenseTensor*>& x,
const TensorArray& x,
const IntArray& axis,
std::vector<DenseTensor*> out);
TensorArray* out);
} // namespace phi
......@@ -16,6 +16,7 @@
#include "paddle/phi/common/int_array.h"
#include "paddle/phi/core/dense_tensor.h"
#include "paddle/phi/core/tensor_array.h"
namespace phi {
......@@ -42,15 +43,14 @@ void StridedSliceGradKernel(const Context& dev_ctx,
DenseTensor* x_grad);
template <typename T, typename Context>
void StridedSliceArrayGradKernel(
const Context& dev_ctx,
const std::vector<const DenseTensor*>& x,
const std::vector<const DenseTensor*>& out_grad,
const std::vector<int>& axes,
const IntArray& starts,
const IntArray& ends,
const IntArray& strides,
const std::vector<int>& infer_flags,
const std::vector<int>& decrease_axis,
std::vector<DenseTensor*> x_grad);
void StridedSliceArrayGradKernel(const Context& dev_ctx,
const TensorArray& x,
const TensorArray& out_grad,
const std::vector<int>& axes,
const IntArray& starts,
const IntArray& ends,
const IntArray& strides,
const std::vector<int>& infer_flags,
const std::vector<int>& decrease_axis,
TensorArray* x_grad);
} // namespace phi
......@@ -16,6 +16,7 @@
#include "paddle/phi/common/int_array.h"
#include "paddle/phi/core/dense_tensor.h"
#include "paddle/phi/core/tensor_array.h"
namespace phi {
......@@ -41,12 +42,12 @@ void StridedSliceKernel(const Context& dev_ctx,
template <typename T, typename Context>
void StridedSliceArrayKernel(const Context& dev_ctx,
const std::vector<const DenseTensor*>& x,
const TensorArray& x,
const std::vector<int>& axes,
const IntArray& starts,
const IntArray& ends,
const IntArray& strides,
const std::vector<int>& infer_flags,
const std::vector<int>& decrease_axis,
std::vector<DenseTensor*> out);
TensorArray* out);
} // namespace phi
......@@ -60,3 +60,8 @@ cc_test(
SRCS test_string_tensor.cc
DEPS string_tensor)
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):
if isinstance(axis, int):
axis = [axis]
if in_dygraph_mode():
if x.type == core.VarDesc.VarType.LOD_TENSOR_ARRAY:
return _C_ops.reverse_array(x, axis)
else:
return _C_ops.reverse(x, axis)
return _C_ops.reverse(x, axis)
helper = LayerHelper("reverse", **locals())
out = helper.create_variable_for_type_inference(dtype=x.dtype)
helper.append_op(type='reverse',
......
......@@ -267,68 +267,6 @@ class TestReverseAxisListTensor(TestReverseAxisTensor):
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__':
paddle.enable_static()
unittest.main()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册