Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
P
pytensor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
testgroup
pytensor
Commits
81e52783
提交
81e52783
authored
7月 27, 2016
作者:
Frédéric Bastien
提交者:
GitHub
7月 27, 2016
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #4669 from sygi/partial-eval-cvm
Partial evaluation in CVM
上级
e4e08782
43b57613
显示空白字符变更
内嵌
并排
正在显示
5 个修改的文件
包含
97 行增加
和
16 行删除
+97
-16
function_module.py
theano/compile/function_module.py
+5
-1
lazylinker_c.c
theano/gof/lazylinker_c.c
+45
-5
lazylinker_c.py
theano/gof/lazylinker_c.py
+1
-1
test_vm.py
theano/gof/tests/test_vm.py
+33
-3
vm.py
theano/gof/vm.py
+13
-6
没有找到文件。
theano/compile/function_module.py
浏览文件 @
81e52783
...
...
@@ -735,9 +735,13 @@ class Function(object):
kwargs : dict
The function inputs can be passed as keyword argument. For this, use
the name of the input or the input instance as the key.
Keyword argument ``output_subset`` is a list of either indices of the
function's outputs or the keys belonging to the `output_keys` dict
and represent outputs that are requested to be calculated.
and represent outputs that are requested to be calculated. Regardless
of the presence of ``output_subset``, the updates are always calculated
and processed. To disable the updates, you should use the ``copy``
method with ``delete_updates=True``.
Returns
-------
...
...
theano/gof/lazylinker_c.c
浏览文件 @
81e52783
...
...
@@ -789,15 +789,47 @@ CLazyLinker_call(PyObject *_self, PyObject *args, PyObject *kwds)
{
CLazyLinker
*
self
=
(
CLazyLinker
*
)
_self
;
static
char
*
kwlist
[]
=
{
(
char
*
)
"time_thunks"
,
(
char
*
)
"time_thunks"
,
(
char
*
)
"n_calls"
,
(
char
*
)
"output_subset"
,
NULL
};
int
n_calls
=
1
;
if
(
!
PyArg_ParseTupleAndKeywords
(
args
,
kwds
,
"|ii"
,
kwlist
,
PyObject
*
output_subset_ptr
=
NULL
;
if
(
!
PyArg_ParseTupleAndKeywords
(
args
,
kwds
,
"|iiO"
,
kwlist
,
&
self
->
do_timing
,
&
n_calls
))
&
n_calls
,
&
output_subset_ptr
))
return
NULL
;
int
err
=
0
;
// parse an output_subset list
// it is stored as a bool list of length n_output_vars: calculate a var or not
char
*
output_subset
=
NULL
;
int
output_subset_size
=
-
1
;
if
(
output_subset_ptr
!=
NULL
)
{
if
(
!
PyList_Check
(
output_subset_ptr
))
{
err
=
1
;
PyErr_SetString
(
PyExc_RuntimeError
,
"Output_subset is not a list"
);
}
else
{
output_subset_size
=
PyList_Size
(
output_subset_ptr
);
output_subset
=
(
char
*
)
calloc
(
self
->
n_output_vars
,
sizeof
(
char
));
for
(
int
it
=
0
;
it
<
output_subset_size
;
++
it
)
{
PyObject
*
elem
=
PyList_GetItem
(
output_subset_ptr
,
it
);
if
(
!
PyInt_Check
(
elem
))
{
err
=
1
;
PyErr_SetString
(
PyExc_RuntimeError
,
"Some elements of output_subset list are not int"
);
}
output_subset
[
PyInt_AsLong
(
elem
)]
=
1
;
}
}
}
self
->
position_of_error
=
-
1
;
// create constants used to fill the var_compute_cells
PyObject
*
one
=
PyInt_FromLong
(
1
);
...
...
@@ -833,10 +865,14 @@ CLazyLinker_call(PyObject *_self, PyObject *args, PyObject *kwds)
}
}
int
first_updated
=
self
->
n_output_vars
-
self
->
n_updates
;
for
(
int
i
=
0
;
i
<
self
->
n_output_vars
&&
(
!
err
);
++
i
)
{
if
(
i
>=
first_updated
||
output_subset
==
NULL
||
output_subset
[
i
]
==
1
)
{
err
=
lazy_rec_eval
(
self
,
self
->
output_vars
[
i
],
one
,
zero
);
}
}
if
(
!
err
)
{
...
...
@@ -848,7 +884,8 @@ CLazyLinker_call(PyObject *_self, PyObject *args, PyObject *kwds)
{
Py_ssize_t
src
=
self
->
output_vars
[
i
];
PyObject
*
item
=
PyList_GetItem
(
self
->
var_value_cells
[
src
],
0
);
if
(
self
->
var_computed
[
src
]
!=
1
)
if
((
output_subset
==
NULL
||
output_subset
[
i
])
&&
self
->
var_computed
[
src
]
!=
1
)
{
err
=
1
;
PyErr_Format
(
PyExc_AssertionError
,
...
...
@@ -901,6 +938,9 @@ CLazyLinker_call(PyObject *_self, PyObject *args, PyObject *kwds)
PyList_SetItem
(
self
->
var_value_cells
[
i
],
0
,
Py_None
);
}
}
if
(
output_subset
!=
NULL
)
free
(
output_subset
);
Py_DECREF
(
one
);
Py_DECREF
(
zero
);
if
(
err
)
...
...
@@ -1014,7 +1054,7 @@ static PyTypeObject lazylinker_ext_CLazyLinkerType = {
static
PyObject
*
get_version
(
PyObject
*
dummy
,
PyObject
*
args
)
{
PyObject
*
result
=
PyFloat_FromDouble
(
0
.
21
);
PyObject
*
result
=
PyFloat_FromDouble
(
0
.
21
1
);
return
result
;
}
...
...
theano/gof/lazylinker_c.py
浏览文件 @
81e52783
...
...
@@ -15,7 +15,7 @@ from theano.gof import cmodule
_logger
=
logging
.
getLogger
(
'theano.gof.lazylinker_c'
)
force_compile
=
False
version
=
0.21
# must match constant returned in function get_version()
version
=
0.21
1
# must match constant returned in function get_version()
lazylinker_ext
=
None
...
...
theano/gof/tests/test_vm.py
浏览文件 @
81e52783
...
...
@@ -197,24 +197,54 @@ def test_speed_lazy():
def
test_partial_function
():
import
numpy
as
np
from
theano.tests
import
unittest_tools
as
utt
def
check_partial_function
(
linker_name
):
x
=
tensor
.
scalar
(
'input'
)
y
=
x
**
2
f
=
theano
.
function
([
x
],
[
y
+
7
,
y
-
9
,
y
/
14.
],
mode
=
Mode
(
optimizer
=
None
,
linker
=
vm
.
VM_Linker
(
allow_partial_eval
=
True
)
))
optimizer
=
None
,
linker
=
linker_name
))
assert
f
(
3
,
output_subset
=
[
0
,
1
,
2
])
==
f
(
3
)
assert
f
(
4
,
output_subset
=
[
0
,
2
])
==
[
f
(
4
)[
0
],
f
(
4
)[
2
]]
utt
.
assert_allclose
(
f
(
5
),
np
.
array
([
32.
,
16.
,
1.7857142857142858
]))
check_partial_function
(
vm
.
VM_Linker
(
allow_partial_eval
=
True
,
use_cloop
=
False
))
check_partial_function
(
'cvm'
)
def
test_partial_function_with_output_keys
():
def
test_partial_function_output_keys
(
):
def
check_partial_function_output_keys
(
linker_name
):
x
=
tensor
.
scalar
(
'input'
)
y
=
3
*
x
f
=
theano
.
function
([
x
],
{
'a'
:
y
*
5
,
'b'
:
y
-
7
},
mode
=
Mode
(
optimizer
=
None
,
linker
=
vm
.
VM_Linker
(
allow_partial_eval
=
True
)
))
optimizer
=
None
,
linker
=
linker_name
))
assert
f
(
5
,
output_subset
=
[
'a'
])[
'a'
]
==
f
(
5
)[
'a'
]
check_partial_function_output_keys
(
vm
.
VM_Linker
(
allow_partial_eval
=
True
,
use_cloop
=
False
))
check_partial_function_output_keys
(
'cvm'
)
def
test_partial_function_with_updates
():
def
check_updates
(
linker_name
):
x
=
tensor
.
lscalar
(
'input'
)
y
=
theano
.
shared
(
1
,
name
=
'global'
)
f
=
theano
.
function
([
x
],
[
x
,
x
+
34
],
updates
=
[(
y
,
x
+
1
)],
mode
=
Mode
(
optimizer
=
None
,
linker
=
linker_name
))
g
=
theano
.
function
([
x
],
[
x
-
6
],
updates
=
[(
y
,
y
+
3
)],
mode
=
Mode
(
optimizer
=
None
,
linker
=
linker_name
))
assert
f
(
3
,
output_subset
=
[])
==
[]
assert
y
.
get_value
()
==
4
assert
g
(
30
,
output_subset
=
[
0
])
==
[
24
]
assert
g
(
40
,
output_subset
=
[])
==
[]
assert
y
.
get_value
()
==
10
check_updates
(
vm
.
VM_Linker
(
allow_partial_eval
=
True
,
use_cloop
=
False
))
check_updates
(
'cvm'
)
def
test_allow_gc_cvm
():
mode
=
theano
.
config
.
mode
...
...
theano/gof/vm.py
浏览文件 @
81e52783
...
...
@@ -332,7 +332,8 @@ class Stack(VM):
def
__init__
(
self
,
nodes
,
thunks
,
pre_call_clear
,
storage_map
,
compute_map
,
fgraph
,
allow_gc
,
dependencies
=
None
,
callback
=
None
,
callback_input
=
None
):
n_updates
,
dependencies
=
None
,
callback
=
None
,
callback_input
=
None
):
super
(
Stack
,
self
)
.
__init__
(
nodes
,
thunks
,
pre_call_clear
)
self
.
allow_gc
=
allow_gc
...
...
@@ -346,6 +347,7 @@ class Stack(VM):
self
.
node_idx
=
node_idx
=
{}
self
.
callback
=
callback
self
.
callback_input
=
callback_input
self
.
n_updates
=
n_updates
ords
=
fgraph
.
orderings
()
...
...
@@ -417,6 +419,9 @@ class Stack(VM):
# apply_stack contains nodes
if
output_subset
is
not
None
:
first_updated
=
len
(
self
.
outputs
)
-
self
.
n_updates
output_subset
=
output_subset
+
list
(
range
(
first_updated
,
len
(
self
.
outputs
)))
apply_stack
=
\
[
self
.
outputs
[
i
]
.
owner
for
i
in
output_subset
if
self
.
outputs
[
i
]
.
owner
]
...
...
@@ -425,7 +430,7 @@ class Stack(VM):
last_apply_stack_len
=
-
1
# This record all function inputs/shared varibles and constants
# This record all function inputs/shared vari
a
bles and constants
for
var
,
data
in
iteritems
(
self
.
storage_map
):
if
data
[
0
]
is
None
:
continue
...
...
@@ -842,7 +847,7 @@ class VM_Linker(link.LocalLinker):
if
(
self
.
callback
is
not
None
or
self
.
callback_input
is
not
None
or
(
config
.
profile
and
config
.
profile_memory
)
or
self
.
allow_partial_eval
):
(
self
.
allow_partial_eval
and
not
self
.
use_cloop
)
):
if
self
.
use_cloop
and
(
self
.
callback
is
not
None
or
self
.
callback_input
is
not
None
):
...
...
@@ -850,9 +855,9 @@ class VM_Linker(link.LocalLinker):
if
self
.
use_cloop
and
config
.
profile_memory
:
warnings
.
warn
(
'CVM does not support memory profile, using Stack VM.'
)
if
self
.
use_cloop
and
self
.
allow_partial_eval
:
if
not
self
.
use_cloop
and
self
.
allow_partial_eval
:
warnings
.
warn
(
'
CVM does not support partial evaluation yet
, '
'
LoopGC does not support partial evaluation
, '
'using Stack VM.'
)
# Needed for allow_gc=True, profiling and storage_map reuse
deps
=
self
.
compute_gc_dependencies
(
storage_map
)
...
...
@@ -860,6 +865,7 @@ class VM_Linker(link.LocalLinker):
nodes
,
thunks
,
pre_call_clear
,
storage_map
,
compute_map
,
self
.
fgraph
,
self
.
allow_gc
,
len
(
updated_vars
),
dependencies
=
deps
,
callback
=
self
.
callback
,
callback_input
=
self
.
callback_input
)
...
...
@@ -1000,7 +1006,8 @@ class VM_Linker(link.LocalLinker):
nodes
,
thunks
,
pre_call_clear
,
storage_map
,
compute_map
,
self
.
fgraph
,
self
.
allow_gc
,
dependencies
=
deps
len
(
updated_vars
),
dependencies
=
deps
,
)
return
vm
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论