diff --git a/paddle/fluid/operators/pad_constant_like_op.cc b/paddle/fluid/operators/pad_constant_like_op.cc index 3f827c26fd415c8a3c2295129f413850ea59bef3..31ed0a686f712bd286b4accda68716b156037dbc 100644 --- a/paddle/fluid/operators/pad_constant_like_op.cc +++ b/paddle/fluid/operators/pad_constant_like_op.cc @@ -13,6 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. */ #include "paddle/fluid/operators/pad_constant_like_op.h" +#include namespace paddle { namespace operators { @@ -38,8 +39,16 @@ class PadConstantLikeOp : public framework::OperatorWithKernel { "The dimention of X and Y should be the same."); for (int i = 0; i < x_dim.size(); ++i) { - PADDLE_ENFORCE_GE(x_dim[i], y_dim[i]); + if ((!ctx->IsRuntime()) && ((x_dim[i] == -1) || (y_dim[i] == -1))) { + continue; + } else { + PADDLE_ENFORCE_GE( + x_dim[i], y_dim[i], + "expected X_dim[i] >= Y_dim[i], but received %d < %d for dim %d", + x_dim[i], y_dim[i], i); + } } + ctx->SetOutputDim("Out", x_dim); ctx->ShareLoD("X", /*->*/ "Out"); } @@ -162,7 +171,14 @@ class PadConstantLikeOpGrad : public framework::OperatorWithKernel { ctx->ShareLoD("Y", /*->*/ y_grad_name); for (int i = 0; i < y_dim.size(); ++i) { - PADDLE_ENFORCE_GE(dout_dim[i], y_dim[i]); + if ((!ctx->IsRuntime()) && ((dout_dim[i] == -1) || (y_dim[i] == -1))) { + continue; + } else { + PADDLE_ENFORCE_GE(dout_dim[i], y_dim[i], + "expected Out_dim[i] >= Y_dim[i], but received %d " + "< %d for dim %d", + dout_dim[i], y_dim[i], i); + } } } } diff --git a/paddle/fluid/operators/pad_op.cc b/paddle/fluid/operators/pad_op.cc index c28106d31273cb54e3974d186296644272d2014c..36dc8b0dbb3d3b6537b6395f4c831ac25b03a4c6 100644 --- a/paddle/fluid/operators/pad_op.cc +++ b/paddle/fluid/operators/pad_op.cc @@ -34,9 +34,16 @@ class PadOp : public framework::OperatorWithKernel { PADDLE_ENFORCE_EQ(x_dim.size() * 2, int64_t(paddings.size()), "Size of paddings should be equal to 2 * dimension size " "of input tensor."); + for (size_t i = 0; i < paddings.size(); ++i) { + PADDLE_ENFORCE_GE(paddings[i], 0, "paddings should >= 0."); + } std::vector out_dims(x_dim.size()); for (int i = 0; i < x_dim.size(); ++i) { - out_dims[i] = x_dim[i] + paddings[i * 2] + paddings[i * 2 + 1]; + if ((!ctx->IsRuntime()) && (x_dim[i] == -1)) { + out_dims[i] = -1; + } else { + out_dims[i] = x_dim[i] + paddings[i * 2] + paddings[i * 2 + 1]; + } } ctx->SetOutputDim("Out", framework::make_ddim(out_dims)); if (out_dims[0] == x_dim[0]) { @@ -100,18 +107,14 @@ class PadOpGrad : public framework::OperatorWithKernel { using framework::OperatorWithKernel::OperatorWithKernel; void InferShape(framework::InferShapeContext* ctx) const override { - auto dout_dims = ctx->GetInputDim(framework::GradVarName("Out")); - auto& paddings = ctx->Attrs().Get>("paddings"); - for (int i = 0; i < dout_dims.size(); ++i) { - dout_dims[i] -= (paddings[i * 2] + paddings[i * 2 + 1]); - } - auto x_grad_name = framework::GradVarName("X"); if (ctx->HasOutput(x_grad_name)) { auto dout_dims = ctx->GetInputDim(framework::GradVarName("Out")); auto& paddings = ctx->Attrs().Get>("paddings"); for (int i = 0; i < dout_dims.size(); ++i) { - dout_dims[i] -= (paddings[i * 2] + paddings[i * 2 + 1]); + if (ctx->IsRuntime() || (dout_dims[i] != -1)) { + dout_dims[i] -= (paddings[i * 2] + paddings[i * 2 + 1]); + } } ctx->SetOutputDim(x_grad_name, dout_dims); }