layer.h 6.6 KB
Newer Older
J
Jiabin Yang 已提交
1
// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
2 3 4 5 6 7 8 9 10 11 12 13 14 15
//
// 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
J
Jiabin Yang 已提交
16
#include <algorithm>
Z
Zeng Jinle 已提交
17
#include <cstdint>
J
Jiabin Yang 已提交
18
#include <list>
19 20
#include <map>
#include <memory>
Z
Zeng Jinle 已提交
21
#include <set>
22 23 24
#include <string>
#include <unordered_map>
#include <unordered_set>
25
#include <utility>
J
Jiabin Yang 已提交
26
#include <vector>
27
#include "paddle/fluid/framework/operator.h"
H
hong 已提交
28 29
#include "paddle/fluid/framework/type_defs.h"
#include "paddle/fluid/framework/var_type.h"
J
Jiabin Yang 已提交
30
#include "paddle/fluid/framework/variable.h"
Z
Zeng Jinle 已提交
31
#include "paddle/fluid/imperative/flags.h"
32
#include "paddle/fluid/imperative/saved_variable_wrapper_list.h"
J
Jiabin Yang 已提交
33
#include "paddle/fluid/imperative/type_defs.h"
34
#include "paddle/fluid/imperative/variable_wrapper.h"
J
Jiabin Yang 已提交
35 36
#include "paddle/fluid/platform/enforce.h"
#include "paddle/fluid/platform/macros.h"
M
minqiyang 已提交
37

38 39 40 41 42
namespace paddle {
namespace imperative {

class OpBase;

Z
Zeng Jinle 已提交
43 44 45 46 47 48 49 50 51 52 53 54 55
class ThreadSafeNameSet {
 public:
  void Insert(const std::string& name);

  void Remove(const std::string& name);

  std::vector<std::string> Names() const;

 private:
  std::multiset<std::string> set_;
  mutable std::mutex mtx_;
};

56
class VarBase {
J
Jiabin Yang 已提交
57 58
  DISABLE_COPY_AND_ASSIGN(VarBase);

59
 public:
Z
Zeng Jinle 已提交
60
  static std::vector<std::string> AliveVarNames();
61 62

 public:
J
Jiabin Yang 已提交
63
  explicit VarBase(bool has_grad, const std::string& name)
64
      : var_(std::make_shared<VariableWrapper>(name)),
J
Jiabin Yang 已提交
65
        grad_var_(has_grad ? new VarBase(false, GradVarName()) : nullptr) {
66 67 68 69
    if (has_grad) {
      var_->SetGradVar(grad_var_->var_);
    }

Z
Zeng Jinle 已提交
70
    if (IsDebugEnabled()) {
71 72
      VLOG(10) << "Construct VarBase: " << Name();
      name_set_.Insert(Name());
Z
Zeng Jinle 已提交
73
    }
74
  }
75

J
Jiabin Yang 已提交
76 77
  explicit VarBase(const std::string& name) : VarBase(true, name) {}

78
  // NOTE(zengjinle): be careful when you use this constructor!!!
79 80
  // Unpack VarBase from VariableWrapper.
  explicit VarBase(const std::shared_ptr<VariableWrapper>& var);
81

J
Jiabin Yang 已提交
82
  ~VarBase() {
83
    VLOG(10) << "Destruct VarBase: " << Name();
Z
Zeng Jinle 已提交
84
    if (IsDebugEnabled()) {
85
      name_set_.Remove(Name());
Z
Zeng Jinle 已提交
86
    }
M
minqiyang 已提交
87
  }
88

89
  const std::shared_ptr<VariableWrapper>& SharedVar() const { return var_; }
90

91 92 93
  const framework::Variable& Var() const { return var_->Var(); }

  framework::Variable* MutableVar() { return var_->MutableVar(); }
M
minqiyang 已提交
94

J
Jiabin Yang 已提交
95 96 97 98
  bool HasGradVar() const { return grad_var_ != nullptr; }

  const std::shared_ptr<VarBase>& GradVarBase() const { return grad_var_; }

99 100 101 102
  void ClearGradVarBase() { grad_var_ = nullptr; }

  const std::shared_ptr<VarBase>& MutableGradVarBase() {
    if (grad_var_ == nullptr) {
103
      if (auto grad_var_wrapper = var_->GetGradVar()) {
104
        grad_var_ = std::make_shared<VarBase>(grad_var_wrapper);
105 106 107 108 109 110 111
      } else {
        grad_var_ = std::make_shared<VarBase>(false, GradVarName());
        var_->SetGradVar(grad_var_->var_);
        grad_var_->var_->SetGradNode(grad_var_->grad_node_);
      }
      // NOTE(zhiqiu): we should keep grad_var_'s stop_gradient property
      // same as fwd varbase
112
      grad_var_->SetOverridedStopGradient(var_->InnerOverridedStopGradient());
113 114 115 116
    }
    return grad_var_;
  }

J
Jiabin Yang 已提交
117
  const framework::Variable& GradVar() const {
118 119 120 121
    PADDLE_ENFORCE_NOT_NULL(
        grad_var_,
        platform::errors::NotFound("Gradient of %s does not exist", Name()));
    return grad_var_->Var();
M
minqiyang 已提交
122
  }
M
minqiyang 已提交
123

J
Jiabin Yang 已提交
124
  framework::Variable* MutableGradVar() {
125 126 127 128
    PADDLE_ENFORCE_NOT_NULL(
        grad_var_,
        platform::errors::NotFound("Gradient of %s does not exist", Name()));
    return grad_var_->MutableVar();
J
Jiabin Yang 已提交
129
  }
X
Xin Pan 已提交
130

131
  void SetOverridedStopGradient(bool stop_gradient) {
132
    var_->SetOverridedStopGradient(stop_gradient);
J
Jiabin Yang 已提交
133
    if (grad_var_) {
134 135 136 137
      grad_var_->SetOverridedStopGradient(stop_gradient);
    }
  }

138
  bool OverridedStopGradient() const { return var_->OverridedStopGradient(); }
139 140

  void InnerSetOverridedStopGradient(bool stop_gradient) {
141 142
    if (var_->InnerOverridedStopGradient() == -1) {
      var_->InnerSetOverridedStopGradient(stop_gradient);
143 144 145 146 147
      if (grad_var_) {
        grad_var_->InnerSetOverridedStopGradient(stop_gradient);
      }
    }
  }
148

149
  void SetPersistable(bool persistable) { var_->SetPersistable(persistable); }
150

151
  bool Persistable() const { return var_->Persistable(); }
X
Xin Pan 已提交
152

153
  // Only grad var is allowed to call these 2 methods
154 155 156
  void SetGradNode(const std::shared_ptr<GradOpNode>& node) {
    grad_node_ = node;
    var_->SetGradNode(node);
157 158
  }

159
  size_t GradOpNum() const;
160

161 162 163
  const std::shared_ptr<GradOpNode>& GradNode() const { return grad_node_; }

  void ClearGradNode() { SetGradNode(nullptr); }
X
Xin Pan 已提交
164

165
  const std::string& Name() const { return var_->Name(); }
M
minqiyang 已提交
166

J
Jiabin Yang 已提交
167
  void SetName(const std::string& name) {
168
    var_->SetName(name);
J
Jiabin Yang 已提交
169 170 171
    if (grad_var_) {
      grad_var_->SetName(GradVarName());
    }
M
minqiyang 已提交
172 173
  }

174
  std::string GradVarName() { return framework::GradVarName(Name()); }
175

176
  void SetType(framework::proto::VarType::Type type) { var_->SetType(type); }
177

178
  framework::proto::VarType::Type Type() const { return var_->Type(); }
179

J
Jiabin Yang 已提交
180
  void SetDataType(framework::proto::VarType::Type data_type) {
181
    var_->SetDataType(data_type);
J
Jiabin Yang 已提交
182
    if (grad_var_) {
183
      grad_var_->SetDataType(data_type);
184 185 186
    }
  }

187
  framework::proto::VarType::Type DataType() const { return var_->DataType(); }
X
polish  
Xin Pan 已提交
188

J
Jiabin Yang 已提交
189
  void ClearGradient();
X
Xin Pan 已提交
190

J
Jiabin Yang 已提交
191 192
  std::shared_ptr<VarBase> NewVarBase(const platform::Place& dst_place,
                                      const bool blocking) const;
M
minqiyang 已提交
193

J
Jiabin Yang 已提交
194
 private:
195 196 197 198 199 200 201
  /**
   * NOTE(zengjinle): never remove the const qualifier of `var_` if you are
   * not very familiar with the autograd idea (including the higher order
   * derivative).
   */
  const std::shared_ptr<VariableWrapper> var_;

J
Jiabin Yang 已提交
202
  std::shared_ptr<VarBase> grad_var_;
203 204 205 206 207 208

  /**
   * NOTE(zengjinle): should consider whether to implement an inlined vector
   * or other things like that.
   */
  std::shared_ptr<GradOpNode> grad_node_;
H
hong 已提交
209

J
Jiabin Yang 已提交
210
  mutable size_t copied_counter_ = 0;
211

J
Jiabin Yang 已提交
212
  static ThreadSafeNameSet name_set_;
213 214 215 216 217 218
};

class Layer {
 public:
  virtual ~Layer() {}

219 220
  virtual std::vector<std::shared_ptr<VarBase>> Forward(
      const std::vector<std::shared_ptr<VarBase>>& inputs) {
J
Jiabin Yang 已提交
221
    return {};
222
  }
X
Xin Pan 已提交
223
};
224

225 226 227 228
std::shared_ptr<GradOpNode> CreateGradOpNode(
    const framework::OperatorBase& op, const NameVarBaseMap& ins,
    const NameVarBaseMap& outs, const framework::AttributeMap& attrs,
    const platform::Place& place);
H
hong 已提交
229

230 231
}  // namespace imperative
}  // namespace paddle