Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
P
pytensor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
testgroup
pytensor
Commits
8d71eb32
提交
8d71eb32
authored
7月 09, 2012
作者:
Ian Goodfellow
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
renamed Env to FunctionGraph. closes 719
上级
56888c31
显示空白字符变更
内嵌
并排
正在显示
13 个修改的文件
包含
75 行增加
和
64 行删除
+75
-64
pipeline.txt
doc/extending/pipeline.txt
+8
-7
debugmode.py
theano/compile/debugmode.py
+2
-2
function_module.py
theano/compile/function_module.py
+1
-1
__init__.py
theano/gof/__init__.py
+4
-2
destroyhandler.py
theano/gof/destroyhandler.py
+1
-1
fg.py
theano/gof/fg.py
+49
-42
op.py
theano/gof/op.py
+1
-1
opt.py
theano/gof/opt.py
+2
-2
test_cc.py
theano/gof/tests/test_cc.py
+3
-2
test_destroyhandler.py
theano/gof/tests/test_destroyhandler.py
+1
-1
test_opt.py
theano/gof/tests/test_opt.py
+1
-1
test_toolbox.py
theano/gof/tests/test_toolbox.py
+1
-1
test_merge.py
theano/tensor/tests/test_merge.py
+1
-1
没有找到文件。
doc/extending/pipeline.txt
浏览文件 @
8d71eb32
...
...
@@ -36,32 +36,32 @@ Here is an overview of the various steps that are done with the
computation graph in the compilation phase:
Step 1 - Create a
n Env
Step 1 - Create a
FunctionGraph
^^^^^^^^^^^^^^^^^^^^^^
The subgraph given by the end user is wrapped in a structure called
*
Env
*. That structure defines several hooks on adding and
*
FunctionGraph
*. That structure defines several hooks on adding and
removing (pruning) nodes as well as on modifying links between nodes
(for example, modifying an input of an :ref:`apply` node) (see the
article about :ref:`libdoc_gof_env` for more information).
Env
provides a method to change the input of an Apply node from one
FunctionGraph
provides a method to change the input of an Apply node from one
Variable to another and a more high-level method to replace a Variable
with another. This is the structure that :ref:`Optimizers
<optimization>` work on.
Some relevant :ref:`Features <libdoc_gof_envfeature>` are typically added to the
Env
, namely to prevent any optimization from operating inplace on
FunctionGraph
, namely to prevent any optimization from operating inplace on
inputs declared as immutable.
Step 2 - Execute main Optimizer
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Once the
Env
is made, an :term:`optimizer` is produced
Once the
FunctionGraph
is made, an :term:`optimizer` is produced
by the :term:`mode` passed to ``function`` or to the Method/Module's
``make`` (the Mode basically has two important fields, ``linker`` and
``optimizer``). That optimizer is applied on the
Env
using its
``optimizer``). That optimizer is applied on the
FunctionGraph
using its
optimize() method.
The optimizer is typically obtained through :attr:`optdb`.
...
...
@@ -71,7 +71,8 @@ Step 3 - Execute linker to obtain a thunk
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Once the computation graph is optimized, the :term:`linker` is
extracted from the Mode. It is then called with the Env as argument to
extracted from the Mode. It is then called with the FunctionGraph as
argument to
produce a ``thunk``, which is a function with no arguments that
returns nothing. Along with the thunk, one list of input containers (a
theano.gof.Container is a sort of object that wraps another and does
...
...
theano/compile/debugmode.py
浏览文件 @
8d71eb32
...
...
@@ -13,7 +13,7 @@ import numpy
import
theano
from
theano
import
gof
from
theano.gof
import
Env
,
graph
,
utils
,
link
,
ops_with_inner_function
from
theano.gof
import
FunctionGraph
as
Env
,
graph
,
utils
,
link
,
ops_with_inner_function
from
theano.gof.link
import
raise_with_op
from
theano.gof.cc
import
CLinker
from
theano.gof.python25
import
all
,
any
,
product
as
itertools_product
...
...
@@ -667,7 +667,7 @@ def _optcheck_env(input_specs, output_specs, accept_inplace=False):
inputs
,
outputs
=
gof
.
graph
.
clone
(
orig_inputs
,
orig_outputs
)
equivalence_tracker
=
_VariableEquivalenceTracker
()
env
=
gof
.
env
.
Env
(
inputs
,
outputs
,
env
=
gof
.
fg
.
FunctionGraph
(
inputs
,
outputs
,
#DestroyHandler is not needed because it is actually installed by an optimization
# after canonicalization. This variables in a big speed gain.
#features=[equivalence_tracker, gof.DestroyHandler(do_imports_on_attach=False)])
...
...
theano/compile/function_module.py
浏览文件 @
8d71eb32
...
...
@@ -129,7 +129,7 @@ def std_env(input_specs, output_specs, accept_inplace = False):
orig_outputs
=
[
spec
.
variable
for
spec
in
output_specs
]
+
updates
inputs
,
outputs
=
gof
.
graph
.
clone
(
orig_inputs
,
orig_outputs
)
env
=
gof
.
env
.
Env
(
inputs
,
outputs
)
env
=
gof
.
fg
.
FunctionGraph
(
inputs
,
outputs
)
for
node
in
env
.
nodes
:
if
getattr
(
node
.
op
,
'destroy_map'
,
None
):
...
...
theano/gof/__init__.py
浏览文件 @
8d71eb32
...
...
@@ -5,8 +5,10 @@ from cc import \
import
compiledir
# adds config vars
from
env
import
\
InconsistencyError
,
MissingInputError
,
Env
from
fg
import
\
InconsistencyError
,
MissingInputError
,
FunctionGraph
#deprecated alias to support code written with old name
Env
=
FunctionGraph
from
destroyhandler
import
\
DestroyHandler
...
...
theano/gof/destroyhandler.py
浏览文件 @
8d71eb32
...
...
@@ -10,7 +10,7 @@ import toolbox
import
graph
from
theano.gof.python25
import
deque
from
env
import
InconsistencyError
from
fg
import
InconsistencyError
class
ProtocolError
(
Exception
):
"""WRITEME"""
...
...
theano/gof/
env
.py
→
theano/gof/
fg
.py
浏览文件 @
8d71eb32
"""WRITEME"""
"""
fg.py: fg stands for FunctionGraph
Contains the FunctionGraph class and exception
types that it can raise
"""
import
sys
from
copy
import
copy
import
graph
import
utils
import
toolbox
...
...
@@ -11,7 +14,7 @@ from theano import config
class
InconsistencyError
(
Exception
):
"""
This exception should be thrown by listeners to
Env
when the
This exception should be thrown by listeners to
FunctionGraph
when the
graph's state is invalid.
"""
pass
...
...
@@ -24,14 +27,18 @@ class MissingInputError(Exception):
class
Env
(
utils
.
object2
):
class
FunctionGraph
(
utils
.
object2
):
""" WRITEME
An Env represents a subgraph bound by a set of input variables and a
set of output variables. The inputs list should contain all the inputs
A FunctionGraph represents a subgraph bound by a set of input variables and a
set of output variables, ie a subgraph that specifies a theano function.
The inputs list should contain all the inputs
on which the outputs depend. Variables of type Constant are
not counted as inputs.
The Env supports the replace operation which allows to replace a
Historically, the FunctionGraph was called an Env. Many other objects refer
to the FunctionGraph they belong to as their "env".
The FunctionGraph supports the replace operation which allows to replace a
variable in the subgraph by another, e.g. replace (x + x).out by (2
* x).out. This is the basis for optimization in theano.
...
...
@@ -42,34 +49,34 @@ class Env(utils.object2):
The .clients field combined with the .owner field and the Apply nodes'
.inputs field allows the graph to be traversed in both directions.
It can also be "extended" using
env
.extend(some_object). See the
It can also be "extended" using
function_graph
.extend(some_object). See the
toolbox and ext modules for common extensions.
Features added with the`extend` function can handle the following events:
- feature.on_attach(
env
)
- feature.on_attach(
function_graph
)
Called by extend. The feature has great freedom in what
it can do with the
env
: it may, for example, add methods
it can do with the
function_graph
: it may, for example, add methods
to it dynamically.
- feature.on_detach(
env
)
- feature.on_detach(
function_graph
)
Called by remove_feature(feature). Should remove any dynamically-added
functionality that it installed into the
env
.
functionality that it installed into the
function_graph
.
- feature.on_import(
env
, node)*
Called whenever a node is imported into
env
, which is
- feature.on_import(
function_graph
, node)*
Called whenever a node is imported into
function_graph
, which is
just before the node is actually connected to the graph.
- feature.on_prune(
env
, node)*
Called whenever a node is pruned (removed) from the
env
,
- feature.on_prune(
function_graph
, node)*
Called whenever a node is pruned (removed) from the
function_graph
,
after it is disconnected from the graph.
- feature.on_change_input(
env
, node, i, r, new_r, [reason=None])*
- feature.on_change_input(
function_graph
, node, i, r, new_r, [reason=None])*
Called whenever node.inputs[i] is changed from r to new_r.
At the moment the callback is done, the change has already
taken place.
- feature.orderings(
env
)
- feature.orderings(
function_graph
)
Called by toposort. It should return a dictionary of
{node: predecessors} where predecessors is a list of
nodes that should be computed before the key node.
...
...
@@ -77,10 +84,10 @@ class Env(utils.object2):
* If you raise an exception in the functions marked with an
asterisk, the state of the graph might be inconsistent.
- feature.on_setup_node(
env
, node):
- feature.on_setup_node(
function_graph
, node):
WRITEME
- feature.on_setup_variable(
env
, variable):
- feature.on_setup_variable(
function_graph
, variable):
WRITEME
"""
...
...
@@ -90,14 +97,14 @@ class Env(utils.object2):
def
__init__
(
self
,
inputs
,
outputs
,
features
=
None
):
"""
Create an
Env
which operates on the subgraph bound by the inputs and
Create an
FunctionGraph
which operates on the subgraph bound by the inputs and
outputs sets.
This class keeps a pointer to the inputs and outputs, and also modifies
them.
#TODO: document what variables are[not] set in the
env
when a feature
is added via the constructor. How constructed is the
env
?
#TODO: document what variables are[not] set in the
FunctionGraph
when a feature
is added via the constructor. How constructed is the
FunctionGraph
?
"""
...
...
@@ -171,12 +178,12 @@ class Env(utils.object2):
def
disown
(
self
):
""" WRITEME
Cleans up all of this
Env
's nodes and variables so they are not
associated with this
Env
anymore.
Cleans up all of this
FunctionGraph
's nodes and variables so they are not
associated with this
FunctionGraph
anymore.
The
Env
should not be used anymore after disown is called.
The
FunctionGraph
should not be used anymore after disown is called.
This may not clean everything this
Env
's features set in the
This may not clean everything this
FunctionGraph
's features set in the
nodes and variables. If there are no features, this should set
them back to what they were originally.
"""
...
...
@@ -362,7 +369,7 @@ class Env(utils.object2):
def
__prune__
(
self
,
node
):
if
node
not
in
self
.
nodes
:
raise
Exception
(
"
%
s does not belong to this
Env
and cannot be pruned."
%
node
)
raise
Exception
(
"
%
s does not belong to this
FunctionGraph
and cannot be pruned."
%
node
)
assert
node
.
env
is
self
# If node's outputs have no clients, removes it from the graph
# and recursively tries to prune its inputs. If at least one
...
...
@@ -392,7 +399,7 @@ class Env(utils.object2):
current value of node.inputs[i] which we want to replace.
For each feature that has a 'on_change_input' method, calls:
feature.on_change_input(
env
, node, i, old_r, new_r, [reason])
feature.on_change_input(
function_graph
, node, i, old_r, new_r, [reason])
"""
# TODO: ERROR HANDLING FOR LISTENERS (should it complete the change or revert it?)
if
node
==
'output'
:
...
...
@@ -405,7 +412,7 @@ class Env(utils.object2):
else
:
if
node
.
env
is
not
self
:
raise
Exception
(
"Cannot operate on
%
s because it does not"
" belong to this
Env
"
%
node
)
" belong to this
FunctionGraph
"
%
node
)
r
=
node
.
inputs
[
i
]
if
not
r
.
type
==
new_r
.
type
:
raise
TypeError
(
"The type of the replacement must be the"
...
...
@@ -432,11 +439,11 @@ class Env(utils.object2):
def
replace
(
self
,
r
,
new_r
,
reason
=
None
):
""" WRITEME
This is the main interface to manipulate the subgraph in
Env
.
This is the main interface to manipulate the subgraph in
FunctionGraph
.
For every node that uses r as input, makes it use new_r instead.
"""
if
r
.
env
is
not
self
:
raise
Exception
(
"Cannot replace
%
s because it does not belong to this
Env
"
%
r
,
str
(
reason
))
raise
Exception
(
"Cannot replace
%
s because it does not belong to this
FunctionGraph
"
%
r
,
str
(
reason
))
if
not
r
.
type
==
new_r
.
type
:
raise
TypeError
(
"The type of the replacement must be the same as the type of the original Variable."
,
r
,
new_r
,
r
.
type
,
new_r
.
type
,
str
(
reason
))
if
r
not
in
self
.
variables
:
...
...
@@ -466,7 +473,7 @@ class Env(utils.object2):
# would expect it to do similarly.
def
extend
(
self
,
feature
):
"""WRITEME
Adds a feature to this
env
. The feature may define one
Adds a feature to this
function_graph
. The feature may define one
or more of the following methods:
"""
...
...
@@ -484,7 +491,7 @@ class Env(utils.object2):
"""WRITEME
Removes the feature from the graph.
Calls feature.on_detach(
env
) if an on_detach method is defined.
Calls feature.on_detach(
function_graph
) if an on_detach method is defined.
"""
try
:
self
.
_features
.
remove
(
feature
)
...
...
@@ -545,7 +552,7 @@ class Env(utils.object2):
an 'orderings' method.
If a feature has an 'orderings' method, it will be called with
this
env
as sole argument. It should return a dictionary of
this
FunctionGraph
as sole argument. It should return a dictionary of
{node: predecessors} where predecessors is a list of nodes
that should be computed before the key node.
"""
...
...
@@ -555,9 +562,9 @@ class Env(utils.object2):
# This special case happens a lot because the OpWiseCLinker produces
# 1-element graphs.
return
list
(
self
.
nodes
)
env
=
self
fg
=
self
ords
=
self
.
orderings
()
order
=
graph
.
io_toposort
(
env
.
inputs
,
env
.
outputs
,
ords
)
order
=
graph
.
io_toposort
(
fg
.
inputs
,
fg
.
outputs
,
ords
)
return
order
def
orderings
(
self
):
...
...
@@ -605,10 +612,10 @@ class Env(utils.object2):
raise
Exception
(
"The nodes are inappropriately cached. missing, in excess: "
,
missing
,
excess
)
for
node
in
nodes
:
if
node
.
env
is
not
self
:
raise
Exception
(
"Node should belong to the
env
."
,
node
)
raise
Exception
(
"Node should belong to the
FunctionGraph
."
,
node
)
for
i
,
variable
in
enumerate
(
node
.
inputs
):
if
variable
.
env
is
not
self
:
raise
Exception
(
"Input of node should belong to the
env
."
,
variable
,
(
node
,
i
))
raise
Exception
(
"Input of node should belong to the
FunctionGraph
."
,
variable
,
(
node
,
i
))
if
(
node
,
i
)
not
in
variable
.
clients
:
raise
Exception
(
"Inconsistent clients list."
,
(
node
,
i
),
variable
.
clients
)
variables
=
set
(
graph
.
variables
(
self
.
inputs
,
self
.
outputs
))
...
...
@@ -620,14 +627,14 @@ class Env(utils.object2):
if
variable
.
owner
is
None
and
variable
not
in
self
.
inputs
and
not
isinstance
(
variable
,
graph
.
Constant
):
raise
Exception
(
"Undeclared input."
,
variable
)
if
variable
.
env
is
not
self
:
raise
Exception
(
"Variable should belong to the
env
."
,
variable
)
raise
Exception
(
"Variable should belong to the
FunctionGraph
."
,
variable
)
for
node
,
i
in
variable
.
clients
:
if
node
==
'output'
:
if
self
.
outputs
[
i
]
is
not
variable
:
raise
Exception
(
"Inconsistent clients list."
,
variable
,
self
.
outputs
[
i
])
continue
if
node
not
in
nodes
:
raise
Exception
(
"Client not in
env
."
,
variable
,
(
node
,
i
))
raise
Exception
(
"Client not in
FunctionGraph
."
,
variable
,
(
node
,
i
))
if
node
.
inputs
[
i
]
is
not
variable
:
raise
Exception
(
"Inconsistent clients list."
,
variable
,
node
.
inputs
[
i
])
...
...
@@ -648,7 +655,7 @@ class Env(utils.object2):
"""WRITEME"""
equiv
=
graph
.
clone_get_equiv
(
self
.
inputs
,
self
.
outputs
)
self
.
check_integrity
()
e
=
Env
([
equiv
[
i
]
for
i
in
self
.
inputs
],
e
=
FunctionGraph
([
equiv
[
i
]
for
i
in
self
.
inputs
],
[
equiv
[
o
]
for
o
in
self
.
outputs
])
e
.
check_integrity
()
for
feature
in
self
.
_features
:
...
...
theano/gof/op.py
浏览文件 @
8d71eb32
...
...
@@ -21,7 +21,7 @@ from theano import config
import
cc
import
graph
import
utils
from
env
import
Env
from
fg
import
FunctionGraph
as
Env
class
CLinkerObject
(
object
):
...
...
theano/gof/opt.py
浏览文件 @
8d71eb32
...
...
@@ -11,7 +11,7 @@ import time
import
numpy
import
graph
from
env
import
InconsistencyError
from
fg
import
InconsistencyError
import
op
import
utils
import
unify
...
...
@@ -598,7 +598,7 @@ def is_same_graph_with_merge(var1, var2, givens=None):
givens
=
copied
[
2
]
# Create Env.
inputs
=
theano
.
gof
.
graph
.
inputs
(
vars
)
env
=
theano
.
gof
.
env
.
Env
(
inputs
,
vars
)
env
=
theano
.
gof
.
fg
.
FunctionGraph
(
inputs
,
vars
)
# Perform Variable substitution.
for
to_replace
,
replace_by
in
givens
.
iteritems
():
env
.
replace
(
to_replace
,
replace_by
)
...
...
theano/gof/tests/test_cc.py
浏览文件 @
8d71eb32
...
...
@@ -6,7 +6,8 @@ from theano.gof.cc import *
from
theano.gof.type
import
Type
from
theano.gof.graph
import
Variable
,
Apply
,
Constant
from
theano.gof.op
import
Op
from
theano.gof
import
env
from
theano.gof
import
fg
env
=
fg
from
theano.gof
import
toolbox
...
...
@@ -171,7 +172,7 @@ def inputs():
def
Env
(
inputs
,
outputs
):
e
=
env
.
Env
(
inputs
,
outputs
)
e
=
fg
.
FunctionGraph
(
inputs
,
outputs
)
return
e
...
...
theano/gof/tests/test_destroyhandler.py
浏览文件 @
8d71eb32
...
...
@@ -8,7 +8,7 @@ from theano.gof.op import Op
from
theano.gof.opt
import
*
from
theano.gof
import
destroyhandler
from
theano.gof.
env
import
Env
,
InconsistencyError
from
theano.gof.
fg
import
FunctionGraph
as
Env
,
InconsistencyError
from
theano.gof.toolbox
import
ReplaceValidate
from
copy
import
copy
...
...
theano/gof/tests/test_opt.py
浏览文件 @
8d71eb32
...
...
@@ -3,7 +3,7 @@ from theano.gof.type import Type
from
theano.gof.graph
import
Variable
,
Apply
,
Constant
from
theano.gof.op
import
Op
from
theano.gof.opt
import
*
from
theano.gof.
env
import
Env
from
theano.gof.
fg
import
FunctionGraph
as
Env
from
theano.gof.toolbox
import
*
...
...
theano/gof/tests/test_toolbox.py
浏览文件 @
8d71eb32
...
...
@@ -3,7 +3,7 @@ from theano.gof.graph import Variable, Apply
from
theano.gof.type
import
Type
from
theano.gof.op
import
Op
from
theano.gof.
env
import
Env
,
InconsistencyError
from
theano.gof.
fg
import
FunctionGraph
as
Env
,
InconsistencyError
from
theano.gof.toolbox
import
*
...
...
theano/tensor/tests/test_merge.py
浏览文件 @
8d71eb32
...
...
@@ -3,7 +3,7 @@ from theano.gof.type import Type
from
theano.gof.graph
import
Variable
,
Apply
,
Constant
from
theano.gof.op
import
Op
from
theano.gof.opt
import
*
from
theano.gof.
env
import
Env
from
theano.gof.
fg
import
FunctionGraph
as
Env
from
theano.gof.toolbox
import
*
import
theano.tensor.basic
as
T
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论