Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 8 commits into from
Jul 14, 2017

Conversation

JiayiFeng
Copy link
Collaborator

  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.

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`.
@JiayiFeng JiayiFeng requested review from reyoung, a user, luotao1, qingqing01 and QiJune July 12, 2017 10:23
}

Tensor slice_tensor = src_tensor.Slice(1, 2);
dst_tensor.CopyFrom(slice_tensor, CPUPlace());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个CopyFrom和memcpy还是不大一样吧。比如memcpy(src_ptr, att + 1, 8 *sizeof(int)),CopyFrom能做么?是准备后续增加?

Copy link
Collaborator Author

@JiayiFeng JiayiFeng Jul 13, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我的理解是,这种可以随意指定开头和长度的拷贝对于tensor来说并不一定有意义,因为很可能拷贝出来的内容无法组成一个tensor,所以并不是CopyFrom应该提供的功能

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. 同意

|| 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)));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tensor() : offset_(0) {}

这个构造函数没有初始化dims_,假如先调用这个空的构造函数,再调用该mutable_data会有问题。

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

确实会有这样的问题……看来需要在mutable_data(Place place)PADDLE_ENFORCE一下:

PADDLE_ENFORCE(product(dims_) > 0)

即使不提供mutable_data(Place place)接口,这个判断应该也是有必要的,因为在调用mutable_data(DDim dims, Place place)的时候也可能传一个{0}的DDim进来。

@@ -63,6 +70,15 @@ class Tensor {
offset_ = src.offset_;
}

void CopyFrom(const Tensor& src, paddle::platform::Place dst_place) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dst_placeplace_可能不一样? 为什么要加dst_place?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

确实可能不一样,可能跨设备拷贝。

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();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

很多地方用了product(),觉得加一个获取size的接口也可以~

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

确实。另外我怀疑product可能存在性能问题,因为目前的实现是把DDim转化为vector<int>,再做连乘,可能会比较慢

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

同意获取size的接口。另外,能加个reshape dim的接口么,比如把dim<1, 10, 20>变成<10, 20>。

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();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

* src.holder_->TypeSize() 也可以在PlaceholderImpl里吧

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个没太理解?

1. Add template T which indicates data type to `CopyFrom()`, `Slice()`
and `ShareData()` functions. This makes `CopyData()` code much clearer.

2. Add `set_dim()`.

3. `product(DDim)` transforms `DDim` to `vector<int>` first and then calculate
its product. That might be quite slow. For `product(dims_)` is frequently
used in Tensor, we add a mumber variable `numel_` as a cache of the
product result.
TODO: refactor `product()` to make it more efficient.

4. Unable Tensor::operator=

5. Remove the limit of POD type, because `float16` and `int8` are not POD type.
}
dims_ = dims;
numel_ = product(dims_);
return;
Copy link
Member

@QiJune QiJune Jul 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return here is unnecessary here, Please remove it

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

inline void CheckDimsValidity() const {
PADDLE_ENFORCE(holder_ != nullptr,
"Tenosr holds no memory. Call Tensor::mutable_data first.");
PADDLE_ENFORCE(holder_->size() > numel_ * sizeof(T) + offset_,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

>= will be good.
And maybe CheckDims is more concise than CheckDimsValidity

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

src.CheckDimsValidity<T>();
size_t size = src.numel_ * sizeof(T);
set_dims(src.dims());
const void* src_ptr = static_cast<const void*>(src.data<T>());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why use const here(static_cast<const void*>)? data() will return a const T*

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const T* is not allowed to transform to void* by static_cast.

T* mutable_data(paddle::platform::Place place) {
PADDLE_ENFORCE(numel_ > 0,
"Tensor::numel_ must be larger than zero to call "
"Tensor::mutable_data.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Users can not call this method, only he calls set_dims or mutable_data(dim,place) first. So, we should inform the users more clearly.

And is mutable_data(dim, place) necessary? It's just the combination of set_dims and mutable_data(place).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Member

@QiJune QiJune left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@JiayiFeng JiayiFeng merged commit c48fc4d into PaddlePaddle:develop Jul 14, 2017
@JiayiFeng JiayiFeng deleted the dev_add_tensor_copy branch July 14, 2017 12:44
heavengate pushed a commit to heavengate/Paddle that referenced this pull request Aug 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants