Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
P
pytensor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
testgroup
pytensor
Commits
d8835a5f
提交
d8835a5f
authored
8月 11, 2015
作者:
Iban Harlouchet
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
numpydoc for theano/gof/cc.py
上级
0a7415d7
显示空白字符变更
内嵌
并排
正在显示
1 个修改的文件
包含
255 行增加
和
113 行删除
+255
-113
cc.py
theano/gof/cc.py
+255
-113
没有找到文件。
theano/gof/cc.py
浏览文件 @
d8835a5f
"""
"""
Defines Linkers that deal with C implementations.
Defines Linkers that deal with C implementations.
"""
"""
from
__future__
import
print_function
from
__future__
import
print_function
...
@@ -45,8 +46,13 @@ run_cthunk = None # Will be imported only when needed.
...
@@ -45,8 +46,13 @@ run_cthunk = None # Will be imported only when needed.
def
get_module_cache
(
init_args
=
None
):
def
get_module_cache
(
init_args
=
None
):
"""
"""
:param init_args: If not None, the (k, v) pairs in this dictionary will
be forwarded to the ModuleCache constructor as keyword arguments.
Parameters
----------
init_args
If not None, the (k, v) pairs in this dictionary will be forwarded to
the ModuleCache constructor as keyword arguments.
"""
"""
return
cmodule
.
get_module_cache
(
config
.
compiledir
,
init_args
=
init_args
)
return
cmodule
.
get_module_cache
(
config
.
compiledir
,
init_args
=
init_args
)
...
@@ -63,25 +69,31 @@ def get_persistent_module_cache():
...
@@ -63,25 +69,31 @@ def get_persistent_module_cache():
class
CodeBlock
:
class
CodeBlock
:
"""WRITEME
"""
WRITEME
Represents a computation unit composed of declare, behavior, and cleanup.
Represents a computation unit composed of declare, behavior, and cleanup.
@ivar declare: C code that declares variables for use by the computation
@ivar behavior: C code that performs the computation
The constructor initializes a L{CodeBlock} with templatized declare,
@ivar cleanup: C code that cleans up things allocated or incref-ed
behavior and cleanup. The sub parameter will be used in the other
in behavior
arguments' templates. sub should contain a key called 'id' that maps to an
identifier for this block. The identifier will be used to determine the
failure code and a label to jump to. It should also contain a key called
'failure_var' that contains the name of the variable that contains the error
code.
Parameters
----------
declare
C code that declares variables for use by the computation.
behavior
C code that performs the computation.
cleanup
C code that cleans up things allocated or incref-ed in behavior.
"""
"""
def
__init__
(
self
,
declare
,
behavior
,
cleanup
,
sub
):
def
__init__
(
self
,
declare
,
behavior
,
cleanup
,
sub
):
"""
Initialize a L{CodeBlock} with templatized declare, behavior
and cleanup. The sub parameter will be used in the other
arguments' templates. sub should contain a key called 'id'
that maps to an identifier for this block.
The identifier will be used to determine the failure code and
a label to jump to. It should also contain a key called
'failure_var' that contains the name of the variable that
contains the error code.
"""
self
.
declare
=
declare
self
.
declare
=
declare
self
.
behavior
=
behavior
self
.
behavior
=
behavior
# the dummy is because gcc throws an error when a label's
# the dummy is because gcc throws an error when a label's
...
@@ -94,10 +106,12 @@ class CodeBlock:
...
@@ -94,10 +106,12 @@ class CodeBlock:
def
failure_code
(
sub
):
def
failure_code
(
sub
):
"""Code contained in sub['fail'], usually substituted for
%(fail)
s.
"""
Code contained in sub['fail'], usually substituted for
%(fail)
s.
It sets information about current error, then goto the code
It sets information about current error, then goto the code
actually handling the failure, which is defined in struct_gen().
actually handling the failure, which is defined in struct_gen().
"""
"""
return
'''{
return
'''{
%(failure_var)
s =
%(id)
s;
%(failure_var)
s =
%(id)
s;
...
@@ -110,7 +124,10 @@ def failure_code(sub):
...
@@ -110,7 +124,10 @@ def failure_code(sub):
def
failure_code_init
(
sub
):
def
failure_code_init
(
sub
):
"Code for failure in the struct init."
"""
Code for failure in the struct init.
"""
return
'''{
return
'''{
if (!PyErr_Occurred()) {
if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_RuntimeError,
PyErr_SetString(PyExc_RuntimeError,
...
@@ -122,10 +139,13 @@ def failure_code_init(sub):
...
@@ -122,10 +139,13 @@ def failure_code_init(sub):
def
code_gen
(
blocks
):
def
code_gen
(
blocks
):
"""WRITEME From a list of L{CodeBlock} instances, returns a string
"""
WRITEME
From a list of L{CodeBlock} instances, returns a string
that executes them all in sequence. eg for C{(decl1, task1,
that executes them all in sequence. eg for C{(decl1, task1,
cleanup1)} and C{(decl2, task2, cleanup2)} the returned string
cleanup1)} and C{(decl2, task2, cleanup2)} the returned string
will be of the form:
:
will be of the form:
decl1
decl1
decl2
decl2
...
@@ -137,8 +157,8 @@ def code_gen(blocks):
...
@@ -137,8 +157,8 @@ def code_gen(blocks):
}
}
cleanup1
cleanup1
}
}
"""
"""
decl
=
""
decl
=
""
head
=
""
head
=
""
tail
=
""
tail
=
""
...
@@ -150,27 +170,39 @@ def code_gen(blocks):
...
@@ -150,27 +170,39 @@ def code_gen(blocks):
def
struct_gen
(
args
,
struct_builders
,
blocks
,
sub
):
def
struct_gen
(
args
,
struct_builders
,
blocks
,
sub
):
"""WRITEME
"""
WRITEME
Generates a struct conforming to the following specifications:
Generates a struct conforming to the following specifications:
* args -> all of the PyObject* type, stored in the struct
Parameters
----------
args
All of the PyObject* type, stored in the struct
they represent the storage and must be length 1 python lists.
they represent the storage and must be length 1 python lists.
* struct_builders -> list of L{CodeBlock} instances such that
struct_builders
List of L{CodeBlock} instances such that
* declarations are in the struct
* declarations are in the struct
* behavior is in the constructor
* behavior is in the constructor
* cleanup is in the destructor
* cleanup is in the destructor
* blocks -> list of CodeBlock instances such that
blocks
List of CodeBlock instances such that
* declarations, behavior and cleanup are in the run()
* declarations, behavior and cleanup are in the run()
method of the struct
method of the struct
* sub -> dictionary used to template the struct.
sub
Dictionary used to template the struct.
* failure_var -> must contain a variable name to use for
* failure_var -> must contain a variable name to use for
the failure code.
the failure code.
Returns
-------
object
In a nutshell, this returns code for a struct that represents
In a nutshell, this returns code for a struct that represents
a function with state. The state's initialization and destruction
a function with state. The state's initialization and destruction
are handled by struct_builders and the actual behavior of the
are handled by struct_builders and the actual behavior of the
function is handled by blocks.
function is handled by blocks.
"""
"""
struct_decl
=
""
struct_decl
=
""
struct_init_head
=
""
struct_init_head
=
""
struct_init_tail
=
""
struct_init_tail
=
""
...
@@ -276,12 +308,18 @@ def struct_gen(args, struct_builders, blocks, sub):
...
@@ -276,12 +308,18 @@ def struct_gen(args, struct_builders, blocks, sub):
# with handling of the py_<name> variable.
# with handling of the py_<name> variable.
def
get_nothing
(
r
,
name
,
sub
):
def
get_nothing
(
r
,
name
,
sub
):
"""WRITEME"""
"""
WRITEME
"""
return
""
return
""
def
get_c_declare
(
r
,
name
,
sub
):
def
get_c_declare
(
r
,
name
,
sub
):
"""Wrapper around c_declare that declares py_name"""
"""
Wrapper around c_declare that declares py_name.
"""
# The declaration will be used by the Apply node that
# The declaration will be used by the Apply node that
# is computing it (`r.owner`), and by each of the clients.
# is computing it (`r.owner`), and by each of the clients.
# If some of these have `check_input=True` in their `.op`,
# If some of these have `check_input=True` in their `.op`,
...
@@ -302,7 +340,10 @@ def get_c_declare(r, name, sub):
...
@@ -302,7 +340,10 @@ def get_c_declare(r, name, sub):
def
get_c_init
(
r
,
name
,
sub
):
def
get_c_init
(
r
,
name
,
sub
):
"""Wrapper around c_init that initializes py_name to Py_None"""
"""
Wrapper around c_init that initializes py_name to Py_None.
"""
pre
=
""
"""
pre
=
""
"""
py_
%(name)
s = Py_None;
py_
%(name)
s = Py_None;
{Py_XINCREF(py_
%(name)
s);}
{Py_XINCREF(py_
%(name)
s);}
...
@@ -311,7 +352,10 @@ def get_c_init(r, name, sub):
...
@@ -311,7 +352,10 @@ def get_c_init(r, name, sub):
def
get_c_extract
(
r
,
name
,
sub
):
def
get_c_extract
(
r
,
name
,
sub
):
"""Wrapper around c_extract that initializes py_name from storage."""
"""
Wrapper around c_extract that initializes py_name from storage.
"""
# `c_extract` is called when getting the value of an apply node's
# `c_extract` is called when getting the value of an apply node's
# input from the compute map, before being used by its clients.
# input from the compute map, before being used by its clients.
# If one of the clients has `check_input=True`, we need to perform
# If one of the clients has `check_input=True`, we need to perform
...
@@ -346,7 +390,10 @@ def get_c_extract(r, name, sub):
...
@@ -346,7 +390,10 @@ def get_c_extract(r, name, sub):
def
get_c_extract_out
(
r
,
name
,
sub
):
def
get_c_extract_out
(
r
,
name
,
sub
):
"""Wrapper around c_extract_out that initializes py_name from storage."""
"""
Wrapper around c_extract_out that initializes py_name from storage.
"""
# `c_extract_out` is used to extract an output variable from
# `c_extract_out` is used to extract an output variable from
# the compute map, to be used as pre-allocated memory for `r`
# the compute map, to be used as pre-allocated memory for `r`
# before its value gets computed.
# before its value gets computed.
...
@@ -376,7 +423,10 @@ def get_c_extract_out(r, name, sub):
...
@@ -376,7 +423,10 @@ def get_c_extract_out(r, name, sub):
def
get_c_cleanup
(
r
,
name
,
sub
):
def
get_c_cleanup
(
r
,
name
,
sub
):
"""Wrapper around c_cleanup that decrefs py_name"""
"""
Wrapper around c_cleanup that decrefs py_name.
"""
post
=
"""
post
=
"""
{Py_XDECREF(py_
%(name)
s);}
{Py_XDECREF(py_
%(name)
s);}
"""
%
locals
()
"""
%
locals
()
...
@@ -384,7 +434,10 @@ def get_c_cleanup(r, name, sub):
...
@@ -384,7 +434,10 @@ def get_c_cleanup(r, name, sub):
def
get_c_sync
(
r
,
name
,
sub
):
def
get_c_sync
(
r
,
name
,
sub
):
"""Wrapper around c_sync that syncs py_name with storage."""
"""
Wrapper around c_sync that syncs py_name with storage.
"""
return
"""
return
"""
if (!
%(failure_var)
s) {
if (!
%(failure_var)
s) {
%(sync)
s
%(sync)
s
...
@@ -397,11 +450,21 @@ def get_c_sync(r, name, sub):
...
@@ -397,11 +450,21 @@ def get_c_sync(r, name, sub):
def
apply_policy
(
policy
,
r
,
name
,
sub
):
def
apply_policy
(
policy
,
r
,
name
,
sub
):
"""WRITEME
"""
@param policy: list of functions that map a L{Variable} to a string,
WRITEME
or a single such function
@type r: L{Variable}
Parameters
@return: C{policy[0](r) + policy[1](r) + ...}
----------
policy
List of functions that map a L{Variable} to a string,
or a single such function.
r: L{Variable}
Returns
-------
object
C{policy[0](r) + policy[1](r) + ...}.
"""
"""
if
isinstance
(
policy
,
(
list
,
tuple
)):
if
isinstance
(
policy
,
(
list
,
tuple
)):
ret
=
""
ret
=
""
...
@@ -412,22 +475,27 @@ def apply_policy(policy, r, name, sub):
...
@@ -412,22 +475,27 @@ def apply_policy(policy, r, name, sub):
def
struct_variable_codeblocks
(
variable
,
policies
,
id
,
symbol_table
,
sub
):
def
struct_variable_codeblocks
(
variable
,
policies
,
id
,
symbol_table
,
sub
):
"""WRITEME
"""
variable -> a Variable
WRITEME
policies -> a pair of tuples ((declare_policy, behavior_policy,
cleanup_policy), -- at construction
Parameters
(declare_policy, behavior_policy,
----------
cleanup_policy)) -- at execution
variable : a Variable
the first list will produce an element of the
policies : a pair of tuples
'struct_builders' argument in struct_gen the second
(declare_policy, behavior_policy, cleanup_policy) -- at construction.
list will produce an element of the 'blocks' argument
(declare_policy, behavior_policy, cleanup_policy)) -- at execution.
in struct_gen
The first list will produce an element of the 'struct_builders' argument
in struct_gen. The second list will produce an element of the 'blocks'
id -> the id assigned to this variable's task in the computation
argument in struct_gen.
symbol_table -> a dict that maps variables to variable names. It
id
is not read by this function but a variable name for the
The id assigned to this variable's task in the computation.
variable is computed and added to the table.
symbol_table
sub -> dictionary for use by L{CodeBlock}.
A dict that maps variables to variable names. It is not read by this
function but a variable name for the variable is computed and added to
the table.
sub
Dictionary for use by L{CodeBlock}.
"""
"""
name
=
"V
%
i"
%
id
name
=
"V
%
i"
%
id
...
@@ -453,7 +521,8 @@ def struct_variable_codeblocks(variable, policies, id, symbol_table, sub):
...
@@ -453,7 +521,8 @@ def struct_variable_codeblocks(variable, policies, id, symbol_table, sub):
class
CLinker
(
link
.
Linker
):
class
CLinker
(
link
.
Linker
):
"""WRITEME
"""
WRITEME
Creates C code for an fgraph, compiles it and returns callables
Creates C code for an fgraph, compiles it and returns callables
through make_thunk and make_function that make use of the compiled
through make_thunk and make_function that make use of the compiled
...
@@ -462,6 +531,7 @@ class CLinker(link.Linker):
...
@@ -462,6 +531,7 @@ class CLinker(link.Linker):
no_recycling can contain a list of Variables that belong to the fgraph.
no_recycling can contain a list of Variables that belong to the fgraph.
If a Variable is in no_recycling, CLinker will clear the output storage
If a Variable is in no_recycling, CLinker will clear the output storage
associated to it during the computation (to avoid reusing it).
associated to it during the computation (to avoid reusing it).
"""
"""
def
__init__
(
self
,
schedule
=
None
):
def
__init__
(
self
,
schedule
=
None
):
...
@@ -470,7 +540,10 @@ class CLinker(link.Linker):
...
@@ -470,7 +540,10 @@ class CLinker(link.Linker):
self
.
schedule
=
schedule
self
.
schedule
=
schedule
def
accept
(
self
,
fgraph
,
no_recycling
=
None
):
def
accept
(
self
,
fgraph
,
no_recycling
=
None
):
"""WRITEME"""
"""
WRITEME
"""
if
no_recycling
is
None
:
if
no_recycling
is
None
:
no_recycling
=
[]
no_recycling
=
[]
if
self
.
fgraph
is
not
None
and
self
.
fgraph
is
not
fgraph
:
if
self
.
fgraph
is
not
None
and
self
.
fgraph
is
not
fgraph
:
...
@@ -483,9 +556,12 @@ class CLinker(link.Linker):
...
@@ -483,9 +556,12 @@ class CLinker(link.Linker):
return
self
return
self
def
fetch_variables
(
self
):
def
fetch_variables
(
self
):
"""WRITEME
"""
Fills the inputs, outputs, variables, orphans,
WRITEME
temps and node_order fields.
Fills the inputs, outputs, variables, orphans, temps and node_order
fields.
"""
"""
fgraph
=
self
.
fgraph
fgraph
=
self
.
fgraph
self
.
inputs
=
fgraph
.
inputs
self
.
inputs
=
fgraph
.
inputs
...
@@ -527,7 +603,9 @@ class CLinker(link.Linker):
...
@@ -527,7 +603,9 @@ class CLinker(link.Linker):
self
.
consts
=
[]
self
.
consts
=
[]
def
code_gen
(
self
):
def
code_gen
(
self
):
"""WRITEME
"""
WRITEME
Generates code for a struct that does the computation of the fgraph and
Generates code for a struct that does the computation of the fgraph and
stores it in the struct_code field of the instance.
stores it in the struct_code field of the instance.
...
@@ -538,6 +616,7 @@ class CLinker(link.Linker):
...
@@ -538,6 +616,7 @@ class CLinker(link.Linker):
is avoided.
is avoided.
This method caches its computations.
This method caches its computations.
"""
"""
if
getattr
(
self
,
'struct_code'
,
False
):
if
getattr
(
self
,
'struct_code'
,
False
):
...
@@ -804,12 +883,15 @@ class CLinker(link.Linker):
...
@@ -804,12 +883,15 @@ class CLinker(link.Linker):
return
self
.
struct_code
return
self
.
struct_code
def
support_code
(
self
):
def
support_code
(
self
):
"""WRITEME
"""
WRITEME
Returns a list of support code strings that are needed by
Returns a list of support code strings that are needed by
one or more Variables or Ops. The support code from Variables is
one or more Variables or Ops. The support code from Variables is
added before the support code from Ops.
added before the support code from Ops.
This might contain duplicates.
This might contain duplicates.
"""
"""
ret
=
[]
ret
=
[]
# generic support code
# generic support code
...
@@ -822,11 +904,14 @@ class CLinker(link.Linker):
...
@@ -822,11 +904,14 @@ class CLinker(link.Linker):
return
ret
return
ret
def
compile_args
(
self
):
def
compile_args
(
self
):
"""WRITEME
"""
WRITEME
Returns a list of compile args that are needed by one
Returns a list of compile args that are needed by one
or more Variables or Ops.
or more Variables or Ops.
This might contain duplicates.
This might contain duplicates.
"""
"""
ret
=
[
"-O3"
]
ret
=
[
"-O3"
]
# this is the param the -ffast-math activate. I put the explicitly as
# this is the param the -ffast-math activate. I put the explicitly as
...
@@ -871,11 +956,14 @@ class CLinker(link.Linker):
...
@@ -871,11 +956,14 @@ class CLinker(link.Linker):
return
ret
return
ret
def
headers
(
self
):
def
headers
(
self
):
"""WRITEME
"""
WRITEME
Returns a list of headers that are needed by one
Returns a list of headers that are needed by one
or more Types or Ops.
or more Types or Ops.
The return value will not contain duplicates.
The return value will not contain duplicates.
"""
"""
ret
=
[]
ret
=
[]
for
x
in
[
y
.
type
for
y
in
self
.
variables
]
+
[
for
x
in
[
y
.
type
for
y
in
self
.
variables
]
+
[
...
@@ -890,7 +978,9 @@ class CLinker(link.Linker):
...
@@ -890,7 +978,9 @@ class CLinker(link.Linker):
"""
"""
Return a list of code snippets that have to be inserted
Return a list of code snippets that have to be inserted
in the module initialization code.
in the module initialization code.
The return value will not contain duplicates.
The return value will not contain duplicates.
"""
"""
ret
=
[]
ret
=
[]
for
x
in
[
y
.
type
for
y
in
self
.
variables
]
+
[
for
x
in
[
y
.
type
for
y
in
self
.
variables
]
+
[
...
@@ -923,11 +1013,14 @@ class CLinker(link.Linker):
...
@@ -923,11 +1013,14 @@ class CLinker(link.Linker):
return
c_compiler
return
c_compiler
def
header_dirs
(
self
):
def
header_dirs
(
self
):
"""WRITEME
"""
WRITEME
Returns a list of lib directories that are needed by one
Returns a list of lib directories that are needed by one
or more Types or Ops.
or more Types or Ops.
The return value will not contain duplicates.
The return value will not contain duplicates.
"""
"""
ret
=
[]
ret
=
[]
for
x
in
[
y
.
type
for
y
in
self
.
variables
]
+
[
for
x
in
[
y
.
type
for
y
in
self
.
variables
]
+
[
...
@@ -939,11 +1032,14 @@ class CLinker(link.Linker):
...
@@ -939,11 +1032,14 @@ class CLinker(link.Linker):
return
utils
.
uniq
(
ret
)
return
utils
.
uniq
(
ret
)
def
libraries
(
self
):
def
libraries
(
self
):
"""WRITEME
"""
WRITEME
Returns a list of libraries that are needed by one
Returns a list of libraries that are needed by one
or more Types or Ops.
or more Types or Ops.
The return value will not contain duplicates.
The return value will not contain duplicates.
"""
"""
ret
=
[]
ret
=
[]
for
x
in
[
y
.
type
for
y
in
self
.
variables
]
+
[
for
x
in
[
y
.
type
for
y
in
self
.
variables
]
+
[
...
@@ -955,11 +1051,14 @@ class CLinker(link.Linker):
...
@@ -955,11 +1051,14 @@ class CLinker(link.Linker):
return
utils
.
uniq
(
ret
)
return
utils
.
uniq
(
ret
)
def
lib_dirs
(
self
):
def
lib_dirs
(
self
):
"""WRITEME
"""
WRITEME
Returns a list of lib directories that are needed by one
Returns a list of lib directories that are needed by one
or more Types or Ops.
or more Types or Ops.
The return value will not contain duplicates.
The return value will not contain duplicates.
"""
"""
ret
=
[]
ret
=
[]
for
x
in
[
y
.
type
for
y
in
self
.
variables
]
+
[
for
x
in
[
y
.
type
for
y
in
self
.
variables
]
+
[
...
@@ -972,18 +1071,26 @@ class CLinker(link.Linker):
...
@@ -972,18 +1071,26 @@ class CLinker(link.Linker):
def
__compile__
(
self
,
input_storage
=
None
,
def
__compile__
(
self
,
input_storage
=
None
,
output_storage
=
None
,
keep_lock
=
False
):
output_storage
=
None
,
keep_lock
=
False
):
"""WRITEME
"""
WRITEME
Compiles this linker's fgraph.
Compiles this linker's fgraph.
@type input_storage: list or None
Parameters
@param input_storage: list of lists of length 1. In order to use
----------
the thunk returned by __compile__, the inputs must be put in
input_storage: list or None
that storage. If None, storage will be allocated.
List of lists of length 1. In order to use the thunk returned
@param output_storage: list of lists of length 1. The thunk returned
by __compile__, the inputs must be put in that storage.
by __compile__ will put the variables of the computation in these
If None, storage will be allocated.
lists. If None, storage will be allocated.
output_storage: list of lists of length 1
The thunk returned by __compile__ will put the variables of the
computation in these lists. If None, storage will be allocated.
Returns
-------
object
Thunk, input_storage, output_storage, error_storage.
Returns: thunk, input_storage, output_storage, error_storage
"""
"""
error_storage
=
[
None
,
None
,
None
]
error_storage
=
[
None
,
None
,
None
]
if
input_storage
is
None
:
if
input_storage
is
None
:
...
@@ -1037,27 +1144,34 @@ class CLinker(link.Linker):
...
@@ -1037,27 +1144,34 @@ class CLinker(link.Linker):
def
make_thunk
(
self
,
input_storage
=
None
,
output_storage
=
None
,
def
make_thunk
(
self
,
input_storage
=
None
,
output_storage
=
None
,
keep_lock
=
False
):
keep_lock
=
False
):
"""WRITEME
"""
WRITEME
Compiles this linker's fgraph and returns a function to perform the
Compiles this linker's fgraph and returns a function to perform the
computations, as well as lists of storage cells for both the
computations, as well as lists of storage cells for both the
inputs
inputs
and outputs.
and outputs.
@type input_storage: list or None
Parameters
@param input_storage: list of lists of length 1. In order to use
----------
input_storage: list or None
List of lists of length 1. In order to use
the thunk returned by __compile__, the inputs must be put in
the thunk returned by __compile__, the inputs must be put in
that storage. If None, storage will be allocated.
that storage. If None, storage will be allocated.
@param output_storage: list of lists of length 1. The thunk returned
output_storage: list of lists of length 1
by __compile__ will put the variables of the computation in these
The thunk returned by __compile__ will put the variables of the
lists. If None, storage will be allocated.
computation in these lists. If None, storage will be allocated.
Returns: thunk, input_storage, output_storage
Returns
-------
object
Thunk, input_storage, output_storage.
The return values can be used as follows:
The return values can be used as follows:
f, istor, ostor = clinker.make_thunk()
f, istor, ostor = clinker.make_thunk()
istor[0].data = first_input
istor[0].data = first_input
istor[1].data = second_input
istor[1].data = second_input
f()
f()
first_output = ostor[0].data
first_output = ostor[0].data
"""
"""
init_tasks
,
tasks
=
self
.
get_init_tasks
()
init_tasks
,
tasks
=
self
.
get_init_tasks
()
cthunk
,
in_storage
,
out_storage
,
error_storage
=
self
.
__compile__
(
cthunk
,
in_storage
,
out_storage
,
error_storage
=
self
.
__compile__
(
...
@@ -1069,7 +1183,8 @@ class CLinker(link.Linker):
...
@@ -1069,7 +1183,8 @@ class CLinker(link.Linker):
return
res
,
in_storage
,
out_storage
return
res
,
in_storage
,
out_storage
def
cmodule_key
(
self
):
def
cmodule_key
(
self
):
"""Return a complete hashable signature of the module we compiled.
"""
Return a complete hashable signature of the module we compiled.
This function must have the property that no two programs that
This function must have the property that no two programs that
compute different things yield the same key.
compute different things yield the same key.
...
@@ -1090,8 +1205,8 @@ class CLinker(link.Linker):
...
@@ -1090,8 +1205,8 @@ class CLinker(link.Linker):
The outer tuple has a brief header, containing the compilation options
The outer tuple has a brief header, containing the compilation options
passed to the compiler, the libraries to link against, an md5 hash
passed to the compiler, the libraries to link against, an md5 hash
of theano.config (for all config options where "in_c_key" is True).
of theano.config (for all config options where "in_c_key" is True).
It is followed by elements for every node in the
It is followed by elements for every node in the
topological ordering
topological ordering
of `self.fgraph`.
of `self.fgraph`.
If the Op of any Apply in the FunctionGraph does not have
If the Op of any Apply in the FunctionGraph does not have
c_code_cache_ok()==True, then this function raises a KeyError
c_code_cache_ok()==True, then this function raises a KeyError
...
@@ -1116,7 +1231,6 @@ class CLinker(link.Linker):
...
@@ -1116,7 +1231,6 @@ class CLinker(link.Linker):
If a variable is also a graph output, then its position in the
If a variable is also a graph output, then its position in the
outputs list is also bundled with this tuple (after the b).
outputs list is also bundled with this tuple (after the b).
The nature of a Constant instance is defined as its signature,
The nature of a Constant instance is defined as its signature,
together with two integers: the topological position of the
together with two integers: the topological position of the
first Apply using that Constant instance, and the lowest index
first Apply using that Constant instance, and the lowest index
...
@@ -1141,6 +1255,7 @@ class CLinker(link.Linker):
...
@@ -1141,6 +1255,7 @@ class CLinker(link.Linker):
booleans, indicating whether each output is in the
booleans, indicating whether each output is in the
no_recycling set. Older versions of compiled modules only have the
no_recycling set. Older versions of compiled modules only have the
no_recycle list.
no_recycle list.
"""
"""
return
self
.
cmodule_key_
(
self
.
fgraph
,
self
.
no_recycling
,
return
self
.
cmodule_key_
(
self
.
fgraph
,
self
.
no_recycling
,
compile_args
=
self
.
compile_args
(),
compile_args
=
self
.
compile_args
(),
...
@@ -1154,7 +1269,8 @@ class CLinker(link.Linker):
...
@@ -1154,7 +1269,8 @@ class CLinker(link.Linker):
c_compiler
=
None
):
c_compiler
=
None
):
"""
"""
Do the actual computation of cmodule_key in a static method
Do the actual computation of cmodule_key in a static method
to allow it to be reused in scalar.Composite.__eq__
to allow it to be reused in scalar.Composite.__eq__.
"""
"""
if
compile_args
is
None
:
if
compile_args
is
None
:
compile_args
=
[]
compile_args
=
[]
...
@@ -1311,6 +1427,7 @@ class CLinker(link.Linker):
...
@@ -1311,6 +1427,7 @@ class CLinker(link.Linker):
"""
"""
This compiles the source code for this linker and returns a
This compiles the source code for this linker and returns a
loaded module.
loaded module.
"""
"""
if
location
is
None
:
if
location
is
None
:
location
=
cmodule
.
dlimport_workdir
(
config
.
compiledir
)
location
=
cmodule
.
dlimport_workdir
(
config
.
compiledir
)
...
@@ -1353,11 +1470,12 @@ class CLinker(link.Linker):
...
@@ -1353,11 +1470,12 @@ class CLinker(link.Linker):
return
module
return
module
def
get_dynamic_module
(
self
):
def
get_dynamic_module
(
self
):
"""
Return a cmodule.DynamicModule instance full of the code
"""
for our fgraph.
Return a cmodule.DynamicModule instance full of the code
for our fgraph.
This method is cached on the first call so it can be called
This method is cached on the first call so it can be called
multiple times without penalty.
multiple times without penalty.
"""
"""
if
not
hasattr
(
self
,
'_mod'
):
if
not
hasattr
(
self
,
'_mod'
):
self
.
code_gen
()
self
.
code_gen
()
...
@@ -1412,16 +1530,24 @@ class CLinker(link.Linker):
...
@@ -1412,16 +1530,24 @@ class CLinker(link.Linker):
def
cthunk_factory
(
self
,
error_storage
,
in_storage
,
out_storage
,
def
cthunk_factory
(
self
,
error_storage
,
in_storage
,
out_storage
,
keep_lock
=
False
):
keep_lock
=
False
):
"""WRITEME
"""
error_storage -> list of length 3
WRITEME
in_storage -> list of lists of length 1, one per input
out_storage -> list of lists of length 1, one per output
Returns a thunk that points to an instance of a C struct that
Parameters
----------
error_storage : list of length 3
in_storage : list of lists of length 1, one per input
out_storage : list of lists of length 1, one per output
Returns
-------
object
A thunk that points to an instance of a C struct that
can carry on the computation of this linker's fgraph. That thunk,
can carry on the computation of this linker's fgraph. That thunk,
when executed, will fetch its inputs from in_storage, put its
when executed, will fetch its inputs from in_storage, put its
outputs in out_storage and if an error occurs will put the
outputs in out_storage and if an error occurs will put the
type, value and traceback of the exception in error_storage.
type, value and traceback of the exception in error_storage.
"""
"""
try
:
try
:
key
=
self
.
cmodule_key
()
key
=
self
.
cmodule_key
()
...
@@ -1481,18 +1607,22 @@ class CLinker(link.Linker):
...
@@ -1481,18 +1607,22 @@ class CLinker(link.Linker):
class
_CThunk
(
object
):
class
_CThunk
(
object
):
"""
"""
A thunk with a C implementation
A thunk with a C implementation.
"""
def
__init__
(
self
,
cthunk
,
init_tasks
,
tasks
,
error_storage
):
"""
Parameters
Parameters
----------
----------
cthunk: the CObject pointer used by run_cthunk
cthunk
init_tasks: WRITEME
The CObject pointer used by run_cthunk.
tasks: WRITEME
init_tasks
error_storage: WRITEME
WRITEME
tasks
WRITEME
error_storage
WRITEME
"""
"""
def
__init__
(
self
,
cthunk
,
init_tasks
,
tasks
,
error_storage
):
global
run_cthunk
global
run_cthunk
if
run_cthunk
is
None
:
if
run_cthunk
is
None
:
# Lazy import to avoid compilation when importing theano.
# Lazy import to avoid compilation when importing theano.
...
@@ -1505,6 +1635,7 @@ class _CThunk(object):
...
@@ -1505,6 +1635,7 @@ class _CThunk(object):
def
find_task
(
self
,
failure_code
):
def
find_task
(
self
,
failure_code
):
"""
"""
Maps a failure code to the task that is associated to it.
Maps a failure code to the task that is associated to it.
"""
"""
failure_code
-=
1
failure_code
-=
1
n
=
len
(
self
.
init_tasks
)
n
=
len
(
self
.
init_tasks
)
...
@@ -1540,7 +1671,9 @@ class _CThunk(object):
...
@@ -1540,7 +1671,9 @@ class _CThunk(object):
class
OpWiseCLinker
(
link
.
LocalLinker
):
class
OpWiseCLinker
(
link
.
LocalLinker
):
"""WRITEME
"""
WRITEME
Uses CLinker on the individual Ops that comprise an fgraph and loops
Uses CLinker on the individual Ops that comprise an fgraph and loops
over them in Python. The variable is slower than a compiled version of
over them in Python. The variable is slower than a compiled version of
the whole fgraph, but saves on compilation time because small changes
the whole fgraph, but saves on compilation time because small changes
...
@@ -1554,10 +1687,12 @@ class OpWiseCLinker(link.LocalLinker):
...
@@ -1554,10 +1687,12 @@ class OpWiseCLinker(link.LocalLinker):
If a Variable is in no_recycling, CLinker will clear the output storage
If a Variable is in no_recycling, CLinker will clear the output storage
associated to it prior to computation (to avoid reusing it).
associated to it prior to computation (to avoid reusing it).
:note: This is in a sense the 'default' linker for Theano. The
Notes
-----
This is in a sense the 'default' linker for Theano. The
overhead of using the OpWiseCLinker as compared with the CLinker
overhead of using the OpWiseCLinker as compared with the CLinker
is only noticeable for graphs of very small tensors (such as 20
is only noticeable for graphs of very small tensors (such as 20
elements or less)
elements or less)
.
"""
"""
...
@@ -1676,9 +1811,12 @@ class OpWiseCLinker(link.LocalLinker):
...
@@ -1676,9 +1811,12 @@ class OpWiseCLinker(link.LocalLinker):
def
_default_checker
(
x
,
y
):
def
_default_checker
(
x
,
y
):
"""WRITEME
"""
WRITEME
Default checker for DualLinker. This checks that the
Default checker for DualLinker. This checks that the
variables contain the same data using ==.
variables contain the same data using ==.
"""
"""
if
x
[
0
]
!=
y
[
0
]:
if
x
[
0
]
!=
y
[
0
]:
raise
Exception
(
"Output mismatch."
,
raise
Exception
(
"Output mismatch."
,
...
@@ -1686,7 +1824,9 @@ def _default_checker(x, y):
...
@@ -1686,7 +1824,9 @@ def _default_checker(x, y):
class
DualLinker
(
link
.
Linker
):
class
DualLinker
(
link
.
Linker
):
"""WRITEME
"""
WRITEME
Runs the fgraph in parallel using PerformLinker and CLinker.
Runs the fgraph in parallel using PerformLinker and CLinker.
The thunk/function produced by DualLinker uses PerformLinker as the
The thunk/function produced by DualLinker uses PerformLinker as the
...
@@ -1695,6 +1835,7 @@ class DualLinker(link.Linker):
...
@@ -1695,6 +1835,7 @@ class DualLinker(link.Linker):
the fgraph on which it runs OpWiseCLinker. At each step, the variables
the fgraph on which it runs OpWiseCLinker. At each step, the variables
of perform and of the C implementation are verified using a checker
of perform and of the C implementation are verified using a checker
function.
function.
"""
"""
def
__init__
(
self
,
checker
=
_default_checker
,
schedule
=
None
):
def
__init__
(
self
,
checker
=
_default_checker
,
schedule
=
None
):
...
@@ -1719,6 +1860,7 @@ class DualLinker(link.Linker):
...
@@ -1719,6 +1860,7 @@ class DualLinker(link.Linker):
no_recycling can contain a list of Variables that belong to the fgraph.
no_recycling can contain a list of Variables that belong to the fgraph.
If a Variable is in no_recycling, CLinker will clear the output storage
If a Variable is in no_recycling, CLinker will clear the output storage
associated to it during the computation (to avoid reusing it).
associated to it during the computation (to avoid reusing it).
"""
"""
self
.
fgraph
=
None
self
.
fgraph
=
None
self
.
checker
=
checker
self
.
checker
=
checker
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论