-
Notifications
You must be signed in to change notification settings - Fork 5.7k
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
Add Tensor::CopyFrom and Tensor::mutable_data(Place place) #2825
Conversation
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`.
paddle/framework/tensor_test.cc
Outdated
} | ||
|
||
Tensor slice_tensor = src_tensor.Slice(1, 2); | ||
dst_tensor.CopyFrom(slice_tensor, CPUPlace()); |
There was a problem hiding this comment.
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能做么?是准备后续增加?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
我的理解是,这种可以随意指定开头和长度的拷贝对于tensor来说并不一定有意义,因为很可能拷贝出来的内容无法组成一个tensor,所以并不是CopyFrom应该提供的功能
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it. 同意
paddle/framework/tensor.h
Outdated
|| 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))); |
There was a problem hiding this comment.
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会有问题。
There was a problem hiding this comment.
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进来。
paddle/framework/tensor.h
Outdated
@@ -63,6 +70,15 @@ class Tensor { | |||
offset_ = src.offset_; | |||
} | |||
|
|||
void CopyFrom(const Tensor& src, paddle::platform::Place dst_place) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dst_place
和place_
可能不一样? 为什么要加dst_place?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
确实可能不一样,可能跨设备拷贝。
paddle/framework/tensor.h
Outdated
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(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
很多地方用了product(),觉得加一个获取size的接口也可以~
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
确实。另外我怀疑product可能存在性能问题,因为目前的实现是把DDim
转化为vector<int>
,再做连乘,可能会比较慢
There was a problem hiding this comment.
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>。
paddle/framework/tensor.h
Outdated
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(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* src.holder_->TypeSize()
也可以在PlaceholderImpl里吧
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个没太理解?
… dev_add_tensor_copy
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.
paddle/framework/tensor.h
Outdated
} | ||
dims_ = dims; | ||
numel_ = product(dims_); | ||
return; |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
paddle/framework/tensor.h
Outdated
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_, |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
paddle/framework/tensor.h
Outdated
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>()); |
There was a problem hiding this comment.
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*
There was a problem hiding this comment.
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.
paddle/framework/tensor.h
Outdated
T* mutable_data(paddle::platform::Place place) { | ||
PADDLE_ENFORCE(numel_ > 0, | ||
"Tensor::numel_ must be larger than zero to call " | ||
"Tensor::mutable_data."); |
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
* fix sync_bn in cpu
Add
Tensor::CopyFrom
. Current version can only support CPU memorycopy. 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, ifwe try to check and reuse
placeholder_
, we have to provide a templateparameter for
CopyFrom
to indicate the data type. It seems strange fora simple copy function.
Add
Tensor::mutable_data(Place place)
, which directly use membervariable
dims_
as its dim parameter. This interface is required byOp::InferShape
.