Add axis for mul_op and rowwise_add_op#3888
Conversation
paddle/framework/eigen.h
Outdated
| PADDLE_ENFORCE(num_row_dims > 0 && num_row_dims < rank, | ||
| "`num_row_dims` must be between (0, rank_of_tensor)."); | ||
| return EigenMatrix::From( | ||
| tensor, make_ddim({static_cast<int>( |
There was a problem hiding this comment.
make_ddim could be removed, just {0, 10} is OK.
There was a problem hiding this comment.
Maybe add a method in class DDim, such as
class DDim {
public:
Dim<2> FlattenToMat(int numFlattenDims) const;
};mul_op and rowwise_add_op
|
Whether should we add a reshape operator? if user want to multiply two tensors, he should reshape the tensor to matrix first. |
|
@QiJune It's a feasible way, but might be slow and consume more memory. |
paddle/framework/attribute.h
Outdated
| public: | ||
| explicit EqualLargerThanChecker(T lower_bound) : lower_bound_(lower_bound) {} | ||
| void operator()(T& value) const { | ||
| PADDLE_ENFORCE(value >= lower_bound_, "equal_larger_than check fail"); |
There was a problem hiding this comment.
check fail -> check fails
paddle/framework/tensor_impl.h
Outdated
| inline const DDim& Tensor::dims() const { return dims_; } | ||
|
|
||
| template <typename T> | ||
| inline Tensor FlattenToMatrix(const Tensor& src, int num_row_dims) { |
There was a problem hiding this comment.
It's better to add the explanation for num_row_dims.
There was a problem hiding this comment.
num_row_dims is not easy to use, so I use num_col_dms instead. And comments have been added.
paddle/operators/mul_op.cc
Outdated
| AddAttr<int>( | ||
| "x_num_row_dims", | ||
| "mul_op can take tensors with more than two dimensions as input `X`, " | ||
| "in that case, tensors will be flattened to a matrix. The matrix's " |
There was a problem hiding this comment.
flattened -> reshaped? In the Numpy, flatten means converting to a vector.
paddle/operators/mul_op.cc
Outdated
| "mul_op can take tensors with more than two dimensions as input `X`, " | ||
| "in that case, tensors will be flattened to a matrix. The matrix's " | ||
| "second dimension(row length) will be the product of tensor's last " | ||
| "`num_row_dims` dimensions, and the matrix's first dimension(column " |
There was a problem hiding this comment.
second dimension(row length)
matrix's first dimension(column length)
matrix's first dimension是 dims[0]? second dimension是dims[1]吗? 如果是,matrix's first dimension表示的row length(也就是height), second dimension表示的是col length(也就是width)。
There was a problem hiding this comment.
我想表达的row length的意思是“行的长度”,所以似乎应该是width?
| "`num_row_dims` dimensions, and the matrix's first dimension(column " | ||
| "length) will be the product of tensor's first `rank - num_row_dims` " | ||
| "dimensions.") | ||
| .SetDefault(1) |
There was a problem hiding this comment.
依据上面的描述,和最常用的情况不符合,最常用的是reshape成:height = dims[0], width = product(dims[1:])
There was a problem hiding this comment.
已经修改,把参数从num_raw_dims改成了num_col_dims,表示乘起来的前面维度的数目
paddle/operators/mul_op.h
Outdated
| 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 | ||
| you may obtain a copy of the License at |
paddle/operators/mul_op.h
Outdated
| 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. | ||
| WITHOUT WARRANTIES OR CONDITIONS OF ANy KIND, either express or implied. |
paddle/operators/mul_op.h
Outdated
| z->mutable_data<T>(context.GetPlace()); | ||
| const Tensor* x = context.Input<Tensor>("X"); | ||
| const Tensor* y = context.Input<Tensor>("Y"); | ||
| Tensor* Z = context.Output<Tensor>("Out"); |
paddle/framework/ddim.cc
Outdated
| DDim flatten_to_2d(const DDim& src, int num_col_dims) { | ||
| int rank = src.size(); | ||
| return make_ddim( | ||
| {static_cast<int>(product(slice_ddim(src, 0, num_col_dims))), |
There was a problem hiding this comment.
Well, it seems that another PR changes int -> int64_t for ddim.
There was a problem hiding this comment.
I forgot to change here. Thanks!
paddle/framework/eigen.h
Outdated
| static typename EigenVector::Type Flatten(Tensor& tensor) { | ||
| return EigenVector::From( | ||
| tensor, make_ddim({static_cast<int>(product(tensor.dims_))})); | ||
| return EigenVector::From(tensor, {static_cast<int>(product(tensor.dims_))}); |
There was a problem hiding this comment.
size_t or ssize_t is better, please do not mix use of int64 and size_t
There was a problem hiding this comment.
product() retuens int64_t now, so static_cast can be removed.
paddle/framework/eigen.h
Outdated
| static typename EigenVector::ConstType Flatten(const Tensor& tensor) { | ||
| return EigenVector::From( | ||
| tensor, make_ddim({static_cast<int>(product(tensor.dims_))})); | ||
| return EigenVector::From(tensor, {static_cast<int>(product(tensor.dims_))}); |
paddle/framework/ddim.cc
Outdated
| } | ||
|
|
||
| DDim flatten_to_1d(const DDim& src) { | ||
| return make_ddim({static_cast<int>(product(src))}); |
paddle/framework/eigen_test.cc
Outdated
| TEST(Eigen, MatrixReshape) { | ||
| Tensor t; | ||
| float* p = | ||
| t.mutable_data<float>(make_ddim({2, 3, 6, 4}), platform::CPUPlace()); |
There was a problem hiding this comment.
make_ddim is not needed, just t.mutable_data<float>({2, 3, 6, 4}) is cool.
| inline const DDim& Tensor::dims() const { return dims_; } | ||
|
|
||
| template <typename T> | ||
| inline Tensor ReshapeToMatrix(const Tensor& src, int num_col_dims) { |
There was a problem hiding this comment.
inline is not needed in class method. It will be compiler's choice whether inline or not.
There was a problem hiding this comment.
It's not a class method. It's a global function.
paddle/framework/tensor_test.cc
Outdated
| using namespace paddle::framework; | ||
| using namespace paddle::platform; | ||
| Tensor src; | ||
| int* src_ptr = src.mutable_data<int>(make_ddim({2, 3, 4, 9}), CPUPlace()); |
paddle/operators/mul_op.cc
Outdated
| ctx.op().Input("Y")); | ||
| auto x_dims = ctx.Input<Tensor>("X")->dims(); | ||
| auto y_dims = ctx.Input<Tensor>("Y")->dims(); | ||
| int x_num_col_dims = GetAttr<int>("x_num_col_dims"); |
There was a problem hiding this comment.
Sorry... I just merge a PR, change GetAttr to Attr. Since all method in Op is Input, Output. Not GetInput or GetOutput.
| AddInput("X", "The first input of mul op"); | ||
| AddInput("Y", "The second input of mul op"); | ||
| AddOutput("Out", "The output of mul op"); | ||
| AddAttr<int>( |
There was a problem hiding this comment.
There is a very useful syntax in C++ 11.
AddAttr<int>("x_num_col_dims", R"DOC(mul_op can take ...
....
)DOC");R"LABEL(...)LABEL" is just like python's """...""". which LABEL is a custom label to identify where the string begins and ends.
See http://en.cppreference.com/w/cpp/language/string_literal
There was a problem hiding this comment.
Got it, Thank you!
paddle/operators/mul_op.cc
Outdated
| "Out@GRAD M X N must equal to Y dims 1, N "); | ||
|
|
||
| auto x_mat_dims = | ||
| framework::flatten_to_2d(x_dims, GetAttr<int>("x_num_col_dims")); |
paddle/operators/mul_op.cc
Outdated
| auto x_mat_dims = | ||
| framework::flatten_to_2d(x_dims, GetAttr<int>("x_num_col_dims")); | ||
| auto y_mat_dims = | ||
| framework::flatten_to_2d(y_dims, GetAttr<int>("y_num_col_dims")); |
| x_dims.size(), b_dims.size(), | ||
| "The rank of input `X` must be larger than the one of input `b`."); | ||
|
|
||
| int num_col_dims = x_dims.size() - b_dims.size(); |
There was a problem hiding this comment.
Interesting implementation here. So the rowwise_add's num_col_dims is decided by the rank difference.
There was a problem hiding this comment.
Yes. It makes sure that b is flattened to a vector.
reyoung
left a comment
There was a problem hiding this comment.
Excellent Job!
But sorry for I just merging A PR change GetAttr -> Attr. So please merge develop branch before merge.
paddle/framework/attribute.h
Outdated
| }; | ||
|
|
||
| template <typename T> | ||
| class EqualLargerThanChecker { |
There was a problem hiding this comment.
The name is better to compatible with gtest. Such as CHECK_GE or something?
There was a problem hiding this comment.
EqualLargerThan is a function, not a macro, so the name shall not be too short.
paddle/framework/attribute.h
Outdated
| public: | ||
| explicit EqualLargerThanChecker(T lower_bound) : lower_bound_(lower_bound) {} | ||
| void operator()(T& value) const { | ||
| PADDLE_ENFORCE(value >= lower_bound_, "equal_larger_than check fails."); |
There was a problem hiding this comment.
PADDLE_ENFORCE_GE(xxx, xxx, "comment")
paddle/framework/eigen.h
Outdated
| static typename EigenVector::Type Flatten(Tensor& tensor) { | ||
| return EigenVector::From( | ||
| tensor, make_ddim({static_cast<int>(product(tensor.dims_))})); | ||
| return EigenVector::From(tensor, {static_cast<int>(product(tensor.dims_))}); |
There was a problem hiding this comment.
size_t or ssize_t is better, please do not mix use of int64 and size_t
| no_grad_set={"Y"}) | ||
|
|
||
|
|
||
| # TODO(dzh,qijun) : mulgrad test case need transpose feature of blas library |
There was a problem hiding this comment.
this line of comment can be removed.
fixes #3722
FlattenToMatrixto convert a tensor to a matrix.x_num_col_dimsandy_num_col_dimsformul_opand adjust itsInferShapeand kernel computation.num_col_dimsmean how many dimensions will be producted togother to build the result matrix's first dimension.e.g. [2,3,4,5,6] num_col_dims=3 ====> [24, 30]
mul_optakes tensors as inputsrowwise_add_oprowwise_add_optakes tensors as inputs