layer.h 9.1 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>
W
wanghuancoder 已提交
27

28
#include "paddle/fluid/framework/data_type.h"
29
#include "paddle/fluid/framework/operator.h"
H
hong 已提交
30 31
#include "paddle/fluid/framework/type_defs.h"
#include "paddle/fluid/framework/var_type.h"
J
Jiabin Yang 已提交
32
#include "paddle/fluid/framework/variable.h"
Z
Zeng Jinle 已提交
33
#include "paddle/fluid/imperative/flags.h"
34
#include "paddle/fluid/imperative/hooks.h"
35
#include "paddle/fluid/imperative/saved_variable_wrapper_list.h"
J
Jiabin Yang 已提交
36
#include "paddle/fluid/imperative/type_defs.h"
37
#include "paddle/fluid/imperative/variable_wrapper.h"
J
Jiabin Yang 已提交
38 39
#include "paddle/fluid/platform/enforce.h"
#include "paddle/fluid/platform/macros.h"
W
wanghuancoder 已提交
40 41 42 43 44 45
namespace paddle {
namespace framework {
class Variable;
}  // namespace framework
}  // namespace paddle

46 47 48
namespace paddle {
namespace imperative {

W
wanghuancoder 已提交
49
class GradOpNode;
50
class OpBase;
W
wanghuancoder 已提交
51
class VariableWrapper;
52

Z
Zeng Jinle 已提交
53 54 55 56 57 58 59 60 61 62 63 64 65
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_;
};

66
class VarBase {
J
Jiabin Yang 已提交
67 68
  DISABLE_COPY_AND_ASSIGN(VarBase);

69
 public:
Z
Zeng Jinle 已提交
70
  static std::vector<std::string> AliveVarNames();
71 72

 public:
J
Jiabin Yang 已提交
73
  explicit VarBase(bool has_grad, const std::string& name)
74
      : var_(std::make_shared<VariableWrapper>(name)),
J
Jiabin Yang 已提交
75
        grad_var_(has_grad ? new VarBase(false, GradVarName()) : nullptr) {
76 77 78 79
    if (has_grad) {
      var_->SetGradVar(grad_var_->var_);
    }

Z
Zeng Jinle 已提交
80
    if (IsDebugEnabled()) {
81 82
      VLOG(10) << "Construct VarBase: " << Name();
      name_set_.Insert(Name());
Z
Zeng Jinle 已提交
83
    }
84
  }
85

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

88
  // NOTE(zengjinle): be careful when you use this constructor!!!
89 90
  // Unpack VarBase from VariableWrapper.
  explicit VarBase(const std::shared_ptr<VariableWrapper>& var);
91

J
Jiabin Yang 已提交
92
  ~VarBase() {
93
    VLOG(10) << "Destruct VarBase: " << Name();
Z
Zeng Jinle 已提交
94
    if (IsDebugEnabled()) {
95
      name_set_.Remove(Name());
Z
Zeng Jinle 已提交
96
    }
M
minqiyang 已提交
97
  }
98

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

101 102 103
  const framework::Variable& Var() const { return var_->Var(); }

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

J
Jiabin Yang 已提交
105 106 107 108
  bool HasGradVar() const { return grad_var_ != nullptr; }

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

109 110
  void ClearGradVarBase() { grad_var_ = nullptr; }

111
  void SetGradVarBase(const VarBase& grad_var) {
C
chentianyu03 已提交
112
    MutableGradVarBase()->CopyFrom(grad_var, true);
113
    MutableGradVarBase()->SharedVar()->SetIsEmpty(false);
C
chentianyu03 已提交
114 115
  }

116 117
  const std::shared_ptr<VarBase>& MutableGradVarBase() {
    if (grad_var_ == nullptr) {
118
      if (auto grad_var_wrapper = var_->GetGradVar()) {
119
        grad_var_ = std::make_shared<VarBase>(grad_var_wrapper);
120 121 122 123 124 125 126
      } 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
127
      grad_var_->SetOverridedStopGradient(var_->InnerOverridedStopGradient());
128 129 130 131
    }
    return grad_var_;
  }

J
Jiabin Yang 已提交
132
  const framework::Variable& GradVar() const {
133 134 135 136
    PADDLE_ENFORCE_NOT_NULL(
        grad_var_,
        platform::errors::NotFound("Gradient of %s does not exist", Name()));
    return grad_var_->Var();
M
minqiyang 已提交
137
  }
M
minqiyang 已提交
138

J
Jiabin Yang 已提交
139
  framework::Variable* MutableGradVar() {
140 141 142 143
    PADDLE_ENFORCE_NOT_NULL(
        grad_var_,
        platform::errors::NotFound("Gradient of %s does not exist", Name()));
    return grad_var_->MutableVar();
J
Jiabin Yang 已提交
144
  }
X
Xin Pan 已提交
145

146 147
  bool IsLeaf() const { return var_->IsLeaf(); }

148
  void SetOverridedStopGradient(bool stop_gradient) {
149
    var_->SetOverridedStopGradient(stop_gradient);
J
Jiabin Yang 已提交
150
    if (grad_var_) {
151 152 153 154
      grad_var_->SetOverridedStopGradient(stop_gradient);
    }
  }

155
  bool OverridedStopGradient() const { return var_->OverridedStopGradient(); }
156 157

  void InnerSetOverridedStopGradient(bool stop_gradient) {
158
    if (InnerOverridedStopGradient() == -1) {
159
      var_->InnerSetOverridedStopGradient(stop_gradient);
160 161 162 163 164
      if (grad_var_) {
        grad_var_->InnerSetOverridedStopGradient(stop_gradient);
      }
    }
  }
165

166 167 168 169
  int InnerOverridedStopGradient() const {
    return var_->InnerOverridedStopGradient();
  }

170
  void SetPersistable(bool persistable) { var_->SetPersistable(persistable); }
171

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

174
  // Only grad var is allowed to call these 2 methods
175 176 177
  void SetGradNode(const std::shared_ptr<GradOpNode>& node) {
    grad_node_ = node;
    var_->SetGradNode(node);
178 179
  }

180
  size_t GradOpNum() const;
181

182 183 184
  const std::shared_ptr<GradOpNode>& GradNode() const { return grad_node_; }

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

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

J
Jiabin Yang 已提交
188
  void SetName(const std::string& name) {
189
    var_->SetName(name);
J
Jiabin Yang 已提交
190 191 192
    if (grad_var_) {
      grad_var_->SetName(GradVarName());
    }
M
minqiyang 已提交
193 194
  }

195
  std::string GradVarName() { return framework::GradVarName(Name()); }
196

197 198 199 200
  void SetGraphIsFreed(bool free) { graph_is_free_ = free; }

  const bool& GraphIsFreed() const { return graph_is_free_; }

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

203
  framework::proto::VarType::Type Type() const { return var_->Type(); }
204

J
Jiabin Yang 已提交
205
  void SetDataType(framework::proto::VarType::Type data_type) {
206
    var_->SetDataType(data_type);
J
Jiabin Yang 已提交
207
    if (grad_var_) {
208
      grad_var_->SetDataType(data_type);
209 210 211
    }
  }

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

214 215 216 217 218 219 220 221
  void SetDataLayout(paddle::experimental::DataLayout data_layout) {
    var_->SetDataLayout(data_layout);
  }

  paddle::experimental::DataLayout DataLayout() const {
    return var_->DataLayout();
  }

222 223
  size_t ElementSize() const { return framework::SizeOfType(var_->DataType()); }

224 225 226 227 228 229 230 231
  void SetForwardDataType(framework::proto::VarType::Type data_type) {
    var_->SetForwardDataType(data_type);
  }

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

232 233
  const platform::Place Place() const { return var_->Place(); }

234 235 236 237
  void ClearGradient(bool set_to_zero = true);

  void _GradientSetEmpty(bool is_empty = true);
  bool _IsGradientSetEmpty();
X
Xin Pan 已提交
238

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

242 243
  void CopyFrom(const imperative::VarBase& src, bool blocking);

244 245
  void BumpInplaceVersion();

246 247
  void _CopyGradientFrom(const imperative::VarBase& src);

248
  /* Hook related method: now only used for GradVarBase */
249
  bool HasVariableWrapperHook() const { return var_->HasVariableWrapperHook(); }
250

251 252
  int64_t AddVariableWrapperHook(std::shared_ptr<VariableWrapperHook>&& hook) {
    return var_->AddVariableWrapperHook(
253 254 255
        std::forward<std::shared_ptr<VariableWrapperHook>>(hook));
  }

256 257 258
  bool RemoveVariableWrapperHook(const int64_t& hook_id) {
    return var_->RemoveVariableWrapperHook(hook_id);
  }
259

260 261 262
  const std::map<int64_t, std::shared_ptr<VariableWrapperHook>>&
  GetVariableWrapperHooks() const {
    return var_->GetVariableWrapperHooks();
263 264
  }

265 266 267
  void AddVoidHook(std::shared_ptr<std::function<void()>>&& hook) {
    var_->AddVoidHook(
        std::forward<std::shared_ptr<std::function<void()>>>(hook));
268 269
  }

J
Jiabin Yang 已提交
270
 private:
271 272 273 274 275 276 277
  /**
   * 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 已提交
278
  std::shared_ptr<VarBase> grad_var_;
279 280 281 282 283 284

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

286 287
  bool graph_is_free_ = false;

J
Jiabin Yang 已提交
288
  mutable size_t copied_counter_ = 0;
289

J
Jiabin Yang 已提交
290
  static ThreadSafeNameSet name_set_;
291 292
};

293 294 295
std::shared_ptr<GradOpNode> CreateGradOpNode(
    const framework::OperatorBase& op, const NameVarBaseMap& ins,
    const NameVarBaseMap& outs, const framework::AttributeMap& attrs,
296
    const framework::AttributeMap& default_attrs, const platform::Place& place,
297
    const std::map<std::string, std::string>& inplace_map);
H
hong 已提交
298

J
Jiabin Yang 已提交
299 300 301 302 303 304
std::shared_ptr<GradOpNode> CreateGradOpNode(
    const framework::OperatorBase& op, const NameTensorMap& ins,
    const NameTensorMap& outs, const framework::AttributeMap& attrs,
    const framework::AttributeMap& default_attrs, const platform::Place& place,
    const std::map<std::string, std::string>& inplace_map);

305 306
void ClearNoNeedBufferInputs(OpBase* op);

307 308
}  // namespace imperative
}  // namespace paddle