From bcac91a463bd90867974ed6d39b1eda5accdac25 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Wed, 21 Jun 2017 18:21:58 +0800 Subject: [PATCH 01/27] scope design doc --- doc/refactor/scope.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 doc/refactor/scope.md diff --git a/doc/refactor/scope.md b/doc/refactor/scope.md new file mode 100644 index 0000000000..15759d6217 --- /dev/null +++ b/doc/refactor/scope.md @@ -0,0 +1,30 @@ +# Scope + +### Define + +Scope is a context to manage Variables. It mainly contains a map from Variable name to Variable. Net will get and update variable throw scope. + +```cpp +class Scope { + Variable GetVar(); + +private: + // var_name -> var + std::map var_map_; + Scope* parent_scope_; +} +``` + +You need to specify a scope to run a Net. One net can run in different scopes and update different variable in the scope. If you did not specify one, It will run in a default scope. +```python +with ScopeGuard(scope): + Net net = Net(); + Net.run() +``` + +### Chain structure + +Scope has a pointer point to it's parent scope, this is mainly used in RNN when it need to create many stepNet. + + +### Scope Guard \ No newline at end of file From 002a6c94eadf63a66c61cf2f280790befc3e0c76 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 21 Jun 2017 21:12:09 +0800 Subject: [PATCH 02/27] Rearrange docs --- doc/{refactor => design}/scope.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename doc/{refactor => design}/scope.md (97%) diff --git a/doc/refactor/scope.md b/doc/design/scope.md similarity index 97% rename from doc/refactor/scope.md rename to doc/design/scope.md index 15759d6217..c8ca62688c 100644 --- a/doc/refactor/scope.md +++ b/doc/design/scope.md @@ -27,4 +27,4 @@ with ScopeGuard(scope): Scope has a pointer point to it's parent scope, this is mainly used in RNN when it need to create many stepNet. -### Scope Guard \ No newline at end of file +### Scope Guard From 674b1d34625bb876299c4500c5a85b0aad8ef808 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 21 Jun 2017 21:31:27 +0800 Subject: [PATCH 03/27] Update code --- doc/design/scope.md | 48 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/doc/design/scope.md b/doc/design/scope.md index c8ca62688c..b8390a3714 100644 --- a/doc/design/scope.md +++ b/doc/design/scope.md @@ -5,21 +5,49 @@ Scope is a context to manage Variables. It mainly contains a map from Variable name to Variable. Net will get and update variable throw scope. ```cpp -class Scope { - Variable GetVar(); +class Variable; +using VariablePtr = std::shared_ptr; + +class Scope final { +public: + Scope(); + Scope(const std::shared_ptr& parent); + + //! Get Variable in this scope. + //! @return nullptr if no such variable. + const VariablePtr& getVar(const std::string& name) const; + + //! Create or get a variable in this scope. + VariablePtr& createOrGetVar(const std::string& name); private: - // var_name -> var - std::map var_map_; - Scope* parent_scope_; -} + /// variable name -> variable + std::unordered_map vars_; + std::shared_ptr parent_{nullptr}; +}; ``` You need to specify a scope to run a Net. One net can run in different scopes and update different variable in the scope. If you did not specify one, It will run in a default scope. -```python -with ScopeGuard(scope): - Net net = Net(); - Net.run() + +```cpp +Scope global; +auto x = newVar("X"); // x is created in scope global, implicitly. +auto y = newVar("Y"); +Net net1; +net1.addOp("add", {x, y}, {x}); // x = x + y; +net1.run(); + +for (size_t i=0; i<10; ++i) { + Scope local; + auto tmp = newVar("tmp"); // tmp is created in scope local. + Net net2; + net2.addOp("add", {x, y}, {tmp}); + net2.run(); // tmp = x + y; +} + +Net net3; +net3.addOp("add", {x, y}, {"tmp"}); // error! cannot found "tmp" in global scope. + ``` ### Chain structure From 7a4850771006937d264039ae782fe7e302545362 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Wed, 21 Jun 2017 23:45:26 +0800 Subject: [PATCH 04/27] fix code style --- doc/design/scope.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/doc/design/scope.md b/doc/design/scope.md index b8390a3714..a0b0be50dc 100644 --- a/doc/design/scope.md +++ b/doc/design/scope.md @@ -9,16 +9,16 @@ class Variable; using VariablePtr = std::shared_ptr; class Scope final { -public: + public: Scope(); Scope(const std::shared_ptr& parent); //! Get Variable in this scope. //! @return nullptr if no such variable. - const VariablePtr& getVar(const std::string& name) const; + const VariablePtr& GetVar(const std::string& name) const; //! Create or get a variable in this scope. - VariablePtr& createOrGetVar(const std::string& name); + VariablePtr& GetOrCreateVar(const std::string& name); private: /// variable name -> variable @@ -31,22 +31,22 @@ You need to specify a scope to run a Net. One net can run in different scopes an ```cpp Scope global; -auto x = newVar("X"); // x is created in scope global, implicitly. -auto y = newVar("Y"); +auto x = NewVar("X"); // x is created in scope global, implicitly. +auto y = NewVar("Y"); Net net1; -net1.addOp("add", {x, y}, {x}); // x = x + y; -net1.run(); +net1.AddOp("add", {x, y}, {x}); // x = x + y; +net1.Run(); for (size_t i=0; i<10; ++i) { Scope local; - auto tmp = newVar("tmp"); // tmp is created in scope local. + auto tmp = NewVar("tmp"); // tmp is created in scope local. Net net2; - net2.addOp("add", {x, y}, {tmp}); - net2.run(); // tmp = x + y; + net2.AddOp("add", {x, y}, {tmp}); + net2.Run(); // tmp = x + y; } Net net3; -net3.addOp("add", {x, y}, {"tmp"}); // error! cannot found "tmp" in global scope. +net3.AddOp("add", {x, y}, {"tmp"}); // error! cannot found "tmp" in global scope. ``` From 3e099787b803b30a4f76cbd0c6738a81e1d16c93 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 22 Jun 2017 14:21:37 +0800 Subject: [PATCH 05/27] Add scope doc --- doc/design/scope.md | 66 ++++++++++++++------------------------------- 1 file changed, 20 insertions(+), 46 deletions(-) diff --git a/doc/design/scope.md b/doc/design/scope.md index b8390a3714..b7e0a10d03 100644 --- a/doc/design/scope.md +++ b/doc/design/scope.md @@ -1,58 +1,32 @@ -# Scope +# What is a scope. -### Define +## Overview -Scope is a context to manage Variables. It mainly contains a map from Variable name to Variable. Net will get and update variable throw scope. +预期使用场景。 -```cpp -class Variable; -using VariablePtr = std::shared_ptr; +引出Scope的两个属性。 + 1. Scope是Variable的Container + 2. Scope可以共享 -class Scope final { -public: - Scope(); - Scope(const std::shared_ptr& parent); +## Scope 是一个Variable的Container - //! Get Variable in this scope. - //! @return nullptr if no such variable. - const VariablePtr& getVar(const std::string& name) const; +解释下为啥Scope是Variable的container。解释下面几个小点的原因。 - //! Create or get a variable in this scope. - VariablePtr& createOrGetVar(const std::string& name); + * 他只包含variable + * 每一个variable也只属于一个Scope + * 每一个Scope析构的时候,会同时析构variable + * 只能通过Scope创建Vairable。 + * 只能通过Scope获取Variable。 -private: - /// variable name -> variable - std::unordered_map vars_; - std::shared_ptr parent_{nullptr}; -}; -``` +## Scope 可以被继承或者叫共享 -You need to specify a scope to run a Net. One net can run in different scopes and update different variable in the scope. If you did not specify one, It will run in a default scope. +解释下Scope如何被共享,如何查找Variable的算法。 + * Scope永远从本地寻找Variable,找不到会从他的父亲Scope寻找Variable + * 嵌套深度不做要求。 -```cpp -Scope global; -auto x = newVar("X"); // x is created in scope global, implicitly. -auto y = newVar("Y"); -Net net1; -net1.addOp("add", {x, y}, {x}); // x = x + y; -net1.run(); +# 接口实现 -for (size_t i=0; i<10; ++i) { - Scope local; - auto tmp = newVar("tmp"); // tmp is created in scope local. - Net net2; - net2.addOp("add", {x, y}, {tmp}); - net2.run(); // tmp = x + y; -} +C++ code. -Net net3; -net3.addOp("add", {x, y}, {"tmp"}); // error! cannot found "tmp" in global scope. -``` - -### Chain structure - -Scope has a pointer point to it's parent scope, this is mainly used in RNN when it need to create many stepNet. - - -### Scope Guard +## 各个接口是啥意思,为啥这么设计 From 04ad9b6b02f0ca69c6b8b879397906edf1fec61f Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 22 Jun 2017 15:10:37 +0800 Subject: [PATCH 06/27] Add Scope Parent & Local section --- doc/design/scope.md | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/doc/design/scope.md b/doc/design/scope.md index e73d3c231c..3ebbd26338 100644 --- a/doc/design/scope.md +++ b/doc/design/scope.md @@ -17,11 +17,34 @@ * 每一个Scope析构的时候,会同时析构variable * 只能通过Scope创建Vairable。 * 只能通过Scope获取Variable。 -## Scope 可以被继承或者叫共享 -解释下Scope如何被共享,如何查找Variable的算法。 - * Scope永远从本地寻找Variable,找不到会从他的父亲Scope寻找Variable - * 嵌套深度不做要求。 +## Parent scope and local scope + +Just like [scope](https://en.wikipedia.org/wiki/Scope_(computer_science)) in programming languages, `Scope` in the neural network also can be local. There are two attributes about local scope. + +* We can create local variables in a local scope, and when that local scope are destroyed, all local variables should also be destroyed. +* Variables in a parent scope can be retrieved from that parent scope's local scope, i.e., when user get a variable from a scope, it will search this variable in current scope firstly. If there is no such variable in local scope, `scope` will keep searching from its parent, until the variable is found or there is no parent. + +```cpp +class Scope { +public: + Scope(const std::shared_ptr& scope): parent_(scope) {} + + Variable* Get(const std::string& name) const { + Variable* var = GetVarLocally(name); + if (var != nullptr) { + return var; + } else if (parent_ != nullptr) { + return parent_->Get(name); + } else { + return nullptr; + } + } + +private: + std::shared_ptr parent_ {nullptr}; +}; +``` # 接口实现 From 581e4c1cbd2208896dbbc6facef4099a607bfc8c Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 22 Jun 2017 15:27:16 +0800 Subject: [PATCH 07/27] Parent & local scope done --- doc/design/scope.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/doc/design/scope.md b/doc/design/scope.md index 3ebbd26338..27ceed961f 100644 --- a/doc/design/scope.md +++ b/doc/design/scope.md @@ -20,10 +20,10 @@ ## Parent scope and local scope -Just like [scope](https://en.wikipedia.org/wiki/Scope_(computer_science)) in programming languages, `Scope` in the neural network also can be local. There are two attributes about local scope. +Just like [scope](https://en.wikipedia.org/wiki/Scope_(computer_science)) in programming languages, `Scope` in the neural network also can be local. There are two attributes about local scope. -* We can create local variables in a local scope, and when that local scope are destroyed, all local variables should also be destroyed. -* Variables in a parent scope can be retrieved from that parent scope's local scope, i.e., when user get a variable from a scope, it will search this variable in current scope firstly. If there is no such variable in local scope, `scope` will keep searching from its parent, until the variable is found or there is no parent. +1. We can create local variables in a local scope, and when that local scope are destroyed, all local variables should also be destroyed. +2. Variables in a parent scope can be retrieved from that parent scope's local scope, i.e., when user get a variable from a scope, it will search this variable in current scope firstly. If there is no such variable in local scope, `scope` will keep searching from its parent, until the variable is found or there is no parent. ```cpp class Scope { @@ -46,6 +46,10 @@ private: }; ``` +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 locally 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. + +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 each variable 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. + # 接口实现 # 各个接口是啥意思,为啥这么设计 From 0b70361a0ee71ed04ca6925a25bbdd3e434c2bfe Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 22 Jun 2017 15:35:00 +0800 Subject: [PATCH 08/27] Refining english --- doc/design/scope.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/design/scope.md b/doc/design/scope.md index 27ceed961f..341ec16d79 100644 --- a/doc/design/scope.md +++ b/doc/design/scope.md @@ -20,10 +20,10 @@ ## Parent scope and local scope -Just like [scope](https://en.wikipedia.org/wiki/Scope_(computer_science)) in programming languages, `Scope` in the neural network also can be local. There are two attributes about local scope. +Just like [scope](https://en.wikipedia.org/wiki/Scope_(computer_science)) in programming languages, `Scope` in the neural network can also be local. There are two attributes about local scope. -1. We can create local variables in a local scope, and when that local scope are destroyed, all local variables should also be destroyed. -2. Variables in a parent scope can be retrieved from that parent scope's local scope, i.e., when user get a variable from a scope, it will search this variable in current scope firstly. If there is no such variable in local scope, `scope` will keep searching from its parent, until the variable is found or there is no parent. +1. We can create local variables in a local scope. When that local scope are destroyed, all local variables should also be destroyed. +2. Variables in a parent scope can be retrieved from that parent scope's local scopes, 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. ```cpp class Scope { @@ -46,9 +46,9 @@ private: }; ``` -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 locally 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. +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. -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 each variable 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. +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. # 接口实现 From 76e2a3cd95236ab29fb1b5562d5aab52afa99470 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 22 Jun 2017 15:40:08 +0800 Subject: [PATCH 09/27] Refine English --- doc/design/scope.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/design/scope.md b/doc/design/scope.md index 341ec16d79..695426b2f2 100644 --- a/doc/design/scope.md +++ b/doc/design/scope.md @@ -20,10 +20,10 @@ ## Parent scope and local scope -Just like [scope](https://en.wikipedia.org/wiki/Scope_(computer_science)) in programming languages, `Scope` in the neural network can also be local. There are two attributes about local scope. +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. 1. We can create local variables in a local scope. When that local scope are destroyed, all local variables should also be destroyed. -2. Variables in a parent scope can be retrieved from that parent scope's local scopes, 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. +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. ```cpp class Scope { From 8282138047cd443aa579d04320bb10ffd5bde5ca Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Thu, 22 Jun 2017 15:49:52 +0800 Subject: [PATCH 10/27] some properties of scope --- doc/design/scope.md | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/doc/design/scope.md b/doc/design/scope.md index e73d3c231c..b0ee744535 100644 --- a/doc/design/scope.md +++ b/doc/design/scope.md @@ -8,15 +8,29 @@ 1. Scope是Variable的Container 2. Scope可以共享 -## Scope 是一个Variable的Container +## Scope is a Container of Variables. -解释下为啥Scope是Variable的container。解释下面几个小点的原因。 + * Scope contains Variables as it's data member. + * Scope contains methods that are used to manage Variables, such as Create/Get/Delete. + * every variable only belong to one certain Scope. + * Scope should destruct all Variables within it when itself is destructed. + * Variable can only be created by Scope. + * Variable can only be got from Scope. + + * Scope do not contains Operators and have no information to run them. + +```cpp +class Scope { + public: + Variable* CreateVariable(const std::string& name); + const Variable* GetVariable(const std::string& name) const; + bool DeleteVariable(const std::string& name); + + private: + std::unordered_map> variable_map_; +}; +``` - * 他只包含variable - * 每一个variable也只属于一个Scope - * 每一个Scope析构的时候,会同时析构variable - * 只能通过Scope创建Vairable。 - * 只能通过Scope获取Variable。 ## Scope 可以被继承或者叫共享 解释下Scope如何被共享,如何查找Variable的算法。 From d7aca775c5bc5b9d914435cd4b4648c2e7cbd687 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 22 Jun 2017 16:31:03 +0800 Subject: [PATCH 11/27] Update API --- doc/design/scope.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/design/scope.md b/doc/design/scope.md index 695426b2f2..6694e275b6 100644 --- a/doc/design/scope.md +++ b/doc/design/scope.md @@ -30,7 +30,7 @@ class Scope { public: Scope(const std::shared_ptr& scope): parent_(scope) {} - Variable* Get(const std::string& name) const { + Variable* GetVar(const std::string& name) const { Variable* var = GetVarLocally(name); if (var != nullptr) { return var; From 2d5507fab26fe990e88cbe3569b5a1f1a810b6b8 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 22 Jun 2017 16:46:41 +0800 Subject: [PATCH 12/27] Add interfaces --- doc/design/scope.md | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/doc/design/scope.md b/doc/design/scope.md index 6694e275b6..68395435dd 100644 --- a/doc/design/scope.md +++ b/doc/design/scope.md @@ -50,6 +50,44 @@ In `Scope` class, there is a private data member called `parent_`. `parent_` is 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. -# 接口实现 +# Interface Design -# 各个接口是啥意思,为啥这么设计 +```cpp +class Variable { +private: + Variable() = default; + friend class Scope; +}; + +using VariablePtr = std::weak_ptr; + +class Scope { +public: + Scope(const std::shared_ptr& parent = nullptr); + + // return nullptr if not found. + VariablePtr GetVariable(const std::string& name) const; + + // return Error if already contains same name variable. + Error CreateVariable(const std::string& name); + +private: + std::shared_ptr parent_; + std::unordered_map> attrs_; +}; +``` +## 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 + +The `VariablePtr` is a `weak_ptr`. `Net` and `Op` can only get a Variable from `Scope`, but cannot hold it. When scope is destroyed, all `VariablePtr`s belong to this Scope will be changed to `nullptr`. + +## 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. + +## 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. From 73b1c5bd96d5bae8e8558839681f955261f4d197 Mon Sep 17 00:00:00 2001 From: Yibing Liu Date: Thu, 22 Jun 2017 16:51:08 +0800 Subject: [PATCH 13/27] add overview for scope design doc --- doc/design/scope.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/design/scope.md b/doc/design/scope.md index de2e67d327..5023d4b0e4 100644 --- a/doc/design/scope.md +++ b/doc/design/scope.md @@ -2,11 +2,12 @@ ## Overview -预期使用场景。 +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: -引出Scope的两个属性。 - 1. Scope是Variable的Container - 2. Scope可以共享 +- Scope is a container of variables +- Scope can be inherited or shared + +A detailed explanation of these two attributes goes as following. ## Scope is a Container of Variables. From 1f0056b242f79f34fa472dcf93014866a787753c Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 22 Jun 2017 16:52:35 +0800 Subject: [PATCH 14/27] Update interface --- doc/design/scope.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/doc/design/scope.md b/doc/design/scope.md index 74bb6242e4..76af6c30c1 100644 --- a/doc/design/scope.md +++ b/doc/design/scope.md @@ -76,9 +76,12 @@ private: using VariablePtr = std::weak_ptr; class Scope { -public: +private: Scope(const std::shared_ptr& parent = nullptr); +public: + static std::shared_ptr Create(const std::shared_ptr& parent = nullptr); + // return nullptr if not found. VariablePtr GetVariable(const std::string& name) const; @@ -102,6 +105,8 @@ The `VariablePtr` is a `weak_ptr`. `Net` and `Op` can only get a Variable from ` 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. +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. + ## 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. From 17eed332af53894b7525ef7584e37e622bca3f4d Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 22 Jun 2017 16:58:03 +0800 Subject: [PATCH 15/27] Update key attributes --- doc/design/scope.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/design/scope.md b/doc/design/scope.md index 5ba3deb847..1bd36beb5a 100644 --- a/doc/design/scope.md +++ b/doc/design/scope.md @@ -4,8 +4,8 @@ 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: -- Scope is a container of variables -- Scope can be inherited or shared +- Scope is an association of a name to variable. +- Variables in a parent scope can be retrieved from local scope. A detailed explanation of these two attributes goes as following. From 37fd48bf159711a525a3f3d67ee055b5a05a5d3a Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Thu, 22 Jun 2017 17:01:59 +0800 Subject: [PATCH 16/27] some detailed explaination of the Scope properties --- doc/design/scope.md | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/doc/design/scope.md b/doc/design/scope.md index 1bd36beb5a..fac9643b4b 100644 --- a/doc/design/scope.md +++ b/doc/design/scope.md @@ -9,16 +9,30 @@ Scope is an important concept in programming languages, which defines a program A detailed explanation of these two attributes goes as following. + ## Scope is a Container of Variables. - * Scope contains Variables as it's data member. - * Scope contains methods that are used to manage Variables, such as Create/Get/Delete. - * every variable only belong to one certain Scope. - * Scope should destruct all Variables within it when itself is destructed. - * Variable can only be created by Scope. - * Variable can only be got from Scope. +Scope is used to provide a running environment for Net. + +1. Scope mainly has Variables as it's data member. + 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. +1. Scope contains methods that are used to manage Variables, such as Create/Get/Delete. + 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. + - `Delete` is used to remove a Variable because sometimes we want to release memory or other resources. + +1. Every variable only belongs to one certain Scope. + Variable can not be shared between nets, if we want to use variables from different scope we can use `Parent scope`. + +1. Scope should destruct all Variables within it when itself is destructed. + Because Variable can only be got from Scope, when destroying Scope, we also need to destroy all the Vars in it. - * Scope do not contains Operators and have no information to run them. +1. Scope do not contain Operators and have no information to run them. + Net is designed to drive the computation, Scope is only used to provide a running environment. ```cpp class Scope { From c3a4b8bc4407b2496378b57dfea54be0dd05f745 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Thu, 22 Jun 2017 17:03:56 +0800 Subject: [PATCH 17/27] refine style of markdown --- doc/design/scope.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/design/scope.md b/doc/design/scope.md index fac9643b4b..a255b361d0 100644 --- a/doc/design/scope.md +++ b/doc/design/scope.md @@ -15,23 +15,28 @@ A detailed explanation of these two attributes goes as following. Scope is used to provide a running environment for Net. 1. Scope mainly has Variables as it's data member. + 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. 1. Scope contains methods that are used to manage Variables, such as Create/Get/Delete. + 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. - `Delete` is used to remove a Variable because sometimes we want to release memory or other resources. 1. Every variable only belongs to one certain Scope. + Variable can not be shared between nets, if we want to use variables from different scope we can use `Parent scope`. 1. Scope should destruct all Variables within it when itself is destructed. + Because Variable can only be got from Scope, when destroying Scope, we also need to destroy all the Vars in it. 1. Scope do not contain Operators and have no information to run them. + Net is designed to drive the computation, Scope is only used to provide a running environment. ```cpp From db96c0eef9dbe860f8ee080d91b157c77bf4ddbc Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 22 Jun 2017 17:10:47 +0800 Subject: [PATCH 18/27] Use unique_ptr instead of shared_ptr/weak_ptr. But user can not hold this pointers. --- doc/design/scope.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/doc/design/scope.md b/doc/design/scope.md index 76af6c30c1..8d5744c227 100644 --- a/doc/design/scope.md +++ b/doc/design/scope.md @@ -73,8 +73,6 @@ private: friend class Scope; }; -using VariablePtr = std::weak_ptr; - class Scope { private: Scope(const std::shared_ptr& parent = nullptr); @@ -83,14 +81,14 @@ public: static std::shared_ptr Create(const std::shared_ptr& parent = nullptr); // return nullptr if not found. - VariablePtr GetVariable(const std::string& name) const; + Variable* GetVariable(const std::string& name) const; // return Error if already contains same name variable. Error CreateVariable(const std::string& name); private: std::shared_ptr parent_; - std::unordered_map> attrs_; + std::unordered_map> attrs_; }; ``` ## Only scope can create a variable @@ -99,7 +97,7 @@ To ensure `only scope can create a variable`, we should mark `Variable`'s constr ## When scope destroyed, all variables inside this scope should be destroyed together -The `VariablePtr` is a `weak_ptr`. `Net` and `Op` can only get a Variable from `Scope`, but cannot hold it. When scope is destroyed, all `VariablePtr`s belong to this Scope will be changed to `nullptr`. +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. ## Sharing a parent scope From f104ce2cd2f047f59d09422643d8791feeba483c Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Thu, 22 Jun 2017 17:12:57 +0800 Subject: [PATCH 19/27] fix a mistake share by nets -> share by scopes --- doc/design/scope.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/design/scope.md b/doc/design/scope.md index a255b361d0..dec033ad63 100644 --- a/doc/design/scope.md +++ b/doc/design/scope.md @@ -29,7 +29,7 @@ Scope is used to provide a running environment for Net. 1. Every variable only belongs to one certain Scope. - Variable can not be shared between nets, if we want to use variables from different scope we can use `Parent scope`. + Variable can not be shared between scopes, if we want to use variables from different scope we can use `Parent scope`. 1. Scope should destruct all Variables within it when itself is destructed. From eab0e5229f1d020c8b495dab4187221517dbfb67 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 22 Jun 2017 17:20:48 +0800 Subject: [PATCH 20/27] To google code style --- doc/design/scope.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/design/scope.md b/doc/design/scope.md index f2869bc254..76616cc6a6 100644 --- a/doc/design/scope.md +++ b/doc/design/scope.md @@ -61,7 +61,7 @@ Just like [scope](https://en.wikipedia.org/wiki/Scope_(computer_science)) in pro ```cpp class Scope { -public: + public: Scope(const std::shared_ptr& scope): parent_(scope) {} Variable* GetVar(const std::string& name) const { @@ -75,7 +75,7 @@ public: } } -private: + private: std::shared_ptr parent_ {nullptr}; }; ``` @@ -88,16 +88,16 @@ A local scope is very useful when we implement Recurrent Neural Network. Each ti ```cpp class Variable { -private: + private: Variable() = default; friend class Scope; }; class Scope { -private: + private: Scope(const std::shared_ptr& parent = nullptr); -public: + public: static std::shared_ptr Create(const std::shared_ptr& parent = nullptr); // return nullptr if not found. @@ -106,7 +106,7 @@ public: // return Error if already contains same name variable. Error CreateVariable(const std::string& name); -private: + private: std::shared_ptr parent_; std::unordered_map> attrs_; }; From 63a56b4a5182d31bdcbabdd15573dfec54a04bb9 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 22 Jun 2017 17:24:30 +0800 Subject: [PATCH 21/27] Change typo --- doc/design/scope.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/design/scope.md b/doc/design/scope.md index 76616cc6a6..cd92ba2aa8 100644 --- a/doc/design/scope.md +++ b/doc/design/scope.md @@ -108,7 +108,7 @@ class Scope { private: std::shared_ptr parent_; - std::unordered_map> attrs_; + std::unordered_map> attrs_; }; ``` ## Only scope can create a variable From 921fa13eef21c63455bfbb9972ac7f16fb345c51 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 22 Jun 2017 17:25:19 +0800 Subject: [PATCH 22/27] Remove delete --- doc/design/scope.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/doc/design/scope.md b/doc/design/scope.md index cd92ba2aa8..e08aebfb01 100644 --- a/doc/design/scope.md +++ b/doc/design/scope.md @@ -20,12 +20,11 @@ Scope is used to provide a running environment for Net. 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. -1. Scope contains methods that are used to manage Variables, such as Create/Get/Delete. +1. Scope contains methods that are used to manage Variables, such as Create/Get. 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. - - `Delete` is used to remove a Variable because sometimes we want to release memory or other resources. 1. Every variable only belongs to one certain Scope. @@ -44,10 +43,9 @@ class Scope { public: Variable* CreateVariable(const std::string& name); const Variable* GetVariable(const std::string& name) const; - bool DeleteVariable(const std::string& name); private: - std::unordered_map> variable_map_; + std::unordered_map> vars_; }; ``` @@ -108,7 +106,7 @@ class Scope { private: std::shared_ptr parent_; - std::unordered_map> attrs_; + std::unordered_map> vars_; }; ``` ## Only scope can create a variable From 5d88249125039a5fcc5f1a33fd84d7accbd2c526 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 22 Jun 2017 17:26:15 +0800 Subject: [PATCH 23/27] Typo --- doc/design/scope.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/design/scope.md b/doc/design/scope.md index e08aebfb01..23893308b2 100644 --- a/doc/design/scope.md +++ b/doc/design/scope.md @@ -62,7 +62,7 @@ class Scope { public: Scope(const std::shared_ptr& scope): parent_(scope) {} - Variable* GetVar(const std::string& name) const { + Variable* GetVariable(const std::string& name) const { Variable* var = GetVarLocally(name); if (var != nullptr) { return var; From f8a209c2dee0ce16dbf12857ae88556c9917e458 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 22 Jun 2017 17:48:19 +0800 Subject: [PATCH 24/27] Rearrange description. --- doc/design/scope.md | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/doc/design/scope.md b/doc/design/scope.md index 23893308b2..1740019f3d 100644 --- a/doc/design/scope.md +++ b/doc/design/scope.md @@ -10,33 +10,30 @@ Scope is an important concept in programming languages, which defines a program A detailed explanation of these two attributes goes as following. -## Scope is a Container of Variables. +## Scope is an association of a name to variable. -Scope is used to provide a running environment for Net. +Scope is an association of a name to variable. All variables belong to `Scope`. You need to specify a scope to run a Net, i.e., `net.Run(&scope)`. One net can run in different scopes and update different variable in the scope. -1. Scope mainly has Variables as it's data member. - 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. -1. Scope contains methods that are used to manage Variables, such as Create/Get. +1. Scope only contains a map of a name to variable. - Because we only need to care about Variable, we only need method to manage the lifecycle of Variable. + All parameters, data, states in a Net should be variables and stored inside a scope. Each op should get inputs and outputs to do computation from a scope, such as data buffer, state(momentum) etc. + +1. Variable can only be created by Scope and a variable can only be got from Scope. User cannot create or get a variable outside a scope. This is a constraints of our framework, and will keep our framework simple and clear. + +1. Scope only contains methods that are used to Create and Get Variables. Scope do not contain Operators and have no information to run them. + + `Net` is designed to drive the computation and Scope only contains a map of variables. There is no computation logic inside a `Scope`. Scope just handles the lifetime management of variables. - `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. - Variable can not be shared between scopes, if we want to use variables from different scope we can use `Parent scope`. - -1. Scope should destruct all Variables within it when itself is destructed. - - Because Variable can only be got from Scope, when destroying Scope, we also need to destroy all the Vars in it. + Variable can not belong to many scopes. If you want to use variables from parent scope, you can use `parent scope`. -1. Scope do not contain Operators and have no information to run them. +1. Scope should destruct all Variables inside it when itself is destructed. User can never store `Variable` pointer somewhere else. - Net is designed to drive the computation, Scope is only used to provide a running environment. + Because Variable can only be got from Scope. When destroying Scope, we also need to destroy all the Variables in it. If user store `Variable` pointer to private data member or some global variable, the pointer will be a invalid pointer when associated `Scope` is destroyed. ```cpp class Scope { @@ -45,7 +42,7 @@ class Scope { const Variable* GetVariable(const std::string& name) const; private: - std::unordered_map> vars_; + std::unordered_map> vars_; }; ``` From c5ad89a24d54f934bb40ec586f3f42fdf007ee16 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 22 Jun 2017 17:51:04 +0800 Subject: [PATCH 25/27] Change title --- doc/design/scope.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/design/scope.md b/doc/design/scope.md index 1740019f3d..d00ab37da4 100644 --- a/doc/design/scope.md +++ b/doc/design/scope.md @@ -1,4 +1,4 @@ -# What is a scope. +# Design of Scope in Paddle ## Overview From 237efc2f263b7cdf7404a065c95b7e45260f4dda Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 22 Jun 2017 18:00:28 +0800 Subject: [PATCH 26/27] Fix markdown --- doc/design/scope.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/design/scope.md b/doc/design/scope.md index d00ab37da4..149e1ea1b9 100644 --- a/doc/design/scope.md +++ b/doc/design/scope.md @@ -22,8 +22,7 @@ Scope is an association of a name to variable. All variables belong to `Scope`. 1. Variable can only be created by Scope and a variable can only be got from Scope. User cannot create or get a variable outside a scope. This is a constraints of our framework, and will keep our framework simple and clear. 1. Scope only contains methods that are used to Create and Get Variables. Scope do not contain Operators and have no information to run them. - - `Net` is designed to drive the computation and Scope only contains a map of variables. There is no computation logic inside a `Scope`. Scope just handles the lifetime management of variables. + `Net` is designed to drive the computation and Scope only contains a map of variables. There is no computation logic inside a `Scope`. Scope just handles the lifetime management of variables. - `Create` is used to create a Variable by its name and add the mapping relation. - `Get` is used to find a Variable by name. From 3bac2d0d7e50f67fd82f96bccaf3bfdeabd930f7 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Thu, 22 Jun 2017 22:00:25 +0800 Subject: [PATCH 27/27] Typo --- doc/design/scope.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/design/scope.md b/doc/design/scope.md index 149e1ea1b9..2ff416f06e 100644 --- a/doc/design/scope.md +++ b/doc/design/scope.md @@ -63,7 +63,7 @@ class Scope { if (var != nullptr) { return var; } else if (parent_ != nullptr) { - return parent_->Get(name); + return parent_->GetVariable(name); } else { return nullptr; } @@ -102,7 +102,7 @@ class Scope { private: std::shared_ptr parent_; - std::unordered_map> vars_; + std::unordered_map> vars_; }; ``` ## Only scope can create a variable