scope.md 6.1 KB
Newer Older
Y
Yu Yang 已提交
1
# What is a scope.
Q
qiaolongfei 已提交
2

Y
Yu Yang 已提交
3
## Overview
Q
qiaolongfei 已提交
4

Y
Yibing Liu 已提交
5
Scope is an important concept in programming languages, which defines a program region that a set of bindings between names and entities applies. In a specific scope, a valid name is uniquely associated with an entity, such as a variable. And in another scope, this name may refer to other entity or nothing at all. It clearly restricts the visibility and validity of names in a program. Hence **Scope** is introduced to PaddlePaddle to manage variables in context. But different from the original abstract concept, Scope now becomes an object with two important attributes:
Q
qiaolongfei 已提交
6

Y
Yu Yang 已提交
7 8
- Scope is an association of a name to variable.
- Variables in a parent scope can be retrieved from local scope.
Y
Yibing Liu 已提交
9 10

A detailed explanation of these two attributes goes as following.
Q
qiaolongfei 已提交
11

Y
Yu Yang 已提交
12

Q
qiaolongfei 已提交
13
## Scope is a Container of Variables.
Y
Yu Yang 已提交
14

15 16 17
Scope is used to provide a running environment for Net.

1. Scope mainly has Variables as it's data member.
Q
qiaolongfei 已提交
18

19 20 21 22
    Scope is a running environment for Net. Net should get all it need to do computation from a scope, such as data buffer, state(momentum) etc.
    All these data/state can be abstracted and create as variable in Paddle, so the only thing Scope need to care about is Variable.
1. Variable can only be created by Scope.
1. Variable can only be got from Scope.
Y
Yu Yang 已提交
23
1. Scope contains methods that are used to manage Variables, such as Create/Get.
Q
qiaolongfei 已提交
24

25 26 27 28 29
    Because we only need to care about Variable, we only need method to manage the lifecycle of Variable.
    - `Create` is used to create a Variable by its name and add the mapping relation.
    - `Get` is used to find a Variable by name.

1. Every variable only belongs to one certain Scope.
Q
qiaolongfei 已提交
30

31
    Variable can not be shared between scopes, if we want to use variables from different scope we can use `Parent scope`.
32 33

1. Scope should destruct all Variables within it when itself is destructed.
Q
qiaolongfei 已提交
34

35
    Because Variable can only be got from Scope, when destroying Scope, we also need to destroy all the Vars in it.
Q
qiaolongfei 已提交
36

37
1. Scope do not contain Operators and have no information to run them.
Q
qiaolongfei 已提交
38

39
    Net is designed to drive the computation, Scope is only used to provide a running environment.
Q
qiaolongfei 已提交
40 41 42 43 44 45 46 47

```cpp
class Scope {
 public:
  Variable* CreateVariable(const std::string& name);
  const Variable* GetVariable(const std::string& name) const;

 private:
Y
Yu Yang 已提交
48
    std::unordered_map<std::string, std::shared_ptr<Vairable>> vars_;
Q
qiaolongfei 已提交
49 50
};
```
Y
Yu Yang 已提交
51

Q
qiaolongfei 已提交
52

Y
Yu Yang 已提交
53 54
## Parent scope and local scope

Y
Yu Yang 已提交
55
Just like [scope](https://en.wikipedia.org/wiki/Scope_(computer_science)) in programming languages, `Scope` in the neural network can also be a local scope. There are two attributes about local scope.
Y
Yu Yang 已提交
56

Y
Yu Yang 已提交
57
1.  We can create local variables in a local scope. When that local scope are destroyed, all local variables should also be destroyed.
Y
Yu Yang 已提交
58
2.  Variables in a parent scope can be retrieved from local scopes of that parent scope, i.e., when user get a variable from a scope, it will try to search this variable in current scope. If there is no such variable in the local scope, `scope` will keep searching from its parent, until the variable is found or there is no parent.
Y
Yu Yang 已提交
59 60 61

```cpp
class Scope {
Y
Yu Yang 已提交
62
 public:
Y
Yu Yang 已提交
63 64
  Scope(const std::shared_ptr<Scope>& scope): parent_(scope) {}

Y
Typo  
Yu Yang 已提交
65
  Variable* GetVariable(const std::string& name) const {
Y
Yu Yang 已提交
66 67 68 69 70 71 72 73 74 75
    Variable* var = GetVarLocally(name);
    if (var != nullptr) {
      return var;
    } else if (parent_ != nullptr) {
      return parent_->Get(name);
    } else {
      return nullptr;
    }
  }

Y
Yu Yang 已提交
76
 private:
Y
Yu Yang 已提交
77 78 79
  std::shared_ptr<Scope> parent_ {nullptr};
};
```
Y
Yu Yang 已提交
80

Y
Yu Yang 已提交
81
In `Scope` class, there is a private data member called `parent_`. `parent_` is a smart pointer to its parent scope. When user `Get` a variable by its `name`, the `name` will be searched inside the current scope. If the variable cannot be found locally and parent scope is not a `nullptr`, the variable will be searched inside that parent scope. `parent_` pointer's default value is `nullptr`. It means that the scope is a global scope when `parent_` is nullptr.
Y
Yu Yang 已提交
82

Y
Yu Yang 已提交
83
A local scope is very useful when we implement Recurrent Neural Network. Each timestep of an RNN should be a `Net`. Each `Net` of timestep (`StepNet` for short) should use an independent local scope. Just like variables in a while loop is inside a local scope in programming languages. By using a single `StepNet` and changing local scope, we can implement an RNN easily.
Y
Yu Yang 已提交
84

Y
Yu Yang 已提交
85
# Interface Design
Y
Yu Yang 已提交
86

Y
Yu Yang 已提交
87 88
```cpp
class Variable {
Y
Yu Yang 已提交
89
 private:
Y
Yu Yang 已提交
90 91 92 93 94
  Variable() = default;
  friend class Scope;
};

class Scope {
Y
Yu Yang 已提交
95
 private:
Y
Yu Yang 已提交
96 97
  Scope(const std::shared_ptr<Scope>& parent = nullptr);

Y
Yu Yang 已提交
98
 public:
Y
Yu Yang 已提交
99 100
  static std::shared_ptr<Scope> Create(const std::shared_ptr<Scope>& parent = nullptr);

Y
Yu Yang 已提交
101
  // return nullptr if not found.
102
  Variable* GetVariable(const std::string& name) const;
Y
Yu Yang 已提交
103 104 105 106

  // return Error if already contains same name variable.
  Error CreateVariable(const std::string& name);

Y
Yu Yang 已提交
107
 private:
Y
Yu Yang 已提交
108
  std::shared_ptr<Scope> parent_;
Y
Yu Yang 已提交
109
  std::unordered_map<std::string, std::unique_ptr<Attribute>> vars_;
Y
Yu Yang 已提交
110 111 112 113 114 115 116 117
};
```
## Only scope can create a variable

To ensure `only scope can create a variable`, we should mark `Variable`'s constructor as a private member function, and Scope is a friend class of Variable. And then only `CreateVariable` can construct `Variable`.

## When scope destroyed, all variables inside this scope should be destroyed together

118
The scope hold unique pointers for all variables. User can `GetVariable` from scope, but he should not hold this pointer as a member variable. Because when scope is destroyed, all variables inside this scope will be destroyed together.
Y
Yu Yang 已提交
119 120 121 122 123

## Sharing a parent scope

Local scope contains a `parent_` pointer. It is a linked-list for scopes. Using a `shared_ptr` because when a local scope is using, its parents cannot be destroyed.

Y
Yu Yang 已提交
124 125
Also, as the parent scope is a `shared_ptr`, we can only `Create()` a scope shared pointer. We cannot construct a scope variable, because it cannot be passed to other scope as `parent` pointer.

Y
Yu Yang 已提交
126 127 128
## Orthogonal interface

`GetVariable` will return `nullptr` when `name` is not found. It can be used as `Contains` method. `CreateVariable` will return a `Error` when there is a name conflict locally. Combine `GetVariable` and `CreateVariable`, we can implement `CreateOrGetVariable` easily.