tracer.h 4.5 KB
Newer Older
X
Xin Pan 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// Copyright (c) 2018 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.

#pragma once

X
Xin Pan 已提交
17
#include <map>
X
Xin Pan 已提交
18
#include <string>
X
Xin Pan 已提交
19
#include <vector>
X
Xin Pan 已提交
20

X
Xin Pan 已提交
21
#include "paddle/fluid/framework/op_desc.h"
X
Xin Pan 已提交
22 23
#include "paddle/fluid/framework/op_registry.h"
#include "paddle/fluid/framework/scope.h"
X
Xin Pan 已提交
24
#include "paddle/fluid/imperative/engine.h"
X
Xin Pan 已提交
25
#include "paddle/fluid/imperative/layer.h"
X
Xin Pan 已提交
26 27 28 29

namespace paddle {
namespace imperative {

X
Xin Pan 已提交
30 31 32 33 34 35 36 37 38 39 40 41 42 43
void CreateGradOp(const framework::OpDesc& op_desc,
                  const std::unordered_set<std::string>& no_grad_set,
                  const std::vector<framework::BlockDesc*>& grad_sub_block,
                  framework::OpDesc** grad_op_desc,
                  std::unordered_map<std::string, std::string>* grad_to_var) {
  std::vector<std::unique_ptr<framework::OpDesc>> grad_op_descs =
      framework::OpInfoMap::Instance()
          .Get(op_desc.Type())
          .GradOpMaker()(op_desc, no_grad_set, grad_to_var, grad_sub_block);
  PADDLE_ENFORCE(grad_op_descs.size() == 1, "Only support 1 grad op now.");
  // TODO(panyx0718): Leak?
  *grad_op_desc = grad_op_descs[0].release();
}

X
Xin Pan 已提交
44 45
class Tracer {
 public:
X
polish  
Xin Pan 已提交
46 47 48 49 50 51
  explicit Tracer(framework::BlockDesc* root_block) : root_block_(root_block) {
    root_scope_ = new framework::Scope();
    scopes_[root_block_] = root_scope_;
  }

  virtual ~Tracer() { delete root_scope_; }
X
Xin Pan 已提交
52

X
Xin Pan 已提交
53
  void Trace(OpBase* op, const std::vector<VarBase*>& inputs,
X
polish  
Xin Pan 已提交
54 55 56
             const std::vector<VarBase*>& outputs,
             framework::BlockDesc* block) {
    framework::Scope* scope = GetScope(block);
X
Xin Pan 已提交
57
    framework::OpDesc* op_desc = op->op_desc_;
X
polish  
Xin Pan 已提交
58
    VLOG(3) << "tracer tracing " << op_desc->Type();
X
polish  
Xin Pan 已提交
59 60
    op_desc->InferShape(*block);
    op_desc->InferVarType(block);
X
Xin Pan 已提交
61
    std::unique_ptr<framework::OperatorBase> op_base =
X
Xin Pan 已提交
62
        framework::OpRegistry::CreateOp(*op_desc);
X
Xin Pan 已提交
63 64 65 66

    *op->input_vars_ = inputs;
    for (VarBase* input : inputs) {
      const std::string vname = input->var_desc_->Name();
X
polish  
Xin Pan 已提交
67
      framework::Variable* var = scope->Var(vname);
X
Xin Pan 已提交
68
      input->var_ = var;
X
Xin Pan 已提交
69
      if (!var->IsInitialized()) {
X
polish  
Xin Pan 已提交
70
        framework::VarDesc* var_desc = block->FindVar(vname);
X
Xin Pan 已提交
71 72 73 74 75 76
        if (var_desc->GetType() == framework::proto::VarType::LOD_TENSOR) {
          var->GetMutable<framework::LoDTensor>();
        } else {
          LOG(ERROR) << "tracer doesn't support yet";
        }
      }
X
Xin Pan 已提交
77 78 79 80 81 82
      if (input->pre_op_) {
        op->pre_ops_->push_back(input->pre_op_);
        op->pre_ops_out_idx_->push_back(input->pre_op_out_idx_);
      } else {
        op->pre_ops_->push_back(nullptr);
      }
X
Xin Pan 已提交
83
    }
X
Xin Pan 已提交
84 85

    *op->output_vars_ = outputs;
X
Xin Pan 已提交
86 87
    for (size_t i = 0; i < outputs.size(); ++i) {
      const std::string vname = outputs[i]->var_desc_->Name();
X
polish  
Xin Pan 已提交
88
      framework::Variable* var = scope->Var(vname);
X
Xin Pan 已提交
89
      if (!var->IsInitialized()) {
X
polish  
Xin Pan 已提交
90
        framework::VarDesc* var_desc = block->FindVar(vname);
X
Xin Pan 已提交
91 92 93 94 95 96
        if (var_desc->GetType() == framework::proto::VarType::LOD_TENSOR) {
          var->GetMutable<framework::LoDTensor>();
        } else {
          LOG(ERROR) << "tracer doesn't support yet";
        }
      }
X
Xin Pan 已提交
97 98 99
      outputs[i]->var_ = var;
      outputs[i]->pre_op_ = op;
      outputs[i]->pre_op_out_idx_ = i;
X
Xin Pan 已提交
100
    }
X
polish  
Xin Pan 已提交
101
    op_base->Run(*scope, platform::CPUPlace());
X
Xin Pan 已提交
102 103
    framework::OpDesc* grad_op_desc;
    auto grad_to_var = new std::unordered_map<std::string, std::string>();
X
polish  
Xin Pan 已提交
104
    CreateGradOp(*op_desc, {}, {block}, &grad_op_desc, grad_to_var);
X
Xin Pan 已提交
105 106
    op->grad_op_desc_ = grad_op_desc;
    op->grad_to_var_ = grad_to_var;
X
polish  
Xin Pan 已提交
107
    op->block_ = block;
X
Xin Pan 已提交
108 109
  }

X
polish  
Xin Pan 已提交
110 111 112 113 114 115 116 117 118 119
  framework::Scope* GetScope(framework::BlockDesc* block) {
    if (scopes_.find(block) != scopes_.end()) {
      return scopes_.at(block);
    }
    framework::BlockDesc* parent_block = block->ParentBlock();
    PADDLE_ENFORCE(scopes_.find(parent_block) != scopes_.end());
    framework::Scope* scope = &scopes_[parent_block]->NewScope();
    scopes_[block] = scope;
    return scope;
  }
X
Xin Pan 已提交
120

X
Xin Pan 已提交
121
 private:
X
polish  
Xin Pan 已提交
122 123 124
  std::map<framework::BlockDesc*, framework::Scope*> scopes_;
  framework::BlockDesc* root_block_;
  framework::Scope* root_scope_;
X
Xin Pan 已提交
125 126 127 128
};

}  // namespace imperative
}  // namespace paddle