set_value_op.cc 10.9 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 40
using Tensor = framework::Tensor;

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 107
        .InEnum({framework::proto::VarType::BOOL,
                 framework::proto::VarType::INT32,
                 framework::proto::VarType::INT64,
                 framework::proto::VarType::FP32,
                 framework::proto::VarType::FP64})
108 109 110 111 112
        .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",
113 114
        "(list<int64_t>) Starting indices of corresponding axis in `axes`.")
        .SetDefault({});
115 116
    AddAttr<std::vector<int64_t>>(
        "ends",
117 118 119 120 121
        "(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({});
122 123 124
    AddAttr<std::vector<int64_t>>("decrease_axes",
                                  "(list<int>) The axes to decrease.")
        .SetDefault({});
Z
zyfncg 已提交
125 126
    AddAttr<std::vector<int64_t>>("none_axes", "(list<int>) The axes to none.")
        .SetDefault({});
127

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

    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");
  }
};
146 147 148 149 150 151 152 153 154

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")) {
155 156 157 158
      op->SetType("set_value_grad");

      op->SetInput(framework::GradVarName("Out"), this->OutputGrad("Out"));
      op->SetInput("ValueTensor", this->Input("ValueTensor"));
159 160 161 162 163 164
      if (this->HasInput("StartsTensorList")) {
        op->SetInput("StartsTensorList", this->Input("StartsTensorList"));
      }
      if (this->HasInput("EndsTensorList")) {
        op->SetInput("EndsTensorList", this->Input("EndsTensorList"));
      }
165 166 167 168 169 170 171 172 173
      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"));
174 175 176 177 178 179 180 181 182

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

183 184 185 186 187
class SetValueGrad : public framework::OperatorWithKernel {
 public:
  using framework::OperatorWithKernel::OperatorWithKernel;

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

    auto in_dims = ctx->GetInputDim(framework::GradVarName("Out"));
    PADDLE_ENFORCE_LT(
195 196
        in_dims.size(),
        7,
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
        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 {
    auto in_tensor = ctx.Input<Tensor>(framework::GradVarName("Out"));
    return framework::OpKernelType(OperatorWithKernel::IndicateVarDataType(
                                       ctx, framework::GradVarName("Out")),
                                   in_tensor->place());
  }
  framework::OpKernelType GetKernelTypeForVar(
219 220
      const std::string &var_name,
      const Tensor &tensor,
221 222 223 224 225
      const framework::OpKernelType &expected_kernel_type) const override {
    if (var_name == "StartsTensorList" || var_name == "EndsTensorList" ||
        var_name == "StepsTensorList") {
      return expected_kernel_type;
    }
226 227
    return framework::OpKernelType(
        expected_kernel_type.data_type_, tensor.place(), tensor.layout());
228 229 230
  }
};

231 232
DECLARE_INPLACE_OP_INFERER(SetValueOpInplaceInferer, {"Input", "Out"});

233 234 235 236
}  // namespace operators
}  // namespace paddle

namespace ops = paddle::operators;
237
namespace plat = paddle::platform;
238

239 240
DECLARE_INFER_SHAPE_FUNCTOR(set_value,
                            SetValueInferShapeFunctor,
241 242
                            PD_INFER_META(phi::SetValueInferMeta));

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

251 252
REGISTER_OPERATOR(set_value_grad, ops::SetValueGrad);

253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
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>{})
277 278
            .NewAttr("steps",
                     "Stride step from the start to the end.",
279 280 281 282 283 284
                     std::vector<int64_t>{}))
    .AddCheckpoint(
        R"ROC(
Upgrade set_value, add 1 attribute [decrease_axes].
              )ROC",
        paddle::framework::compatible::OpVersionDesc().NewAttr(
Z
zyfncg 已提交
285 286 287 288 289 290 291
            "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>{}));