set_value_op.cc 11.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
//   Copyright (c) 2020 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/fluid/operators/set_value_op.h"
16

17
#include <string>
18 19

#include "paddle/fluid/framework/infershape_utils.h"
20
#include "paddle/fluid/framework/op_version_registry.h"
21 22 23
#include "paddle/phi/core/infermeta_utils.h"
#include "paddle/phi/infermeta/unary.h"

24 25 26 27 28 29 30 31 32 33 34 35
namespace paddle {
namespace framework {
class InferShapeContext;
class OpDesc;
template <typename T>
class EmptyGradOpMaker;
}  // namespace framework
namespace imperative {
class OpBase;
}  // namespace imperative
}  // namespace paddle

36 37 38
namespace paddle {
namespace operators {

39
using Tensor = phi::DenseTensor;
40

41 42
class SetValue : public framework::OperatorWithKernel {
 public:
43 44
  SetValue(const std::string &type,
           const framework::VariableNameMap &inputs,
45 46 47 48 49 50 51 52
           const framework::VariableNameMap &outputs,
           const framework::AttributeMap &attrs)
      : OperatorWithKernel(type, inputs, outputs, attrs) {}

 protected:
  framework::OpKernelType GetExpectedKernelType(
      const framework::ExecutionContext &ctx) const override {
    return framework::OpKernelType(
53
        OperatorWithKernel::IndicateVarDataType(ctx, "Input"), ctx.GetPlace());
54
  }
55 56

  framework::OpKernelType GetKernelTypeForVar(
57 58
      const std::string &var_name,
      const Tensor &tensor,
59 60 61 62 63
      const framework::OpKernelType &expected_kernel_type) const override {
    if (var_name == "StartsTensorList" || var_name == "EndsTensorList" ||
        var_name == "StepsTensorList") {
      return expected_kernel_type;
    }
64 65
    return framework::OpKernelType(
        expected_kernel_type.data_type_, tensor.place(), tensor.layout());
66
  }
67 68 69 70 71
};

class SetValueMaker : public framework::OpProtoAndCheckerMaker {
 public:
  void Make() override {
72
    // Input
73 74 75
    AddInput("Input", "(Tensor) Input tensor of set_value operator.");
    AddInput("ValueTensor", "(Tensor) Value tensor of set_value operator.")
        .AsDispensable();
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
    AddInput("StartsTensorList",
             "(vector<Tensor<int32>>, optional) If provided, set_value will "
             "use this. The shape of the tensor in vector must be [1]."
             "It has higher priority compare with attr(starts).")
        .AsDuplicable()
        .AsDispensable();
    AddInput("EndsTensorList",
             "(vector<Tensor<int32>>, optional) If provided, set_value will "
             "use this. The shape of the tensor in vector must BE [1]."
             "It has higher priority compare with attr(ends).")
        .AsDuplicable()
        .AsDispensable();

    AddInput("StepsTensorList",
             "(vector<Tensor<int32>>, optional) If provided, set_value will "
             "use this. The shape of the tensor in vector must BE [1]."
             "It has higher priority compare with attr(steps).")
        .AsDuplicable()
        .AsDispensable();

    // Output
97 98 99 100
    AddOutput("Out",
              "(Tensor) Output tensor of set_value operator. The output is the "
              "same Tensor as input");

101
    // Attr
102
    AddAttr<int>("dtype", "data type of input.")
103 104 105 106
        .InEnum({framework::proto::VarType::BOOL,
                 framework::proto::VarType::INT32,
                 framework::proto::VarType::INT64,
                 framework::proto::VarType::FP32,
107 108
                 framework::proto::VarType::FP64,
                 framework::proto::VarType::FP16})
109 110 111 112 113
        .SetDefault(framework::proto::VarType::FP32);
    AddAttr<std::vector<int64_t>>(
        "axes", "(list<int64_t>) Axes that `starts` and `ends` apply to.");
    AddAttr<std::vector<int64_t>>(
        "starts",
114 115
        "(list<int64_t>) Starting indices of corresponding axis in `axes`.")
        .SetDefault({});
116 117
    AddAttr<std::vector<int64_t>>(
        "ends",
118 119 120 121 122
        "(list<int64_t>) Ending indices of corresponding axis in `axes`.")
        .SetDefault({});
    AddAttr<std::vector<int64_t>>(
        "steps", "(list<int64_t>) Stride step from the start to the end.")
        .SetDefault({});
123 124 125
    AddAttr<std::vector<int64_t>>("decrease_axes",
                                  "(list<int>) The axes to decrease.")
        .SetDefault({});
Z
zyfncg 已提交
126 127
    AddAttr<std::vector<int64_t>>("none_axes", "(list<int>) The axes to none.")
        .SetDefault({});
128

129
    AddAttr<std::vector<int>>("bool_values", "Store the bool values.")
130
        .SetDefault({});
131
    AddAttr<std::vector<float>>("fp32_values", "Store the float32 values.")
132
        .SetDefault({});
133
    AddAttr<std::vector<int>>("int32_values", "Store the int32 values.")
134
        .SetDefault({});
135
    AddAttr<std::vector<int64_t>>("int64_values", "Store the int64 values.")
136
        .SetDefault({});
137
    AddAttr<std::vector<double>>("fp64_values", "Store the float64 values.")
138
        .SetDefault({});
139 140
    AddAttr<std::vector<float>>("fp16_values", "Store the float16 values.")
        .SetDefault({});
141 142 143 144 145 146 147 148

    AddAttr<std::vector<int64_t>>("shape", "(vector<int64_t>) Shape of values.")
        .SetDefault({});
    AddComment(R"DOC(SetValue operator.
Assignment to a Tensor in static mode.
)DOC");
  }
};
149 150 151 152 153 154 155 156 157

template <typename T>
class SetValueGradMaker : public framework::SingleGradOpMaker<T> {
 public:
  using framework::SingleGradOpMaker<T>::SingleGradOpMaker;

 protected:
  void Apply(GradOpPtr<T> op) const override {
    if (this->HasInput("ValueTensor")) {
158 159 160 161
      op->SetType("set_value_grad");

      op->SetInput(framework::GradVarName("Out"), this->OutputGrad("Out"));
      op->SetInput("ValueTensor", this->Input("ValueTensor"));
162 163 164 165 166 167
      if (this->HasInput("StartsTensorList")) {
        op->SetInput("StartsTensorList", this->Input("StartsTensorList"));
      }
      if (this->HasInput("EndsTensorList")) {
        op->SetInput("EndsTensorList", this->Input("EndsTensorList"));
      }
168 169 170 171 172 173 174 175 176
      if (this->HasInput("StepsTensorList")) {
        op->SetInput("StepsTensorList", this->Input("StepsTensorList"));
      }

      op->SetAttrMap(this->Attrs());

      op->SetOutput(framework::GradVarName("ValueTensor"),
                    this->InputGrad("ValueTensor"));
      op->SetOutput(framework::GradVarName("Input"), this->InputGrad("Input"));
177 178 179 180 181 182 183 184 185

    } else {
      op->SetType("assign");
      op->SetInput("X", this->OutputGrad("Out"));
      op->SetOutput("Out", this->InputGrad("Input"));
    }
  }
};

186 187 188 189 190
class SetValueGrad : public framework::OperatorWithKernel {
 public:
  using framework::OperatorWithKernel::OperatorWithKernel;

  void InferShape(framework::InferShapeContext *ctx) const override {
191 192 193 194
    OP_INOUT_CHECK(ctx->HasInput(framework::GradVarName("Out")),
                   "Input",
                   framework::GradVarName("Out"),
                   "set_value_grad");
195 196 197

    auto in_dims = ctx->GetInputDim(framework::GradVarName("Out"));
    PADDLE_ENFORCE_LT(
198 199
        in_dims.size(),
        7,
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
        platform::errors::InvalidArgument(
            "The dimension of set_value_grad operator's input should be less "
            "than 7, but received dimension is %d.",
            in_dims.size()));

    if (ctx->HasOutput(framework::GradVarName("ValueTensor"))) {
      ctx->ShareDim("ValueTensor",
                    /*->*/ framework::GradVarName("ValueTensor"));
      ctx->ShareLoD("ValueTensor",
                    /*->*/ framework::GradVarName("ValueTensor"));
    }
  }

 protected:
  framework::OpKernelType GetExpectedKernelType(
      const framework::ExecutionContext &ctx) const override {
216
    auto in_tensor = ctx.Input<phi::DenseTensor>(framework::GradVarName("Out"));
217 218 219 220 221
    return framework::OpKernelType(OperatorWithKernel::IndicateVarDataType(
                                       ctx, framework::GradVarName("Out")),
                                   in_tensor->place());
  }
  framework::OpKernelType GetKernelTypeForVar(
222 223
      const std::string &var_name,
      const Tensor &tensor,
224 225 226 227 228
      const framework::OpKernelType &expected_kernel_type) const override {
    if (var_name == "StartsTensorList" || var_name == "EndsTensorList" ||
        var_name == "StepsTensorList") {
      return expected_kernel_type;
    }
229 230
    return framework::OpKernelType(
        expected_kernel_type.data_type_, tensor.place(), tensor.layout());
231 232 233
  }
};

234 235
DECLARE_INPLACE_OP_INFERER(SetValueOpInplaceInferer, {"Input", "Out"});

236 237 238 239
}  // namespace operators
}  // namespace paddle

namespace ops = paddle::operators;
240
namespace plat = paddle::platform;
241

242 243
DECLARE_INFER_SHAPE_FUNCTOR(set_value,
                            SetValueInferShapeFunctor,
244 245
                            PD_INFER_META(phi::SetValueInferMeta));

246 247 248
REGISTER_OPERATOR(set_value,
                  ops::SetValue,
                  ops::SetValueMaker,
249 250
                  ops::SetValueGradMaker<paddle::framework::OpDesc>,
                  ops::SetValueGradMaker<paddle::imperative::OpBase>,
251 252
                  ops::SetValueOpInplaceInferer,
                  SetValueInferShapeFunctor);
253

254 255
REGISTER_OPERATOR(set_value_grad, ops::SetValueGrad);

256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
REGISTER_OP_VERSION(set_value)
    .AddCheckpoint(
        R"ROC(
Upgrade set_value, add 3 inputs [StartsTensorList, EndsTensorList, StepsTensorList] and 1 attribute [steps].
              )ROC",
        paddle::framework::compatible::OpVersionDesc()
            .NewInput("StartsTensorList",
                      "If provided, set_value will use this.The shape of the "
                      "tensor in vector must be [1]. It has higher priority "
                      "compare with attr(starts).")
            .NewInput("EndsTensorList",
                      "If provided, set_value will use this.The shape of the "
                      "tensor in vector must be [1]. It has higher priority "
                      "compare with attr(ends).")
            .NewInput("StepsTensorList",
                      "If provided, set_value will use this.The shape of the "
                      "tensor in vector must be [1]. It has higher priority "
                      "compare with attr(steps).")
            .ModifyAttr("starts",
                        "Starting indices of corresponding axis in `axes`.",
                        std::vector<int64_t>{})
            .ModifyAttr("ends",
                        "Ending indices of corresponding axis in `axes`.",
                        std::vector<int64_t>{})
280 281
            .NewAttr("steps",
                     "Stride step from the start to the end.",
282 283 284 285 286 287
                     std::vector<int64_t>{}))
    .AddCheckpoint(
        R"ROC(
Upgrade set_value, add 1 attribute [decrease_axes].
              )ROC",
        paddle::framework::compatible::OpVersionDesc().NewAttr(
Z
zyfncg 已提交
288 289 290 291 292 293 294
            "decrease_axes", "The axes to decrease.", std::vector<int64_t>{}))
    .AddCheckpoint(
        R"ROC(
Upgrade set_value, add 1 attribute [none_axes].
              )ROC",
        paddle::framework::compatible::OpVersionDesc().NewAttr(
            "none_axes", "The axes with none index.", std::vector<int64_t>{}));