“e983cc90fcee4e5b73bce9d4853b85aac4661e3a”上不存在“python/paddle/fluid/tests/unittests/detected_xpu.py”
未验证 提交 080024f0 编写于 作者: Z zyfncg 提交者: GitHub

refactor unary infermeta (#40365)

上级 ec09ef26
...@@ -26,6 +26,82 @@ limitations under the License. */ ...@@ -26,6 +26,82 @@ limitations under the License. */
namespace phi { namespace phi {
void ArgMinMaxInferMeta(const MetaTensor& x,
int64_t axis,
bool keepdims,
bool flatten,
int dtype,
MetaTensor* out,
MetaConfig config) {
const auto& x_dims = x.dims();
PADDLE_ENFORCE_GE(
axis,
-x_dims.size(),
phi::errors::InvalidArgument("'axis'(%d) must be greater than or equal to"
" -Rank(X)(%d).",
axis,
-x_dims.size()));
PADDLE_ENFORCE_LT(axis,
x_dims.size(),
phi::errors::InvalidArgument(
"'axis'(%d) must be less than Rank(X)(%d) of Input(X).",
axis,
x_dims.size()));
PADDLE_ENFORCE_EQ(
(dtype < 0 || dtype == 2 || dtype == 3),
true,
phi::errors::InvalidArgument(
"The attribute of dtype in argmin/argmax must be [%s] or [%s], but "
"received [%s]",
paddle::framework::DataTypeToString(
paddle::framework::proto::VarType::INT32),
paddle::framework::DataTypeToString(
paddle::framework::proto::VarType::INT64),
paddle::framework::DataTypeToString(
static_cast<paddle::framework::proto::VarType::Type>(dtype))));
auto x_rank = x_dims.size();
if (axis < 0) axis += x_rank;
if (config.is_runtime) {
if (dtype == paddle::framework::proto::VarType::INT32) {
int64_t all_element_num = 0;
if (flatten) {
all_element_num = phi::product(x_dims);
} else {
all_element_num = x_dims[axis];
}
PADDLE_ENFORCE_LE(
all_element_num,
INT_MAX,
phi::errors::InvalidArgument(
"The element num of the argmin/argmax input at axis is "
"%d, is larger than int32 maximum value:%d, you must "
"set the dtype of argmin/argmax to 'int64'.",
all_element_num,
INT_MAX));
}
}
std::vector<int64_t> vec;
if (flatten) {
vec.emplace_back(static_cast<int64_t>(1));
} else {
for (int64_t i = 0; i < axis; i++) vec.emplace_back(x_dims[i]);
if (keepdims) {
vec.emplace_back(static_cast<int64_t>(1));
}
for (int64_t i = axis + 1; i < x_rank; i++) vec.emplace_back(x_dims[i]);
}
out->set_dims(phi::make_ddim(vec));
if (dtype == 2) {
out->set_dtype(DataType::INT32);
} else if (dtype == 3) {
out->set_dtype(DataType::INT64);
}
}
void ArgsortInferMeta(const MetaTensor& input, void ArgsortInferMeta(const MetaTensor& input,
int axis, int axis,
bool descending, bool descending,
...@@ -54,96 +130,6 @@ void ArgsortInferMeta(const MetaTensor& input, ...@@ -54,96 +130,6 @@ void ArgsortInferMeta(const MetaTensor& input,
indices->share_lod(input); indices->share_lod(input);
} }
void UnchangedInferMeta(const MetaTensor& x, MetaTensor* out) {
out->share_meta(x);
}
// meta x -> out without change, check if axis in range [-Rank(x), Rank(x)-1]
void UnchangedInferMetaCheckAxis(const MetaTensor& x,
int axis,
MetaTensor* out) {
auto rank = x.dims().size();
PADDLE_ENFORCE_GE(
axis,
-rank,
errors::InvalidArgument(
"Attr(axis) value should be in range [-R, R-1], "
"R is the rank of Input(X). But received axis: %d, R: %d.",
axis,
rank));
PADDLE_ENFORCE_LT(
axis,
rank,
phi::errors::InvalidArgument(
"Attr(axis) value should be in range [-R, R-1], "
"R is the rank of Input(X). But received axis: %d, R: %d.",
axis,
rank));
out->share_meta(x);
}
void RealAndImagInferMeta(const MetaTensor& x, MetaTensor* out) {
out->set_dims(x.dims());
out->set_dtype(dtype::ToReal(x.dtype()));
out->set_layout(x.layout());
}
void FlattenInferMeta(const MetaTensor& x,
int start_axis,
int stop_axis,
MetaTensor* out) {
auto x_dims = x.dims();
int in_dims_size = x_dims.size();
if (start_axis < 0) {
start_axis = start_axis + in_dims_size;
}
if (stop_axis < 0) {
stop_axis = stop_axis + in_dims_size;
}
PADDLE_ENFORCE_GE(
stop_axis,
start_axis,
phi::errors::InvalidArgument("The stop_axis should be greater"
"than or equal to start_axis."));
int64_t outer = 1;
std::vector<int32_t> out_shape;
out_shape.reserve(in_dims_size - stop_axis + start_axis);
for (int i = 0; i < start_axis; ++i) {
out_shape.push_back(x_dims[i]);
}
for (int i = start_axis; i <= stop_axis; i++) {
if (x_dims[i] == -1 || outer == -1) {
outer = -1;
} else {
outer *= x_dims[i];
}
}
out_shape.push_back(outer);
for (int i = stop_axis + 1; i < in_dims_size; i++) {
out_shape.push_back(x_dims[i]);
}
const auto& out_dims = phi::make_ddim(out_shape);
out->set_dims(out_dims);
out->set_dtype(x.dtype());
out->set_layout(x.layout());
if (x_dims[0] == out_dims[0]) {
// Only pass LoD when the first dimension of output and Input(X)
// are the same.
out->share_lod(x);
}
}
void GumbelSoftmaxInferMeta(const MetaTensor& x,
float temperature,
bool hard,
int axis,
MetaTensor* out) {
UnchangedInferMetaCheckAxis(x, axis, out);
}
void CastInferMeta(const MetaTensor& x, DataType out_dtype, MetaTensor* out) { void CastInferMeta(const MetaTensor& x, DataType out_dtype, MetaTensor* out) {
out->set_dims(x.dims()); out->set_dims(x.dims());
out->set_dtype(out_dtype); out->set_dtype(out_dtype);
...@@ -203,50 +189,252 @@ void CumsumInferMeta(const MetaTensor& x, ...@@ -203,50 +189,252 @@ void CumsumInferMeta(const MetaTensor& x,
out->share_lod(x); out->share_lod(x);
} }
void IncrementInferMeta(const MetaTensor& x, float value, MetaTensor* out) { void DiagInferMeta(const MetaTensor& x,
PADDLE_ENFORCE_EQ( int offset,
product(x.dims()), float padding_value,
1UL, MetaTensor* out) {
errors::InvalidArgument("The number of elements in Input(X) should be 1." auto x_dims = x.dims();
"Now the number is %d.",
product(x.dims()))); if (x_dims.size() == 1UL) {
out->set_dims(x.dims()); int64_t size_ = x_dims[0] + std::abs(offset);
out->share_lod(x); out->set_dims({size_, size_});
out->set_dtype(x.dtype());
} else if (x_dims.size() == 2UL) {
int64_t size_ = 0;
if (offset >= 0) {
// Note(LutaoChu): Do not use std::min here, otherwise the calculation
// of `size_` will have unexpected result on Windows Python3.8
if (x_dims[0] < x_dims[1] - offset) {
size_ = x_dims[0];
} else {
size_ = x_dims[1] - offset;
}
} else {
// Note(LutaoChu): Do not use std::min here, otherwise the calculation
// of `size_` will have unexpected result on Windows Python3.8
if (x_dims[0] + offset < x_dims[1]) {
size_ = x_dims[0] + offset;
} else {
size_ = x_dims[1];
}
}
out->set_dims({size_});
out->set_dtype(x.dtype()); out->set_dtype(x.dtype());
} else {
PADDLE_THROW(phi::errors::InvalidArgument(
"The input tensor X's dimensions of DiagV2Op should be either 1 or "
"2, but received %d.",
x_dims.size()));
}
} }
static phi::DDim ValidateShape(const std::vector<int64_t> shape, void DiagonalInferMeta(const MetaTensor& input,
const phi::DDim& in_dims) { int offset,
const int64_t in_size = phi::product(in_dims); int axis1,
auto in_dims_vec = phi::vectorize(in_dims); int axis2,
bool all_positive = std::all_of(in_dims_vec.cbegin(), MetaTensor* out) {
in_dims_vec.cend(), auto x_dims = input.dims();
[](int64_t i) { return i > 0; }); int offset_ = offset;
// only one dimension can be set to -1, whose size will be automatically int axis1_ = axis1 < 0 ? x_dims.size() + axis1 : axis1;
// infered. int axis2_ = axis2 < 0 ? x_dims.size() + axis2 : axis2;
const int64_t unk_dim_val = -1;
const int64_t copy_dim_val = 0;
std::vector<int64_t> output_shape(shape.size(), 0); PADDLE_ENFORCE_GE(
int64_t capacity = 1; x_dims.size(),
int unk_dim_idx = -1; 2,
for (size_t i = 0; i < shape.size(); ++i) { phi::errors::OutOfRange("Input's dim is out of range (expected at "
if (shape[i] == unk_dim_val) { "least 2 dimensions, but got %ld).",
PADDLE_ENFORCE_EQ( x_dims.size()));
unk_dim_idx,
-1,
phi::errors::InvalidArgument(
"Only one dimension value of 'shape' in ReshapeOp can "
"be -1. But received shape = [%s], shape[%d] is also -1.",
phi::make_ddim(shape),
i));
unk_dim_idx = i;
} else if (shape[i] == copy_dim_val) {
PADDLE_ENFORCE_LT( PADDLE_ENFORCE_LT(
static_cast<int>(i), axis1_,
in_dims.size(), x_dims.size(),
phi::errors::InvalidArgument( phi::errors::OutOfRange(
"The index of 0 in `shape` must be less than " "Attr(axis1) is out of range (expected to be in range of [%ld, "
"%ld], but got %ld).",
-(x_dims.size()),
(x_dims.size() - 1),
axis1));
PADDLE_ENFORCE_LT(
axis2_,
x_dims.size(),
phi::errors::OutOfRange(
"Attr(axis2) is out of range (expected to be in range of [%ld, "
"%ld], but got %ld).",
-(x_dims.size()),
(x_dims.size() - 1),
axis2));
PADDLE_ENFORCE_NE(
axis1_,
axis2_,
phi::errors::InvalidArgument("The dimensions should not be identical "
"%d vs %d.",
axis1,
axis2));
auto out_dims = vectorize(x_dims);
// from out_dims get the dim size of axis1_.
auto axis1_size = out_dims[axis1_];
auto axis2_size = out_dims[axis2_];
// delete two dims by attr axis1 and axis2 from out_dims.
/* example:
out_dim = [2, 3, 4];
axis1 = 0;
axis2 = 1;
according to the attr of axis1 and axis2, we get:
out_dim = [4].
*/
out_dims.erase(out_dims.begin() + std::max(axis1_, axis2_));
out_dims.erase(out_dims.begin() + std::min(axis1_, axis2_));
if (offset_ == 0) {
out_dims.push_back(std::min(axis1_size, axis2_size));
} else if (offset_ > 0) {
if ((axis2_size - offset_) > 0) {
out_dims.push_back(std::min(axis1_size, axis2_size - offset_));
} else {
out_dims.push_back(0);
}
} else {
if ((axis1_size + offset_) > 0) {
out_dims.push_back(std::min(axis1_size + offset_, axis2_size));
} else {
out_dims.push_back(0);
}
}
out->set_dims(phi::make_ddim(out_dims));
}
void EighInferMeta(const MetaTensor& x,
const std::string& uplo,
MetaTensor* out_w,
MetaTensor* out_v) {
auto input_dim = x.dims();
auto rank = input_dim.size();
PADDLE_ENFORCE_GE(rank,
2,
phi::errors::InvalidArgument(
"The Input(X) should have at least 2 dimensions."
"But received a %d dimension tensor.",
rank));
PADDLE_ENFORCE_EQ(
input_dim[rank - 2],
input_dim[rank - 1],
phi::errors::InvalidArgument(
"Eigh op is designed for square matrix, consequently"
"inner-most 2 dimensions of Input(X) should be symmetric."
"But received X's shape[-2] = %d and shape[-1] = %d.",
input_dim[rank - 2],
input_dim[rank - 1]));
std::vector<int64_t> values_dim;
for (auto i = 0; i < rank - 1; i++) {
values_dim.emplace_back(input_dim[i]);
}
out_w->set_dims(phi::make_ddim(values_dim));
out_v->set_dims(input_dim);
}
void FlattenInferMeta(const MetaTensor& x,
int start_axis,
int stop_axis,
MetaTensor* out) {
auto x_dims = x.dims();
int in_dims_size = x_dims.size();
if (start_axis < 0) {
start_axis = start_axis + in_dims_size;
}
if (stop_axis < 0) {
stop_axis = stop_axis + in_dims_size;
}
PADDLE_ENFORCE_GE(
stop_axis,
start_axis,
phi::errors::InvalidArgument("The stop_axis should be greater"
"than or equal to start_axis."));
int64_t outer = 1;
std::vector<int32_t> out_shape;
out_shape.reserve(in_dims_size - stop_axis + start_axis);
for (int i = 0; i < start_axis; ++i) {
out_shape.push_back(x_dims[i]);
}
for (int i = start_axis; i <= stop_axis; i++) {
if (x_dims[i] == -1 || outer == -1) {
outer = -1;
} else {
outer *= x_dims[i];
}
}
out_shape.push_back(outer);
for (int i = stop_axis + 1; i < in_dims_size; i++) {
out_shape.push_back(x_dims[i]);
}
const auto& out_dims = phi::make_ddim(out_shape);
out->set_dims(out_dims);
out->set_dtype(x.dtype());
out->set_layout(x.layout());
if (x_dims[0] == out_dims[0]) {
// Only pass LoD when the first dimension of output and Input(X)
// are the same.
out->share_lod(x);
}
}
void GumbelSoftmaxInferMeta(const MetaTensor& x,
float temperature,
bool hard,
int axis,
MetaTensor* out) {
UnchangedInferMetaCheckAxis(x, axis, out);
}
void IncrementInferMeta(const MetaTensor& x, float value, MetaTensor* out) {
PADDLE_ENFORCE_EQ(
product(x.dims()),
1UL,
errors::InvalidArgument("The number of elements in Input(X) should be 1."
"Now the number is %d.",
product(x.dims())));
out->set_dims(x.dims());
out->share_lod(x);
out->set_dtype(x.dtype());
}
static phi::DDim ValidateShape(const std::vector<int64_t> shape,
const phi::DDim& in_dims) {
const int64_t in_size = phi::product(in_dims);
auto in_dims_vec = phi::vectorize(in_dims);
bool all_positive = std::all_of(in_dims_vec.cbegin(),
in_dims_vec.cend(),
[](int64_t i) { return i > 0; });
// only one dimension can be set to -1, whose size will be automatically
// infered.
const int64_t unk_dim_val = -1;
const int64_t copy_dim_val = 0;
std::vector<int64_t> output_shape(shape.size(), 0);
int64_t capacity = 1;
int unk_dim_idx = -1;
for (size_t i = 0; i < shape.size(); ++i) {
if (shape[i] == unk_dim_val) {
PADDLE_ENFORCE_EQ(
unk_dim_idx,
-1,
phi::errors::InvalidArgument(
"Only one dimension value of 'shape' in ReshapeOp can "
"be -1. But received shape = [%s], shape[%d] is also -1.",
phi::make_ddim(shape),
i));
unk_dim_idx = i;
} else if (shape[i] == copy_dim_val) {
PADDLE_ENFORCE_LT(
static_cast<int>(i),
in_dims.size(),
phi::errors::InvalidArgument(
"The index of 0 in `shape` must be less than "
"the input tensor X's dimensions. " "the input tensor X's dimensions. "
"But received shape = [%s], shape[%d] = 0, X's shape = [%s], " "But received shape = [%s], shape[%d] = 0, X's shape = [%s], "
"X's dimensions = %d.", "X's dimensions = %d.",
...@@ -360,6 +548,11 @@ void IsEmptyInferMeta(const MetaTensor& x, MetaTensor* out) { ...@@ -360,6 +548,11 @@ void IsEmptyInferMeta(const MetaTensor& x, MetaTensor* out) {
out->set_dtype(DataType::BOOL); out->set_dtype(DataType::BOOL);
} }
void IsfiniteInferMeta(const MetaTensor& x, MetaTensor* out) {
out->set_dims(x.dims());
out->set_dtype(DataType::BOOL);
}
void MultinomialInferMeta(const MetaTensor& x, void MultinomialInferMeta(const MetaTensor& x,
int num_samples, int num_samples,
bool replacement, bool replacement,
...@@ -395,124 +588,97 @@ void MultinomialInferMeta(const MetaTensor& x, ...@@ -395,124 +588,97 @@ void MultinomialInferMeta(const MetaTensor& x,
out->set_dtype(DataType::INT64); out->set_dtype(DataType::INT64);
} }
void TileInferMeta(const MetaTensor& x, void PadInferMeta(const MetaTensor& input,
const ScalarArray& repeat_times, const std::vector<int>& paddings,
float pad_value,
MetaTensor* out, MetaTensor* out,
MetaConfig config) { MetaConfig config) {
#define MAX_RANK_SUPPORTED 6 auto x_dim = input.dims();
PADDLE_ENFORCE_EQ(
auto repeat_times_data = repeat_times.GetData(); static_cast<int>(paddings.size()),
auto x_dims = x.dims(); x_dim.size() * 2,
if (repeat_times_data.size() == 0) { phi::errors::InvalidArgument(
repeat_times_data = std::vector<int64_t>(x_dims.size(), -1); "Size of 'paddings' dimension should be equal to 2 * size of "
"Input(X)'s dimension, but received (size of 'paddings' dimension "
"is) %d vs (2 * size of Input(X)'s dimension is) %d.",
static_cast<int>(paddings.size()),
x_dim.size() * 2));
for (size_t i = 0; i < paddings.size(); ++i) {
PADDLE_ENFORCE_GE(paddings[i],
0,
phi::errors::InvalidArgument(
"The element of 'paddings' should >= 0, but "
"received %d for index %d.",
paddings[i],
static_cast<int>(i)));
} }
std::vector<int64_t> out_dims(x_dim.size());
for (int i = 0; i < x_dim.size(); ++i) {
if ((!config.is_runtime) && (x_dim[i] == -1)) {
out_dims[i] = -1;
} else {
out_dims[i] = x_dim[i] + paddings[i * 2] + paddings[i * 2 + 1];
}
}
out->set_dims(phi::make_ddim(out_dims));
if (out_dims[0] == x_dim[0]) {
// Only pass LoD when the first dimension is equal between
// output and input.
out->share_lod(input);
}
out->set_dtype(input.dtype());
}
PADDLE_ENFORCE_LE( void PixelShuffleInferMeta(const MetaTensor& x,
x_dims.size(), int upscale_factor,
MAX_RANK_SUPPORTED, const std::string& data_format,
errors::InvalidArgument( MetaTensor* out) {
"The rank of the input 'x' for tile op " auto input_dims = x.dims();
"must not be greater than %d, but the value received is %d.", PADDLE_ENFORCE_EQ(input_dims.size(),
MAX_RANK_SUPPORTED, 4,
x_dims.size())); phi::errors::InvalidArgument(
PADDLE_ENFORCE_LE( "Input should be a 4-D tensor of format [N, C, H, W] "
repeat_times_data.size(), "or [N, H, W, C], but got %u.",
MAX_RANK_SUPPORTED, input_dims.size()));
errors::InvalidArgument(
"The size of the shape of input 'repeat_times' for tile op "
"must not be greater than %d, but the value received is %d.",
MAX_RANK_SUPPORTED,
repeat_times_data.size()));
PADDLE_ENFORCE_GE(
repeat_times_data.size(),
1,
errors::InvalidArgument(
"The size of the shape of input 'repeat_times' for tile op "
"must be positive integers, but the value received is %d.",
repeat_times_data.size()));
auto out_rank =
std::max(static_cast<size_t>(x_dims.size()), repeat_times_data.size());
std::vector<int64_t> out_shape(out_rank);
auto x_dim_vec = phi::vectorize<int>(x_dims);
if (x_dim_vec.size() > repeat_times_data.size()) {
auto diff = x_dim_vec.size() - repeat_times_data.size();
repeat_times_data.insert(repeat_times_data.begin(), diff, -1);
} else {
auto diff = repeat_times_data.size() - x_dim_vec.size();
x_dim_vec.insert(x_dim_vec.begin(), diff, -1);
}
for (size_t i = 0; i < repeat_times_data.size(); ++i) {
if (x_dim_vec[i] == -1 || repeat_times_data[i] == -1) {
out_shape[i] = -1;
} else {
PADDLE_ENFORCE_GT(
repeat_times_data[i],
0,
errors::InvalidArgument(
"Every element of the input 'repeat_times' for tile op must be "
"greater than 0, but the value given is %d.",
repeat_times_data[i]));
out_shape[i] = x_dim_vec[i] * repeat_times_data[i];
}
}
out->set_dims(phi::make_ddim(out_shape)); const bool channel_last = (data_format == "NHWC");
if (out_shape[0] == x_dims[0]) {
out->share_lod(x);
}
}
void ReshapeInferMeta(const MetaTensor& x, if (!channel_last) {
const ScalarArray& shape, PADDLE_ENFORCE_EQ(input_dims[1] % (upscale_factor * upscale_factor),
MetaTensor* out,
MetaConfig config) {
auto& shape_data = shape.GetData();
PADDLE_ENFORCE_NOT_NULL(out,
phi::errors::InvalidArgument(
"Output(Out) of ReshapeOp should not be null."));
if (!config.is_runtime && shape.FromTensor()) {
out->set_dims(phi::make_ddim(shape_data));
out->share_lod(x);
return;
}
PADDLE_ENFORCE_GT(shape_data.size(),
0, 0,
phi::errors::InvalidArgument( phi::errors::InvalidArgument(
"The shape's size in ReshapeOp can't be zero.")); "The square of upscale_factor[%u] should divide the "
InferMetaFromVecValue(x, shape_data, out); "number of channel[%u]",
} upscale_factor * upscale_factor,
input_dims[1]));
void ReshapeWithXShapeInferMeta(const MetaTensor& x, } else {
const ScalarArray& shape, PADDLE_ENFORCE_EQ(input_dims[3] % (upscale_factor * upscale_factor),
MetaTensor* xshape, 0,
MetaTensor* out,
MetaConfig config) {
PADDLE_ENFORCE_NOT_NULL(
xshape,
phi::errors::InvalidArgument( phi::errors::InvalidArgument(
"Output(XShape) of ReshapeOp should not be null.")); "The square of upscale_factor[%u] should divide the "
const auto& x_dims = x.dims(); "number of channel[%u]",
std::vector<int64_t> xshape_dims(x_dims.size() + 1); upscale_factor * upscale_factor,
xshape_dims[0] = 0; input_dims[3]));
for (int i = 0; i < x_dims.size(); ++i) {
xshape_dims[i + 1] = x_dims[i];
} }
xshape->set_dims(phi::make_ddim(xshape_dims)); auto output_dims = input_dims;
xshape->share_lod(x); output_dims[0] = input_dims[0];
ReshapeInferMeta(x, shape, out, config); if (!channel_last) {
output_dims[1] = input_dims[1] / (upscale_factor * upscale_factor);
output_dims[2] = input_dims[2] * upscale_factor;
output_dims[3] = input_dims[3] * upscale_factor;
} else {
output_dims[1] = input_dims[1] * upscale_factor;
output_dims[2] = input_dims[2] * upscale_factor;
output_dims[3] = input_dims[3] / (upscale_factor * upscale_factor);
}
out->set_dtype(x.dtype());
out->set_dims(output_dims);
} }
/* Why not use SumRawInferMeta directly? void RealAndImagInferMeta(const MetaTensor& x, MetaTensor* out) {
Because we need make InferMetaFunction's args follow the design of api.yaml out->set_dims(x.dims());
*/ out->set_dtype(dtype::ToReal(x.dtype()));
void SumInferMeta(const MetaTensor& x, out->set_layout(x.layout());
const std::vector<int64_t>& axis,
DataType dtype,
bool keep_dim,
MetaTensor* out) {
bool reduce_all = false;
SumRawInferMeta(x, axis, keep_dim, reduce_all, dtype, out);
} }
DDim ReduceInferDim(const MetaTensor& x, DDim ReduceInferDim(const MetaTensor& x,
...@@ -584,29 +750,12 @@ DDim ReduceInferDim(const MetaTensor& x, ...@@ -584,29 +750,12 @@ DDim ReduceInferDim(const MetaTensor& x,
return out_dim; return out_dim;
} }
void SumRawInferMeta(const MetaTensor& x, void ReduceInferMeta(const MetaTensor& x,
const std::vector<int64_t>& axis, const std::vector<int64_t>& axis,
bool keep_dim, bool keep_dim,
bool reduce_all,
DataType dtype,
MetaTensor* out) { MetaTensor* out) {
DDim out_dim = ReduceInferDim(x, axis, keep_dim, reduce_all); bool reduce_all = false;
ReduceInferMetaBase(x, axis, keep_dim, reduce_all, out);
DataType out_dtype;
if (dtype != DataType::UNDEFINED) {
out_dtype = dtype;
} else {
if (x.dtype() == DataType::BOOL || x.dtype() == DataType::INT32 ||
x.dtype() == DataType::INT64) {
out_dtype = DataType::INT64;
} else {
out_dtype = x.dtype();
}
}
out->set_dims(out_dim);
out->set_dtype(out_dtype);
out->set_layout(x.layout());
} }
void ReduceInferMetaBase(const MetaTensor& x, void ReduceInferMetaBase(const MetaTensor& x,
...@@ -620,20 +769,96 @@ void ReduceInferMetaBase(const MetaTensor& x, ...@@ -620,20 +769,96 @@ void ReduceInferMetaBase(const MetaTensor& x,
out->set_layout(x.layout()); out->set_layout(x.layout());
} }
void ReduceInferMeta(const MetaTensor& x, void ReshapeInferMeta(const MetaTensor& x,
const std::vector<int64_t>& axis, const ScalarArray& shape,
bool keep_dim, MetaTensor* out,
MetaTensor* out) { MetaConfig config) {
bool reduce_all = false; auto& shape_data = shape.GetData();
ReduceInferMetaBase(x, axis, keep_dim, reduce_all, out); PADDLE_ENFORCE_NOT_NULL(out,
phi::errors::InvalidArgument(
"Output(Out) of ReshapeOp should not be null."));
if (!config.is_runtime && shape.FromTensor()) {
out->set_dims(phi::make_ddim(shape_data));
out->share_lod(x);
return;
}
PADDLE_ENFORCE_GT(shape_data.size(),
0,
phi::errors::InvalidArgument(
"The shape's size in ReshapeOp can't be zero."));
InferMetaFromVecValue(x, shape_data, out);
} }
void TransferLayoutInferMeta(const MetaTensor& x, void ReshapeWithXShapeInferMeta(const MetaTensor& x,
DataLayout layout, const ScalarArray& shape,
MetaTensor* out) { MetaTensor* xshape,
MetaTensor* out,
MetaConfig config) {
PADDLE_ENFORCE_NOT_NULL(
xshape,
phi::errors::InvalidArgument(
"Output(XShape) of ReshapeOp should not be null."));
const auto& x_dims = x.dims();
std::vector<int64_t> xshape_dims(x_dims.size() + 1);
xshape_dims[0] = 0;
for (int i = 0; i < x_dims.size(); ++i) {
xshape_dims[i + 1] = x_dims[i];
}
xshape->set_dims(phi::make_ddim(xshape_dims));
xshape->share_lod(x);
ReshapeInferMeta(x, shape, out, config);
}
void ShardIndexInferMeta(const MetaTensor& in,
int index_num,
int nshards,
int shard_id,
int ignore_value,
MetaTensor* out,
MetaConfig config) {
auto x_dims = in.dims();
PADDLE_ENFORCE_GE(
x_dims.size(),
2,
phi::errors::InvalidArgument("Rank of Input(X) should be at least 2, "
"but the value given is %d.",
x_dims.size()));
if (config.is_runtime || x_dims[x_dims.size() - 1] > 0) {
PADDLE_ENFORCE_EQ(x_dims[x_dims.size() - 1],
1U,
phi::errors::InvalidArgument(
"The last dimension of Input(X) should be 1, "
"but the value given is %d.",
x_dims[x_dims.size() - 1]));
}
out->set_dims(x_dims);
out->share_lod(in);
out->set_dtype(in.dtype());
}
void SizeInferMeta(const MetaTensor& input, MetaTensor* out) {
out->set_dtype(DataType::INT64);
out->set_dims({1});
}
void SoftmaxInferMeta(const MetaTensor& x, int axis, MetaTensor* out) {
auto dim_x = x.dims();
auto rank_x = dim_x.size();
PADDLE_ENFORCE_GE(axis,
-rank_x,
phi::errors::InvalidArgument(
"Attr(axis) value should be in range [-R, R-1], "
"R is the rank of Input(X)."));
PADDLE_ENFORCE_LT(axis,
rank_x,
phi::errors::InvalidArgument(
"Attr(axis) value should be in range [-R, R-1], "
"R is the rank of Input(X)."));
out->set_dims(x.dims()); out->set_dims(x.dims());
out->set_dtype(x.dtype()); out->set_dtype(x.dtype());
out->set_layout(layout); out->share_lod(x);
} }
void SplitInferMeta(const MetaTensor& x, void SplitInferMeta(const MetaTensor& x,
...@@ -767,22 +992,108 @@ void SplitInferMeta(const MetaTensor& x, ...@@ -767,22 +992,108 @@ void SplitInferMeta(const MetaTensor& x,
} }
} }
void UnbindInferMeta(const MetaTensor& x, /* Why not use SumRawInferMeta directly?
int axis, Because we need make InferMetaFunction's args follow the design of api.yaml
std::vector<MetaTensor>* outs) { */
auto in_dims = x.dims(); void SumInferMeta(const MetaTensor& x,
std::vector<int> out_dim; const std::vector<int64_t>& axis,
axis = axis < 0 ? in_dims.size() + axis : axis; DataType dtype,
for (int i = 0; i < in_dims.size(); ++i) { bool keep_dim,
if (i != axis) out_dim.push_back(in_dims[i]); MetaTensor* out) {
} bool reduce_all = false;
auto out_dims = phi::make_ddim(out_dim); SumRawInferMeta(x, axis, keep_dim, reduce_all, dtype, out);
}
for (size_t i = 0; i < outs->size(); ++i) {
(*outs)[i].set_dtype(x.dtype()); void SumRawInferMeta(const MetaTensor& x,
(*outs)[i].set_dims(out_dims); const std::vector<int64_t>& axis,
(*outs)[i].set_layout(x.layout()); bool keep_dim,
(*outs)[i].share_lod(x); bool reduce_all,
DataType dtype,
MetaTensor* out) {
DDim out_dim = ReduceInferDim(x, axis, keep_dim, reduce_all);
DataType out_dtype;
if (dtype != DataType::UNDEFINED) {
out_dtype = dtype;
} else {
if (x.dtype() == DataType::BOOL || x.dtype() == DataType::INT32 ||
x.dtype() == DataType::INT64) {
out_dtype = DataType::INT64;
} else {
out_dtype = x.dtype();
}
}
out->set_dims(out_dim);
out->set_dtype(out_dtype);
out->set_layout(x.layout());
}
void TileInferMeta(const MetaTensor& x,
const ScalarArray& repeat_times,
MetaTensor* out,
MetaConfig config) {
#define MAX_RANK_SUPPORTED 6
auto repeat_times_data = repeat_times.GetData();
auto x_dims = x.dims();
if (repeat_times_data.size() == 0) {
repeat_times_data = std::vector<int64_t>(x_dims.size(), -1);
}
PADDLE_ENFORCE_LE(
x_dims.size(),
MAX_RANK_SUPPORTED,
errors::InvalidArgument(
"The rank of the input 'x' for tile op "
"must not be greater than %d, but the value received is %d.",
MAX_RANK_SUPPORTED,
x_dims.size()));
PADDLE_ENFORCE_LE(
repeat_times_data.size(),
MAX_RANK_SUPPORTED,
errors::InvalidArgument(
"The size of the shape of input 'repeat_times' for tile op "
"must not be greater than %d, but the value received is %d.",
MAX_RANK_SUPPORTED,
repeat_times_data.size()));
PADDLE_ENFORCE_GE(
repeat_times_data.size(),
1,
errors::InvalidArgument(
"The size of the shape of input 'repeat_times' for tile op "
"must be positive integers, but the value received is %d.",
repeat_times_data.size()));
auto out_rank =
std::max(static_cast<size_t>(x_dims.size()), repeat_times_data.size());
std::vector<int64_t> out_shape(out_rank);
auto x_dim_vec = phi::vectorize<int>(x_dims);
if (x_dim_vec.size() > repeat_times_data.size()) {
auto diff = x_dim_vec.size() - repeat_times_data.size();
repeat_times_data.insert(repeat_times_data.begin(), diff, -1);
} else {
auto diff = repeat_times_data.size() - x_dim_vec.size();
x_dim_vec.insert(x_dim_vec.begin(), diff, -1);
}
for (size_t i = 0; i < repeat_times_data.size(); ++i) {
if (x_dim_vec[i] == -1 || repeat_times_data[i] == -1) {
out_shape[i] = -1;
} else {
PADDLE_ENFORCE_GT(
repeat_times_data[i],
0,
errors::InvalidArgument(
"Every element of the input 'repeat_times' for tile op must be "
"greater than 0, but the value given is %d.",
repeat_times_data[i]));
out_shape[i] = x_dim_vec[i] * repeat_times_data[i];
}
}
out->set_dims(phi::make_ddim(out_shape));
if (out_shape[0] == x_dims[0]) {
out->share_lod(x);
} }
} }
...@@ -840,97 +1151,130 @@ void TraceInferMeta( ...@@ -840,97 +1151,130 @@ void TraceInferMeta(
out->set_dtype(x.dtype()); out->set_dtype(x.dtype());
} }
void DiagonalInferMeta(const MetaTensor& input, void TransferLayoutInferMeta(const MetaTensor& x,
int offset, DataLayout layout,
int axis1,
int axis2,
MetaTensor* out) { MetaTensor* out) {
auto x_dims = input.dims(); out->set_dims(x.dims());
int offset_ = offset; out->set_dtype(x.dtype());
int axis1_ = axis1 < 0 ? x_dims.size() + axis1 : axis1; out->set_layout(layout);
int axis2_ = axis2 < 0 ? x_dims.size() + axis2 : axis2; }
void TransposeInferMeta(const MetaTensor& x,
const std::vector<int>& axis,
MetaTensor* out) {
auto x_dims = x.dims();
size_t x_rank = x_dims.size();
size_t axis_size = axis.size();
PADDLE_ENFORCE_EQ(
x_rank,
axis_size,
errors::InvalidArgument("The input tensor's dimension "
"should be equal to the axis's size. "
"But received input tensor's dimension is %d, "
"axis's size is %d",
x_rank,
axis_size));
std::vector<int> count(axis_size, 0);
for (size_t i = 0; i < axis_size; i++) {
PADDLE_ENFORCE_GE( PADDLE_ENFORCE_GE(
x_dims.size(), axis[i],
2, 0,
phi::errors::OutOfRange("Input's dim is out of range (expected at " errors::InvalidArgument("The axis should be greater than or equal to 0."
"least 2 dimensions, but got %ld).", "But received %d of axis[%d]",
x_dims.size())); axis[i],
PADDLE_ENFORCE_LT( i));
axis1_,
x_dims.size(),
phi::errors::OutOfRange(
"Attr(axis1) is out of range (expected to be in range of [%ld, "
"%ld], but got %ld).",
-(x_dims.size()),
(x_dims.size() - 1),
axis1));
PADDLE_ENFORCE_LT(
axis2_,
x_dims.size(),
phi::errors::OutOfRange(
"Attr(axis2) is out of range (expected to be in range of [%ld, "
"%ld], but got %ld).",
-(x_dims.size()),
(x_dims.size() - 1),
axis2));
PADDLE_ENFORCE_NE(
axis1_,
axis2_,
phi::errors::InvalidArgument("The dimensions should not be identical "
"%d vs %d.",
axis1,
axis2));
auto out_dims = vectorize(x_dims); PADDLE_ENFORCE_EQ(
// from out_dims get the dim size of axis1_. axis[i] < static_cast<int>(axis_size) && ++count[axis[i]] == 1,
auto axis1_size = out_dims[axis1_]; true,
auto axis2_size = out_dims[axis2_]; errors::InvalidArgument(
// delete two dims by attr axis1 and axis2 from out_dims. "Each element of Attribute axis should "
/* example: "be a unique value range from 0 to (dims - 1), "
out_dim = [2, 3, 4]; "where the dims is the axis's size, "
axis1 = 0; "unique value means this axis value can appear only once. "
axis2 = 1; "But received axis[%d] is %d, axis_size is %d, "
according to the attr of axis1 and axis2, we get: "count[axis[%d]] is %d",
out_dim = [4]. i,
*/ axis[i],
out_dims.erase(out_dims.begin() + std::max(axis1_, axis2_)); axis_size,
out_dims.erase(out_dims.begin() + std::min(axis1_, axis2_)); i,
count[axis[i]]));
}
if (offset_ == 0) { phi::DDim out_dims(x_dims);
out_dims.push_back(std::min(axis1_size, axis2_size)); for (size_t i = 0; i < axis_size; ++i) {
} else if (offset_ > 0) { out_dims[i] = x_dims[axis[i]];
if ((axis2_size - offset_) > 0) {
out_dims.push_back(std::min(axis1_size, axis2_size - offset_));
} else {
out_dims.push_back(0);
} }
} else {
if ((axis1_size + offset_) > 0) { out->set_dims(out_dims);
out_dims.push_back(std::min(axis1_size + offset_, axis2_size)); out->set_dtype(x.dtype());
} else { }
out_dims.push_back(0);
void UnbindInferMeta(const MetaTensor& x,
int axis,
std::vector<MetaTensor>* outs) {
auto in_dims = x.dims();
std::vector<int> out_dim;
axis = axis < 0 ? in_dims.size() + axis : axis;
for (int i = 0; i < in_dims.size(); ++i) {
if (i != axis) out_dim.push_back(in_dims[i]);
} }
auto out_dims = phi::make_ddim(out_dim);
for (size_t i = 0; i < outs->size(); ++i) {
(*outs)[i].set_dtype(x.dtype());
(*outs)[i].set_dims(out_dims);
(*outs)[i].set_layout(x.layout());
(*outs)[i].share_lod(x);
} }
out->set_dims(phi::make_ddim(out_dims));
} }
void UnfoldInferMeta(const MetaTensor& x, void UnchangedInferMeta(const MetaTensor& x, MetaTensor* out) {
const std::vector<int>& kernel_sizes, out->share_meta(x);
const std::vector<int>& strides, }
const std::vector<int>& paddings,
const std::vector<int>& dilations, // meta x -> out without change, check if axis in range [-Rank(x), Rank(x)-1]
MetaTensor* out, void UnchangedInferMetaCheckAxis(const MetaTensor& x,
MetaConfig config) { int axis,
auto in_dims = x.dims(); MetaTensor* out) {
// Only [N, C, H, W] input supported now auto rank = x.dims().size();
PADDLE_ENFORCE_EQ( PADDLE_ENFORCE_GE(
in_dims.size(), axis,
4, -rank,
phi::errors::InvalidArgument( errors::InvalidArgument(
"Input should be 4-D tensor of format [N, C, H, W], but get %u", "Attr(axis) value should be in range [-R, R-1], "
in_dims.size())); "R is the rank of Input(X). But received axis: %d, R: %d.",
PADDLE_ENFORCE_EQ( axis,
rank));
PADDLE_ENFORCE_LT(
axis,
rank,
phi::errors::InvalidArgument(
"Attr(axis) value should be in range [-R, R-1], "
"R is the rank of Input(X). But received axis: %d, R: %d.",
axis,
rank));
out->share_meta(x);
}
void UnfoldInferMeta(const MetaTensor& x,
const std::vector<int>& kernel_sizes,
const std::vector<int>& strides,
const std::vector<int>& paddings,
const std::vector<int>& dilations,
MetaTensor* out,
MetaConfig config) {
auto in_dims = x.dims();
// Only [N, C, H, W] input supported now
PADDLE_ENFORCE_EQ(
in_dims.size(),
4,
phi::errors::InvalidArgument(
"Input should be 4-D tensor of format [N, C, H, W], but get %u",
in_dims.size()));
PADDLE_ENFORCE_EQ(
in_dims.size() - kernel_sizes.size(), in_dims.size() - kernel_sizes.size(),
2U, 2U,
phi::errors::InvalidArgument( phi::errors::InvalidArgument(
...@@ -1073,303 +1417,6 @@ void UnfoldInferMeta(const MetaTensor& x, ...@@ -1073,303 +1417,6 @@ void UnfoldInferMeta(const MetaTensor& x,
out->set_dims(phi::make_ddim(out_dims)); out->set_dims(phi::make_ddim(out_dims));
} }
void DiagInferMeta(const MetaTensor& x,
int offset,
float padding_value,
MetaTensor* out) {
auto x_dims = x.dims();
if (x_dims.size() == 1UL) {
int64_t size_ = x_dims[0] + std::abs(offset);
out->set_dims({size_, size_});
out->set_dtype(x.dtype());
} else if (x_dims.size() == 2UL) {
int64_t size_ = 0;
if (offset >= 0) {
// Note(LutaoChu): Do not use std::min here, otherwise the calculation
// of `size_` will have unexpected result on Windows Python3.8
if (x_dims[0] < x_dims[1] - offset) {
size_ = x_dims[0];
} else {
size_ = x_dims[1] - offset;
}
} else {
// Note(LutaoChu): Do not use std::min here, otherwise the calculation
// of `size_` will have unexpected result on Windows Python3.8
if (x_dims[0] + offset < x_dims[1]) {
size_ = x_dims[0] + offset;
} else {
size_ = x_dims[1];
}
}
out->set_dims({size_});
out->set_dtype(x.dtype());
} else {
PADDLE_THROW(phi::errors::InvalidArgument(
"The input tensor X's dimensions of DiagV2Op should be either 1 or "
"2, but received %d.",
x_dims.size()));
}
}
void ArgMinMaxInferMeta(const MetaTensor& x,
int64_t axis,
bool keepdims,
bool flatten,
int dtype,
MetaTensor* out,
MetaConfig config) {
const auto& x_dims = x.dims();
PADDLE_ENFORCE_GE(
axis,
-x_dims.size(),
phi::errors::InvalidArgument("'axis'(%d) must be greater than or equal to"
" -Rank(X)(%d).",
axis,
-x_dims.size()));
PADDLE_ENFORCE_LT(axis,
x_dims.size(),
phi::errors::InvalidArgument(
"'axis'(%d) must be less than Rank(X)(%d) of Input(X).",
axis,
x_dims.size()));
PADDLE_ENFORCE_EQ(
(dtype < 0 || dtype == 2 || dtype == 3),
true,
phi::errors::InvalidArgument(
"The attribute of dtype in argmin/argmax must be [%s] or [%s], but "
"received [%s]",
paddle::framework::DataTypeToString(
paddle::framework::proto::VarType::INT32),
paddle::framework::DataTypeToString(
paddle::framework::proto::VarType::INT64),
paddle::framework::DataTypeToString(
static_cast<paddle::framework::proto::VarType::Type>(dtype))));
auto x_rank = x_dims.size();
if (axis < 0) axis += x_rank;
if (config.is_runtime) {
if (dtype == paddle::framework::proto::VarType::INT32) {
int64_t all_element_num = 0;
if (flatten) {
all_element_num = phi::product(x_dims);
} else {
all_element_num = x_dims[axis];
}
PADDLE_ENFORCE_LE(
all_element_num,
INT_MAX,
phi::errors::InvalidArgument(
"The element num of the argmin/argmax input at axis is "
"%d, is larger than int32 maximum value:%d, you must "
"set the dtype of argmin/argmax to 'int64'.",
all_element_num,
INT_MAX));
}
}
std::vector<int64_t> vec;
if (flatten) {
vec.emplace_back(static_cast<int64_t>(1));
} else {
for (int64_t i = 0; i < axis; i++) vec.emplace_back(x_dims[i]);
if (keepdims) {
vec.emplace_back(static_cast<int64_t>(1));
}
for (int64_t i = axis + 1; i < x_rank; i++) vec.emplace_back(x_dims[i]);
}
out->set_dims(phi::make_ddim(vec));
if (dtype == 2) {
out->set_dtype(DataType::INT32);
} else if (dtype == 3) {
out->set_dtype(DataType::INT64);
}
}
void SizeInferMeta(const MetaTensor& input, MetaTensor* out) {
out->set_dtype(DataType::INT64);
out->set_dims({1});
}
void PadInferMeta(const MetaTensor& input,
const std::vector<int>& paddings,
float pad_value,
MetaTensor* out,
MetaConfig config) {
auto x_dim = input.dims();
PADDLE_ENFORCE_EQ(
static_cast<int>(paddings.size()),
x_dim.size() * 2,
phi::errors::InvalidArgument(
"Size of 'paddings' dimension should be equal to 2 * size of "
"Input(X)'s dimension, but received (size of 'paddings' dimension "
"is) %d vs (2 * size of Input(X)'s dimension is) %d.",
static_cast<int>(paddings.size()),
x_dim.size() * 2));
for (size_t i = 0; i < paddings.size(); ++i) {
PADDLE_ENFORCE_GE(paddings[i],
0,
phi::errors::InvalidArgument(
"The element of 'paddings' should >= 0, but "
"received %d for index %d.",
paddings[i],
static_cast<int>(i)));
}
std::vector<int64_t> out_dims(x_dim.size());
for (int i = 0; i < x_dim.size(); ++i) {
if ((!config.is_runtime) && (x_dim[i] == -1)) {
out_dims[i] = -1;
} else {
out_dims[i] = x_dim[i] + paddings[i * 2] + paddings[i * 2 + 1];
}
}
out->set_dims(phi::make_ddim(out_dims));
if (out_dims[0] == x_dim[0]) {
// Only pass LoD when the first dimension is equal between
// output and input.
out->share_lod(input);
}
out->set_dtype(input.dtype());
}
void IsfiniteInferMeta(const MetaTensor& x, MetaTensor* out) {
out->set_dims(x.dims());
out->set_dtype(DataType::BOOL);
}
void PixelShuffleInferMeta(const MetaTensor& x,
int upscale_factor,
const std::string& data_format,
MetaTensor* out) {
auto input_dims = x.dims();
PADDLE_ENFORCE_EQ(input_dims.size(),
4,
phi::errors::InvalidArgument(
"Input should be a 4-D tensor of format [N, C, H, W] "
"or [N, H, W, C], but got %u.",
input_dims.size()));
const bool channel_last = (data_format == "NHWC");
if (!channel_last) {
PADDLE_ENFORCE_EQ(input_dims[1] % (upscale_factor * upscale_factor),
0,
phi::errors::InvalidArgument(
"The square of upscale_factor[%u] should divide the "
"number of channel[%u]",
upscale_factor * upscale_factor,
input_dims[1]));
} else {
PADDLE_ENFORCE_EQ(input_dims[3] % (upscale_factor * upscale_factor),
0,
phi::errors::InvalidArgument(
"The square of upscale_factor[%u] should divide the "
"number of channel[%u]",
upscale_factor * upscale_factor,
input_dims[3]));
}
auto output_dims = input_dims;
output_dims[0] = input_dims[0];
if (!channel_last) {
output_dims[1] = input_dims[1] / (upscale_factor * upscale_factor);
output_dims[2] = input_dims[2] * upscale_factor;
output_dims[3] = input_dims[3] * upscale_factor;
} else {
output_dims[1] = input_dims[1] * upscale_factor;
output_dims[2] = input_dims[2] * upscale_factor;
output_dims[3] = input_dims[3] / (upscale_factor * upscale_factor);
}
out->set_dtype(x.dtype());
out->set_dims(output_dims);
}
void TransposeInferMeta(const MetaTensor& x,
const std::vector<int>& axis,
MetaTensor* out) {
auto x_dims = x.dims();
size_t x_rank = x_dims.size();
size_t axis_size = axis.size();
PADDLE_ENFORCE_EQ(
x_rank,
axis_size,
errors::InvalidArgument("The input tensor's dimension "
"should be equal to the axis's size. "
"But received input tensor's dimension is %d, "
"axis's size is %d",
x_rank,
axis_size));
std::vector<int> count(axis_size, 0);
for (size_t i = 0; i < axis_size; i++) {
PADDLE_ENFORCE_GE(
axis[i],
0,
errors::InvalidArgument("The axis should be greater than or equal to 0."
"But received %d of axis[%d]",
axis[i],
i));
PADDLE_ENFORCE_EQ(
axis[i] < static_cast<int>(axis_size) && ++count[axis[i]] == 1,
true,
errors::InvalidArgument(
"Each element of Attribute axis should "
"be a unique value range from 0 to (dims - 1), "
"where the dims is the axis's size, "
"unique value means this axis value can appear only once. "
"But received axis[%d] is %d, axis_size is %d, "
"count[axis[%d]] is %d",
i,
axis[i],
axis_size,
i,
count[axis[i]]));
}
phi::DDim out_dims(x_dims);
for (size_t i = 0; i < axis_size; ++i) {
out_dims[i] = x_dims[axis[i]];
}
out->set_dims(out_dims);
out->set_dtype(x.dtype());
}
void EighInferMeta(const MetaTensor& x,
const std::string& uplo,
MetaTensor* out_w,
MetaTensor* out_v) {
auto input_dim = x.dims();
auto rank = input_dim.size();
PADDLE_ENFORCE_GE(rank,
2,
phi::errors::InvalidArgument(
"The Input(X) should have at least 2 dimensions."
"But received a %d dimension tensor.",
rank));
PADDLE_ENFORCE_EQ(
input_dim[rank - 2],
input_dim[rank - 1],
phi::errors::InvalidArgument(
"Eigh op is designed for square matrix, consequently"
"inner-most 2 dimensions of Input(X) should be symmetric."
"But received X's shape[-2] = %d and shape[-1] = %d.",
input_dim[rank - 2],
input_dim[rank - 1]));
std::vector<int64_t> values_dim;
for (auto i = 0; i < rank - 1; i++) {
values_dim.emplace_back(input_dim[i]);
}
out_w->set_dims(phi::make_ddim(values_dim));
out_v->set_dims(input_dim);
}
void WhereIndexInferMeta(const MetaTensor& condition, MetaTensor* out) { void WhereIndexInferMeta(const MetaTensor& condition, MetaTensor* out) {
auto rank = condition.dims().size(); auto rank = condition.dims().size();
PADDLE_ENFORCE_GE( PADDLE_ENFORCE_GE(
...@@ -1381,53 +1428,6 @@ void WhereIndexInferMeta(const MetaTensor& condition, MetaTensor* out) { ...@@ -1381,53 +1428,6 @@ void WhereIndexInferMeta(const MetaTensor& condition, MetaTensor* out) {
out->set_dtype(DataType::INT64); out->set_dtype(DataType::INT64);
} }
void ShardIndexInferMeta(const MetaTensor& in,
int index_num,
int nshards,
int shard_id,
int ignore_value,
MetaTensor* out,
MetaConfig config) {
auto x_dims = in.dims();
PADDLE_ENFORCE_GE(
x_dims.size(),
2,
phi::errors::InvalidArgument("Rank of Input(X) should be at least 2, "
"but the value given is %d.",
x_dims.size()));
if (config.is_runtime || x_dims[x_dims.size() - 1] > 0) {
PADDLE_ENFORCE_EQ(x_dims[x_dims.size() - 1],
1U,
phi::errors::InvalidArgument(
"The last dimension of Input(X) should be 1, "
"but the value given is %d.",
x_dims[x_dims.size() - 1]));
}
out->set_dims(x_dims);
out->share_lod(in);
out->set_dtype(in.dtype());
}
void SoftmaxInferMeta(const MetaTensor& x, int axis, MetaTensor* out) {
auto dim_x = x.dims();
auto rank_x = dim_x.size();
PADDLE_ENFORCE_GE(axis,
-rank_x,
phi::errors::InvalidArgument(
"Attr(axis) value should be in range [-R, R-1], "
"R is the rank of Input(X)."));
PADDLE_ENFORCE_LT(axis,
rank_x,
phi::errors::InvalidArgument(
"Attr(axis) value should be in range [-R, R-1], "
"R is the rank of Input(X)."));
out->set_dims(x.dims());
out->set_dtype(x.dtype());
out->share_lod(x);
}
} // namespace phi } // namespace phi
PD_REGISTER_INFER_META_FN(copy_to, phi::CopyToInferMeta); PD_REGISTER_INFER_META_FN(copy_to, phi::CopyToInferMeta);
......
...@@ -32,32 +32,20 @@ class MetaConfig; ...@@ -32,32 +32,20 @@ class MetaConfig;
// Because functions in this file not only can infer shape, but also need // Because functions in this file not only can infer shape, but also need
// infer lod or other useful data. // infer lod or other useful data.
void ArgMinMaxInferMeta(const MetaTensor& x,
int64_t axis,
bool keepdims,
bool flatten,
int dtype,
MetaTensor* out,
MetaConfig config = MetaConfig());
void ArgsortInferMeta(const MetaTensor& input, void ArgsortInferMeta(const MetaTensor& input,
int axis, int axis,
bool descending, bool descending,
MetaTensor* output, MetaTensor* output,
MetaTensor* indices); MetaTensor* indices);
void UnchangedInferMeta(const MetaTensor& x, MetaTensor* out);
// meta x -> out without change, check if axis in range [-Rank(x), Rank(x)-1]
void UnchangedInferMetaCheckAxis(const MetaTensor& x,
int axis,
MetaTensor* out);
void RealAndImagInferMeta(const MetaTensor& x, MetaTensor* out);
void FlattenInferMeta(const MetaTensor& x,
int start_axis,
int stop_axis,
MetaTensor* out);
void GumbelSoftmaxInferMeta(const MetaTensor& x,
float temperature,
bool hard,
int axis,
MetaTensor* out);
void CastInferMeta(const MetaTensor& x, DataType out_dtype, MetaTensor* out); void CastInferMeta(const MetaTensor& x, DataType out_dtype, MetaTensor* out);
void CholeskyInferMeta(const MetaTensor& x, bool upper, MetaTensor* out); void CholeskyInferMeta(const MetaTensor& x, bool upper, MetaTensor* out);
...@@ -76,6 +64,30 @@ void CumsumInferMeta(const MetaTensor& x, ...@@ -76,6 +64,30 @@ void CumsumInferMeta(const MetaTensor& x,
bool reverse, bool reverse,
MetaTensor* out); MetaTensor* out);
void DiagInferMeta(const MetaTensor& x,
int offset,
float padding_value,
MetaTensor* out);
void DiagonalInferMeta(
const MetaTensor& input, int offset, int axis1, int axis2, MetaTensor* out);
void EighInferMeta(const MetaTensor& x,
const std::string& uplo,
MetaTensor* out_w,
MetaTensor* out_v);
void FlattenInferMeta(const MetaTensor& x,
int start_axis,
int stop_axis,
MetaTensor* out);
void GumbelSoftmaxInferMeta(const MetaTensor& x,
float temperature,
bool hard,
int axis,
MetaTensor* out);
void IncrementInferMeta(const MetaTensor& x, float value, MetaTensor* out); void IncrementInferMeta(const MetaTensor& x, float value, MetaTensor* out);
void InferMetaFromVecValue(const MetaTensor& x, void InferMetaFromVecValue(const MetaTensor& x,
...@@ -84,11 +96,37 @@ void InferMetaFromVecValue(const MetaTensor& x, ...@@ -84,11 +96,37 @@ void InferMetaFromVecValue(const MetaTensor& x,
void IsEmptyInferMeta(const MetaTensor& x, MetaTensor* out); void IsEmptyInferMeta(const MetaTensor& x, MetaTensor* out);
void IsfiniteInferMeta(const MetaTensor& input, MetaTensor* out);
void MultinomialInferMeta(const MetaTensor& x, void MultinomialInferMeta(const MetaTensor& x,
int num_samples, int num_samples,
bool replacement, bool replacement,
MetaTensor* out); MetaTensor* out);
void PadInferMeta(const MetaTensor& input,
const std::vector<int>& paddings,
float pad_value,
MetaTensor* out,
MetaConfig config = MetaConfig());
void PixelShuffleInferMeta(const MetaTensor& x,
int upscale_factor,
const std::string& data_format,
MetaTensor* out);
void RealAndImagInferMeta(const MetaTensor& x, MetaTensor* out);
void ReduceInferMeta(const MetaTensor& x,
const std::vector<int64_t>& axis,
bool keep_dim,
MetaTensor* out);
void ReduceInferMetaBase(const MetaTensor& x,
const std::vector<int64_t>& axis,
bool keep_dim,
bool reduce_all,
MetaTensor* out);
void ReshapeInferMeta(const MetaTensor& x, void ReshapeInferMeta(const MetaTensor& x,
const ScalarArray& shape, const ScalarArray& shape,
MetaTensor* out, MetaTensor* out,
...@@ -100,50 +138,63 @@ void ReshapeWithXShapeInferMeta(const MetaTensor& x, ...@@ -100,50 +138,63 @@ void ReshapeWithXShapeInferMeta(const MetaTensor& x,
MetaTensor* out, MetaTensor* out,
MetaConfig config = MetaConfig()); MetaConfig config = MetaConfig());
void TileInferMeta(const MetaTensor& x, void ShardIndexInferMeta(const MetaTensor& in,
const ScalarArray& repeat_times, int index_num,
int nshards,
int shard_id,
int ignore_value,
MetaTensor* out, MetaTensor* out,
MetaConfig config = MetaConfig()); MetaConfig config = MetaConfig());
void SumRawInferMeta(const MetaTensor& x, void SizeInferMeta(const MetaTensor& input, MetaTensor* out);
void SoftmaxInferMeta(const MetaTensor& x, int axis, MetaTensor* out);
void SplitInferMeta(const MetaTensor& x_meta,
const ScalarArray& num_or_sections,
const Scalar& axis,
std::vector<MetaTensor*> out,
MetaConfig config = MetaConfig());
void SumInferMeta(const MetaTensor& x,
const std::vector<int64_t>& axis, const std::vector<int64_t>& axis,
bool keep_dim,
bool reduce_all,
DataType dtype, DataType dtype,
bool keep_dim,
MetaTensor* out); MetaTensor* out);
void ReduceInferMetaBase(const MetaTensor& x, void SumRawInferMeta(const MetaTensor& x,
const std::vector<int64_t>& axis, const std::vector<int64_t>& axis,
bool keep_dim, bool keep_dim,
bool reduce_all, bool reduce_all,
DataType dtype,
MetaTensor* out); MetaTensor* out);
void ReduceInferMeta(const MetaTensor& x, void TileInferMeta(const MetaTensor& x,
const std::vector<int64_t>& axis, const ScalarArray& repeat_times,
bool keep_dim, MetaTensor* out,
MetaTensor* out); MetaConfig config = MetaConfig());
void SumInferMeta(const MetaTensor& x, void TraceInferMeta(
const std::vector<int64_t>& axis, const MetaTensor& x, int offset, int axis1, int axis2, MetaTensor* out);
DataType dtype,
bool keep_dim,
MetaTensor* out);
void TransferLayoutInferMeta(const MetaTensor& x, void TransferLayoutInferMeta(const MetaTensor& x,
DataLayout layout, DataLayout layout,
MetaTensor* out); MetaTensor* out);
void SplitInferMeta(const MetaTensor& x_meta, void TransposeInferMeta(const MetaTensor& x,
const ScalarArray& num_or_sections, const std::vector<int>& axis,
const Scalar& axis, MetaTensor* out);
std::vector<MetaTensor*> out,
MetaConfig config = MetaConfig());
void UnbindInferMeta(const MetaTensor& x, void UnbindInferMeta(const MetaTensor& x,
int axis, int axis,
std::vector<MetaTensor>* outs); std::vector<MetaTensor>* outs);
void TraceInferMeta(
const MetaTensor& x, int offset, int axis1, int axis2, MetaTensor* out); void UnchangedInferMeta(const MetaTensor& x, MetaTensor* out);
// meta x -> out without change, check if axis in range [-Rank(x), Rank(x)-1]
void UnchangedInferMetaCheckAxis(const MetaTensor& x,
int axis,
MetaTensor* out);
void UnfoldInferMeta(const MetaTensor& x, void UnfoldInferMeta(const MetaTensor& x,
const std::vector<int>& kernel_sizes, const std::vector<int>& kernel_sizes,
...@@ -153,56 +204,6 @@ void UnfoldInferMeta(const MetaTensor& x, ...@@ -153,56 +204,6 @@ void UnfoldInferMeta(const MetaTensor& x,
MetaTensor* out, MetaTensor* out,
MetaConfig config = MetaConfig()); MetaConfig config = MetaConfig());
void DiagInferMeta(const MetaTensor& x,
int offset,
float padding_value,
MetaTensor* out);
void ArgMinMaxInferMeta(const MetaTensor& x,
int64_t axis,
bool keepdims,
bool flatten,
int dtype,
MetaTensor* out,
MetaConfig config = MetaConfig());
void SizeInferMeta(const MetaTensor& input, MetaTensor* out);
void PadInferMeta(const MetaTensor& input,
const std::vector<int>& paddings,
float pad_value,
MetaTensor* out,
MetaConfig config = MetaConfig());
void DiagonalInferMeta(
const MetaTensor& input, int offset, int axis1, int axis2, MetaTensor* out);
void PixelShuffleInferMeta(const MetaTensor& x,
int upscale_factor,
const std::string& data_format,
MetaTensor* out);
void IsfiniteInferMeta(const MetaTensor& input, MetaTensor* out);
void TransposeInferMeta(const MetaTensor& x,
const std::vector<int>& axis,
MetaTensor* out);
void EighInferMeta(const MetaTensor& x,
const std::string& uplo,
MetaTensor* out_w,
MetaTensor* out_v);
void WhereIndexInferMeta(const MetaTensor& condition, MetaTensor* out); void WhereIndexInferMeta(const MetaTensor& condition, MetaTensor* out);
void ShardIndexInferMeta(const MetaTensor& in,
int index_num,
int nshards,
int shard_id,
int ignore_value,
MetaTensor* out,
MetaConfig config = MetaConfig());
void SoftmaxInferMeta(const MetaTensor& x, int axis, MetaTensor* out);
} // namespace phi } // namespace phi
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册