Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
P
pytensor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
testgroup
pytensor
Commits
3578c80c
提交
3578c80c
authored
5月 22, 2015
作者:
Arnaud Bergeron
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Flake8 for compile/debugmode.py
上级
90e512d6
隐藏空白字符变更
内嵌
并排
正在显示
2 个修改的文件
包含
452 行增加
和
410 行删除
+452
-410
debugmode.py
theano/compile/debugmode.py
+452
-409
test_flake8.py
theano/tests/test_flake8.py
+0
-1
没有找到文件。
theano/compile/debugmode.py
浏览文件 @
3578c80c
...
...
@@ -7,7 +7,10 @@ from __future__ import print_function
__docformat__
=
"restructuredtext en"
import
copy
,
sys
,
copy_reg
,
gc
import
copy
import
sys
import
copy_reg
import
gc
from
itertools
import
izip
import
numpy
...
...
@@ -16,10 +19,9 @@ import theano
from
theano
import
gof
from
theano.compat
import
get_unbound_function
,
product
as
itertools_product
from
theano.compat.six
import
StringIO
from
theano.gof
import
(
FunctionGraph
,
graph
,
utils
,
link
,
from
theano.gof
import
(
graph
,
utils
,
link
,
ops_with_inner_function
)
from
theano.gof.link
import
raise_with_op
from
theano.gof.cc
import
CLinker
from
theano.configparser
import
(
config
,
AddConfigVar
,
BoolParam
,
IntParam
,
StrParam
)
from
theano.compile.function_module
import
(
...
...
@@ -30,37 +32,37 @@ from theano.compile.mode import Mode, register_mode
from
theano.compile.ops
import
OutputGuard
AddConfigVar
(
'DebugMode.patience'
,
"Optimize graph this many times to detect inconsistency"
,
IntParam
(
10
,
lambda
i
:
i
>
0
),
in_c_key
=
False
)
"Optimize graph this many times to detect inconsistency"
,
IntParam
(
10
,
lambda
i
:
i
>
0
),
in_c_key
=
False
)
AddConfigVar
(
'DebugMode.check_c'
,
"Run C implementations where possible"
,
BoolParam
(
bool
(
theano
.
config
.
cxx
)),
in_c_key
=
False
)
"Run C implementations where possible"
,
BoolParam
(
bool
(
theano
.
config
.
cxx
)),
in_c_key
=
False
)
AddConfigVar
(
'DebugMode.check_py'
,
"Run Python implementations where possible"
,
BoolParam
(
True
),
in_c_key
=
False
)
"Run Python implementations where possible"
,
BoolParam
(
True
),
in_c_key
=
False
)
AddConfigVar
(
'DebugMode.check_finite'
,
"True -> complain about NaN/Inf results"
,
BoolParam
(
True
),
in_c_key
=
False
)
"True -> complain about NaN/Inf results"
,
BoolParam
(
True
),
in_c_key
=
False
)
AddConfigVar
(
'DebugMode.check_strides'
,
(
"Check that Python- and C-produced ndarrays have same strides.
"
"On difference: (0) - ignore, (1) warn, or (2) raise error"
),
IntParam
(
1
,
lambda
i
:
i
in
(
0
,
1
,
2
)),
in_c_key
=
False
)
(
"Check that Python- and C-produced ndarrays have same strides.
"
"On difference: (0) - ignore, (1) warn, or (2) raise error"
),
IntParam
(
1
,
lambda
i
:
i
in
(
0
,
1
,
2
)),
in_c_key
=
False
)
AddConfigVar
(
'DebugMode.warn_input_not_reused'
,
(
"Generate a warning when destroy_map or view_map says that an "
"op works inplace, but the op did not reuse the input for its output.
"
),
BoolParam
(
True
),
in_c_key
=
False
)
(
"Generate a warning when destroy_map or view_map says that an "
"op works inplace, but the op did not reuse the input for its
"
"output."
),
BoolParam
(
True
),
in_c_key
=
False
)
def
is_valid_check_preallocated_output_param
(
param
):
...
...
@@ -74,25 +76,25 @@ def is_valid_check_preallocated_output_param(param):
return
True
AddConfigVar
(
'DebugMode.check_preallocated_output'
,
(
'Test thunks with pre-allocated memory as output storage. '
'This is a list of strings separated by ":". Valid values are: '
'"initial" (initial storage in storage map, happens with Scan),'
'"previous" (previously-returned memory), '
'"c_contiguous", "f_contiguous", '
'"strided" (positive and negative strides), '
'"wrong_size" (larger and smaller dimensions), and '
'"ALL" (all of the above).'
),
StrParam
(
''
,
is_valid
=
is_valid_check_preallocated_output_param
),
in_c_key
=
False
)
(
'Test thunks with pre-allocated memory as output storage. '
'This is a list of strings separated by ":". Valid values are: '
'"initial" (initial storage in storage map, happens with Scan),'
'"previous" (previously-returned memory), '
'"c_contiguous", "f_contiguous", '
'"strided" (positive and negative strides), '
'"wrong_size" (larger and smaller dimensions), and '
'"ALL" (all of the above).'
),
StrParam
(
''
,
is_valid
=
is_valid_check_preallocated_output_param
),
in_c_key
=
False
)
AddConfigVar
(
'DebugMode.check_preallocated_output_ndim'
,
(
'When testing with "strided" preallocated output memory, '
'test all combinations of strides over that number of '
'(inner-most) dimensions. You may want to reduce that number '
'to reduce memory or time usage, but it is advised to keep a '
'minimum of 2.'
),
IntParam
(
4
,
lambda
i
:
i
>
0
),
in_c_key
=
False
)
(
'When testing with "strided" preallocated output memory, '
'test all combinations of strides over that number of '
'(inner-most) dimensions. You may want to reduce that number '
'to reduce memory or time usage, but it is advised to keep a '
'minimum of 2.'
),
IntParam
(
4
,
lambda
i
:
i
>
0
),
in_c_key
=
False
)
import
logging
_logger
=
logging
.
getLogger
(
"theano.compile.debugmode"
)
...
...
@@ -148,7 +150,7 @@ class BadThunkOutput(DebugModeError):
def
__init__
(
self
,
r
,
thunk1
,
val1
,
thunk2
,
val2
,
inputs_val
=
()):
"""Initialize members"""
DebugModeError
.
__init__
(
self
)
# to be compatible with python2.4
super
(
BadThunkOutput
,
self
)
.
__init__
()
self
.
r
=
r
self
.
thunk1
=
thunk1
self
.
val1
=
val1
...
...
@@ -173,12 +175,14 @@ class BadThunkOutput(DebugModeError):
print
(
" op :"
,
self
.
offending_op
(),
file
=
sio
)
print
(
" Outputs Type:"
,
self
.
r
.
type
,
file
=
sio
)
print
(
" Outputs Shape:"
,
getattr
(
self
.
val1
,
'shape'
,
None
),
file
=
sio
)
print
(
" Outputs Strides:"
,
getattr
(
self
.
val1
,
'strides'
,
None
),
file
=
sio
)
print
(
" Inputs Type :"
,
[
i
.
type
for
i
in
self
.
r
.
owner
.
inputs
],
file
=
sio
)
print
(
" Outputs Strides:"
,
getattr
(
self
.
val1
,
'strides'
,
None
),
file
=
sio
)
print
(
" Inputs Type :"
,
[
i
.
type
for
i
in
self
.
r
.
owner
.
inputs
],
file
=
sio
)
print
(
" Inputs Shape:"
,
[
getattr
(
val
,
'shape'
,
None
)
for
val
in
self
.
inputs_val
],
file
=
sio
)
for
val
in
self
.
inputs_val
],
file
=
sio
)
print
(
" Inputs Strides:"
,
[
getattr
(
val
,
'strides'
,
None
)
for
val
in
self
.
inputs_val
],
file
=
sio
)
for
val
in
self
.
inputs_val
],
file
=
sio
)
print
(
" Bad Variable:"
,
self
.
r
,
file
=
sio
)
print
(
" thunk1 :"
,
self
.
thunk1
,
file
=
sio
)
print
(
" thunk2 :"
,
self
.
thunk2
,
file
=
sio
)
...
...
@@ -226,7 +230,7 @@ class BadOptimization(DebugModeError):
def
__init__
(
self
,
old_r
,
new_r
,
old_r_val
,
new_r_val
,
reason
,
old_graph
,
new_graph
):
"""Initialize members"""
DebugModeError
.
__init__
(
self
)
# to be compatible with python2.4
super
(
BadOptimization
,
self
)
.
__init__
()
self
.
old_r
=
old_r
self
.
new_r
=
new_r
self
.
old_r_val
=
old_r_val
...
...
@@ -244,7 +248,7 @@ class BadOptimization(DebugModeError):
sio
=
StringIO
()
val_str_len_limit
=
800
print
(
"BadOptimization Error"
,
super
(
BadOptimization
,
self
)
.
__str__
(),
file
=
sio
)
self
)
.
__str__
(),
file
=
sio
)
print
(
" Variable: id"
,
id
(
self
.
new_r
),
self
.
new_r
,
file
=
sio
)
print
(
" Op"
,
self
.
new_r
.
owner
,
file
=
sio
)
print
(
" Value Type:"
,
type
(
self
.
new_r_val
),
file
=
sio
)
...
...
@@ -287,25 +291,21 @@ class BadOptimization(DebugModeError):
ov
=
numpy
.
asarray
(
self
.
old_r_val
)
nv
=
numpy
.
asarray
(
self
.
new_r_val
)
ssio
=
StringIO
()
print
(
" Max Abs Diff: "
,
numpy
.
max
(
numpy
.
absolute
(
nv
-
ov
)),
file
=
ssio
)
print
(
" Mean Abs Diff: "
,
numpy
.
mean
(
numpy
.
absolute
(
nv
-
ov
)),
file
=
ssio
)
print
(
" Median Abs Diff: "
,
numpy
.
median
(
numpy
.
absolute
(
nv
-
ov
)),
file
=
ssio
)
print
(
" Std Abs Diff: "
,
numpy
.
std
(
numpy
.
absolute
(
nv
-
ov
)),
file
=
ssio
)
arg_max_val
=
numpy
.
argmax
(
numpy
.
absolute
(
nv
-
ov
))
abs_diff
=
numpy
.
absolute
(
nv
-
ov
)
print
(
" Max Abs Diff: "
,
numpy
.
max
(
abs_diff
),
file
=
ssio
)
print
(
" Mean Abs Diff: "
,
numpy
.
mean
(
abs_diff
),
file
=
ssio
)
print
(
" Median Abs Diff: "
,
numpy
.
median
(
abs_diff
),
file
=
ssio
)
print
(
" Std Abs Diff: "
,
numpy
.
std
(
abs_diff
),
file
=
ssio
)
arg_max_val
=
numpy
.
argmax
(
abs_diff
)
values_at_max
=
(
nv
.
flatten
()[
arg_max_val
],
ov
.
flatten
()[
arg_max_val
])
print
(
" Value at Max Diff: "
,
values_at_max
,
file
=
ssio
)
# N.B. the maximum(..., 1e-8) protects against div by 0 when
# nv == ov == 0
reldiff
=
(
numpy
.
absolute
(
nv
-
ov
)
/
numpy
.
maximum
(
numpy
.
absolute
(
nv
)
+
numpy
.
absolute
(
ov
),
1e-8
))
reldiff
=
(
abs_diff
/
numpy
.
maximum
(
numpy
.
absolute
(
nv
)
+
numpy
.
absolute
(
ov
),
1e-8
))
print
(
" Max Rel Diff: "
,
numpy
.
max
(
reldiff
),
file
=
ssio
)
print
(
" Mean Rel Diff: "
,
numpy
.
mean
(
reldiff
),
file
=
ssio
)
print
(
" Median Rel Diff: "
,
numpy
.
median
(
reldiff
),
file
=
ssio
)
...
...
@@ -325,8 +325,10 @@ class BadOptimization(DebugModeError):
print
(
" New Graph:"
,
file
=
sio
)
print
(
self
.
new_graph
,
file
=
sio
)
print
(
""
,
file
=
sio
)
print
(
"Hint: relax the tolerance by setting tensor.cmp_sloppy=1"
,
file
=
sio
)
print
(
" or even tensor.cmp_sloppy=2 for less-strict comparison"
,
file
=
sio
)
print
(
"Hint: relax the tolerance by setting tensor.cmp_sloppy=1"
,
file
=
sio
)
print
(
" or even tensor.cmp_sloppy=2 for less-strict comparison"
,
file
=
sio
)
return
sio
.
getvalue
()
...
...
@@ -334,8 +336,7 @@ class BadDestroyMap(DebugModeError):
"""Exception: Some perform() or c_code() modified an input that
wasn't in the destroy_map"""
def
__init__
(
self
,
node
,
idx
,
old_val
,
new_val
,
perform
):
#super(BadDestroyMap, self).__init__()
DebugModeError
.
__init__
(
self
)
# to be compatible with python2.4
super
(
BadDestroyMap
,
self
)
.
__init__
()
self
.
node
=
node
self
.
idx
=
idx
self
.
old_val
=
old_val
...
...
@@ -347,30 +348,42 @@ class BadDestroyMap(DebugModeError):
print
(
" node:"
,
self
.
node
,
file
=
sio
)
print
(
" perform:"
,
self
.
perform
,
file
=
sio
)
print
(
" node.inputs:"
,
[(
str
(
i
),
id
(
i
))
for
i
in
self
.
node
.
inputs
],
file
=
sio
)
for
i
in
self
.
node
.
inputs
],
file
=
sio
)
print
(
" destroy_map:"
,
getattr
(
self
.
node
.
op
,
'destroy_map'
,
{}),
file
=
sio
)
'destroy_map'
,
{}),
file
=
sio
)
print
(
" changed input idx:"
,
self
.
idx
,
file
=
sio
)
print
(
" changed input type:"
,
self
.
node
.
inputs
[
self
.
idx
]
.
type
,
file
=
sio
)
print
(
" changed input type:"
,
self
.
node
.
inputs
[
self
.
idx
]
.
type
,
file
=
sio
)
print
(
" repr (old val):"
,
repr
(
self
.
old_val
),
file
=
sio
)
print
(
" repr (new val):"
,
repr
(
self
.
new_val
),
file
=
sio
)
try
:
npy_old_val
=
numpy
.
asarray
(
self
.
old_val
)
npy_new_val
=
numpy
.
asarray
(
self
.
new_val
)
print
(
" value dtype (new <space> old):"
,
npy_new_val
.
dtype
,
npy_old_val
.
dtype
,
file
=
sio
)
print
(
" value shape (new <space> old):"
,
npy_new_val
.
shape
,
npy_old_val
.
shape
,
file
=
sio
)
print
(
" value min (new <space> old):"
,
npy_new_val
.
min
(),
npy_old_val
.
min
(),
file
=
sio
)
print
(
" value max (new <space> old):"
,
npy_new_val
.
max
(),
npy_old_val
.
max
(),
file
=
sio
)
print
(
" value dtype (new <space> old):"
,
npy_new_val
.
dtype
,
npy_old_val
.
dtype
,
file
=
sio
)
print
(
" value shape (new <space> old):"
,
npy_new_val
.
shape
,
npy_old_val
.
shape
,
file
=
sio
)
print
(
" value min (new <space> old):"
,
npy_new_val
.
min
(),
npy_old_val
.
min
(),
file
=
sio
)
print
(
" value max (new <space> old):"
,
npy_new_val
.
max
(),
npy_old_val
.
max
(),
file
=
sio
)
delta
=
npy_new_val
-
npy_old_val
print
(
" value min (new-old):"
,
delta
.
min
(),
file
=
sio
)
print
(
" value max (new-old):"
,
delta
.
max
(),
file
=
sio
)
print
(
" value argmin (new-old):"
,
numpy
.
unravel_index
(
delta
.
argmin
(),
npy_new_val
.
shape
),
file
=
sio
)
print
(
" value argmax (new-old):"
,
numpy
.
unravel_index
(
delta
.
argmax
(),
npy_new_val
.
shape
),
file
=
sio
)
print
(
" location of first 10 mismatches:"
,
numpy
.
transpose
(
numpy
.
nonzero
(
delta
))[:
10
],
file
=
sio
)
print
(
" value argmin (new-old):"
,
numpy
.
unravel_index
(
delta
.
argmin
(),
npy_new_val
.
shape
),
file
=
sio
)
print
(
" value argmax (new-old):"
,
numpy
.
unravel_index
(
delta
.
argmax
(),
npy_new_val
.
shape
),
file
=
sio
)
print
(
" location of first 10 mismatches:"
,
numpy
.
transpose
(
numpy
.
nonzero
(
delta
))[:
10
],
file
=
sio
)
print
(
""
,
file
=
sio
)
except
Exception
as
e
:
print
(
"(Numpy-hints failed with:
%
s)"
%
str
(
e
),
file
=
sio
)
print
(
" Hint: this can also be caused by a deficient values_eq_approx() or __eq__() implementation [which compared input values]"
,
file
=
sio
)
print
(
" Hint: this can also be caused by a deficient "
"values_eq_approx() or __eq__() implementation "
"[which compared input values]"
,
file
=
sio
)
return
sio
.
getvalue
()
...
...
@@ -379,8 +392,7 @@ class BadViewMap(DebugModeError):
that wasn't in the view_map"""
def
__init__
(
self
,
node
,
output_idx
,
out_storage
,
in_alias_idx
=
None
,
out_alias_idx
=
None
):
#super(BadViewMap, self).__init__()
DebugModeError
.
__init__
(
self
)
# to be compatible with python2.4
super
(
BadViewMap
,
self
)
.
__init__
()
self
.
node
=
node
self
.
output_idx
=
output_idx
self
.
out_storage
=
out_storage
...
...
@@ -391,12 +403,12 @@ class BadViewMap(DebugModeError):
sio
=
StringIO
()
print
(
" node:"
,
self
.
node
,
file
=
sio
)
print
(
" node.inputs:"
,
[(
str
(
i
),
id
(
i
))
for
i
in
self
.
node
.
inputs
],
file
=
sio
)
for
i
in
self
.
node
.
inputs
],
file
=
sio
)
print
(
" node.outputs:"
,
[(
str
(
i
),
id
(
i
))
for
i
in
self
.
node
.
outputs
],
file
=
sio
)
for
i
in
self
.
node
.
outputs
],
file
=
sio
)
print
(
" view_map:"
,
getattr
(
self
.
node
.
op
,
'view_map'
,
{}),
file
=
sio
)
print
(
" destroy_map:"
,
getattr
(
self
.
node
.
op
,
'destroy_map'
,
{}),
file
=
sio
)
'destroy_map'
,
{}),
file
=
sio
)
print
(
" aliased output:"
,
self
.
output_idx
,
file
=
sio
)
print
(
" aliased output storage:"
,
self
.
out_storage
,
file
=
sio
)
if
self
.
in_alias_idx
:
...
...
@@ -425,8 +437,7 @@ class InvalidValueError(DebugModeError):
the Type of that output"""
def
__init__
(
self
,
r
,
v
,
client_node
=
None
,
hint
=
'none'
,
specific_hint
=
'none'
):
#super(InvalidValueError, self).__init__()
DebugModeError
.
__init__
(
self
)
# to be compatible with python2.4
super
(
InvalidValueError
,
self
)
.
__init__
()
self
.
r
=
r
self
.
v
=
v
self
.
client_node
=
client_node
...
...
@@ -454,7 +465,8 @@ class InvalidValueError(DebugModeError):
client_node
=
self
.
client_node
hint
=
self
.
hint
specific_hint
=
self
.
specific_hint
context
=
debugprint
(
r
,
prefix
=
' '
,
depth
=
12
,
file
=
StringIO
())
.
getvalue
()
context
=
debugprint
(
r
,
prefix
=
' '
,
depth
=
12
,
file
=
StringIO
())
.
getvalue
()
return
"""InvalidValueError
type(variable) =
%(type_r)
s
variable =
%(r)
s
...
...
@@ -512,7 +524,8 @@ def debugprint(r, prefix='', depth=-1, done=None, print_type=False,
and their associated printed ids
:param print_type: whether to print the Variable type after the other infos
:param file: file-like object to which to print
:param print_destroy_map: whether to print the op destroy_map after other info
:param print_destroy_map: whether to print the op destroy_map after
other info
:param print_view_map: whether to print the op view_map after other info
:param order: If not empty will print the index in the toposort.
:param ids: How do we print the identifier of the variable
...
...
@@ -592,23 +605,23 @@ def debugprint(r, prefix='', depth=-1, done=None, print_type=False,
already_printed
=
a
in
done
# get_id_str put it in the dict
id_str
=
get_id_str
(
a
)
if
profile
==
None
or
a
not
in
profile
.
apply_time
:
if
profile
is
None
or
a
not
in
profile
.
apply_time
:
if
len
(
a
.
outputs
)
==
1
:
print
(
'
%
s
%
s
%
s
%
s
\'
%
s
\'
%
s
%
s
%
s'
%
(
prefix
,
a
.
op
,
id_str
,
type_str
,
r_name
,
destroy_map_str
,
view_map_str
,
o
),
file
=
file
)
id_str
,
type_str
,
r_name
,
destroy_map_str
,
view_map_str
,
o
),
file
=
file
)
else
:
print
(
'
%
s
%
s.
%
i
%
s
%
s
\'
%
s
\'
%
s
%
s
%
s'
%
(
prefix
,
a
.
op
,
a
.
outputs
.
index
(
r
),
id_str
,
type_str
,
r_name
,
destroy_map_str
,
view_map_str
,
o
),
file
=
file
)
a
.
outputs
.
index
(
r
),
id_str
,
type_str
,
r_name
,
destroy_map_str
,
view_map_str
,
o
),
file
=
file
)
else
:
op_time
=
profile
.
apply_time
[
a
]
op_time_percent
=
(
op_time
/
profile
.
fct_call_time
)
*
100
...
...
@@ -617,33 +630,35 @@ def debugprint(r, prefix='', depth=-1, done=None, print_type=False,
tot_time_percent
=
(
tot_time_dict
[
a
]
/
profile
.
fct_call_time
)
*
100
if
len
(
a
.
outputs
)
==
1
:
print
(
'
%
s
%
s
%
s
%
s
\'
%
s
\'
%
s
%
s
%
s -->
%8.2
es
%4.1
f
%% %8.2
es
%4.1
f
%%
'
\
%
(
prefix
,
a
.
op
,
id_str
,
type_str
,
r_name
,
destroy_map_str
,
view_map_str
,
o
,
op_time
,
op_time_percent
,
tot_time
,
tot_time_percent
),
file
=
file
)
print
(
"
%
s
%
s
%
s
%
s '
%
s'
%
s
%
s
%
s --> "
"
%8.2
es
%4.1
f
%% %8.2
es
%4.1
f
%%
"
%
(
prefix
,
a
.
op
,
id_str
,
type_str
,
r_name
,
destroy_map_str
,
view_map_str
,
o
,
op_time
,
op_time_percent
,
tot_time
,
tot_time_percent
),
file
=
file
)
else
:
print
(
'
%
s
%
s.
%
i
%
s
%
s
\'
%
s
\'
%
s
%
s
%
s -->
%8.2
es
%4.1
f
%% %8.2
es
%4.1
f
%%
'
\
%
(
prefix
,
a
.
op
,
a
.
outputs
.
index
(
r
),
id_str
,
type_str
,
r_name
,
destroy_map_str
,
view_map_str
,
o
,
op_time
,
op_time_percent
,
tot_time
,
tot_time_percent
),
file
=
file
)
print
(
"
%
s
%
s.
%
i
%
s
%
s '
%
s'
%
s
%
s
%
s --> "
"
%8.2
es
%4.1
f
%% %8.2
es
%4.1
f
%%
"
%
(
prefix
,
a
.
op
,
a
.
outputs
.
index
(
r
),
id_str
,
type_str
,
r_name
,
destroy_map_str
,
view_map_str
,
o
,
op_time
,
op_time_percent
,
tot_time
,
tot_time_percent
),
file
=
file
)
if
not
already_printed
:
if
(
not
stop_on_name
or
not
(
hasattr
(
r
,
'name'
)
and
r
.
name
is
not
None
)):
not
(
hasattr
(
r
,
'name'
)
and
r
.
name
is
not
None
)):
new_prefix
=
prefix_child
+
' |'
new_prefix_child
=
prefix_child
+
' |'
...
...
@@ -652,14 +667,15 @@ def debugprint(r, prefix='', depth=-1, done=None, print_type=False,
new_prefix_child
=
prefix_child
+
' '
if
hasattr
(
i
,
'owner'
)
and
hasattr
(
i
.
owner
,
'op'
):
if
isinstance
(
i
.
owner
.
op
,
theano
.
scan_module
.
scan_op
.
Scan
):
if
isinstance
(
i
.
owner
.
op
,
theano
.
scan_module
.
scan_op
.
Scan
):
scan_ops
.
append
(
i
)
debugprint
(
i
,
new_prefix
,
depth
=
depth
-
1
,
done
=
done
,
print_type
=
print_type
,
file
=
file
,
order
=
order
,
ids
=
ids
,
stop_on_name
=
stop_on_name
,
prefix_child
=
new_prefix_child
,
scan_ops
=
scan_ops
,
profile
=
profile
)
prefix_child
=
new_prefix_child
,
scan_ops
=
scan_ops
,
profile
=
profile
)
else
:
# this is an input variable
...
...
@@ -679,7 +695,8 @@ def _optcheck_fgraph(input_specs, output_specs, accept_inplace=False):
:param accept_inplace: are inplace ops permitted in the original graph?
:type accept_inplace: Bool
:rtype: `FunctionGraph`
:returns: a new FunctionGraph with a cloned graph, with debugging `Feature` instances already installed.
:returns: a new FunctionGraph with a cloned graph, with debugging
`Feature` instances already installed.
"""
orig_inputs
=
[
spec
.
variable
for
spec
in
input_specs
]
updates
=
[
spec
.
update
for
spec
in
input_specs
if
spec
.
update
]
...
...
@@ -687,15 +704,15 @@ def _optcheck_fgraph(input_specs, output_specs, accept_inplace=False):
equivalence_tracker
=
_VariableEquivalenceTracker
()
fgraph
=
gof
.
fg
.
FunctionGraph
(
orig_inputs
,
orig_outputs
,
# DestroyHandler may not be needed yet, as there is usually no
# inplace operation in the graph at this stage. DestroyHandler
# will be installed by an optimization after canonicalization,
# before the inplace operations are applied.
# This results in a big speed gain.
# If inplace operations are accepted and present, however,
# DestroyHandler will be inserted in the loop below.
# features=[equivalence_tracker, gof.DestroyHandler(do_imports_on_attach=False)])
features
=
[
equivalence_tracker
])
features
=
[
equivalence_tracker
])
# DestroyHandler may not be needed yet, as there is usually no
# inplace operation in the graph at this stage. DestroyHandler
# will be installed by an optimization after canonicalization,
# before the inplace operations are applied. This results in a big
# speed gain.
#
# If inplace operations are accepted and present, however,
# DestroyHandler will be inserted in the loop below.
if
not
accept_inplace
:
for
node
in
fgraph
.
apply_nodes
:
...
...
@@ -711,9 +728,10 @@ def _optcheck_fgraph(input_specs, output_specs, accept_inplace=False):
break
# We need to protect all immutable inputs from inplace operations.
fgraph
.
attach_feature
(
Supervisor
(
input
for
spec
,
input
in
zip
(
input_specs
,
fgraph
.
inputs
)
if
not
(
spec
.
mutable
or
(
hasattr
(
fgraph
,
'destroyers'
)
and
fgraph
.
destroyers
(
input
)))))
fgraph
.
attach_feature
(
Supervisor
(
input
for
spec
,
input
in
zip
(
input_specs
,
fgraph
.
inputs
)
if
not
(
spec
.
mutable
or
(
hasattr
(
fgraph
,
'destroyers'
)
and
fgraph
.
destroyers
(
input
)))))
for
feature
in
std_fgraph
.
features
:
fgraph
.
attach_feature
(
feature
())
...
...
@@ -762,7 +780,7 @@ def _check_inputs(node, storage_map, r_vals, dr_vals, active_nodes,
out_var
=
storage_map
[
var
][
0
]
in_var
=
storage_map
[
node
.
inputs
[
ii
[
0
]]][
0
]
if
(
hasattr
(
var
.
type
,
'may_share_memory'
)
and
var
.
type
.
may_share_memory
(
out_var
,
in_var
)):
var
.
type
.
may_share_memory
(
out_var
,
in_var
)):
actually_inplace_outputs
.
append
(
node
.
outputs
[
oo
])
if
warn_input_not_reused
and
destroyed_res_list
:
...
...
@@ -772,8 +790,8 @@ def _check_inputs(node, storage_map, r_vals, dr_vals, active_nodes,
continue
if
out_var
is
not
in_var
:
_logger
.
warning
(
"Optimization Warning: input idx
%
d marked "
"as destroyed was not changed for node '
%
s'"
,
ii
[
0
],
str
(
node
))
"as destroyed was not changed for node '
%
s'"
,
ii
[
0
],
str
(
node
))
vmap
=
getattr
(
node
.
op
,
'view_map'
,
{})
for
oo
,
ii
in
vmap
.
iteritems
():
...
...
@@ -797,8 +815,8 @@ def _check_inputs(node, storage_map, r_vals, dr_vals, active_nodes,
continue
if
not
may_share
:
_logger
.
warning
(
"Optimization Warning: input idx
%
d marked "
"as viewed but new memory allocated by node '
%
s'"
,
ii
[
0
],
str
(
node
))
"as viewed but new memory allocated by node "
"'
%
s'"
,
ii
[
0
],
str
(
node
))
for
r_idx
,
r
in
enumerate
(
node
.
inputs
):
if
not
r
.
type
.
values_eq
(
r_vals
[
r
],
storage_map
[
r
][
0
]):
...
...
@@ -808,10 +826,12 @@ def _check_inputs(node, storage_map, r_vals, dr_vals, active_nodes,
# ok, we expected r to be destroyed
if
node
in
active_nodes
:
if
dr_vals
.
get
(
r
,
(
0
,
node
))[
1
]
is
not
node
:
# bad: there should only be one active node that destroys any variable
# bad: there should only be one active node
# that destroys any variable
raise
Exception
(
'failure in topological ordering'
)
if
clobber_dr_vals
:
dr_vals
[
r
]
=
(
storage_map
[
r
][
0
],
node
)
# no copy, this is the last use of this variable
# no copy, this is the last use of this variable
dr_vals
[
r
]
=
(
storage_map
[
r
][
0
],
node
)
# make sure that dr_vals[r] doens't get used again
storage_map
[
r
][
0
]
=
data_destroyed
else
:
...
...
@@ -823,8 +843,10 @@ def _check_inputs(node, storage_map, r_vals, dr_vals, active_nodes,
def
_check_viewmap
(
node
,
storage_map
):
"""
This functions raises a BadViewMap exception when it detects the following:
- output node storages aliased to input storage, with no declaration in view_map
This functions raises a BadViewMap exception when it detects the
following:
- output node storages aliased to input storage, with no declaration
in view_map
- if not aliased to an input, check if two outputs are aliased together
and used subsequently in the graph
"""
...
...
@@ -851,14 +873,14 @@ def _check_viewmap(node, storage_map):
# useless check.
continue
if
(
hasattr
(
inode
.
type
,
'may_share_memory'
)
and
inode
.
type
.
may_share_memory
(
outstorage
,
in_storage
)):
inode
.
type
.
may_share_memory
(
outstorage
,
in_storage
)):
nodeid
=
id
(
inode
)
bad_alias
[
nodeid
]
=
ii
# check that the aliasing was declared in [view|destroy]_map
if
([
ii
]
==
view_map
.
get
(
oi
,
None
)
or
[
ii
]
==
destroy_map
.
get
(
oi
,
None
)):
[
ii
]
==
destroy_map
.
get
(
oi
,
None
)):
good_alias
[
nodeid
]
=
bad_alias
.
pop
(
nodeid
)
...
...
@@ -970,12 +992,12 @@ def _find_bad_optimizations0(order, reasons, r_vals):
check
=
r
.
type
.
values_eq_approx
(
r_val
,
new_r_val
)
if
not
check
:
raise
BadOptimization
(
old_r
=
r
,
new_r
=
new_r
,
old_r_val
=
r_val
,
new_r_val
=
new_r_val
,
reason
=
reason
,
old_graph
=
old_graph_str
,
new_graph
=
new_graph_str
)
new_r
=
new_r
,
old_r_val
=
r_val
,
new_r_val
=
new_r_val
,
reason
=
reason
,
old_graph
=
old_graph_str
,
new_graph
=
new_graph_str
)
def
_find_bad_optimizations1
(
order
,
reasons
,
r_vals
):
...
...
@@ -993,7 +1015,7 @@ def _find_bad_optimizations1(order, reasons, r_vals):
equivalence_sets
.
setdefault
(
new_r
,
set
([
new_r
]))
for
reason
,
r
,
old_graph_str
,
new_graph_str
in
reasons
[
new_r
]:
equivalence_sets
[
new_r
]
.
update
(
equivalence_sets
.
setdefault
(
r
,
set
([
r
])))
r
,
set
([
r
])))
for
er
in
equivalence_sets
[
r
]:
equivalence_sets
[
er
]
=
equivalence_sets
[
new_r
]
...
...
@@ -1050,28 +1072,25 @@ def _find_bad_optimizations2(order, reasons, r_vals):
if
(
r
.
type
!=
new_r
.
type
)
or
(
not
r
.
type
.
values_eq_approx
(
r_val
,
new_r_val
)):
raise
BadOptimization
(
old_r
=
r
,
new_r
=
new_r
,
old_r_val
=
r_val
,
new_r_val
=
new_r_val
,
reason
=
reason
,
old_graph
=
old_graph_str
,
new_graph
=
new_graph_str
)
new_r
=
new_r
,
old_r_val
=
r_val
,
new_r_val
=
new_r_val
,
reason
=
reason
,
old_graph
=
old_graph_str
,
new_graph
=
new_graph_str
)
def
check_variable
(
r
):
if
r
in
checked_variables
:
return
checked_variables
.
add
(
r
)
# (recursively) first check all the variables that could make r look bad:
# (recursively) first check all the variables that could make
# r look bad:
list_of_vars
=
[
old_r
for
(
reason
,
old_r
,
olds
,
news
)
in
reasons
[
r
]]
if
(
None
is
not
r
.
owner
):
list_of_vars
+=
r
.
owner
.
inputs
for
var_that_could_make_r_look_bad
in
\
list_of_vars
:
# backport
#[old_r for (reason, old_r, olds, news) in reasons[r]] \
#+ ([] if (None is r.owner) else r.owner.inputs):
for
var_that_could_make_r_look_bad
in
list_of_vars
:
check_variable
(
var_that_could_make_r_look_bad
)
check_variable_norec
(
r
)
...
...
@@ -1087,8 +1106,8 @@ _find_bad_optimizations = _find_bad_optimizations0
def
_get_preallocated_maps
(
node
,
thunk
,
prealloc_modes
,
def_val
,
storage_map
,
r_vals
,
dr_vals
,
perform
,
active_order_set
,
inplace_outs
,
init_outputs
):
storage_map
,
r_vals
,
dr_vals
,
perform
,
active_order_set
,
inplace_outs
,
init_outputs
):
'''Preallocate outputs in different memory layouts'''
# To avoid circular imports
...
...
@@ -1137,7 +1156,7 @@ def _get_preallocated_maps(node, thunk, prealloc_modes, def_val,
# inplace.
if
isinstance
(
r
.
type
,
(
TensorType
,
CudaNdarrayType
)):
reuse_outputs
[
r
][
...
]
=
numpy
.
asarray
(
def_val
)
.
astype
(
r
.
type
.
dtype
)
def_val
)
.
astype
(
r
.
type
.
dtype
)
if
reuse_outputs
:
yield
(
'previous'
,
reuse_outputs
)
...
...
@@ -1169,16 +1188,16 @@ def _get_preallocated_maps(node, thunk, prealloc_modes, def_val,
for
r
in
considered_outputs
:
if
isinstance
(
r
.
type
,
(
TensorType
,
CudaNdarrayType
)):
new_buf
=
numpy
.
zeros
(
shape
=
r_vals
[
r
]
.
shape
,
dtype
=
r_vals
[
r
]
.
dtype
,
order
=
'F'
)
shape
=
r_vals
[
r
]
.
shape
,
dtype
=
r_vals
[
r
]
.
dtype
,
order
=
'F'
)
new_buf
[
...
]
=
def_val
if
isinstance
(
r
.
type
,
CudaNdarrayType
):
# When the CudaNdarray is built, the underlying memory
# is c-contiguous, so we transpose it before and after.
new_buf
=
CudaNdarray
(
new_buf
.
T
)
new_buf
=
cuda_dimshuffle
(
new_buf
,
range
(
new_buf
.
ndim
)[::
-
1
])
range
(
new_buf
.
ndim
)[::
-
1
])
f_cont_outputs
[
r
]
=
new_buf
...
...
@@ -1195,8 +1214,8 @@ def _get_preallocated_maps(node, thunk, prealloc_modes, def_val,
# Dimensions should be align by the innermost index, so we iterate
# from the end of shapes.
if
(
'strided'
in
prealloc_modes
or
'wrong_size'
in
prealloc_modes
or
'ALL'
in
prealloc_modes
):
'wrong_size'
in
prealloc_modes
or
'ALL'
in
prealloc_modes
):
max_ndim
=
0
rev_out_broadcastable
=
[]
for
r
in
considered_outputs
:
...
...
@@ -1297,11 +1316,11 @@ def _get_preallocated_maps(node, thunk, prealloc_modes, def_val,
if
isinstance
(
r
.
type
,
(
TensorType
,
CudaNdarrayType
)):
r_shape_diff
=
shape_diff
[:
r
.
ndim
]
out_shape
=
[
max
((
s
+
sd
),
0
)
for
s
,
sd
in
zip
(
r_vals
[
r
]
.
shape
,
r_shape_diff
)]
for
s
,
sd
in
zip
(
r_vals
[
r
]
.
shape
,
r_shape_diff
)]
new_buf
=
r
.
type
.
value_zeros
(
out_shape
)
new_buf
[
...
]
=
numpy
.
asarray
(
def_val
)
.
astype
(
r
.
type
.
dtype
)
def_val
)
.
astype
(
r
.
type
.
dtype
)
wrong_size
[
r
]
=
new_buf
if
wrong_size
:
...
...
@@ -1310,8 +1329,8 @@ def _get_preallocated_maps(node, thunk, prealloc_modes, def_val,
def
_check_preallocated_output
(
node
,
thunk
,
prealloc_modes
,
def_val
,
storage_map
,
r_vals
,
dr_vals
,
perform
,
active_order_set
,
inplace_outs
,
init_outputs
):
storage_map
,
r_vals
,
dr_vals
,
perform
,
active_order_set
,
inplace_outs
,
init_outputs
):
'''Try to apply thunk() on different output storages'''
# If node has an inner compiled Theano function with mode DebugMode,
...
...
@@ -1325,7 +1344,7 @@ def _check_preallocated_output(node, thunk, prealloc_modes, def_val,
or
not
hasattr
(
fn
,
'maker'
)
or
not
hasattr
(
fn
.
maker
,
'mode'
)):
_logger
.
warn
(
'Expected theano function not found in
%
s.
%
s'
,
node
.
op
,
fn_attr_name
)
node
.
op
,
fn_attr_name
)
else
:
if
isinstance
(
fn
.
maker
.
mode
,
DebugMode
):
backup_mode
=
fn
.
maker
.
mode
...
...
@@ -1378,9 +1397,10 @@ def _check_preallocated_output(node, thunk, prealloc_modes, def_val,
# Check outputs
for
r
in
node
.
outputs
:
if
not
r
.
type
.
is_valid_value
(
storage_map
[
r
][
0
]):
raise
InvalidValueError
(
r
,
storage_map
[
r
][
0
],
hint
=
thunk_name
,
specific_hint
=
r
.
type
.
value_validity_msg
(
raise
InvalidValueError
(
r
,
storage_map
[
r
][
0
],
hint
=
thunk_name
,
specific_hint
=
r
.
type
.
value_validity_msg
(
storage_map
[
r
][
0
]))
_check_inputs
(
node
,
storage_map
,
r_vals
,
dr_vals
,
active_order_set
,
...
...
@@ -1393,11 +1413,14 @@ def _check_preallocated_output(node, thunk, prealloc_modes, def_val,
for
r
in
node
.
outputs
:
if
not
check_eq
(
r
,
r_vals
[
r
],
storage_map
[
r
][
0
]):
# TODO: indicate it is not a C/Py problem
inputs_val
=
[
storage_map
[
inp
][
0
]
for
inp
in
r
.
owner
.
inputs
]
inputs_val
=
[
storage_map
[
inp
][
0
]
for
inp
in
r
.
owner
.
inputs
]
raise
BadThunkOutput
(
r
,
thunk1
=
'Reference value'
,
val1
=
r_vals
[
r
],
thunk2
=
thunk_name
,
val2
=
storage_map
[
r
][
0
],
inputs_val
=
inputs_val
)
thunk1
=
'Reference value'
,
val1
=
r_vals
[
r
],
thunk2
=
thunk_name
,
val2
=
storage_map
[
r
][
0
],
inputs_val
=
inputs_val
)
# Clear storage_map
for
r
in
node
.
outputs
:
...
...
@@ -1451,12 +1474,10 @@ class _FunctionGraphEvent(object):
msg
=
''
return
' '
.
join
([
'change'
,
self
.
reason
,
str
(
self
.
op
),
str
(
self
.
idx
),
msg
])
# backport
# str(len(self.node.inputs)) if (self.op != 'output') else ''])
self
.
reason
,
str
(
self
.
op
),
str
(
self
.
idx
),
msg
])
else
:
return
str
(
self
.
__dict__
)
...
...
@@ -1475,7 +1496,8 @@ class _FunctionGraphEvent(object):
class
_VariableEquivalenceTracker
(
object
):
"""A FunctionGraph Feature that keeps tabs on an FunctionGraph and tries to detect problems."""
"""A FunctionGraph Feature that keeps tabs on an FunctionGraph and
tries to detect problems."""
fgraph
=
None
"""WRITEME"""
...
...
@@ -1524,7 +1546,6 @@ class _VariableEquivalenceTracker(object):
def
on_prune
(
self
,
fgraph
,
node
,
reason
):
self
.
event_list
.
append
(
_FunctionGraphEvent
(
'prune'
,
node
,
reason
=
reason
))
# print 'PRUNING NODE', node, id(node)
assert
node
in
self
.
active_nodes
assert
node
not
in
self
.
inactive_nodes
self
.
active_nodes
.
remove
(
node
)
...
...
@@ -1534,7 +1555,6 @@ class _VariableEquivalenceTracker(object):
self
.
event_list
.
append
(
_FunctionGraphEvent
(
'import'
,
node
,
reason
=
reason
))
# print 'NEW NODE', node, id(node)
assert
node
not
in
self
.
active_nodes
self
.
active_nodes
.
add
(
node
)
...
...
@@ -1554,9 +1574,8 @@ class _VariableEquivalenceTracker(object):
self
.
replaced_by
.
setdefault
(
r
,
[])
def
on_change_input
(
self
,
fgraph
,
node
,
i
,
r
,
new_r
,
reason
=
None
):
# print 'CHANGE by', reason, 'to use', new_r, type(new_r)
self
.
event_list
.
append
(
_FunctionGraphEvent
(
'change'
,
node
,
reason
=
str
(
reason
),
idx
=
i
))
reason
=
str
(
reason
),
idx
=
i
))
self
.
reasons
.
setdefault
(
new_r
,
[])
self
.
replaced_by
.
setdefault
(
new_r
,
[])
...
...
@@ -1570,12 +1589,13 @@ class _VariableEquivalenceTracker(object):
# N.B. compute the debugprint now, because future
# optimizations will change the graph
done
=
dict
()
self
.
reasons
[
new_r
]
.
append
((
reason
,
r
,
debugprint
(
r
,
prefix
=
' '
,
depth
=
6
,
file
=
StringIO
(),
done
=
done
)
.
getvalue
(),
debugprint
(
new_r
,
prefix
=
' '
,
depth
=
6
,
file
=
StringIO
(),
done
=
done
)
.
getvalue
()))
self
.
reasons
[
new_r
]
.
append
(
(
reason
,
r
,
debugprint
(
r
,
prefix
=
' '
,
depth
=
6
,
file
=
StringIO
(),
done
=
done
)
.
getvalue
(),
debugprint
(
new_r
,
prefix
=
' '
,
depth
=
6
,
file
=
StringIO
(),
done
=
done
)
.
getvalue
()))
self
.
replaced_by
[
r
]
.
append
((
reason
,
new_r
))
if
r
in
self
.
equiv
:
...
...
@@ -1647,26 +1667,28 @@ class _Linker(gof.link.LocalLinker):
self
.
no_recycling
=
no_recycling
return
self
def
make_all
(
self
,
profiler
=
None
,
input_storage
=
None
,
output_storage
=
None
):
def
make_all
(
self
,
profiler
=
None
,
input_storage
=
None
,
output_storage
=
None
):
# can't import at toplevel because of circular import TODO:
# don't do this ugly hacky way of setting the
# filter_checks_isfinite
from
theano.tensor
import
TensorType
# to set filter_check_isfinite
if
1
:
# can't import at toplevel because of circular import TODO:
# don't do this ugly hacky way of setting the
# filter_checks_isfinite
from
theano.tensor
import
TensorType
# to set filter_check_isfinite
fgraph
=
self
.
fgraph
input_storage_
=
input_storage
output_storage_
=
output_storage
#order = self.schedule(fgraph)
# Compute a topological ordering that IGNORES the destroy_map of destructive Ops.
# This will be OK, because every thunk is evaluated on a copy of its input.
order_outputs
=
copy
.
copy
(
fgraph
.
equivalence_tracker
.
all_variables_ever
)
# Compute a topological ordering that IGNORES the destroy_map
# of destructive Ops. This will be OK, because every thunk is
# evaluated on a copy of its input.
fgraph_equiv
=
fgraph
.
equivalence_tracker
order_outputs
=
copy
.
copy
(
fgraph_equiv
.
all_variables_ever
)
del
fgraph_equiv
order_outputs
.
reverse
()
order
=
graph
.
io_toposort
(
fgraph
.
inputs
,
order_outputs
)
active_order
=
self
.
schedule
(
fgraph
)
# an ordering of just the active nodes
# an ordering of just the active nodes
active_order
=
self
.
schedule
(
fgraph
)
active_order_set
=
set
(
active_order
)
# Disable no_recycling, in order to be able to use
...
...
@@ -1682,9 +1704,6 @@ class _Linker(gof.link.LocalLinker):
thunks_c
=
[]
# c thunks
for
node
in
order
:
node_input_storage
=
[
storage_map
[
r
]
for
r
in
node
.
inputs
]
node_output_storage
=
[
storage_map
[
r
]
for
r
in
node
.
outputs
]
compute_map
=
{}
for
k
in
node
.
inputs
:
compute_map
[
k
]
=
[
True
]
...
...
@@ -1696,7 +1715,8 @@ class _Linker(gof.link.LocalLinker):
# the compilation of some dependency is triggered there.
thunk_other
=
None
if
get_unbound_function
(
node
.
op
.
make_thunk
)
not
in
default_make_thunk
:
if
(
get_unbound_function
(
node
.
op
.
make_thunk
)
not
in
default_make_thunk
):
thunk
=
node
.
op
.
make_thunk
(
node
,
storage_map
,
compute_map
,
...
...
@@ -1725,7 +1745,8 @@ class _Linker(gof.link.LocalLinker):
# raises an not implemented exception), so in those cases we
# consider that we don't have a python implementation
if
((
self
.
maker
.
mode
.
check_py_code
or
thunks_c
[
-
1
]
is
None
)
and
node
.
op
.
perform
.
func_code
!=
gof
.
op
.
PureOp
.
perform
.
func_code
):
(
node
.
op
.
perform
.
func_code
!=
gof
.
op
.
PureOp
.
perform
.
func_code
)):
thunk
=
node
.
op
.
make_py_thunk
(
node
,
storage_map
,
compute_map
,
no_recycling
)
thunks_py
.
append
(
thunk
)
...
...
@@ -1739,7 +1760,9 @@ class _Linker(gof.link.LocalLinker):
elif
thunks_c
[
-
1
]
is
None
:
thunks_c
[
-
1
]
=
thunk_other
else
:
_logger
.
warn
(
"We won't check the perform function of node '
%
s' but we will check its make_thunk function"
%
node
)
_logger
.
warn
(
"We won't check the perform function "
"of node '
%
s' but we will check its "
"make_thunk function"
%
node
)
thunks_py
[
-
1
]
=
thunk_other
# Use self.no_recycling (that was passed in accept()) to always
...
...
@@ -1747,10 +1770,11 @@ class _Linker(gof.link.LocalLinker):
# function's outputs. no_recycling_map will be used in f() below.
if
self
.
no_recycling
is
True
:
no_recycling_map
=
storage_map
.
values
()
no_recycling_map
=
utils
.
difference
(
no_recycling_map
,
input_storage
)
no_recycling_map
=
utils
.
difference
(
no_recycling_map
,
input_storage
)
else
:
no_recycling_map
=
[
storage_map
[
r
]
for
r
in
self
.
no_recycling
if
r
not
in
fgraph
.
inputs
]
if
r
not
in
fgraph
.
inputs
]
# Precompute some things for storage pre-allocation
try
:
...
...
@@ -1769,7 +1793,7 @@ class _Linker(gof.link.LocalLinker):
#####
_logger
.
debug
(
"starting a DebugMode call"
)
_logger
.
debug
(
"self.maker.mode.check_preallocated_output:
%
s"
,
self
.
maker
.
mode
.
check_preallocated_output
)
self
.
maker
.
mode
.
check_preallocated_output
)
for
x
in
no_recycling_map
:
x
[
0
]
=
None
...
...
@@ -1784,14 +1808,17 @@ class _Linker(gof.link.LocalLinker):
# the evaluation of this function, even when the graph
# has destructive ops in it
#
# This dictionary is used to populate the storage_map as necessary
# This dictionary is used to populate the storage_map
# as necessary
r_vals
=
{}
# dr_vals are the values taken by variables after being destroyed
# dr_vals are the values taken by variables after
# being destroyed
dr_vals
=
{}
assert
len
(
thunks_py
)
==
len
(
order
)
# transfer the initial values from the storage_map to the r_vals
# transfer the initial values from the storage_map to
# the r_vals
_logger
.
debug
(
"DEBUGMODE: transfer initial values"
)
# r_vals_initialized keeps track of the values that have
# actually been transferred from storage_map to r_vals
...
...
@@ -1803,17 +1830,20 @@ class _Linker(gof.link.LocalLinker):
# for a Generic object). We only want to raise
# an error if it is not valid.
if
(
storage_map
[
r
][
0
]
is
None
):
raise
InvalidValueError
(
r
,
storage_map
[
r
][
0
],
hint
=
"Graph Input '
%
s' is missing"
%
str
(
r
))
raise
InvalidValueError
(
r
,
storage_map
[
r
][
0
],
hint
=
(
"Graph Input '
%
s' has invalid value "
"
%
s"
%
(
r
,
storage_map
[
r
][
0
])))
raise
InvalidValueError
(
r
,
storage_map
[
r
][
0
],
hint
=
(
"Graph Input '
%
s' is missing"
%
str
(
r
)))
raise
InvalidValueError
(
r
,
storage_map
[
r
][
0
],
hint
=
(
"Graph Input '
%
s' has invalid value "
"
%
s"
%
(
r
,
storage_map
[
r
][
0
])))
r_vals
[
r
]
=
storage_map
[
r
][
0
]
storage_map
[
r
][
0
]
=
None
r_vals_initialized
.
append
(
r
)
# store preallocated outputs in another map, and test
the thunks on
# them as output storages.
# store preallocated outputs in another map, and test
# the
thunks on the
m as output storages.
init_outputs
=
{}
for
r
in
storage_map
:
if
r
in
fgraph
.
outputs
:
...
...
@@ -1835,8 +1865,6 @@ class _Linker(gof.link.LocalLinker):
for
i
,
(
thunk_py
,
thunk_c
,
node
)
in
enumerate
(
zip
(
thunks_py
,
thunks_c
,
order
)):
this_node_destroyed_variables
=
set
()
_logger
.
debug
(
"
%
i - starting node
%
i
%
s"
,
i
,
i
,
node
)
# put a copy of each input into the storage_map
...
...
@@ -1844,7 +1872,6 @@ class _Linker(gof.link.LocalLinker):
for
r
in
node
.
inputs
:
assert
isinstance
(
r
,
gof
.
Variable
)
assert
r
in
r_vals
# print >> sys.stderr,i, "DEBUGMODE: deepcopy input ", r
storage_map
[
r
][
0
]
=
_lessbroken_deepcopy
(
r_vals
[
r
])
if
not
r
.
type
.
is_valid_value
(
storage_map
[
r
][
0
]):
raise
InvalidValueError
(
r
,
storage_map
[
r
][
0
],
...
...
@@ -1854,7 +1881,7 @@ class _Linker(gof.link.LocalLinker):
# storage will be None
if
thunk_py
:
_logger
.
debug
(
"
%
i - running thunk_py with None as "
"output storage"
,
i
)
"output storage"
,
i
)
try
:
thunk_py
()
except
utils
.
MethodNotDefined
:
...
...
@@ -1872,10 +1899,12 @@ class _Linker(gof.link.LocalLinker):
raise
opt
=
str
(
reason
[
0
][
0
])
msg
=
(
"An optimization (probably
%
s ) inserted an apply node that raise an error."
%
opt
+
"
\n
The information we have about this optimizations is:"
+
str
(
reason
[
0
][
1
])
+
"
\n
"
+
reason
[
0
][
2
]
+
"
\n\n
The original exception:
\n
"
+
str
(
e
))
"An optimization (probably
%
s) inserted an "
"apply node that raise an error."
%
opt
+
"
\n
The information we have about this "
"optimizations is:"
+
str
(
reason
[
0
][
1
])
+
"
\n
"
+
reason
[
0
][
2
]
+
"
\n\n
The original exception:
\n
"
+
str
(
e
))
new_e
=
e
.
__class__
(
msg
)
exc_type
,
exc_value
,
exc_trace
=
sys
.
exc_info
()
exc_value
=
new_e
...
...
@@ -1891,45 +1920,42 @@ class _Linker(gof.link.LocalLinker):
raise
InvalidValueError
(
r
,
storage_map
[
r
][
0
],
hint
=
'perform output'
,
specific_hint
=
hint2
)
warn_inp
=
config
.
DebugMode
.
warn_input_not_reused
py_inplace_outs
=
_check_inputs
(
node
,
storage_map
,
r_vals
,
dr_vals
,
active_order_set
,
clobber_dr_vals
=
True
,
perform
=
'py'
,
warn_input_not_reused
=
config
.
DebugMode
.
warn_input_not_reused
)
node
,
storage_map
,
r_vals
,
dr_vals
,
active_order_set
,
clobber_dr_vals
=
True
,
perform
=
'py'
,
warn_input_not_reused
=
warn_inp
)
_check_viewmap
(
node
,
storage_map
)
# Retrieve each output from the storage_map
# The return values of this first run will be the reference ones
# Retrieve each output from the storage_map.
# The return values of this first run will be
# the reference ones
for
r
in
node
.
outputs
:
assert
r
not
in
r_vals
# print >> sys.stderr, i, "DEBUGMODE storing reference output %x" % id(storage_map[r][0])
r_vals
[
r
]
=
storage_map
[
r
][
0
]
# clear the storage_map of outputs for the thunk_c
storage_map
[
r
][
0
]
=
None
if
self
.
maker
.
mode
.
check_preallocated_output
:
prealloc_modes
=
\
self
.
maker
.
mode
.
check_preallocated_output
self
.
maker
.
mode
.
check_preallocated_output
_logger
.
debug
(
'
%
i - calling _check_preallocated_output '
'with thunk_py'
,
i
)
'
%
i - calling _check_preallocated_output '
'with thunk_py'
,
i
)
_check_preallocated_output
(
node
=
node
,
thunk
=
thunk_py
,
prealloc_modes
=
prealloc_modes
,
def_val
=
def_val
,
storage_map
=
storage_map
,
r_vals
=
r_vals
,
dr_vals
=
dr_vals
,
perform
=
'py'
,
active_order_set
=
active_order_set
,
inplace_outs
=
py_inplace_outs
,
init_outputs
=
init_outputs
)
# print >> sys.stderr, i, "DEBUGMODE thunk_py %100s %50s %30s" % (node,
#[(id(o), numpy.asarray(storage_map[o][0])[0,0]) for o in node.inputs],
#[(id(o), numpy.asarray(storage_map[o][0])[0,0]) for o in node.outputs])
node
=
node
,
thunk
=
thunk_py
,
prealloc_modes
=
prealloc_modes
,
def_val
=
def_val
,
storage_map
=
storage_map
,
r_vals
=
r_vals
,
dr_vals
=
dr_vals
,
perform
=
'py'
,
active_order_set
=
active_order_set
,
inplace_outs
=
py_inplace_outs
,
init_outputs
=
init_outputs
)
sys
.
stdout
.
flush
()
if
thunk_c
:
...
...
@@ -1939,18 +1965,22 @@ class _Linker(gof.link.LocalLinker):
dmap
=
getattr
(
node
.
op
,
'destroy_map'
,
{})
vmap
=
getattr
(
node
.
op
,
'view_map'
,
{})
for
i
,
r
in
enumerate
(
node
.
inputs
):
# if thunk_py ran, and we still got this far,
# it means that the destroy_map of the Op (and view_map) are
# accurate
# so we can assume that inputs not marked as destroyed have in
# fact not been destroyed.
# Therefore... we only need to overwrite inputs that *have*
# been marked as destroyed.
# Inputs marked as viewd are unsafe too,
# because the corresponding output can
# be destroyed.
if
any
(
i
in
v
for
v
in
(
dmap
.
values
()
+
vmap
.
values
())):
storage_map
[
r
][
0
]
=
_lessbroken_deepcopy
(
r_vals
[
r
])
# if thunk_py ran, and we still got
# this far, it means that the
# destroy_map of the Op (and view_map)
# are accurate so we can assume that
# inputs not marked as destroyed have
# in fact not been destroyed.
# Therefore... we only need to
# overwrite inputs that *have* been
# marked as destroyed. Inputs marked
# as viewd are unsafe too, because the
# corresponding output can be
# destroyed.
if
any
(
i
in
v
for
v
in
(
dmap
.
values
()
+
vmap
.
values
())):
storage_map
[
r
][
0
]
=
_lessbroken_deepcopy
(
r_vals
[
r
])
clobber
=
False
...
...
@@ -1969,10 +1999,12 @@ class _Linker(gof.link.LocalLinker):
raise
opt
=
str
(
reason
[
0
][
0
])
msg
=
(
"An optimization (probably
%
s ) inserted an apply node that raise an error."
%
opt
+
"
\n
The information we have about this optimizations is:"
+
str
(
reason
[
0
][
1
])
+
"
\n
"
+
reason
[
0
][
2
]
+
"
\n\n
The original exception:
\n
"
+
str
(
e
))
"An optimization (probably
%
s) inserted "
"an apply node that raise an error."
%
opt
+
"
\n
The information we have about this "
"optimizations is:"
+
str
(
reason
[
0
][
1
])
+
"
\n
"
+
reason
[
0
][
2
]
+
"
\n\n
The original exception:
\n
"
+
str
(
e
))
new_e
=
e
.
__class__
(
msg
)
exc_type
,
exc_value
,
exc_trace
=
sys
.
exc_info
()
exc_value
=
new_e
...
...
@@ -1982,21 +2014,26 @@ class _Linker(gof.link.LocalLinker):
for
r
in
node
.
outputs
:
# check output values for type-correctness
if
not
r
.
type
.
is_valid_value
(
storage_map
[
r
][
0
]):
raise
InvalidValueError
(
r
,
storage_map
[
r
][
0
],
hint
=
'c output'
)
raise
InvalidValueError
(
r
,
storage_map
[
r
][
0
],
hint
=
'c output'
)
if
thunk_py
:
assert
r
in
r_vals
# because we put it in during the thunk_py branch
# check for stride correctness (may raise exception)
_check_strides_match
(
r_vals
[
r
],
storage_map
[
r
][
0
],
# because we put it in during the
# thunk_py branch
assert
r
in
r_vals
# check for stride correctness (may
# raise exception)
_check_strides_match
(
r_vals
[
r
],
storage_map
[
r
][
0
],
self
.
maker
.
mode
.
require_matching_strides
,
node
.
op
)
warn_inp
=
config
.
DebugMode
.
warn_input_not_reused
c_inplace_outs
=
_check_inputs
(
node
,
storage_map
,
r_vals
,
dr_vals
,
active_order_set
,
clobber_dr_vals
=
clobber
,
perform
=
'c'
,
warn_input_not_reused
=
config
.
DebugMode
.
warn_input_not_reused
)
node
,
storage_map
,
r_vals
,
dr_vals
,
active_order_set
,
clobber_dr_vals
=
clobber
,
perform
=
'c'
,
warn_input_not_reused
=
warn_inp
)
_check_viewmap
(
node
,
storage_map
)
...
...
@@ -2006,11 +2043,14 @@ class _Linker(gof.link.LocalLinker):
# compares the version from thunk_py
# (in r_vals) to the version produced
# by thunk_c (in storage_map)
if
not
check_eq
(
r
,
r_vals
[
r
],
storage_map
[
r
][
0
]):
inputs_val
=
[
storage_map
[
inp
][
0
]
for
inp
in
r
.
owner
.
inputs
]
if
not
check_eq
(
r
,
r_vals
[
r
],
storage_map
[
r
][
0
]):
inputs_val
=
[
storage_map
[
inp
][
0
]
for
inp
in
r
.
owner
.
inputs
]
raise
BadThunkOutput
(
r
,
thunk1
=
'perform'
,
val1
=
r_vals
[
r
],
thunk2
=
'c_code'
,
val2
=
storage_map
[
r
][
0
],
thunk2
=
'c_code'
,
val2
=
storage_map
[
r
][
0
],
inputs_val
=
inputs_val
)
else
:
# retrieve each output from the storage_map
...
...
@@ -2020,37 +2060,34 @@ class _Linker(gof.link.LocalLinker):
if
self
.
maker
.
mode
.
check_preallocated_output
:
prealloc_modes
=
\
self
.
maker
.
mode
.
check_preallocated_output
self
.
maker
.
mode
.
check_preallocated_output
def
thunk
():
try
:
thunk_c
()
except
Exception
:
raise_with_op
(
node
,
thunk_c
)
_logger
.
debug
(
'
%
i - calling _check_preallocated_output '
'with thunk_c'
,
i
)
'
%
i - calling _check_preallocated_output '
'with thunk_c'
,
i
)
_check_preallocated_output
(
node
=
node
,
thunk
=
thunk
,
prealloc_modes
=
prealloc_modes
,
def_val
=
def_val
,
storage_map
=
storage_map
,
r_vals
=
r_vals
,
dr_vals
=
dr_vals
,
perform
=
'c code'
,
active_order_set
=
active_order_set
,
inplace_outs
=
c_inplace_outs
,
init_outputs
=
init_outputs
)
# print >> sys.stderr, i, "DEBUGMODE thunk_c %100s %50s %30s" % (node,
#[(id(o), numpy.asarray(storage_map[o][0])[0,0]) for o in node.inputs],
#[(id(o), numpy.asarray(storage_map[o][0])[0,0]) for o in node.outputs])
node
=
node
,
thunk
=
thunk
,
prealloc_modes
=
prealloc_modes
,
def_val
=
def_val
,
storage_map
=
storage_map
,
r_vals
=
r_vals
,
dr_vals
=
dr_vals
,
perform
=
'c code'
,
active_order_set
=
active_order_set
,
inplace_outs
=
c_inplace_outs
,
init_outputs
=
init_outputs
)
sys
.
stdout
.
flush
()
# we're done with this thunk
# clear everything out of the storage_map
for
r
in
node
.
inputs
:
#print >> sys.stderr, i, "DEBUGMODE clearing input", r
storage_map
[
r
][
0
]
=
None
_logger
.
debug
(
"
%
i - done with node"
,
i
)
...
...
@@ -2059,7 +2096,8 @@ class _Linker(gof.link.LocalLinker):
# But it is very slow and it is not sure it will help.
gc
.
collect
()
_find_bad_optimizations
(
order
,
fgraph
.
equivalence_tracker
.
reasons
,
_find_bad_optimizations
(
order
,
fgraph
.
equivalence_tracker
.
reasons
,
r_vals
)
#####
...
...
@@ -2081,18 +2119,24 @@ class _Linker(gof.link.LocalLinker):
for
r
in
r_vals
:
if
r
.
owner
is
None
:
if
r
in
fgraph
.
inputs
:
assert
storage_map
[
r
]
is
input_storage
[
fgraph
.
inputs
.
index
(
r
)]
assert
(
storage_map
[
r
]
is
input_storage
[
fgraph
.
inputs
.
index
(
r
)])
storage_map
[
r
][
0
]
=
r_vals
[
r
]
# if an input was destroyed, the destroyed value should be returned
# if an input was destroyed, the destroyed value
# should be returned
for
r
in
dr_vals
:
assert
dr_vals
[
r
][
0
]
is
not
None
if
r
.
owner
is
None
:
assert
r
in
fgraph
.
inputs
# HACK TO LOOK LIKE A REAL DESTRUCTIVE ACTION TOOK PLACE
if
type
(
dr_vals
[
r
][
0
])
in
(
numpy
.
ndarray
,
numpy
.
memmap
)
\
and
dr_vals
[
r
][
0
]
.
dtype
==
storage_map
[
r
][
0
]
.
dtype
\
and
dr_vals
[
r
][
0
]
.
shape
==
storage_map
[
r
][
0
]
.
shape
:
# HACK TO LOOK LIKE A REAL DESTRUCTIVE ACTION
# TOOK PLACE
if
((
type
(
dr_vals
[
r
][
0
])
in
(
numpy
.
ndarray
,
numpy
.
memmap
))
and
(
dr_vals
[
r
][
0
]
.
dtype
==
storage_map
[
r
][
0
]
.
dtype
)
and
(
dr_vals
[
r
][
0
]
.
shape
==
storage_map
[
r
][
0
]
.
shape
)):
if
len
(
dr_vals
[
r
][
0
]
.
shape
):
storage_map
[
r
][
0
][:]
=
dr_vals
[
r
][
0
]
else
:
...
...
@@ -2111,10 +2155,6 @@ class _Linker(gof.link.LocalLinker):
storage_map
[
r
][
0
]
=
None
raise
# print ""
# print output_storage
# print dr_vals
# print storage_map
for
r
in
storage_map
:
if
(
r
.
owner
is
None
):
if
not
r
.
type
.
is_valid_value
(
None
):
...
...
@@ -2130,12 +2170,14 @@ class _Linker(gof.link.LocalLinker):
# so it will screw up if we are trying to use
# multiple modes at once.
old_filter_checks_isfinite
=
TensorType
.
filter_checks_isfinite
TensorType
.
filter_checks_isfinite
=
self
.
maker
.
mode
.
check_isfinite
TensorType
.
filter_checks_isfinite
=
\
self
.
maker
.
mode
.
check_isfinite
try
:
return
f
()
finally
:
# put back the filter_checks_isfinite
TensorType
.
filter_checks_isfinite
=
old_filter_checks_isfinite
TensorType
.
filter_checks_isfinite
=
\
old_filter_checks_isfinite
return
deco
f
=
run_with_tensortype_filter_check
(
f
)
...
...
@@ -2143,12 +2185,12 @@ class _Linker(gof.link.LocalLinker):
f
.
allow_gc
=
True
assert
len
(
fgraph
.
inputs
)
==
len
(
input_storage
)
assert
len
(
fgraph
.
outputs
)
==
len
(
output_storage
)
# print 'make_all returning output', [id(z) for z in output_storage]
return
f
,
[
link
.
Container
(
input
,
storage
,
readonly
=
False
)
for
input
,
storage
in
zip
(
fgraph
.
inputs
,
input_storage
)],
\
[
link
.
Container
(
output
,
storage
,
readonly
=
True
)
for
output
,
storage
in
zip
(
fgraph
.
outputs
,
output_storage
)],
\
thunks_py
,
order
return
(
f
,
[
link
.
Container
(
input
,
storage
,
readonly
=
False
)
for
input
,
storage
in
zip
(
fgraph
.
inputs
,
input_storage
)],
[
link
.
Container
(
output
,
storage
,
readonly
=
True
)
for
output
,
storage
in
zip
(
fgraph
.
outputs
,
output_storage
)],
thunks_py
,
order
)
_NODEFAULT
=
[
'NODEFAULT'
]
...
...
@@ -2162,33 +2204,37 @@ class _Maker(FunctionMaker): # inheritance buys a few helper functions
0: silent)"""
def
__init__
(
self
,
inputs
,
outputs
,
optimizer
,
mode
,
accept_inplace
=
False
,
function_builder
=
Function
,
profile
=
None
,
on_unused_input
=
None
,
output_keys
=
None
):
accept_inplace
=
False
,
function_builder
=
Function
,
profile
=
None
,
on_unused_input
=
None
,
output_keys
=
None
):
"""
:type inputs: a list of SymbolicInput instances
:type outputs: a list of SymbolicOutput instances
outputs may also be a single Variable (not a list), in which
case the functions produced by FunctionMaker will return
their output value directly
:type outputs: a list of SymbolicOutput instances outputs may
also be a single Variable (not a list), in
which case the functions produced by
FunctionMaker will return their output value
directly
:param accept_inplace: True iff it is acceptable to have
inplace operations in the graph from the inputs to
the outputs
:param on_unused_input: What to do if a variable in the 'inputs' list is
not used in the graph. Possible values are 'raise', 'warn', and 'ignore'.
:param on_unused_input: What to do if a variable in the
'inputs' list is not used in the
graph. Possible values are 'raise',
'warn', and 'ignore'.
:param output_keys: If the outputs argument for theano.function was a
list, then output_keys is None. If the outputs argument was a dict,
then output_keys is a sorted list of the keys from that dict.
:param output_keys: If the outputs argument for
theano.function was a list, then
output_keys is None. If the outputs
argument was a dict, then output_keys is a
sorted list of the keys from that dict.
:note: this function sets TensorType.filter_checks_isfinite
when `mode.check_isfinite` is True
when `mode.check_isfinite` is True
"""
self
.
profile
=
profile
# Handle the case where inputs and/or outputs is a single
...
...
@@ -2205,7 +2251,8 @@ class _Maker(FunctionMaker): # inheritance buys a few helper functions
inputs
=
[
inputs
]
# Wrap them in In or Out instances if needed.
inputs
,
outputs
=
map
(
self
.
wrap_in
,
inputs
),
map
(
self
.
wrap_out
,
outputs
)
inputs
=
map
(
self
.
wrap_in
,
inputs
),
outputs
=
map
(
self
.
wrap_out
,
outputs
)
_inputs
=
gof
.
graph
.
inputs
([
o
.
variable
for
o
in
outputs
]
+
[
i
.
update
for
i
in
inputs
if
getattr
(
i
,
'update'
,
False
)])
...
...
@@ -2213,9 +2260,11 @@ class _Maker(FunctionMaker): # inheritance buys a few helper functions
# Check if some input variables are unused
self
.
_check_unused_inputs
(
inputs
,
outputs
,
on_unused_input
)
# Make a list of (SymbolicInput|SymblicInputKits, indices, [SymbolicInput,...]), one
# tuple for each input. (See Function.indices for more details)
indices
=
[[
input
]
+
self
.
expand_in
(
input
,
_inputs
)
for
input
in
inputs
]
# Make a list of (SymbolicInput|SymblicInputKits, indices,
# [SymbolicInput,...]), one tuple for each input. (See
# Function.indices for more details)
indices
=
[[
input
]
+
self
.
expand_in
(
input
,
_inputs
)
for
input
in
inputs
]
# make the fgraph
for
i
in
xrange
(
mode
.
stability_patience
):
...
...
@@ -2226,58 +2275,53 @@ class _Maker(FunctionMaker): # inheritance buys a few helper functions
# optimize the fgraph
compute_test_value_orig
=
theano
.
config
.
compute_test_value
try
:
theano
.
config
.
compute_test_value
=
theano
.
config
.
compute_test_value_opt
theano
.
config
.
compute_test_value
=
\
theano
.
config
.
compute_test_value_opt
optimizer
(
fgraph
)
theano
.
compile
.
function_module
.
insert_deepcopy
(
fgraph
,
inputs
,
outputs
+
additional_outputs
)
theano
.
compile
.
function_module
.
insert_deepcopy
(
fgraph
,
inputs
,
outputs
+
additional_outputs
)
finally
:
theano
.
config
.
compute_test_value
=
compute_test_value_orig
if
i
:
if
i
==
0
:
fgraph0
=
fgraph
else
:
li
=
fgraph
.
equivalence_tracker
.
event_list
l0
=
fgraph0
.
equivalence_tracker
.
event_list
if
li
!=
l0
:
if
li
!=
l0
:
infolog
=
StringIO
()
print
(
"WARNING: Optimization process is unstable..."
,
file
=
infolog
)
print
(
" (HINT: Ops that the nodes point to must compare equal)"
,
file
=
infolog
)
print
(
"(event index) (one event trace) (other event trace)"
,
file
=
infolog
)
print
(
"-----------------------------------------------------"
,
file
=
infolog
)
print
(
"WARNING: Optimization process is unstable..."
,
file
=
infolog
)
print
(
" (HINT: Ops that the nodes point to must compare "
"equal)"
,
file
=
infolog
)
print
(
"(event index) (one event trace) (other event "
"trace)"
,
file
=
infolog
)
print
(
"-------------------------------------------------"
"----"
,
file
=
infolog
)
for
j
in
xrange
(
max
(
len
(
li
),
len
(
l0
))):
if
j
>=
len
(
li
):
print
(
'trailing event in optimization 0 :'
,
j
,
file
=
infolog
)
print
(
'trailing event in optimization 0 :'
,
j
,
file
=
infolog
)
print
(
' '
,
str
(
l0
[
j
]),
file
=
infolog
)
elif
j
>=
len
(
l0
):
print
(
'trailing event in optimization'
,
i
,
':'
,
j
,
file
=
infolog
)
print
(
'trailing event in optimization'
,
i
,
':'
,
j
,
file
=
infolog
)
print
(
' '
,
str
(
li
[
j
]),
file
=
infolog
)
elif
li
[
j
]
!=
l0
[
j
]:
print
(
'non-equal optimization events'
,
i
,
':'
,
j
,
file
=
infolog
)
print
(
'non-equal optimization events'
,
i
,
':'
,
j
,
file
=
infolog
)
print
(
' '
,
str
(
l0
[
j
]),
file
=
infolog
)
print
(
' '
,
str
(
li
[
j
]),
file
=
infolog
)
#print >> infolog, "* ", j,
# if j < len(li):
# msg = str(li[j])
# else:
# msg = '-'
#print >> infolog, " ", msg
# if j < len(l0):
# msg = str(l0[j])
# else:
# msg = '-'
#print >> infolog, " ", msg
else
:
pass
raise
StochasticOrder
(
infolog
.
getvalue
())
else
:
if
self
.
verbose
:
print
(
"OPTCHECK: optimization"
,
i
,
\
"of"
,
len
(
li
),
"events was stable."
,
file
=
sys
.
stderr
)
else
:
fgraph0
=
fgraph
del
fgraph0
print
(
"OPTCHECK: optimization"
,
i
,
"of"
,
len
(
li
),
"events was stable."
,
file
=
sys
.
stderr
)
self
.
fgraph
=
fgraph
# equivalence_tracker.printstuff()
linker
=
_Linker
(
self
)
...
...
@@ -2285,14 +2329,14 @@ class _Maker(FunctionMaker): # inheritance buys a few helper functions
# the internal storage pointer.
no_borrow
=
[
output
for
output
,
spec
in
izip
(
fgraph
.
outputs
,
outputs
+
additional_outputs
)
if
not
spec
.
borrow
]
output
for
output
,
spec
in
izip
(
fgraph
.
outputs
,
outputs
+
additional_outputs
)
if
not
spec
.
borrow
]
if
no_borrow
:
self
.
linker
=
linker
.
accept
(
fgraph
,
no_recycling
=
infer_reuse_pattern
(
fgraph
,
no_borrow
))
fgraph
,
no_recycling
=
infer_reuse_pattern
(
fgraph
,
no_borrow
))
else
:
self
.
linker
=
linker
.
accept
(
fgraph
)
...
...
@@ -2351,8 +2395,8 @@ class _Maker(FunctionMaker): # inheritance buys a few helper functions
input_storage
+=
[
default
[
i
]
.
storage
for
i
in
indices
]
else
:
raise
ValueError
(
'Not enough storage for SymbolicInputKit'
,
input
,
indices
,
default
)
'Not enough storage for SymbolicInputKit'
,
input
,
indices
,
default
)
default
=
_NODEFAULT
else
:
input_storage
+=
[[
None
]
for
i
in
indices
]
...
...
@@ -2389,8 +2433,8 @@ class _Maker(FunctionMaker): # inheritance buys a few helper functions
else
:
# This might catch some bugs early
raise
ValueError
(
"A default (initial) value is required for an "
"input which can update itself."
,
input
)
"A default (initial) value is required for an "
"input which can update itself."
,
input
)
else
:
_defaults
.
append
((
False
,
False
,
default
))
else
:
...
...
@@ -2512,14 +2556,14 @@ class DebugMode(Mode):
return
_Maker
(
i
,
o
,
self
.
optimizer
,
self
,
*
args
,
**
kwargs
)
def
__init__
(
self
,
optimizer
=
'fast_run'
,
stability_patience
=
None
,
check_c_code
=
None
,
check_py_code
=
None
,
check_isfinite
=
None
,
check_preallocated_output
=
None
,
require_matching_strides
=
None
,
linker
=
_DummyLinker
()):
optimizer
=
'fast_run'
,
stability_patience
=
None
,
check_c_code
=
None
,
check_py_code
=
None
,
check_isfinite
=
None
,
check_preallocated_output
=
None
,
require_matching_strides
=
None
,
linker
=
_DummyLinker
()):
"""Initialize member variables.
If any of these arguments (except optimizer) is not None, it overrides
...
...
@@ -2532,9 +2576,8 @@ class DebugMode(Mode):
raise
Exception
(
"DebugMode can only use its own linker! You "
"should not provide one."
,
linker
)
super
(
DebugMode
,
self
)
.
__init__
(
optimizer
=
optimizer
,
linker
=
linker
)
super
(
DebugMode
,
self
)
.
__init__
(
optimizer
=
optimizer
,
linker
=
linker
)
if
stability_patience
is
not
None
:
self
.
stability_patience
=
stability_patience
...
...
@@ -2561,6 +2604,6 @@ class DebugMode(Mode):
def
__str__
(
self
):
return
"DebugMode(linker=
%
s, optimizer=
%
s)"
%
(
self
.
provided_linker
,
self
.
provided_optimizer
)
self
.
provided_linker
,
self
.
provided_optimizer
)
register_mode
(
'DEBUG_MODE'
,
DebugMode
(
optimizer
=
'fast_run'
))
theano/tests/test_flake8.py
浏览文件 @
3578c80c
...
...
@@ -38,7 +38,6 @@ whitelist_flake8 = [
"tests/test_tutorial.py"
,
"tests/disturb_mem.py"
,
"tests/unittest_tools.py"
,
"compile/debugmode.py"
,
"compile/function.py"
,
"compile/pfunc.py"
,
"compile/mode.py"
,
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论