提交 69d99d48 编写于 作者: F fengjiayi

Add Tensor::CopyFrom and Tensor::mutable_data(Place place)

1. Add `Tensor::CopyFrom`. Current version can only support CPU memory
copy. The support of GPU will be provided later by `paddle::memory`.
The current implementation of `Tensor::CopyFrom` is a little inefficient:
Every time `CopyFrom` is called, tensor will re-allocate its memory. However, if
we try to check and reuse `placeholder_`, we have to provide a template
parameter for `CopyFrom` to indicate the data type. It seems strange for
a simple copy function.

2. Add `Tensor::mutable_data(Place place)`, which directly use member
variable `dims_` as its dim parameter. This interface is required by
`Op::InferShape`.
上级 8681c580
......@@ -15,6 +15,7 @@ limitations under the License. */
#pragma once
#include <cstdint>
#include <cstring>
#include <memory>
#include <type_traits>
#include "paddle/framework/ddim.h"
......@@ -44,11 +45,17 @@ class Tensor {
typename std::enable_if<std::is_pod<T>::value>::type* = nullptr>
T* mutable_data(DDim dims, paddle::platform::Place place) {
dims_ = dims;
return mutable_data<T>(place);
}
template <typename T, // must be POD types
typename std::enable_if<std::is_pod<T>::value>::type* = nullptr>
T* mutable_data(paddle::platform::Place place) {
if (holder_ == nullptr ||
!(holder_->Place() ==
place) /* some versions of boost::variant don't have operator!= */
|| holder_->Size() < product(dims) * sizeof(T) + offset_) {
holder_.reset(new PlaceholderImpl<T>(place, product(dims) * sizeof(T)));
|| holder_->Size() < product(dims_) * sizeof(T) + offset_) {
holder_.reset(new PlaceholderImpl<T>(place, product(dims_) * sizeof(T)));
offset_ = 0;
}
return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(holder_->Ptr()) +
......@@ -63,6 +70,15 @@ class Tensor {
offset_ = src.offset_;
}
void CopyFrom(const Tensor& src, paddle::platform::Place dst_place) {
PADDLE_ENFORCE(src.holder_ != nullptr,
"Can not copy from an uninitialized tensor.");
size_t size = product(src.dims()) * src.holder_->TypeSize();
holder_.reset(src.holder_->Clone(src.offset_, size, dst_place));
dims_ = src.dims();
offset_ = 0;
}
Tensor Slice(const int& begin_idx, const int& end_idx) const {
PADDLE_ENFORCE(holder_ != nullptr,
"The sliced tenosr has not been initialized.");
......@@ -95,6 +111,8 @@ class Tensor {
virtual paddle::platform::Place Place() const = 0;
virtual size_t Size() const = 0;
virtual size_t TypeSize() const = 0;
virtual Placeholder* Clone(size_t begin, size_t size,
paddle::platform::Place place) const = 0;
};
template <typename T>
......@@ -122,6 +140,18 @@ class Tensor {
virtual size_t Size() const { return size_; }
virtual paddle::platform::Place Place() const { return place_; }
virtual size_t TypeSize() const { return sizeof(T); }
// TODO: Clone only support CPU now. GPU support is needed.
virtual Placeholder* Clone(size_t begin, size_t size,
paddle::platform::Place place) const {
PADDLE_ENFORCE(paddle::platform::is_cpu_place(place_) &&
paddle::platform::is_cpu_place(place),
"PlaceholderImpl::Clone only support CPU now.");
PlaceholderImpl<T>* dst = new PlaceholderImpl<T>(place, size);
void* begin_ptr =
reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(Ptr()) + begin);
memcpy(dst->Ptr(), begin_ptr, size);
return dst;
}
std::unique_ptr<T, Deleter> ptr_;
paddle::platform::Place place_; // record the place of ptr_.
......
......@@ -178,4 +178,29 @@ TEST(Tensor, Slice) {
}
}
TEST(Tensor, CopyFrom) {
using namespace paddle::framework;
using namespace paddle::platform;
Tensor src_tensor;
int* src_ptr = src_tensor.mutable_data<int>(make_ddim({3, 3}), CPUPlace());
int arr[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
memcpy(src_ptr, arr, 9 * sizeof(int));
Tensor dst_tensor;
dst_tensor.CopyFrom(src_tensor, CPUPlace());
const int* dst_ptr = dst_tensor.data<int>();
ASSERT_NE(src_ptr, dst_ptr);
for (size_t i = 0; i < 9; ++i) {
EXPECT_EQ(src_ptr[i], dst_ptr[i]);
}
Tensor slice_tensor = src_tensor.Slice(1, 2);
dst_tensor.CopyFrom(slice_tensor, CPUPlace());
const int* slice_ptr = slice_tensor.data<int>();
dst_ptr = dst_tensor.data<int>();
ASSERT_NE(dst_ptr, slice_ptr);
for (size_t i = 0; i < 3; ++i) {
EXPECT_EQ(dst_ptr[i], slice_ptr[i]);
}
}
*/
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册