未验证 提交 a0a6dc6a 编写于 作者: HappyHeavyRain's avatar HappyHeavyRain 提交者: GitHub

[New features]Add function node in phi_kernel for MKLDNN (#51073)

* Add function node in phi_kernel for MKLDNN

* fix the bug in 'BuildInferVarKernelContext'

* add infer_varkernel_utils.cc

* fix the bug:the first two parametes of 'BuildInferVarKernelContext' can't be template variable

* change the code according to first review

* change the code according to first review

* change the mode of paddle_build.sh

* change 'infer_var_kernel_fn_' to 'get_kerneltype_forvar_fn_'

* add the error information

* fix NotFound infomation warning

* fix NotFound infomation warning

* fix NotFound infomation warning
上级 bfb79ee2
......@@ -479,7 +479,8 @@ if(WITH_XPU)
kernel_factory
infershape_utils
op_utils
op_compat_infos)
op_compat_infos
get_kerneltype_forvar_utils)
else()
cc_library(
operator
......@@ -505,7 +506,8 @@ else()
kernel_factory
infershape_utils
op_utils
op_compat_infos)
op_compat_infos
get_kerneltype_forvar_utils)
endif()
cc_test(
......
......@@ -156,5 +156,31 @@ void SetTensorToVariable(const Variable &in_var,
}
}
phi::GetKernelTypeForVarContext BuildGetKernelTypeForVarContext(
const phi::KernelKey &kernel_key,
const AttributeMap &fluid_attrs,
phi::AttributeMap *phi_attrs,
bool has_infer_varkernel_fn) {
// According to "GetKernelTypeForVar" in some ops those have MKLDNN codes,
// the only "string" member, such as "data_layout" 、"data_format" of
// AttibuteMap is useful. In the future the other args maybe used. Because the
// "phi" module should not depend on the "fluid", transform
// "framework::AttributeMap" to "phi::AttributeMap".
if (has_infer_varkernel_fn) {
for (auto &attr : fluid_attrs) {
switch (attr.second.index()) {
case 3: // string type in framwork::Attribute
(*phi_attrs)[attr.first] = PADDLE_GET_CONST(std::string, attr.second);
break;
default:
VLOG(6) << "GetKernelTypeForVarContext currently only use "
"std::string. You add other type if need.";
break;
}
}
}
return phi::GetKernelTypeForVarContext(&kernel_key, phi_attrs);
}
} // namespace framework
} // namespace paddle
......@@ -25,6 +25,7 @@ limitations under the License. */
#include "paddle/fluid/platform/device_context.h"
#include "paddle/fluid/platform/macros.h"
#include "paddle/phi/common/transform.h"
#include "paddle/phi/core/compat/get_kerneltype_forvar_utils.h"
#include "paddle/phi/kernels/funcs/math_function.h"
namespace paddle {
......@@ -45,5 +46,12 @@ void TransformData(const phi::KernelKey &expected_kernel_type,
void SetTensorToVariable(const Variable &in_var,
const phi::DenseTensor &tensor,
Variable *out_var);
phi::GetKernelTypeForVarContext BuildGetKernelTypeForVarContext(
const phi::KernelKey &kernel_key,
const AttributeMap &fluid_attrs,
phi::AttributeMap *phi_attrs,
bool has_infer_varkernel_fn);
} // namespace framework
} // namespace paddle
......@@ -15,6 +15,7 @@
#include "paddle/fluid/framework/new_executor/interpreter/data_transfer.h"
#include "paddle/fluid/framework/convert_utils.h"
#include "paddle/fluid/framework/data_transform.h"
#include "paddle/fluid/framework/new_executor/interpreter/interpreter_util.h"
#include "paddle/phi/core/kernel_context.h"
#include "paddle/phi/core/kernel_factory.h"
......@@ -474,7 +475,17 @@ void ApplyDataTransform(const OpKernelType& expected_kernel_key,
bool transfered = false;
DataTranferHelper data_transfer_helper(place, var_scope, local_scope);
phi::Kernel* phi_kernel = op_func_node->phi_kernel_;
auto has_infer_varkernel_fn =
(phi_kernel && phi_kernel->get_kerneltype_forvar_fn_ != nullptr);
phi::AttributeMap infer_attrs{};
auto fluid_attrs =
static_cast<const framework::OperatorWithKernel*>(op_base)->Attrs();
auto phi_kernelkey =
framework::TransOpKernelTypeToPhiKernelKey(expected_kernel_key);
phi::GetKernelTypeForVarContext infer_varkernel_context =
BuildGetKernelTypeForVarContext(
phi_kernelkey, fluid_attrs, &infer_attrs, has_infer_varkernel_fn);
auto apply_data_transform_for_one_parameter =
[&](const std::string& parameter_name,
const std::vector<std::string>& argument_names,
......@@ -551,11 +562,15 @@ void ApplyDataTransform(const OpKernelType& expected_kernel_key,
auto kernel_key_for_var =
static_cast<const framework::OperatorWithKernel*>(op_base)
->GetKernelTypeForVar(
parameter_name,
*tensor_in,
framework::TransOpKernelTypeToPhiKernelKey(
expected_kernel_key));
parameter_name, *tensor_in, phi_kernelkey);
if (has_infer_varkernel_fn) {
infer_varkernel_context.SetVarName(
const_cast<std::string*>(&parameter_name));
infer_varkernel_context.SetDenseTensor(
const_cast<phi::DenseTensor*>(tensor_in));
kernel_key_for_var = phi_kernel->get_kerneltype_forvar_fn_(
&infer_varkernel_context);
}
std::unique_ptr<phi::KernelKey>
expected_kernel_key_for_argument_def = nullptr;
if (argument_def &&
......@@ -634,7 +649,6 @@ void ApplyDataTransform(const OpKernelType& expected_kernel_key,
}
};
phi::Kernel* phi_kernel = op_func_node->phi_kernel_;
if (phi_kernel && phi_kernel->IsValid() &&
phi_kernel->GetKernelRegisteredType() ==
phi::KernelRegisteredType::FUNCTION) {
......
......@@ -37,6 +37,7 @@ limitations under the License. */
#include "paddle/fluid/platform/profiler/supplement_tracing.h"
#include "paddle/phi/common/int_array.h"
#include "paddle/phi/common/scalar.h"
#include "paddle/phi/core/compat/get_kerneltype_forvar_utils.h"
#include "paddle/phi/core/ddim.h"
#include "paddle/phi/core/kernel_context.h"
#include "paddle/phi/core/kernel_factory.h"
......@@ -2448,6 +2449,16 @@ Scope* OperatorWithKernel::PrepareData(
}
}
auto has_infer_varkernel_fn =
(run_phi_kernel_ && phi_kernel_->get_kerneltype_forvar_fn_ != nullptr);
phi::AttributeMap infer_attrs{};
auto fluid_attrs = Attrs();
phi::GetKernelTypeForVarContext infer_varkernel_context =
BuildGetKernelTypeForVarContext(expected_kernel_key,
fluid_attrs,
&infer_attrs,
has_infer_varkernel_fn);
const auto& name_map = Inputs();
auto prepare_input_data = [&](const std::string& in_name,
std::vector<Variable*>* in_vars,
......@@ -2510,6 +2521,13 @@ Scope* OperatorWithKernel::PrepareData(
auto kernel_type_for_var =
GetKernelTypeForVar(in_name, *tensor_in, expected_kernel_key);
if (has_infer_varkernel_fn) {
infer_varkernel_context.SetVarName(const_cast<std::string*>(&in_name));
infer_varkernel_context.SetDenseTensor(
const_cast<phi::DenseTensor*>(tensor_in));
kernel_type_for_var =
phi_kernel_->get_kerneltype_forvar_fn_(&infer_varkernel_context);
}
bool need_trans_dtype =
NeedTransformDataType(expected_kernel_key, kernel_type_for_var);
bool need_trans_layout = NeedTransformLayout(
......
/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserve.
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
http://www.apache.org/licenses/LICENSE-2.0
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.
See the License for the specific language governing permissions and
limitations under the License. */
#include <memory>
#include <string>
#include <vector>
#include "paddle/fluid/framework/infershape_utils.h"
#include "paddle/fluid/framework/op_registry.h"
#include "paddle/phi/core/infermeta_utils.h"
#include "paddle/phi/infermeta/multiary.h"
#ifdef PADDLE_WITH_MKLDNN
#include "paddle/fluid/platform/mkldnn_helper.h"
#endif
namespace paddle {
namespace operators {
using DataLayout = phi::DataLayout;
static void Interpolate1DInferShapeCheck(framework::InferShapeContext* ctx) {
auto dim_x = ctx->GetInputDim("X");
auto interp_method = ctx->Attrs().Get<std::string>("interp_method");
PADDLE_ENFORCE_EQ("linear",
interp_method,
platform::errors::InvalidArgument(
"Interpolation method can only be \"linear\" when"
"Input(X) dimension is 3, but got method = %s .",
interp_method));
const DataLayout data_layout =
phi::StringToDataLayout(ctx->Attrs().Get<std::string>("data_layout"));
for (int i = 0; i < dim_x.size(); ++i) {
PADDLE_ENFORCE_NE(dim_x[i],
0,
platform::errors::InvalidArgument(
"The shape of input(x) should be larged "
"than 0, bug received shape[%d] is %d ",
i,
dim_x[i]));
}
if (ctx->HasInputs("SizeTensor")) {
// top prority size
auto inputs_name = ctx->Inputs("SizeTensor");
PADDLE_ENFORCE_EQ(
inputs_name.size(),
1,
platform::errors::InvalidArgument(
"Input(SizeTensor)'size of Op(interpolate) must be 1. "
"Attr(out_shape)'s length must be 1 for 3-D input tensor, but got "
"size = %d .",
inputs_name.size()));
int out_w = ctx->Attrs().Get<int>("out_w");
framework::DDim dim_out;
if (data_layout == DataLayout::kNCHW) {
dim_out = {dim_x[0], dim_x[1], out_w};
} else {
dim_out = {dim_x[0], out_w, dim_x[2]};
}
ctx->SetOutputDim("Out", dim_out);
return;
}
int out_w;
if (ctx->HasInput("Scale")) {
auto scale_tensor = ctx->GetInputDim("Scale");
PADDLE_ENFORCE_EQ(
scale_tensor.size(),
1,
platform::errors::InvalidArgument(
"Scale's dimension size must be 1, but got dimension = %d .",
scale_tensor.size()));
PADDLE_ENFORCE_EQ(
scale_tensor[0],
1,
platform::errors::InvalidArgument(
"Scale's shape must be 1, but got shape = %d .", scale_tensor[0]));
out_w = -1;
} else {
auto scale = ctx->Attrs().Get<std::vector<float>>("scale");
if (scale.size() > 0) {
float scale_w = -1;
scale_w = scale[0];
PADDLE_ENFORCE_EQ(
scale_w > 0,
true,
platform::errors::InvalidArgument(
"The scale_w in Attr(scale) of Operator(interpolate) "
"should be greater than 0, but received value is %d.",
scale_w));
if (scale_w > 0.) {
// round down
out_w = (data_layout == DataLayout::kNCHW
? static_cast<int>(dim_x[2] * scale_w)
: static_cast<int>(dim_x[1] * scale_w));
// protect when input shape is -1
out_w = out_w > 0 ? out_w : -1;
}
} else {
out_w = ctx->Attrs().Get<int>("out_w");
}
}
if (ctx->HasInput("OutSize") && ctx->IsRuntime()) {
auto out_size_dim = ctx->GetInputDim("OutSize");
PADDLE_ENFORCE_EQ(
out_size_dim.size(),
1,
platform::errors::InvalidArgument(
"OutSize's dimension size must be 1, but got dimention = %d .",
out_size_dim.size()));
PADDLE_ENFORCE_EQ(
out_size_dim[0],
1,
platform::errors::InvalidArgument(
"OutSize's 0-th dimension's value must be 1, but got value = %d .",
out_size_dim[0]));
ctx->ShareLoD("X", "Out");
return;
}
framework::DDim dim_out;
if (data_layout == DataLayout::kNCHW) {
dim_out = {dim_x[0], dim_x[1], out_w};
} else {
dim_out = {dim_x[0], out_w, dim_x[2]};
}
ctx->SetOutputDim("Out", dim_out);
}
static void Interpolate2DInferShapeCheck(framework::InferShapeContext* ctx) {
auto dim_x = ctx->GetInputDim("X");
auto interp_method = ctx->Attrs().Get<std::string>("interp_method");
PADDLE_ENFORCE(
"bilinear" == interp_method || "nearest" == interp_method ||
"bicubic" == interp_method,
platform::errors::InvalidArgument(
"Interpolation method can only be \"bilinear\" or \"nearest\" when "
"Input(X) dimension is 4, but got method = %s.",
interp_method));
const DataLayout data_layout =
phi::StringToDataLayout(ctx->Attrs().Get<std::string>("data_layout"));
for (int i = 0; i < dim_x.size(); ++i) {
PADDLE_ENFORCE_NE(dim_x[i],
0,
platform::errors::InvalidArgument(
"The shape of input(x) should be larged "
"than 0, bug received shape[%d] is %d ",
i,
dim_x[i]));
}
if (ctx->HasInputs("SizeTensor")) {
// top prority size
auto inputs_name = ctx->Inputs("SizeTensor");
PADDLE_ENFORCE_EQ(
inputs_name.size(),
2,
platform::errors::InvalidArgument(
"Input(SizeTensor)'size of Op(interpolate) must be 2. "
"Attr(out_shape)'s length must be 2 for 4-D input "
"tensor, but got size = %d .",
inputs_name.size()));
int out_h = ctx->Attrs().Get<int>("out_h");
int out_w = ctx->Attrs().Get<int>("out_w");
framework::DDim dim_out;
if (data_layout == DataLayout::kNCHW) {
dim_out = {dim_x[0], dim_x[1], out_h, out_w};
} else {
dim_out = {dim_x[0], out_h, out_w, dim_x[3]};
}
ctx->SetOutputDim("Out", dim_out);
return;
}
int out_h, out_w;
if (ctx->HasInput("Scale")) {
auto scale_tensor = ctx->GetInputDim("Scale");
PADDLE_ENFORCE_EQ(
scale_tensor.size(),
1,
platform::errors::InvalidArgument(
"Scale's dimension size must be 1, but got dimension = %d .",
scale_tensor.size()));
PADDLE_ENFORCE_EQ(scale_tensor[0] == 2 || scale_tensor[0] == 1,
true,
platform::errors::InvalidArgument(
"Scale's shape must be 2 or 1, but got shape = %d .",
scale_tensor[0]));
out_h = -1;
out_w = -1;
} else {
auto scale = ctx->Attrs().Get<std::vector<float>>("scale");
if (scale.size() > 0) {
float scale_h = -1;
float scale_w = -1;
scale_h = scale[0];
scale_w = scale[1];
PADDLE_ENFORCE_EQ(
scale_w > 0,
true,
platform::errors::InvalidArgument(
"The scale_w in Attr(scale) of Operator(interpolate) "
"should be greater than 0, but received value is %d.",
scale_w));
PADDLE_ENFORCE_EQ(
scale_h > 0,
true,
platform::errors::InvalidArgument(
"The scale_h in Attr(scale) of Operator(interpolate) "
"should be greater than 0, but received value is %d.",
scale_h));
if (scale_h > 0. && scale_w > 0.) {
// round down
out_h = (data_layout == DataLayout::kNCHW
? static_cast<int>(dim_x[2] * scale_h)
: static_cast<int>(dim_x[1] * scale_h));
out_w = (data_layout == DataLayout::kNCHW
? static_cast<int>(dim_x[3] * scale_w)
: static_cast<int>(dim_x[2] * scale_w));
// protect when input shape is -1
out_h = out_h > 0 ? out_h : -1;
out_w = out_w > 0 ? out_w : -1;
}
} else {
out_h = ctx->Attrs().Get<int>("out_h");
out_w = ctx->Attrs().Get<int>("out_w");
}
}
if (ctx->HasInput("OutSize") && ctx->IsRuntime()) {
auto out_size_dim = ctx->GetInputDim("OutSize");
PADDLE_ENFORCE_EQ(
out_size_dim.size(),
1,
platform::errors::InvalidArgument(
"OutSize's dimension size must be 1, but got dimension = %d .",
out_size_dim.size()));
PADDLE_ENFORCE_EQ(
out_size_dim[0],
2,
platform::errors::InvalidArgument(
"OutSize's dim[0] must be 2, but got dimention = %d .",
out_size_dim[0]));
ctx->ShareLoD("X", "Out");
return;
}
framework::DDim dim_out;
if (data_layout == DataLayout::kNCHW) {
dim_out = {dim_x[0], dim_x[1], out_h, out_w};
} else {
dim_out = {dim_x[0], out_h, out_w, dim_x[3]};
}
ctx->SetOutputDim("Out", dim_out);
}
static void Interpolate3DInferShapeCheck(framework::InferShapeContext* ctx) {
auto dim_x = ctx->GetInputDim("X");
auto interp_method = ctx->Attrs().Get<std::string>("interp_method");
PADDLE_ENFORCE("nearest" == interp_method || "trilinear" == interp_method,
platform::errors::InvalidArgument(
"Interpolation method can only be \"trilinear\" or "
"\"nearest\" when Input(X) "
"dimension is 5, but got method = %s .",
interp_method));
const DataLayout data_layout =
phi::StringToDataLayout(ctx->Attrs().Get<std::string>("data_layout"));
for (int i = 0; i < dim_x.size(); ++i) {
PADDLE_ENFORCE_NE(dim_x[i],
0,
platform::errors::InvalidArgument(
"The shape of input(x) should be larged "
"than 0, bug received shape[%d] is %d ",
i,
dim_x[i]));
}
if (ctx->HasInputs("SizeTensor")) {
// top prority size
auto inputs_name = ctx->Inputs("SizeTensor");
PADDLE_ENFORCE_EQ(
inputs_name.size(),
3,
platform::errors::InvalidArgument(
"Input(SizeTensor)'s size of Op(interpolate) must be 3. "
"Attr(out_shape)'s length must be 3 for 5-D input "
"tensor, but got size = %d .",
inputs_name.size()));
int out_d = ctx->Attrs().Get<int>("out_d");
int out_h = ctx->Attrs().Get<int>("out_h");
int out_w = ctx->Attrs().Get<int>("out_w");
framework::DDim dim_out;
if (data_layout == DataLayout::kNCHW) {
dim_out = {dim_x[0], dim_x[1], out_d, out_h, out_w};
} else {
dim_out = {dim_x[0], out_d, out_h, out_w, dim_x[4]};
}
ctx->SetOutputDim("Out", dim_out);
return;
}
int out_d, out_h, out_w;
if (ctx->HasInput("Scale")) {
auto scale_tensor = ctx->GetInputDim("Scale");
PADDLE_ENFORCE_EQ(
scale_tensor.size(),
1,
platform::errors::InvalidArgument(
"Scale's dimension size must be 1, but got size = %d .",
scale_tensor.size()));
PADDLE_ENFORCE_EQ(scale_tensor[0] == 3 || scale_tensor[0] == 1,
true,
platform::errors::InvalidArgument(
"Scale's shape must be 3 or 1, but got shape = %d .",
scale_tensor[0]));
out_d = -1;
out_h = -1;
out_w = -1;
} else {
auto scale = ctx->Attrs().Get<std::vector<float>>("scale");
if (scale.size() > 0) {
float scale_d = -1;
float scale_h = -1;
float scale_w = -1;
scale_d = scale[0];
scale_h = scale[1];
scale_w = scale[2];
PADDLE_ENFORCE_EQ(
scale_w > 0,
true,
platform::errors::InvalidArgument(
"The scale_w in Attr(scale) of Operator(interpolate) "
"should be greater than 0, but received value is %d.",
scale_w));
PADDLE_ENFORCE_EQ(
scale_h > 0,
true,
platform::errors::InvalidArgument(
"The scale_h in Attr(scale) of Operator(interpolate) "
"should be greater than 0, but received value is %d.",
scale_h));
PADDLE_ENFORCE_EQ(
scale_d > 0,
true,
platform::errors::InvalidArgument(
"The scale_d in Attr(scale) of Operator(interpolate) "
"should be greater than 0, but received value is %d.",
scale_d));
if (scale_d > 0. && scale_h > 0. && scale_w > 0.) {
// round down
out_d = (data_layout == DataLayout::kNCHW
? static_cast<int>(dim_x[2] * scale_d)
: static_cast<int>(dim_x[1] * scale_d));
out_h = (data_layout == DataLayout::kNCHW
? static_cast<int>(dim_x[3] * scale_h)
: static_cast<int>(dim_x[2] * scale_h));
out_w = (data_layout == DataLayout::kNCHW
? static_cast<int>(dim_x[4] * scale_w)
: static_cast<int>(dim_x[3] * scale_w));
// protect when input shape is -1
out_d = out_d > 0 ? out_d : -1;
out_h = out_h > 0 ? out_h : -1;
out_w = out_w > 0 ? out_w : -1;
}
} else {
out_d = ctx->Attrs().Get<int>("out_d");
out_h = ctx->Attrs().Get<int>("out_h");
out_w = ctx->Attrs().Get<int>("out_w");
}
}
if (ctx->HasInput("OutSize") && ctx->IsRuntime()) {
auto out_size_dim = ctx->GetInputDim("OutSize");
PADDLE_ENFORCE_EQ(
out_size_dim.size(),
1,
platform::errors::InvalidArgument(
"OutSize's dimension size must be 1, but got size is %d.",
out_size_dim.size()));
PADDLE_ENFORCE_EQ(out_size_dim[0],
3,
platform::errors::InvalidArgument(
"OutSize's dim[0] must be 3, but got size is %d.",
out_size_dim[0]));
ctx->ShareLoD("X", "Out");
return;
}
framework::DDim dim_out;
if (data_layout == DataLayout::kNCHW) {
dim_out = {dim_x[0], dim_x[1], out_d, out_h, out_w};
} else {
dim_out = {dim_x[0], out_d, out_h, out_w, dim_x[4]};
}
ctx->SetOutputDim("Out", dim_out);
}
class InterpolateV2Op : public framework::OperatorWithKernel {
public:
using framework::OperatorWithKernel::OperatorWithKernel;
protected:
void InferShape(framework::InferShapeContext* ctx) const override {
OP_INOUT_CHECK(ctx->HasInput("X"), "Input", "X", "Interpolate");
OP_INOUT_CHECK(ctx->HasOutput("Out"), "Output", "Out", "Interpolate");
auto dim_x = ctx->GetInputDim("X"); // NCHW format
PADDLE_ENFORCE(
dim_x.size() == 3 || dim_x.size() == 4 || dim_x.size() == 5,
platform::errors::Unimplemented(
"Input(X) dimension must be 3, 4 or 5, but got dimension = %d .",
dim_x.size()));
if (dim_x.size() == 3) {
// shape check for 1D interpolate for input tensor shape NCHW
Interpolate1DInferShapeCheck(ctx);
} else if (dim_x.size() == 4) {
// shape check for 2D interpolate for input tensor shape NCHW
Interpolate2DInferShapeCheck(ctx);
} else { // dim_x.size() == 5
// shape check for 3D interpolate for input tensor shape NCDHW
Interpolate3DInferShapeCheck(ctx);
}
}
protected:
phi::KernelKey GetExpectedKernelType(
const framework::ExecutionContext& ctx) const override {
auto data_type = OperatorWithKernel::IndicateVarDataType(ctx, "X");
return phi::KernelKey(data_type, ctx.GetPlace());
}
phi::KernelKey GetKernelTypeForVar(
const std::string& var_name,
const phi::DenseTensor& tensor,
const phi::KernelKey& expected_kernel_type) const override {
#ifdef PADDLE_WITH_MKLDNN
if ((expected_kernel_type.layout() == phi::DataLayout::ONEDNN) &&
(tensor.layout() != phi::DataLayout::ONEDNN)) {
auto attrs = Attrs();
auto ar = paddle::framework::AttrReader(attrs);
const std::string data_format = ar.Get<std::string>("data_layout");
auto dl = phi::StringToDataLayout(data_format);
// Some models may have intentionally set "AnyLayout" for pool
// op. Treat this as NCHW (default data_format value)
if (dl != phi::DataLayout::kAnyLayout) {
return phi::KernelKey(tensor.place(), dl, expected_kernel_type.dtype());
}
}
#endif
if (var_name == "OutSize" || var_name == "SizeTensor" ||
var_name == "Scale") {
return phi::KernelKey(phi::Backend::ALL_BACKEND,
expected_kernel_type.layout(),
expected_kernel_type.dtype());
}
return phi::KernelKey(
tensor.place(), tensor.layout(), expected_kernel_type.dtype());
}
};
class InterpolateV2OpMaker : public framework::OpProtoAndCheckerMaker {
public:
void Make() override {
AddInput("X",
"The input tensor of interpolate operator, "
"This is a 4-D tensor with shape of [N, C, H, W] or a "
"5-D tensor with shape of [N, C, D, H, W].");
AddInput("OutSize",
"This is a 1-D tensor with two numbers to specify output size. "
"It should be [output_height, output_width] when input is a 4-D "
"tensor and should be [output_depth, output_height, output_width] "
"when input is a 5-D tensor. It has a higher priority than "
"the attr(out_d), attr(out_h), attr(out_w) and attr(scale).")
.AsDispensable();
AddInput("SizeTensor",
"(vector<Tensor<int32>>, optional). If provided, interpolate will "
"use this. The shape of the tensor in vector MUST BE [1]. "
"It has the highest priority compare with Input(OutSize) and "
"attr(out_d), attr(out_h), attr(out_w) and attr(scale).")
.AsDuplicable()
.AsDispensable();
AddInput("Scale",
"This is a 1-D tensor with one number to specify output scale. "
"It has the higher priority compare with attr(scale).")
.AsDispensable();
AddOutput("Out",
"The output tensor of interpolate operator, "
"This is a tensor in same rank with Input(X).");
AddAttr<std::string>(
"data_layout",
"(string, default NCHW) Only used in "
"an optional string from: \"NHWC\", \"NCHW\". "
"Specify that the data format of the input and output data is "
"channel_first or channel_last.")
.SetDefault("NCHW");
AddAttr<int>("out_d", "output depth of interpolate op.").SetDefault(0);
AddAttr<int>("out_h", "output height of interpolate op.").SetDefault(0);
AddAttr<int>("out_w", "output width of interpolate op.").SetDefault(0);
AddAttr<std::vector<float>>("scale", "scale_d factor of interpolate op.")
.SetDefault(std::vector<float>{});
AddAttr<std::string>("interp_method",
"(string, default \"bilinear\"), interpolation "
"method, can be \"linear\" for linear interpolation"
",\"bilinear\" for "
"bilinear interpolation, \"trilinear\" for trilinear "
"interpolation and \"nearest\" for nearest "
"neighbor interpolation, and \"bicubic\" for bicubic"
"interpolation.")
.SetDefault("bilinear");
AddAttr<bool>(
"align_corners",
"an optional bool. Defaults to True. "
"If True, the centers of 4 corner pixels of the input and output "
"tensors are aligned, preserving the values at the corner pixels, "
"If False, are not aligned")
.SetDefault(true);
AddAttr<int>("align_mode",
"(int, default \'1\'), optional for bilinear interpolation, "
"can be \'0\' for src_idx = scale*(dst_indx+0.5)-0.5 , "
"can be \'1\' for src_idx = scale*dst_index .")
.SetDefault(1);
AddComment(R"DOC(
This operator samples input X to given output shape by using specified
interpolation method, the interpolation methods can be \"nearest\"
for nearest neighbor interpolation and \"bilinear\" for bilinear
interpolation and \"linear\" for linear interpolation..
Nearest neighbor interpolation is to perform nearest neighbor interpolation
in both the 3rd dimension(in height direction) and the 4th dimension(in width
direction) on input tensor.
Linear interpolation is the method of using a line connecting two known quantities
to determine the value of an unknown quantity between the two known quantities.
Bilinear interpolation is an extension of linear interpolation for
interpolating functions of two variables (e.g. H-direction and
W-direction in this op) on a rectilinear 2D grid. The key idea is
to perform linear interpolation first in one direction, and then
again in the other direction.
Trilinear interpolation is an extension of linear interpolation for
interpolating functions of three variables (e.g. D-direction,
H-direction and W-direction in this op) on a rectilinear 3D grid.
The linear interpolation is performed on three directions.
Bicubic interpolation is an extension of cubic interpolation for interpolating
data points on a two-dimensional regular grid. The interpolated surface is
smoother than corresponding surfaces obtained by bilinear interpolation or
nearest-neighbor interpolation.
Align_corners and align_mode are optional parameters,the calculation method
of interpolation can be selected by them.
Example:
For scale:
if align_corners = True and out_{size}>1 :
scale_{factor} = (in_{size}-1.0)/(out_{size}-1.0)
else:
scale_{factor} = float(in_{size}/out_{size})
Nearest neighbor interpolation:
if:
align_corners = False
input : (N,C,H_in,W_in)
output: (N,C,H_out,W_out) where:
H_out = \left \lfloor {H_{in} * scale_{}factor}} \right \rfloor
W_out = \left \lfloor {W_{in} * scale_{}factor}} \right \rfloor
else:
align_corners = True
input : (N,C,H_in,W_in)
output: (N,C,H_out,W_out) where:
H_out = round(H_{in} * scale_{factor})
W_out = round(W_{in} * scale_{factor})
Bilinear interpolation:
if:
align_corners = False , align_mode = 0
input : (N,C,H_in,W_in)
output: (N,C,H_out,W_out) where:
H_out = (H_{in}+0.5) * scale_{factor} - 0.5
W_out = (W_{in}+0.5) * scale_{factor} - 0.5
else:
input : (N,C,H_in,W_in)
output: (N,C,H_out,W_out) where:
H_out = H_{in} * scale_{factor}
W_out = W_{in} * scale_{factor}
Trilinear interpolation:
if:
align_corners = False , align_mode = 0
input : (N,C,D_in,H_in,W_in)
output: (N,C,D_out,H_out,W_out) where:
D_out = (D_{in}+0.5) * scale_{factor} - 0.5
H_out = (H_{in}+0.5) * scale_{factor} - 0.5
W_out = (W_{in}+0.5) * scale_{factor} - 0.5
else:
input : (N,C,D_in,H_in,W_in)
output: (N,C,D_out,H_out,W_out) where:
D_out = D_{in} * scale_{factor}
H_out = H_{in} * scale_{factor}
W_out = W_{in} * scale_{factor}
Bicubic interpolation:
if:
align_corners = False
input : (N,C,H_in,W_in)
output: (N,C,H_out,W_out) where:
H_out = (H_{in}+0.5) * scale_{factor} - 0.5
W_out = (W_{in}+0.5) * scale_{factor} - 0.5
else:
input : (N,C,H_in,W_in)
output: (N,C,H_out,W_out) where:
H_out = H_{in} * scale_{factor}
W_out = W_{in} * scale_{factor}
For details of nearest neighbor interpolation, please refer to Wikipedia:
https://en.wikipedia.org/wiki/Nearest-neighbor_interpolation
For details of bilinear interpolation, please refer to Wikipedia:
https://en.wikipedia.org/wiki/Bilinear_interp_v2olation
For details of trilinear interpolation, please refer to Wikipedia:
https://en.wikipedia.org/wiki/Trilinear_interp_v2olation
For details of bicubic interpolation, please refer to Wikipedia:
https://en.wikipedia.org/wiki/Bicubic_interpolation
)DOC");
}
};
class InterpolateV2OpGrad : public framework::OperatorWithKernel {
public:
using framework::OperatorWithKernel::OperatorWithKernel;
protected:
void InferShape(framework::InferShapeContext* ctx) const override {
OP_INOUT_CHECK(ctx->HasInput("X"), "Input", "X", "InterpolateGrad");
OP_INOUT_CHECK(ctx->HasInput(framework::GradVarName("Out")),
"Input",
"Out@GRAD",
"InterpolateGrad");
auto dim_x = ctx->GetInputDim("X");
if (ctx->HasOutput(framework::GradVarName("X"))) {
ctx->SetOutputDim(framework::GradVarName("X"), dim_x);
}
}
phi::KernelKey GetExpectedKernelType(
const framework::ExecutionContext& ctx) const override {
return phi::KernelKey(OperatorWithKernel::IndicateVarDataType(
ctx, framework::GradVarName("Out")),
ctx.GetPlace());
}
phi::KernelKey GetKernelTypeForVar(
const std::string& var_name,
const phi::DenseTensor& tensor,
const phi::KernelKey& expected_kernel_type) const override {
if (var_name == "OutSize" || var_name == "SizeTensor" ||
var_name == "Scale") {
return phi::KernelKey(phi::Backend::ALL_BACKEND,
expected_kernel_type.layout(),
expected_kernel_type.dtype());
}
return phi::KernelKey(
tensor.place(), tensor.layout(), expected_kernel_type.dtype());
}
};
template <typename T>
class InterpolateV2GradMaker : public framework::SingleGradOpMaker<T> {
public:
using framework::SingleGradOpMaker<T>::SingleGradOpMaker;
protected:
void Apply(GradOpPtr<T> op) const override {
op->SetType(this->ForwardOpType() + "_grad");
op->SetInput("X", this->Input("X"));
if (this->HasInput("SizeTensor") > 0) {
op->SetInput("SizeTensor", this->Input("SizeTensor"));
}
if (this->HasInput("OutSize") > 0) {
op->SetInput("OutSize", this->Input("OutSize"));
}
if (this->HasInput("Scale") > 0) {
op->SetInput("Scale", this->Input("Scale"));
}
op->SetInput(framework::GradVarName("Out"), this->OutputGrad("Out"));
op->SetOutput(framework::GradVarName("X"), this->InputGrad("X"));
op->SetAttrMap(this->Attrs());
}
};
DECLARE_NO_NEED_BUFFER_VARS_INFERER(InterpolateV2GradNoNeedBufferVarsInferer,
"X");
} // namespace operators
} // namespace paddle
// interp_v2 support scale_factor whose input type is list, this operation is
// not
// compatible with interp_op, so a new one is added in paddle2.0
namespace ops = paddle::operators;
DECLARE_INFER_SHAPE_FUNCTOR(bilinear_interp_v2,
BilinearInterpInferShapeFunctor,
PD_INFER_META(phi::InterpolateInferMeta));
DECLARE_INFER_SHAPE_FUNCTOR(nearest_interp_v2,
NearestInterpInferShapeFunctor,
PD_INFER_META(phi::InterpolateInferMeta));
DECLARE_INFER_SHAPE_FUNCTOR(trilinear_interp_v2,
TrilinearInterpInferShapeFunctor,
PD_INFER_META(phi::InterpolateInferMeta));
DECLARE_INFER_SHAPE_FUNCTOR(bicubic_interp_v2,
BicubicInterpInferShapeFunctor,
PD_INFER_META(phi::InterpolateInferMeta));
DECLARE_INFER_SHAPE_FUNCTOR(linear_interp_v2,
LinearInterpInferShapeFunctor,
PD_INFER_META(phi::InterpolateInferMeta));
REGISTER_OPERATOR(bilinear_interp_v2,
ops::InterpolateV2Op,
ops::InterpolateV2OpMaker,
ops::InterpolateV2GradMaker<paddle::framework::OpDesc>,
ops::InterpolateV2GradMaker<paddle::imperative::OpBase>,
BilinearInterpInferShapeFunctor);
REGISTER_OPERATOR(bilinear_interp_v2_grad,
ops::InterpolateV2OpGrad,
ops::InterpolateV2GradNoNeedBufferVarsInferer);
REGISTER_OPERATOR(nearest_interp_v2,
ops::InterpolateV2Op,
ops::InterpolateV2OpMaker,
ops::InterpolateV2GradMaker<paddle::framework::OpDesc>,
ops::InterpolateV2GradMaker<paddle::imperative::OpBase>,
NearestInterpInferShapeFunctor);
REGISTER_OPERATOR(nearest_interp_v2_grad,
ops::InterpolateV2OpGrad,
ops::InterpolateV2GradNoNeedBufferVarsInferer);
REGISTER_OPERATOR(trilinear_interp_v2,
ops::InterpolateV2Op,
ops::InterpolateV2OpMaker,
ops::InterpolateV2GradMaker<paddle::framework::OpDesc>,
ops::InterpolateV2GradMaker<paddle::imperative::OpBase>,
TrilinearInterpInferShapeFunctor);
REGISTER_OPERATOR(trilinear_interp_v2_grad,
ops::InterpolateV2OpGrad,
ops::InterpolateV2GradNoNeedBufferVarsInferer);
REGISTER_OPERATOR(bicubic_interp_v2,
ops::InterpolateV2Op,
ops::InterpolateV2OpMaker,
ops::InterpolateV2GradMaker<paddle::framework::OpDesc>,
ops::InterpolateV2GradMaker<paddle::imperative::OpBase>,
BicubicInterpInferShapeFunctor);
REGISTER_OPERATOR(bicubic_interp_v2_grad,
ops::InterpolateV2OpGrad,
ops::InterpolateV2GradNoNeedBufferVarsInferer);
REGISTER_OPERATOR(linear_interp_v2,
ops::InterpolateV2Op,
ops::InterpolateV2OpMaker,
ops::InterpolateV2GradMaker<paddle::framework::OpDesc>,
ops::InterpolateV2GradMaker<paddle::imperative::OpBase>,
LinearInterpInferShapeFunctor);
REGISTER_OPERATOR(linear_interp_v2_grad,
ops::InterpolateV2OpGrad,
ops::InterpolateV2GradNoNeedBufferVarsInferer);
......@@ -118,6 +118,36 @@
func : atanh_grad
inplace : (out_grad -> x_grad)
- backward_op : bicubic_interp_grad
forward : bicubic_interp (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, str data_layout="NCHW", int out_d=0, int out_h=0, int out_w=0, float[] scale={}, str interp_method="bilinear", bool align_corners=true, int align_mode=1) -> Tensor(output)
args : (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, Tensor output_grad, str data_layout, int out_d, int out_h, int out_w, float[] scale, str interp_method, bool align_corners, int align_mode)
output : Tensor(x_grad)
infer_meta :
func : UnchangedInferMeta
param: [x]
optional: out_size, size_tensor, scale_tensor
no_need_buffer : x
kernel :
func : bicubic_interp_grad
data_type : output_grad
data_transform :
skip_transform : out_size, size_tensor, scale_tensor
- backward_op : bilinear_interp_grad
forward : bilinear_interp (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, str data_layout="NCHW", int out_d=0, int out_h=0, int out_w=0, float[] scale={}, str interp_method="bilinear", bool align_corners=true, int align_mode=1) -> Tensor(output)
args : (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, Tensor output_grad, str data_layout, int out_d, int out_h, int out_w, float[] scale, str interp_method, bool align_corners, int align_mode)
output : Tensor(x_grad)
infer_meta :
func : UnchangedInferMeta
param: [x]
no_need_buffer : x
optional: out_size, size_tensor, scale_tensor
kernel :
func : bilinear_interp_grad
data_type : output_grad
data_transform :
skip_transform : out_size, size_tensor, scale_tensor
- backward_op : bmm_grad
forward : bmm (Tensor x, Tensor y) -> Tensor(out)
args : (Tensor x, Tensor y, Tensor out_grad)
......@@ -763,6 +793,21 @@
kernel :
func : lgamma_grad
- backward_op : linear_interp_grad
forward : linear_interp (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, str data_layout="NCHW", int out_d=0, int out_h=0, int out_w=0, float[] scale={}, str interp_method="bilinear", bool align_corners=true, int align_mode=1) -> Tensor(output)
args : (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, Tensor output_grad, str data_layout, int out_d, int out_h, int out_w, float[] scale, str interp_method, bool align_corners, int align_mode)
output : Tensor(x_grad)
infer_meta :
func : UnchangedInferMeta
param: [x]
optional: out_size, size_tensor, scale_tensor
no_need_buffer : x
kernel :
func : linear_interp_grad
data_type : output_grad
data_transform :
skip_transform : out_size, size_tensor, scale_tensor
- backward_op : log10_grad
forward : log10 (Tensor x) -> Tensor(out)
args : (Tensor x, Tensor out_grad)
......@@ -943,6 +988,21 @@
kernel :
func : mv_grad
- backward_op : nearest_interp_grad
forward : nearest_interp (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, str data_layout="NCHW", int out_d=0, int out_h=0, int out_w=0, float[] scale={}, str interp_method="bilinear", bool align_corners=true, int align_mode=1) -> Tensor(output)
args : (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, Tensor output_grad, str data_layout, int out_d, int out_h, int out_w, float[] scale, str interp_method, bool align_corners, int align_mode)
output : Tensor(x_grad)
infer_meta :
func : UnchangedInferMeta
param: [x]
optional: out_size, size_tensor, scale_tensor
no_need_buffer : x
kernel :
func : nearest_interp_grad
data_type : output_grad
data_transform :
skip_transform : out_size, size_tensor, scale_tensor
- backward_op : nll_loss_grad
forward : nll_loss (Tensor input, Tensor label, Tensor weight, int64_t ignore_index = -100, str reduction = "mean") -> Tensor(out), Tensor(total_weight)
args : (Tensor input, Tensor label, Tensor weight, Tensor total_weight, Tensor out_grad, int64_t ignore_index, str reduction)
......@@ -1576,6 +1636,21 @@
data_type : out_grad
no_need_buffer : x
- backward_op : trilinear_interp_grad
forward : trilinear_interp (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, str data_layout="NCHW", int out_d=0, int out_h=0, int out_w=0, float[] scale={}, str interp_method="bilinear", bool align_corners=true, int align_mode=1) -> Tensor(output)
args : (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, Tensor output_grad, str data_layout, int out_d, int out_h, int out_w, float[] scale, str interp_method, bool align_corners, int align_mode)
output : Tensor(x_grad)
infer_meta :
func : UnchangedInferMeta
param: [x]
optional: out_size, size_tensor, scale_tensor
no_need_buffer : x
kernel :
func : trilinear_interp_grad
data_type : output_grad
data_transform :
skip_transform : out_size, size_tensor, scale_tensor
- backward_op : trunc_grad
forward : trunc (Tensor input) -> Tensor(out)
args : (Tensor out_grad)
......
......@@ -143,30 +143,6 @@
func : bce_loss_grad
inplace : (out_grad -> input_grad)
- backward_op : bicubic_interp_grad
forward : bicubic_interp (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, str data_layout, int out_d, int out_h, int out_w, float[] scale, str interp_method, bool align_corners, int align_mode) -> Tensor(output)
args : (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, Tensor output_grad, str data_layout, int out_d, int out_h, int out_w, float[] scale, str interp_method, bool align_corners, int align_mode)
output : Tensor(x_grad)
infer_meta :
func : UnchangedInferMeta
param: [x]
optional: out_size, size_tensor, scale_tensor
kernel :
func : bicubic_interp_grad
data_type : output_grad
- backward_op : bilinear_interp_grad
forward : bilinear_interp (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, str data_layout, int out_d, int out_h, int out_w, float[] scale, str interp_method, bool align_corners, int align_mode) -> Tensor(output)
args : (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, Tensor output_grad, str data_layout, int out_d, int out_h, int out_w, float[] scale, str interp_method, bool align_corners, int align_mode)
output : Tensor(x_grad)
infer_meta :
func : UnchangedInferMeta
param: [x]
optional: out_size, size_tensor, scale_tensor
kernel :
func : bilinear_interp_grad
data_type : output_grad
- backward_op : bilinear_tensor_product_grad
forward : bilinear_tensor_product (Tensor x, Tensor y, Tensor weight, Tensor bias) -> Tensor(out)
args : (Tensor x, Tensor y, Tensor weight, Tensor out_grad)
......@@ -654,18 +630,6 @@
no_need_buffer : bias
optional : scale, bias
- backward_op : linear_interp_grad
forward : linear_interp (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, str data_layout, int out_d, int out_h, int out_w, float[] scale, str interp_method, bool align_corners, int align_mode) -> Tensor(output)
args : (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, Tensor output_grad, str data_layout, int out_d, int out_h, int out_w, float[] scale, str interp_method, bool align_corners, int align_mode)
output : Tensor(x_grad)
infer_meta :
func : UnchangedInferMeta
param: [x]
optional: out_size, size_tensor, scale_tensor
kernel :
func : linear_interp_grad
data_type : output_grad
- backward_op : log_softmax_grad
forward : log_softmax(Tensor x, int axis) -> Tensor(out)
args : (Tensor out, Tensor out_grad, int axis)
......@@ -884,18 +848,6 @@
func : multiply_triple_grad
optional : fwd_grad_grad_x, fwd_grad_grad_y, grad_x_grad, grad_y_grad, grad_grad_out_grad
- backward_op : nearest_interp_grad
forward : nearest_interp (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, str data_layout, int out_d, int out_h, int out_w, float[] scale, str interp_method, bool align_corners, int align_mode) -> Tensor(output)
args : (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, Tensor output_grad, str data_layout, int out_d, int out_h, int out_w, float[] scale, str interp_method, bool align_corners, int align_mode)
output : Tensor(x_grad)
infer_meta :
func : UnchangedInferMeta
param: [x]
optional: out_size, size_tensor, scale_tensor
kernel :
func : nearest_interp_grad
data_type : output_grad
- backward_op : norm_grad
forward : norm (Tensor x, int axis, float epsilon, bool is_test) -> Tensor(out), Tensor(norm)
args : (Tensor x, Tensor norm, Tensor out_grad, int axis, float epsilon, bool is_test)
......@@ -1370,18 +1322,6 @@
kernel :
func : tril_grad
- backward_op : trilinear_interp_grad
forward : trilinear_interp (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, str data_layout, int out_d, int out_h, int out_w, float[] scale, str interp_method, bool align_corners, int align_mode) -> Tensor(output)
args : (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, Tensor output_grad, str data_layout, int out_d, int out_h, int out_w, float[] scale, str interp_method, bool align_corners, int align_mode)
output : Tensor(x_grad)
infer_meta :
func : UnchangedInferMeta
param: [x]
optional: out_size, size_tensor, scale_tensor
kernel :
func : trilinear_interp_grad
data_type : output_grad
- backward_op : triu_grad
forward : triu(Tensor x, int diagonal) -> Tensor(out)
args : (Tensor out_grad, int diagonal)
......
......@@ -241,28 +241,6 @@
func : bce_loss
backward : bce_loss_grad
- op : bicubic_interp
args : (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, str data_layout, int out_d, int out_h, int out_w, float[] scale, str interp_method, bool align_corners, int align_mode)
output : Tensor(output)
infer_meta :
func : InterpolateInferMeta
optional: out_size, size_tensor, scale_tensor
kernel :
func : bicubic_interp
data_type : x
backward : bicubic_interp_grad
- op : bilinear_interp
args : (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, str data_layout, int out_d, int out_h, int out_w, float[] scale, str interp_method, bool align_corners, int align_mode)
output : Tensor(output)
infer_meta :
func : InterpolateInferMeta
optional: out_size, size_tensor, scale_tensor
kernel :
func : bilinear_interp
data_type : x
backward : bilinear_interp_grad
- op : bilinear_tensor_product
args : (Tensor x, Tensor y, Tensor weight, Tensor bias)
output : Tensor
......@@ -933,17 +911,6 @@
kernel :
func : less_than
- op : linear_interp
args : (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, str data_layout, int out_d, int out_h, int out_w, float[] scale, str interp_method, bool align_corners, int align_mode)
output : Tensor(output)
infer_meta :
func : InterpolateInferMeta
optional: out_size, size_tensor, scale_tensor
kernel :
func : linear_interp
data_type : x
backward : linear_interp_grad
- op : linspace
args : (Tensor start, Tensor stop, Tensor number, DataType dtype, Place place)
output : Tensor(out)
......@@ -1231,17 +1198,6 @@
multiply_sr {selected_rows, dense -> selected_rows}
backward : multiply_grad
- op : nearest_interp
args : (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, str data_layout, int out_d, int out_h, int out_w, float[] scale, str interp_method, bool align_corners, int align_mode)
output : Tensor(output)
infer_meta :
func : InterpolateInferMeta
optional: out_size, size_tensor, scale_tensor
kernel :
func : nearest_interp
data_type : x
backward : nearest_interp_grad
- op : nms
args : (Tensor x, float threshold)
output : Tensor(out)
......@@ -1733,17 +1689,6 @@
data_type : dtype
backend : place
- op : trilinear_interp
args : (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, str data_layout, int out_d, int out_h, int out_w, float[] scale, str interp_method, bool align_corners, int align_mode)
output : Tensor(output)
infer_meta :
func : InterpolateInferMeta
optional: out_size, size_tensor, scale_tensor
kernel :
func : trilinear_interp
data_type : x
backward : trilinear_interp_grad
- op : triu
args : (Tensor x, int diagonal)
output : Tensor(out)
......
......@@ -163,11 +163,19 @@
- op : bicubic_interp (bicubic_interp_v2)
backward : bicubic_interp_grad (bicubic_interp_v2_grad)
inputs :
{x : X, out_size : OutSize, size_tensor : SizeTensor, scale_tensor : Scale}
outputs :
output : Out
extra :
attrs : [bool use_mkldnn = false]
- op : bilinear_interp (bilinear_interp_v2)
backward : bilinear_interp_grad (bilinear_interp_v2_grad)
inputs :
{x : X, out_size : OutSize, size_tensor : SizeTensor, scale_tensor : Scale}
outputs :
output : Out
extra :
attrs : [bool use_mkldnn = false]
......@@ -983,6 +991,10 @@
- op : linear_interp (linear_interp_v2)
backward : linear_interp_grad (linear_interp_v2_grad)
inputs :
{x : X, out_size : OutSize, size_tensor : SizeTensor, scale_tensor : Scale}
outputs :
output : Out
extra :
attrs : [bool use_mkldnn = false]
......@@ -1205,6 +1217,10 @@
- op : nearest_interp (nearest_interp_v2)
backward : nearest_interp_grad (nearest_interp_v2_grad)
inputs :
{x : X, out_size : OutSize, size_tensor : SizeTensor, scale_tensor : Scale}
outputs :
output : Out
extra :
attrs : [bool use_mkldnn = false]
......@@ -1800,6 +1816,10 @@
- op : trilinear_interp (trilinear_interp_v2)
backward : trilinear_interp_grad (trilinear_interp_v2_grad)
inputs :
{x : X, out_size : OutSize, size_tensor : SizeTensor, scale_tensor : Scale}
outputs :
output : Out
extra :
attrs : [bool use_mkldnn = false]
......
......@@ -125,6 +125,32 @@
kernel :
func : bernoulli
- op : bicubic_interp
args : (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, str data_layout="NCHW", int out_d=0, int out_h=0, int out_w=0, float[] scale={}, str interp_method="bilinear", bool align_corners=true, int align_mode=1)
output : Tensor(output)
infer_meta :
func : InterpolateInferMeta
optional: out_size, size_tensor, scale_tensor
kernel :
func : bicubic_interp
data_type : x
backward : bicubic_interp_grad
data_transform :
skip_transform : out_size, size_tensor, scale_tensor
- op : bilinear_interp
args : (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, str data_layout="NCHW", int out_d=0, int out_h=0, int out_w=0, float[] scale={}, str interp_method="bilinear", bool align_corners=true, int align_mode=1)
output : Tensor(output)
infer_meta :
func : InterpolateInferMeta
optional: out_size, size_tensor, scale_tensor
kernel :
func : bilinear_interp
data_type : x
backward : bilinear_interp_grad
data_transform :
skip_transform : out_size, size_tensor, scale_tensor
- op : bitwise_and
args : (Tensor x, Tensor y)
output : Tensor(out)
......@@ -780,6 +806,19 @@
func : lgamma
backward : lgamma_grad
- op : linear_interp
args : (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, str data_layout="NCHW", int out_d=0, int out_h=0, int out_w=0, float[] scale={}, str interp_method="bilinear", bool align_corners=true, int align_mode=1)
output : Tensor(output)
infer_meta :
func : InterpolateInferMeta
optional: out_size, size_tensor, scale_tensor
kernel :
func : linear_interp
data_type : x
backward : linear_interp_grad
data_transform :
skip_transform : out_size, size_tensor, scale_tensor
- op : log
args : (Tensor x)
output : Tensor
......@@ -938,6 +977,19 @@
func : mv
backward : mv_grad
- op : nearest_interp
args : (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, str data_layout="NCHW", int out_d=0, int out_h=0, int out_w=0, float[] scale={}, str interp_method="bilinear", bool align_corners=true, int align_mode=1)
output : Tensor(output)
infer_meta :
func : InterpolateInferMeta
optional: out_size, size_tensor, scale_tensor
kernel :
func : nearest_interp
data_type : x
backward : nearest_interp_grad
data_transform :
skip_transform : out_size, size_tensor, scale_tensor
- op : nll_loss
args : (Tensor input, Tensor label, Tensor weight, int64_t ignore_index = -100, str reduction = "mean")
output : Tensor(out), Tensor(total_weight)
......@@ -1406,6 +1458,19 @@
func : trace
backward : trace_grad
- op : trilinear_interp
args : (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, str data_layout="NCHW", int out_d=0, int out_h=0, int out_w=0, float[] scale={}, str interp_method="bilinear", bool align_corners=true, int align_mode=1)
output : Tensor(output)
infer_meta :
func : InterpolateInferMeta
optional: out_size, size_tensor, scale_tensor
kernel :
func : trilinear_interp
data_type : x
backward : trilinear_interp_grad
data_transform :
skip_transform : out_size, size_tensor, scale_tensor
- op : trunc
args : (Tensor input)
output : Tensor
......
......@@ -101,6 +101,7 @@ cc_library(
infermeta_utils
SRCS infermeta_utils.cc
DEPS meta_tensor)
cc_library(
selected_rows
SRCS selected_rows_impl.cc selected_rows.cc
......
......@@ -6,6 +6,7 @@ cc_library(
op_utils
SRCS op_utils.cc
DEPS arg_map_context enforce)
cc_library(get_kerneltype_forvar_utils SRCS get_kerneltype_forvar_utils.cc)
set(convert_utils_deps data_type place op_utils phi_backends)
......
// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.
//
// 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
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// 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.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "paddle/phi/core/compat/get_kerneltype_forvar_utils.h"
namespace phi {
const std::string& GetKernelTypeForVarContext::GetVarName(void) const {
return *var_name_;
}
const DenseTensor& GetKernelTypeForVarContext::GetTensor(void) const {
return *tensor_;
}
const KernelKey& GetKernelTypeForVarContext::GetKernelKey(void) const {
return *kernel_key_;
}
const AttributeMap& GetKernelTypeForVarContext::GetAttrs(void) const {
return *attrs_;
}
void GetKernelTypeForVarContext::SetVarName(std::string* var_name) {
this->var_name_ = var_name;
}
void GetKernelTypeForVarContext::SetDenseTensor(DenseTensor* tensor) {
this->tensor_ = tensor;
}
} // namespace phi
// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.
//
// 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
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// 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.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include "paddle/phi/core/attribute.h"
namespace phi {
class KernelKey;
class DenseTensor;
/**
* Note: GetKernelTypeForVarContext is currently designed to MKLDNN kernel when
* the related memeber function 'GetKernelTypeForVar' is special. It is
* possiable to uesed for other custom hardwares in the future.
*/
class GetKernelTypeForVarContext {
public:
GetKernelTypeForVarContext() = default;
GetKernelTypeForVarContext(const GetKernelTypeForVarContext&) = default;
explicit GetKernelTypeForVarContext(const phi::KernelKey* kernel_key,
const AttributeMap* attrs)
: kernel_key_(kernel_key), attrs_(attrs) {}
const std::string& GetVarName(void) const;
const DenseTensor& GetTensor(void) const;
const KernelKey& GetKernelKey(void) const;
const AttributeMap& GetAttrs(void) const;
void SetVarName(std::string* var_name);
void SetDenseTensor(DenseTensor* tensor);
private:
const KernelKey* kernel_key_; // not owned
// Use AttributeMap in namespace 'phi' to avoid depending 'fuild'
const AttributeMap* attrs_; // not owned
std::string* var_name_; // not owned
DenseTensor* tensor_; // not owned
};
typedef KernelKey (*GetKernelTypeForVarFn)(const GetKernelTypeForVarContext*);
} // namespace phi
......@@ -24,12 +24,12 @@
#include "paddle/phi/common/data_type.h"
#include "paddle/phi/common/layout.h"
#include "paddle/phi/core/compat/convert_utils.h"
#include "paddle/phi/core/compat/get_kerneltype_forvar_utils.h"
#include "paddle/phi/core/enforce.h"
#include "paddle/phi/core/type_defs.h"
#include "paddle/phi/core/utils/data_type.h"
#include "paddle/utils/flat_hash_map.h"
#include "paddle/utils/small_vector.h"
namespace phi {
using DataType = paddle::experimental::DataType;
......@@ -286,6 +286,8 @@ class Kernel {
return kernel_registered_type_;
}
GetKernelTypeForVarFn get_kerneltype_forvar_fn_{nullptr};
private:
KernelFn fn_{nullptr};
void* variadic_fn_ = nullptr;
......
......@@ -154,7 +154,12 @@ file(GLOB kernel_xpu "xpu/*.cc" "selected_rows/xpu/*.cc" "fusion/xpu/*.cc")
add_library(phi_cpu ${kernel_cc})
kernel_declare("${kernel_cc}")
target_link_libraries(phi_cpu ${COMMON_KERNEL_DEPS})
if(WITH_MKLDNN)
target_link_libraries(phi_cpu ${COMMON_KERNEL_DEPS}
get_kerneltype_forvar_utils)
else()
target_link_libraries(phi_cpu ${COMMON_KERNEL_DEPS})
endif()
set(ADD_PHI_KERNELS phi_cpu)
......
......@@ -15,11 +15,41 @@
#include "paddle/phi/kernels/interpolate_kernel.h"
#include "paddle/phi/backends/onednn/onednn_reuse.h"
#include "paddle/phi/core/compat/get_kerneltype_forvar_utils.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/funcs/interpolate_function.h"
namespace phi {
KernelKey InterpolateGetKernelTypeForVar(
const GetKernelTypeForVarContext* ctx) {
const std::string& var_name = ctx->GetVarName();
const DenseTensor& tensor = ctx->GetTensor();
const KernelKey& expected_kernel_type = ctx->GetKernelKey();
const AttributeMap& attrs = ctx->GetAttrs();
// Only input require reshaping, weights and
// bias are having shape in NCHW order
if ((expected_kernel_type.layout() == DataLayout::ONEDNN) &&
(tensor.layout() != DataLayout::ONEDNN)) {
auto it = attrs.find("data_layout");
const std::string data_layout = PADDLE_GET_CONST(std::string, it->second);
auto dl = StringToDataLayout(data_layout);
// Some models may have intentionally set "AnyLayout" for pool
// op. Treat this as NCHW (default data_format value)
if (dl != DataLayout::kAnyLayout) {
return KernelKey(tensor.place(), dl, expected_kernel_type.dtype());
}
}
if (var_name == "OutSize" || var_name == "SizeTensor" ||
var_name == "Scale") {
return KernelKey(Backend::ALL_BACKEND,
expected_kernel_type.layout(),
expected_kernel_type.dtype());
}
return KernelKey(
tensor.place(), tensor.layout(), expected_kernel_type.dtype());
}
namespace funcs {
template <typename T = float>
class InterpolateOneDNNHandler
......@@ -233,7 +263,9 @@ PD_REGISTER_KERNEL(bilinear_interp,
phi::BilinearInterpKernel,
float,
phi::dtype::bfloat16,
phi::dtype::float16) {}
phi::dtype::float16) {
kernel->get_kerneltype_forvar_fn_ = phi::InterpolateGetKernelTypeForVar;
}
PD_REGISTER_KERNEL(nearest_interp,
OneDNN,
......@@ -243,4 +275,6 @@ PD_REGISTER_KERNEL(nearest_interp,
phi::dtype::bfloat16,
phi::dtype::float16,
int8_t,
uint8_t) {}
uint8_t) {
kernel->get_kerneltype_forvar_fn_ = phi::InterpolateGetKernelTypeForVar;
}
/* Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
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
http://www.apache.org/licenses/LICENSE-2.0
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.
See the License for the specific language governing permissions and
limitations under the License. */
#include "paddle/phi/core/compat/op_utils.h"
namespace phi {
KernelSignature BilinearInterpOpArgumentMapping(
const ArgumentMappingContext& ctx) {
return KernelSignature("bilinear_interp",
{"X", "OutSize", "SizeTensor", "Scale"},
{"data_layout",
"out_d",
"out_h",
"out_w",
"scale",
"interp_method",
"align_corners",
"align_mode"},
{"Out"});
}
KernelSignature NearestInterpOpArgumentMapping(
const ArgumentMappingContext& ctx) {
return KernelSignature("nearest_interp",
{"X", "OutSize", "SizeTensor", "Scale"},
{"data_layout",
"out_d",
"out_h",
"out_w",
"scale",
"interp_method",
"align_corners",
"align_mode"},
{"Out"});
}
KernelSignature TrilinearInterpOpArgumentMapping(
const ArgumentMappingContext& ctx) {
return KernelSignature("trilinear_interp",
{"X", "OutSize", "SizeTensor", "Scale"},
{"data_layout",
"out_d",
"out_h",
"out_w",
"scale",
"interp_method",
"align_corners",
"align_mode"},
{"Out"});
}
KernelSignature LinearInterpOpArgumentMapping(
const ArgumentMappingContext& ctx) {
return KernelSignature("linear_interp",
{"X", "OutSize", "SizeTensor", "Scale"},
{"data_layout",
"out_d",
"out_h",
"out_w",
"scale",
"interp_method",
"align_corners",
"align_mode"},
{"Out"});
}
KernelSignature BicubicInterpOpArgumentMapping(
const ArgumentMappingContext& ctx) {
return KernelSignature("bicubic_interp",
{"X", "OutSize", "SizeTensor", "Scale"},
{"data_layout",
"out_d",
"out_h",
"out_w",
"scale",
"interp_method",
"align_corners",
"align_mode"},
{"Out"});
}
KernelSignature BilinearInterpGradOpArgumentMapping(
const ArgumentMappingContext& ctx) {
return KernelSignature("bilinear_interp_grad",
{"X", "OutSize", "SizeTensor", "Scale", "Out@GRAD"},
{"data_layout",
"out_d",
"out_h",
"out_w",
"scale",
"interp_method",
"align_corners",
"align_mode"},
{"X@GRAD"});
}
KernelSignature NearestInterpGradOpArgumentMapping(
const ArgumentMappingContext& ctx) {
return KernelSignature("nearest_interp_grad",
{"X", "OutSize", "SizeTensor", "Scale", "Out@GRAD"},
{"data_layout",
"out_d",
"out_h",
"out_w",
"scale",
"interp_method",
"align_corners",
"align_mode"},
{"X@GRAD"});
}
KernelSignature TrilinearInterpGradOpArgumentMapping(
const ArgumentMappingContext& ctx) {
return KernelSignature("trilinear_interp_grad",
{"X", "OutSize", "SizeTensor", "Scale", "Out@GRAD"},
{"data_layout",
"out_d",
"out_h",
"out_w",
"scale",
"interp_method",
"align_corners",
"align_mode"},
{"X@GRAD"});
}
KernelSignature LinearInterpGradOpArgumentMapping(
const ArgumentMappingContext& ctx) {
return KernelSignature("linear_interp_grad",
{"X", "OutSize", "SizeTensor", "Scale", "Out@GRAD"},
{"data_layout",
"out_d",
"out_h",
"out_w",
"scale",
"interp_method",
"align_corners",
"align_mode"},
{"X@GRAD"});
}
KernelSignature BicubicInterpGradOpArgumentMapping(
const ArgumentMappingContext& ctx) {
return KernelSignature("bicubic_interp_grad",
{"X", "OutSize", "SizeTensor", "Scale", "Out@GRAD"},
{"data_layout",
"out_d",
"out_h",
"out_w",
"scale",
"interp_method",
"align_corners",
"align_mode"},
{"X@GRAD"});
}
} // namespace phi
PD_REGISTER_BASE_KERNEL_NAME(linear_interp_v2, linear_interp);
PD_REGISTER_BASE_KERNEL_NAME(bilinear_interp_v2, bilinear_interp);
PD_REGISTER_BASE_KERNEL_NAME(trilinear_interp_v2, trilinear_interp);
PD_REGISTER_BASE_KERNEL_NAME(nearest_interp_v2, nearest_interp);
PD_REGISTER_BASE_KERNEL_NAME(bicubic_interp_v2, bicubic_interp);
PD_REGISTER_BASE_KERNEL_NAME(linear_interp_v2_grad, linear_interp_grad);
PD_REGISTER_BASE_KERNEL_NAME(bilinear_interp_v2_grad, bilinear_interp_grad);
PD_REGISTER_BASE_KERNEL_NAME(trilinear_interp_v2_grad, trilinear_interp_grad);
PD_REGISTER_BASE_KERNEL_NAME(nearest_interp_v2_grad, nearest_interp_grad);
PD_REGISTER_BASE_KERNEL_NAME(bicubic_interp_v2_grad, bicubic_interp_grad);
PD_REGISTER_ARG_MAPPING_FN(bilinear_interp_v2,
phi::BilinearInterpOpArgumentMapping);
PD_REGISTER_ARG_MAPPING_FN(nearest_interp_v2,
phi::NearestInterpOpArgumentMapping);
PD_REGISTER_ARG_MAPPING_FN(trilinear_interp_v2,
phi::TrilinearInterpOpArgumentMapping);
PD_REGISTER_ARG_MAPPING_FN(linear_interp_v2,
phi::LinearInterpOpArgumentMapping);
PD_REGISTER_ARG_MAPPING_FN(bicubic_interp_v2,
phi::BicubicInterpOpArgumentMapping);
PD_REGISTER_ARG_MAPPING_FN(bilinear_interp_v2_grad,
phi::BilinearInterpGradOpArgumentMapping);
PD_REGISTER_ARG_MAPPING_FN(nearest_interp_v2_grad,
phi::NearestInterpGradOpArgumentMapping);
PD_REGISTER_ARG_MAPPING_FN(trilinear_interp_v2_grad,
phi::TrilinearInterpGradOpArgumentMapping);
PD_REGISTER_ARG_MAPPING_FN(linear_interp_v2_grad,
phi::LinearInterpGradOpArgumentMapping);
PD_REGISTER_ARG_MAPPING_FN(bicubic_interp_v2_grad,
phi::BicubicInterpGradOpArgumentMapping);
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册