|
|
|
@ -16,6 +16,7 @@ limitations under the License. */
|
|
|
|
|
#include <memory>
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include "paddle/fluid/framework/data_layout.h"
|
|
|
|
|
#include "paddle/fluid/platform/cudnn_workspace_helper.h"
|
|
|
|
|
|
|
|
|
|
#ifdef PADDLE_WITH_MKLDNN
|
|
|
|
@ -25,12 +26,14 @@ limitations under the License. */
|
|
|
|
|
namespace paddle {
|
|
|
|
|
namespace operators {
|
|
|
|
|
|
|
|
|
|
using DataLayout = framework::DataLayout;
|
|
|
|
|
|
|
|
|
|
void ConvTransposeOp::InferShape(framework::InferShapeContext* ctx) const {
|
|
|
|
|
PADDLE_ENFORCE(ctx->HasInput("Input"),
|
|
|
|
|
PADDLE_ENFORCE_EQ(ctx->HasInput("Input"), true,
|
|
|
|
|
"Input(Input) of ConvTransposeOp should not be null.");
|
|
|
|
|
PADDLE_ENFORCE(ctx->HasInput("Filter"),
|
|
|
|
|
PADDLE_ENFORCE_EQ(ctx->HasInput("Filter"), true,
|
|
|
|
|
"Input(Filter) of ConvTransposeOp should not be null.");
|
|
|
|
|
PADDLE_ENFORCE(ctx->HasOutput("Output"),
|
|
|
|
|
PADDLE_ENFORCE_EQ(ctx->HasOutput("Output"), true,
|
|
|
|
|
"Output(Output) of ConvTransposeOp should not be null.");
|
|
|
|
|
|
|
|
|
|
auto in_dims = ctx->GetInputDim("Input");
|
|
|
|
@ -41,52 +44,75 @@ void ConvTransposeOp::InferShape(framework::InferShapeContext* ctx) const {
|
|
|
|
|
std::vector<int> paddings = ctx->Attrs().Get<std::vector<int>>("paddings");
|
|
|
|
|
std::vector<int> dilations = ctx->Attrs().Get<std::vector<int>>("dilations");
|
|
|
|
|
int groups = ctx->Attrs().Get<int>("groups");
|
|
|
|
|
std::string padding_algorithm =
|
|
|
|
|
ctx->Attrs().Get<std::string>("padding_algorithm");
|
|
|
|
|
const DataLayout data_layout = framework::StringToDataLayout(
|
|
|
|
|
ctx->Attrs().Get<std::string>("data_format"));
|
|
|
|
|
|
|
|
|
|
PADDLE_ENFORCE(in_dims.size() == 4 || in_dims.size() == 5,
|
|
|
|
|
PADDLE_ENFORCE_EQ(in_dims.size() == 4 || in_dims.size() == 5, true,
|
|
|
|
|
"ConvTransposeOp intput should be 4-D or 5-D tensor.");
|
|
|
|
|
PADDLE_ENFORCE_EQ(in_dims.size(), filter_dims.size(),
|
|
|
|
|
"ConvTransposeOp input dimension and filter dimension "
|
|
|
|
|
"should be the same.");
|
|
|
|
|
PADDLE_ENFORCE(in_dims.size() - strides.size() == 2U,
|
|
|
|
|
PADDLE_ENFORCE_EQ(
|
|
|
|
|
in_dims.size() - strides.size(), 2U,
|
|
|
|
|
"ConvTransposeOp input dimension and strides dimension should "
|
|
|
|
|
"be consistent.");
|
|
|
|
|
if (output_size.size())
|
|
|
|
|
PADDLE_ENFORCE_EQ(output_size.size(), strides.size(),
|
|
|
|
|
"ConvTransposeOp output_size dimension and strides "
|
|
|
|
|
"dimension should be the same.");
|
|
|
|
|
PADDLE_ENFORCE_EQ(paddings.size(), strides.size(),
|
|
|
|
|
"ConvTransposeOp paddings dimension and strides "
|
|
|
|
|
"dimension should be the same.");
|
|
|
|
|
PADDLE_ENFORCE_EQ(paddings.size(), dilations.size(),
|
|
|
|
|
"ConvTransposeOp paddings dimension and dilations "
|
|
|
|
|
"dimension should be the same.");
|
|
|
|
|
PADDLE_ENFORCE_EQ(in_dims[1], filter_dims[0],
|
|
|
|
|
"In ConvTransposeOp, The number of input channels should "
|
|
|
|
|
|
|
|
|
|
const int64_t C =
|
|
|
|
|
(data_layout == DataLayout::kNCHW ? in_dims[1]
|
|
|
|
|
: in_dims[in_dims.size() - 1]);
|
|
|
|
|
PADDLE_ENFORCE_EQ(
|
|
|
|
|
C, filter_dims[0],
|
|
|
|
|
"The number of input channels of Op(ConvTransposeOp) should "
|
|
|
|
|
"be equal to the number of filter's channels.");
|
|
|
|
|
|
|
|
|
|
std::vector<int64_t> output_shape({in_dims[0], filter_dims[1] * groups});
|
|
|
|
|
framework::DDim in_data_dims;
|
|
|
|
|
if (data_layout == DataLayout::kNCHW) {
|
|
|
|
|
in_data_dims = framework::slice_ddim(in_dims, 2, in_dims.size());
|
|
|
|
|
} else {
|
|
|
|
|
in_data_dims = framework::slice_ddim(in_dims, 1, in_dims.size() - 1);
|
|
|
|
|
}
|
|
|
|
|
framework::DDim filter_data_dims =
|
|
|
|
|
framework::slice_ddim(filter_dims, 2, filter_dims.size());
|
|
|
|
|
std::vector<int> ksize = framework::vectorize<int>(filter_data_dims);
|
|
|
|
|
UpdatePaddingAndDilation(&paddings, &dilations, padding_algorithm,
|
|
|
|
|
in_data_dims, strides, ksize);
|
|
|
|
|
|
|
|
|
|
std::vector<int64_t> output_shape({in_dims[0]});
|
|
|
|
|
if (data_layout == DataLayout::kNCHW) {
|
|
|
|
|
output_shape.push_back(filter_dims[1] * groups);
|
|
|
|
|
}
|
|
|
|
|
const int offset = (data_layout == DataLayout::kNCHW ? 2 : 1);
|
|
|
|
|
for (size_t i = 0; i < strides.size(); ++i) {
|
|
|
|
|
auto filter_extent = dilations[i] * (filter_dims[i + 2] - 1) + 1;
|
|
|
|
|
auto infer_shape =
|
|
|
|
|
(in_dims[i + 2] - 1) * strides[i] - 2 * paddings[i] + filter_extent;
|
|
|
|
|
auto infer_shape = (in_dims[i + offset] - 1) * strides[i] -
|
|
|
|
|
paddings[2 * i] - paddings[2 * i + 1] + filter_extent;
|
|
|
|
|
if (output_size.size()) {
|
|
|
|
|
PADDLE_ENFORCE((output_size[i] >= infer_shape &&
|
|
|
|
|
PADDLE_ENFORCE_EQ((output_size[i] >= infer_shape &&
|
|
|
|
|
output_size[i] < infer_shape + strides[i]),
|
|
|
|
|
"ConvTransposeOp output_size should be "
|
|
|
|
|
true,
|
|
|
|
|
"output_size of Op(ConvTransposeOp) should be "
|
|
|
|
|
"in appropriate range.");
|
|
|
|
|
output_shape.push_back(output_size[i]);
|
|
|
|
|
} else {
|
|
|
|
|
output_shape.push_back(infer_shape);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (data_layout == DataLayout::kNHWC) {
|
|
|
|
|
output_shape.push_back(filter_dims[1] * groups);
|
|
|
|
|
}
|
|
|
|
|
ctx->SetOutputDim("Output", framework::make_ddim(output_shape));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
framework::OpKernelType ConvTransposeOp::GetExpectedKernelType(
|
|
|
|
|
const framework::ExecutionContext& ctx) const {
|
|
|
|
|
framework::LibraryType library_{framework::LibraryType::kPlain};
|
|
|
|
|
std::string data_format = ctx.Attr<std::string>("data_format");
|
|
|
|
|
framework::DataLayout layout_ = framework::StringToDataLayout(data_format);
|
|
|
|
|
framework::DataLayout layout_ = framework::DataLayout::kAnyLayout;
|
|
|
|
|
bool use_cudnn = ctx.Attr<bool>("use_cudnn");
|
|
|
|
|
use_cudnn &= platform::is_gpu_place(ctx.GetPlace());
|
|
|
|
|
#ifdef PADDLE_WITH_CUDA
|
|
|
|
@ -115,12 +141,11 @@ void Conv2DTransposeOpMaker::Make() {
|
|
|
|
|
"(bool, default false) Set to true for inference only, false "
|
|
|
|
|
"for training. Some layers may run faster when this is true.")
|
|
|
|
|
.SetDefault(false);
|
|
|
|
|
AddInput(
|
|
|
|
|
"Input",
|
|
|
|
|
AddInput("Input",
|
|
|
|
|
"(Tensor) The input tensor of convolution transpose operator. "
|
|
|
|
|
"The format of input tensor is NCHW. Where N is batch size, C is the "
|
|
|
|
|
"number of input channels, H is the height of the feature, and "
|
|
|
|
|
"W is the width of the feature.");
|
|
|
|
|
"The format of input tensor is NCHW or NHWC. Where N is batch size, "
|
|
|
|
|
"C is the number of input channels, H is the height of the feature, "
|
|
|
|
|
"and W is the width of the feature.");
|
|
|
|
|
AddInput(
|
|
|
|
|
"Filter",
|
|
|
|
|
"(Tensor) The filter tensor of convolution transpose operator. "
|
|
|
|
@ -137,7 +162,7 @@ void Conv2DTransposeOpMaker::Make() {
|
|
|
|
|
|
|
|
|
|
AddOutput("Output",
|
|
|
|
|
"(Tensor) The output tensor of convolution transpose operator. "
|
|
|
|
|
"The format of output tensor is also NCHW.");
|
|
|
|
|
"The format of output tensor is the same as input tensor.");
|
|
|
|
|
AddAttr<std::vector<int>>("output_size",
|
|
|
|
|
"(vector<int> default: []), the "
|
|
|
|
|
"size of the output tensor")
|
|
|
|
@ -182,10 +207,15 @@ void Conv2DTransposeOpMaker::Make() {
|
|
|
|
|
"data_format",
|
|
|
|
|
"(string, default NCHW) Only used in "
|
|
|
|
|
"An optional string from: \"NHWC\", \"NCHW\". "
|
|
|
|
|
"Defaults to \"NHWC\". Specify the data format of the output data, "
|
|
|
|
|
"the input will be transformed automatically. ")
|
|
|
|
|
.SetDefault("AnyLayout");
|
|
|
|
|
// TODO(dzhwinter): need to registered layout transform function
|
|
|
|
|
"Specify that the data format of the input and output data is "
|
|
|
|
|
"channel_first or channel_last.")
|
|
|
|
|
.SetDefault("NCHW");
|
|
|
|
|
AddAttr<std::string>(
|
|
|
|
|
"padding_algorithm",
|
|
|
|
|
"(string, default \"EXPLICIT\") An optional string from: \"EXPLICIT\","
|
|
|
|
|
"\"SAME\",\"VALID\". Set to \"EXPLICIT\" for explicit padding. "
|
|
|
|
|
"Set to \"SAME\" or \"VALID\" for algorithm of padding. ")
|
|
|
|
|
.SetDefault("EXPLICIT");
|
|
|
|
|
AddAttr<int>("workspace_size_MB",
|
|
|
|
|
"Used in cudnn kernel only. workspace size for cudnn, in MB, "
|
|
|
|
|
"workspace is a section of GPU memory which will be "
|
|
|
|
@ -199,7 +229,7 @@ Convolution2D Transpose Operator.
|
|
|
|
|
The convolution transpose operation calculates the output based on the input, filter
|
|
|
|
|
and dilations, strides, paddings, groups parameters. The size of each dimension of the
|
|
|
|
|
parameters is checked in the infer-shape.
|
|
|
|
|
Input(Input) and output(Output) are in NCHW format. Where N is batchsize, C is the
|
|
|
|
|
Input(Input) and output(Output) are in NCHW or NHWC format. Where N is batchsize, C is the
|
|
|
|
|
number of channels, H is the height of the feature, and W is the width of the feature.
|
|
|
|
|
Filter(Input) is in MCHW format. Where M is the number of input feature channels,
|
|
|
|
|
C is the number of output feature channels, H is the height of the filter,
|
|
|
|
@ -216,19 +246,19 @@ For an example:
|
|
|
|
|
Output shape: $(N, C_{out}, H_{out}, W_{out})$
|
|
|
|
|
Where
|
|
|
|
|
$$
|
|
|
|
|
H_{out} = (H_{in} - 1) * strides[0] - 2 * paddings[0] + dilations[0] * (H_f - 1) + 1 \\
|
|
|
|
|
W_{out} = (W_{in} - 1) * strides[1] - 2 * paddings[1] + dilations[1] * (W_f - 1) + 1
|
|
|
|
|
H_{out} = (H_{in} - 1) * strides[0] - pad_height_top - pad_height_bottom + dilations[0] * (H_f - 1) + 1 \\
|
|
|
|
|
W_{out} = (W_{in} - 1) * strides[1] - pad_width_left - pad_width_right + dilations[1] * (W_f - 1) + 1
|
|
|
|
|
$$
|
|
|
|
|
)DOC");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Conv3DTransposeOpMaker::Make() {
|
|
|
|
|
AddInput("Input",
|
|
|
|
|
AddInput(
|
|
|
|
|
"Input",
|
|
|
|
|
"(Tensor) The input tensor of convolution transpose operator."
|
|
|
|
|
"The format of input tensor is NCDHW. Where N is batch size, C is "
|
|
|
|
|
"the number of channels, D is the depth of the feature, H is the "
|
|
|
|
|
"height of the feature, and "
|
|
|
|
|
"W is the width of the feature.");
|
|
|
|
|
"The format of input tensor is NCDHW or NDHWC. Where N is batch "
|
|
|
|
|
"size, C is the number of channels, D is the depth of the feature, "
|
|
|
|
|
"H is the height of the feature, and W is the width of the feature.");
|
|
|
|
|
AddInput("Filter",
|
|
|
|
|
"(Tensor) The filter tensor of convolution transpose operator."
|
|
|
|
|
"The format of the filter tensor is MCDHW, where M is the number of "
|
|
|
|
@ -240,7 +270,7 @@ void Conv3DTransposeOpMaker::Make() {
|
|
|
|
|
"the convolution3d transpose scenario.");
|
|
|
|
|
AddOutput("Output",
|
|
|
|
|
"(Tensor) The output tensor of convolution transpose operator."
|
|
|
|
|
"The format of output tensor is also NCDHW."
|
|
|
|
|
"The format of output tensor is the same as input tensor."
|
|
|
|
|
"Where N is batch size, C is "
|
|
|
|
|
"the number of channels, D is the depth of the feature, H is the "
|
|
|
|
|
"height of the feature, and W is the width of the feature.");
|
|
|
|
@ -278,10 +308,15 @@ void Conv3DTransposeOpMaker::Make() {
|
|
|
|
|
"data_format",
|
|
|
|
|
"(string, default NCHW) Only used in "
|
|
|
|
|
"An optional string from: \"NHWC\", \"NCHW\". "
|
|
|
|
|
"Defaults to \"NHWC\". Specify the data format of the output data, "
|
|
|
|
|
"the input will be transformed automatically. ")
|
|
|
|
|
.SetDefault("AnyLayout");
|
|
|
|
|
// TODO(dzhwinter): need to registered layout transform function
|
|
|
|
|
"Specify that the data format of the input and output data is "
|
|
|
|
|
"channel_first or channel_last.")
|
|
|
|
|
.SetDefault("NCHW");
|
|
|
|
|
AddAttr<std::string>(
|
|
|
|
|
"padding_algorithm",
|
|
|
|
|
"(string, default \"EXPLICIT\") An optional string from: \"EXPLICIT\","
|
|
|
|
|
"\"SAME\",\"VALID\". Set to \"EXPLICIT\" for explicit padding. "
|
|
|
|
|
"Set to \"SAME\" or \"VALID\" for algorithm of padding. ")
|
|
|
|
|
.SetDefault("EXPLICIT");
|
|
|
|
|
AddAttr<int>("workspace_size_MB",
|
|
|
|
|
"Used in cudnn kernel only. workspace size for cudnn, in MB, "
|
|
|
|
|
"workspace is a section of GPU memory which will be "
|
|
|
|
@ -295,7 +330,7 @@ Convolution3D Transpose Operator.
|
|
|
|
|
The convolution transpose operation calculates the output based on the input, filter
|
|
|
|
|
and dilations, strides, paddings, groups parameters. The size of each dimension of the
|
|
|
|
|
parameters is checked in the infer-shape.
|
|
|
|
|
Input(Input) and output(Output) are in NCDHW format. Where N is batch size, C is the
|
|
|
|
|
Input(Input) and output(Output) are in NCDHW or NDHWC format. Where N is batch size, C is the
|
|
|
|
|
number of channels, D is the depth of the feature, H is the height of the feature,
|
|
|
|
|
and W is the width of the feature.
|
|
|
|
|
Filter(Input) is in MCDHW format. Where M is the number of input feature channels,
|
|
|
|
@ -313,9 +348,9 @@ Example:
|
|
|
|
|
Output shape: $(N, C_{out}, D_{out}, H_{out}, W_{out})$
|
|
|
|
|
Where
|
|
|
|
|
$$
|
|
|
|
|
D_{out} = (D_{in} - 1) * strides[0] - 2 * paddings[0] + dilations[0] * (D_f - 1) + 1 \\
|
|
|
|
|
H_{out} = (H_{in} - 1) * strides[1] - 2 * paddings[1] + dilations[1] * (H_f - 1) + 1 \\
|
|
|
|
|
W_{out} = (W_{in} - 1) * strides[2] - 2 * paddings[2] + dilations[2] * (W_f - 1) + 1
|
|
|
|
|
D_{out} = (D_{in} - 1) * strides[0] - pad_depth_front - pad_depth_back + dilations[0] * (D_f - 1) + 1 \\
|
|
|
|
|
H_{out} = (H_{in} - 1) * strides[1] - pad_height_top - pad_height_bottom + dilations[1] * (H_f - 1) + 1 \\
|
|
|
|
|
W_{out} = (W_{in} - 1) * strides[2] - pad_width_left - pad_width_right + dilations[2] * (W_f - 1) + 1
|
|
|
|
|
$$
|
|
|
|
|
)DOC");
|
|
|
|
|
}
|
|
|
|
@ -348,8 +383,7 @@ framework::OpKernelType ConvTransposeOpGrad::GetExpectedKernelType(
|
|
|
|
|
library_ = framework::LibraryType::kPlain;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string data_format = ctx.Attr<std::string>("data_format");
|
|
|
|
|
framework::DataLayout layout_ = framework::StringToDataLayout(data_format);
|
|
|
|
|
framework::DataLayout layout_ = framework::DataLayout::kAnyLayout;
|
|
|
|
|
return framework::OpKernelType(ctx.Input<Tensor>("Input")->type(),
|
|
|
|
|
ctx.GetPlace(), layout_, library_);
|
|
|
|
|
}
|
|
|
|
|