Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
P
pytensor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
testgroup
pytensor
Commits
c23da129
提交
c23da129
authored
3月 20, 2008
作者:
Olivier Breuleux
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
added documentation for almost everything
上级
9bc72d95
隐藏空白字符变更
内嵌
并排
正在显示
5 个修改的文件
包含
115 行增加
和
173 行删除
+115
-173
features.py
gof/features.py
+1
-1
link.py
gof/link.py
+66
-135
modes.py
gof/modes.py
+7
-1
op.py
gof/op.py
+16
-18
result.py
gof/result.py
+25
-18
没有找到文件。
gof/features.py
浏览文件 @
c23da129
...
@@ -103,7 +103,7 @@ class Tool(Feature):
...
@@ -103,7 +103,7 @@ class Tool(Feature):
def
uniq_features
(
_features
,
*
_rest
):
def
uniq_features
(
_features
,
*
_rest
):
"""Return a list such that no element is a subclass of another"""
"""Return a list such that no element is a subclass of another"""
# used in Env.__init__
to
# used in Env.__init__
features
=
[
x
for
x
in
_features
]
features
=
[
x
for
x
in
_features
]
for
other
in
_rest
:
for
other
in
_rest
:
features
+=
[
x
for
x
in
other
]
features
+=
[
x
for
x
in
other
]
...
...
gof/link.py
浏览文件 @
c23da129
# from features import Tool
from
utils
import
AbstractFunctionError
from
utils
import
AbstractFunctionError
import
utils
import
utils
...
@@ -10,8 +8,16 @@ import traceback
...
@@ -10,8 +8,16 @@ import traceback
__excepthook
=
sys
.
excepthook
__excepthook
=
sys
.
excepthook
def
thunk_hook
(
type
,
value
,
trace
):
def
thunk_hook
(
type
,
value
,
trace
):
"""
This function is meant to replace excepthook and do some
special work if the exception value has a __thunk_trace__
field. In that case, it retrieves the field, which should
contain a trace as returned by traceback.extract_stack,
and prints it out on stderr.
The normal excepthook is then called.
"""
if
hasattr
(
value
,
'__thunk_trace__'
):
if
hasattr
(
value
,
'__thunk_trace__'
):
# such a hack :(
trace2
=
value
.
__thunk_trace__
trace2
=
value
.
__thunk_trace__
if
trace2
is
None
:
if
trace2
is
None
:
print
>>
sys
.
stderr
,
"Could not find where this Op was defined."
print
>>
sys
.
stderr
,
"Could not find where this Op was defined."
...
@@ -24,22 +30,6 @@ def thunk_hook(type, value, trace):
...
@@ -24,22 +30,6 @@ def thunk_hook(type, value, trace):
__excepthook
(
type
,
value
,
trace
)
__excepthook
(
type
,
value
,
trace
)
sys
.
excepthook
=
thunk_hook
sys
.
excepthook
=
thunk_hook
# __excepthook = sys.excepthook
# def thunk_hook(type, value, trace):
# if len(value.args) > 0 and hasattr(value[0], '__thunk_trace__'):
# # such a hack :(
# trace2 = value[0].__thunk_trace__ #.exc_info
# if trace2 is None:
# print>>sys.stderr, "Could not find where this Op was defined."
# print>>sys.stderr, " * You might have instantiated this Op directly instead of using a constructor."
# print>>sys.stderr, " * The Op you constructed might have been optimized. Try turning off optimizations."
# elif trace2:
# print>>sys.stderr, "Definition in: "
# for line in traceback.format_list(trace2):
# print>>sys.stderr, line,
# __excepthook(type, value, trace)
# sys.excepthook = thunk_hook
class
Linker
:
class
Linker
:
...
@@ -108,6 +98,10 @@ class Linker:
...
@@ -108,6 +98,10 @@ class Linker:
class
PerformLinker
(
Linker
):
class
PerformLinker
(
Linker
):
"""
Basic Linker subclass that calls the perform method on each op in
the env in the order given by env.toposort.
"""
def
make_thunk
(
self
,
inplace
=
False
):
def
make_thunk
(
self
,
inplace
=
False
):
if
inplace
:
if
inplace
:
...
@@ -133,127 +127,64 @@ class PerformLinker(Linker):
...
@@ -133,127 +127,64 @@ class PerformLinker(Linker):
return
f
,
env
.
inputs
,
env
.
outputs
return
f
,
env
.
inputs
,
env
.
outputs
class
ProfilePerformLinker
(
Linker
):
def
compile
(
self
):
order
=
self
.
env
.
toposort
()
thunks
=
[
op
.
perform
for
op
in
order
]
self
.
n_calls
=
0
self
.
n_thunks
=
0
self
.
times
=
[
0.0
for
op
in
self
.
order
]
def
f
():
for
thunk
in
thunks
:
thunk
()
self
.
thunk
=
f
self
.
order
=
order
self
.
thunks
=
thunks
def
slow_call
(
self
):
"""Run the program, timing each thunk."""
for
i
,
thunk
in
enumerate
(
self
.
thunks
):
start_time
=
time
.
time
()
thunk
()
self
.
times
[
i
]
+=
time
.
time
()
-
start_time
self
.
n_thunks
+=
1
self
.
n_calls
+=
1
def
fast_call
(
self
):
"""Run the program, but only time the entire loop."""
start_time
=
time
.
time
()
for
thunk
in
self
.
thunks
:
thunk
()
self
.
n_thunks
+=
len
(
self
.
thunks
)
self
.
n_calls
+=
1
self
.
times
[
0
]
+=
time
.
time
()
-
start_time
__call__
=
slow_call
def
dump
(
self
,
proportion
=
True
):
"""Print statistics accumulated so far."""
total_time
=
sum
(
self
.
times
)
print
self
.
n_calls
,
'calls took'
,
total_time
,
'seconds to evaluate'
,
print
self
.
n_thunks
,
'thunks'
if
0
:
print
'Proportion of CPU per op'
for
op
,
t
in
zip
(
self
.
order
,
self
.
times
):
s_op
=
str
(
op
)
.
split
()[
0
][
1
:]
print
"
%-35
s
%4.5
f"
%
(
s_op
,
t
/
total_time
)
print
'Proportion of CPU per op class'
dct
=
{}
for
op
,
t
in
zip
(
self
.
order
,
self
.
times
):
s_op
=
str
(
op
)
.
split
()[
0
][
1
:]
dct
[
s_op
]
=
dct
.
get
(
s_op
,
0.0
)
+
t
for
t
,
s_op
in
reversed
(
sorted
([(
t
,
op
)
for
op
,
t
in
dct
.
items
()])):
if
proportion
:
print
"
%-35
s
%4.5
f"
%
(
s_op
,
t
/
total_time
)
else
:
print
"
%-35
s
%4.5
f"
%
(
s_op
,
t
)
### PROFILEPERFORMLINKER USES COMPLETELY OUTDATED INTERFACE - FIX ###
# class
Linker(Tool
):
# class
ProfilePerformLinker(Linker
):
# def compile(self):
# def compile(self):
# raise AbstractFunctionError()
# order = self.env.toposort()
# thunks = [op.perform for op in order]
# def run(self):
# self.n_calls = 0
# raise AbstractFunctionError()
# self.n_thunks = 0
# self.times = [0.0 for op in self.order]
# def f():
# for thunk in thunks:
# thunk()
# self.thunk = f
# self.order = order
# self.thunks = thunks
# def slow_call(self):
# """Run the program, timing each thunk."""
# for i, thunk in enumerate(self.thunks):
# start_time = time.time()
# def perform_linker(env, target = None):
# order = env.toposort()
# thunks = [op.perform for op in order]
# def ret():
# for thunk in thunks:
# thunk()
# thunk()
# if not target:
# self.times[i] += time.time() - start_time
# return ret
# self.n_thunks += 1
# else:
# self.n_calls += 1
# raise NotImplementedError("Cannot write thunk representation to a file.")
# def fast_call(self):
# """Run the program, but only time the entire loop."""
# def perform_linker_nochecks(env, target = None):
# start_time = time.time()
# order = env.toposort()
# for thunk in self.thunks:
# thunks = [op._perform for op in order]
# def ret():
# for thunk in thunks:
# thunk()
# thunk()
# if not target:
# self.n_thunks += len(self.thunks)
# return ret
# self.n_calls += 1
# else:
# self.times[0] += time.time() - start_time
# raise NotImplementedError("Cannot write thunk representation to a file.")
# __call__ = slow_call
# def cthunk_linker(env):
# def dump(self, proportion=True):
# order = env.toposort()
# """Print statistics accumulated so far."""
# thunks = []
# total_time = sum(self.times)
# cstreak = []
# print self.n_calls, 'calls took', total_time, 'seconds to evaluate',
# print self.n_thunks, 'thunks'
# def append_cstreak():
# if cstreak:
# if 0:
# thunks.append(cutils.create_cthunk_loop(*cstreak))
# print 'Proportion of CPU per op'
# cstreak = []
# for op, t in zip(self.order, self.times):
# def ret():
# s_op = str(op).split()[0][1:]
# for thunk in thunks:
# print " %-35s %4.5f"% (s_op, t/total_time)
# thunk()
# print 'Proportion of CPU per op class'
# for op in order:
# dct = {}
# if hasattr(op, 'cthunk'):
# for op, t in zip(self.order, self.times):
# cstreak.append(op.cthunk())
# s_op = str(op).split()[0][1:]
# else:
# dct[s_op] = dct.get(s_op, 0.0) + t
# append_cstreak()
# for t, s_op in reversed(sorted([(t,op) for op, t in dct.items()])):
# thunks.append(op.perform)
# if proportion:
# print " %-35s %4.5f"% (s_op, t/total_time)
# if len(thunks) == 1:
# else:
# return thunks[0]
# print " %-35s %4.5f"% (s_op, t)
# else:
# return ret
gof/modes.py
浏览文件 @
c23da129
### CODE CAN BE SIMPLIFIED IF WE ONLY KEEP BUILD MODE ###
import
utils
import
utils
import
traceback
import
traceback
from
op
import
Op
from
op
import
Op
...
@@ -50,7 +52,11 @@ def add_modal_members(cls, *members):
...
@@ -50,7 +52,11 @@ def add_modal_members(cls, *members):
def
attach_trace
(
op
):
def
attach_trace
(
op
):
stack
=
traceback
.
extract_stack
()[:
-
3
]
"""
Extracts the stack trace at the point of construction and
puts it in the op's trace field.
"""
stack
=
traceback
.
extract_stack
()[:
-
3
]
# we discard 3 levels
op
.
trace
=
stack
op
.
trace
=
stack
def
build_mode
(
op
):
def
build_mode
(
op
):
...
...
gof/op.py
浏览文件 @
c23da129
...
@@ -4,7 +4,6 @@ Contains the Op class, which is the base interface for all operations
...
@@ -4,7 +4,6 @@ Contains the Op class, which is the base interface for all operations
compatible with gof's graph manipulation routines.
compatible with gof's graph manipulation routines.
"""
"""
# from result import BrokenLinkError
from
utils
import
ClsInit
,
all_bases
,
all_bases_collect
,
AbstractFunctionError
from
utils
import
ClsInit
,
all_bases
,
all_bases_collect
,
AbstractFunctionError
import
graph
import
graph
...
@@ -25,9 +24,6 @@ class Op(object):
...
@@ -25,9 +24,6 @@ class Op(object):
list of at most one Op, its owner. It is the responsibility of the
list of at most one Op, its owner. It is the responsibility of the
Op to ensure that it owns its outputs and it is encouraged (though
Op to ensure that it owns its outputs and it is encouraged (though
not required) that it creates them.
not required) that it creates them.
After construction, self.inputs and self.outputs should only be
modified through the set_input and set_output methods.
"""
"""
__slots__
=
[
'_inputs'
,
'_outputs'
]
__slots__
=
[
'_inputs'
,
'_outputs'
]
...
@@ -42,13 +38,13 @@ class Op(object):
...
@@ -42,13 +38,13 @@ class Op(object):
raise
AttributeError
(
"Op does not have a default output."
)
raise
AttributeError
(
"Op does not have a default output."
)
out
=
property
(
default_output
,
out
=
property
(
default_output
,
doc
=
"Same as self.outputs[0] if this Op's has_default_output field is True."
)
doc
=
"Same as self.outputs[0] if this Op's has_default_output field is True."
)
def
__init__
(
self
,
*
inputs
):
def
__init__
(
self
,
*
inputs
):
# this might be a bit brainless
raise
AbstractFunctionError
(
"Op is an abstract class. Its constructor does nothing, you must override it."
)
raise
AbstractFunctionError
(
"Op is an abstract class. Its constructor does nothing, you must override it."
)
def
get_input
(
self
,
i
):
def
get_input
(
self
,
i
):
return
self
.
_inputs
[
i
]
return
self
.
_inputs
[
i
]
def
set_input
(
self
,
i
,
new
):
def
set_input
(
self
,
i
,
new
):
...
@@ -121,9 +117,8 @@ class Op(object):
...
@@ -121,9 +117,8 @@ class Op(object):
def
perform
(
self
):
def
perform
(
self
):
"""
"""
(abstract) Performs the computation associated to this Op,
Performs the computation associated to this Op and places the
places the result(s) in the output Results and gives them
result(s) in the output Results.
the Computed status.
"""
"""
raise
AbstractFunctionError
()
raise
AbstractFunctionError
()
...
@@ -142,11 +137,12 @@ class Op(object):
...
@@ -142,11 +137,12 @@ class Op(object):
def
c_validate_update
(
self
):
def
c_validate_update
(
self
):
"""
"""
Returns
C code that checks that the inputs to this function
Returns
templated C code that checks that the inputs to this
can be worked on. If a failure occurs, set an Exceptio
n
function can be worked on. If a failure occurs, set a
n
and insert "
%(fail)
s".
Exception
and insert "
%(fail)
s".
You may use the variable names defined by c_var_names()
You may use the variable names defined by c_var_names() in
the template.
"""
"""
raise
AbstractFunctionError
()
raise
AbstractFunctionError
()
...
@@ -158,11 +154,12 @@ class Op(object):
...
@@ -158,11 +154,12 @@ class Op(object):
def
c_code
(
self
):
def
c_code
(
self
):
"""
"""
Returns
C code that does the computation associated to this
Returns
templated C code that does the computation associated
Op. You may assume that input validation and output allocation
to this Op. You may assume that input validation and output
have already been done.
allocation
have already been done.
You may use the variable names defined by c_var_names()
You may use the variable names defined by c_var_names() in
the templates.
"""
"""
raise
AbstractFunctionError
()
raise
AbstractFunctionError
()
...
@@ -193,7 +190,8 @@ class Op(object):
...
@@ -193,7 +190,8 @@ class Op(object):
def
c_support_code
(
self
):
def
c_support_code
(
self
):
"""
"""
Return utility code for use by this Op.
Return utility code for use by this Op. It may refer to support code
defined for its input Results.
"""
"""
raise
AbstractFunctionError
()
raise
AbstractFunctionError
()
...
...
gof/result.py
浏览文件 @
c23da129
...
@@ -17,6 +17,8 @@ __all__ = ['ResultBase',
...
@@ -17,6 +17,8 @@ __all__ = ['ResultBase',
]
]
### CLEANUP - DO WE REALLY EVEN THE STATE ANYMORE? ###
class
StateError
(
Exception
):
class
StateError
(
Exception
):
"""The state of the Result is a problem"""
"""The state of the Result is a problem"""
...
@@ -46,14 +48,8 @@ class ResultBase(object):
...
@@ -46,14 +48,8 @@ class ResultBase(object):
index - (ro)
index - (ro)
data - (rw) : calls data_filter when setting
data - (rw) : calls data_filter when setting
Methods:
alloc() - create storage in data, suitable for use by C ops.
(calls data_alloc)
Abstract Methods:
Abstract Methods:
data_filter
data_filter
data_alloc
"""
"""
__slots__
=
[
'_role'
,
'_data'
,
'state'
,
'_name'
]
__slots__
=
[
'_role'
,
'_data'
,
'state'
,
'_name'
]
...
@@ -95,7 +91,7 @@ class ResultBase(object):
...
@@ -95,7 +91,7 @@ class ResultBase(object):
return
self
.
_role
[
0
]
return
self
.
_role
[
0
]
owner
=
property
(
__get_owner
,
owner
=
property
(
__get_owner
,
doc
=
"Op of which this Result is an output, or None if role is None"
)
doc
=
"Op of which this Result is an output, or None if role is None"
)
#
#
# index
# index
...
@@ -106,7 +102,7 @@ class ResultBase(object):
...
@@ -106,7 +102,7 @@ class ResultBase(object):
return
self
.
_role
[
1
]
return
self
.
_role
[
1
]
index
=
property
(
__get_index
,
index
=
property
(
__get_index
,
doc
=
"position of self in owner's outputs, or None if role is None"
)
doc
=
"position of self in owner's outputs, or None if role is None"
)
#
#
...
@@ -117,6 +113,9 @@ class ResultBase(object):
...
@@ -117,6 +113,9 @@ class ResultBase(object):
return
self
.
_data
[
0
]
return
self
.
_data
[
0
]
def
__set_data
(
self
,
data
):
def
__set_data
(
self
,
data
):
"""
Filters the data provided and sets the result in the storage.
"""
if
data
is
self
.
_data
[
0
]:
if
data
is
self
.
_data
[
0
]:
return
return
if
data
is
None
:
if
data
is
None
:
...
@@ -134,12 +133,12 @@ class ResultBase(object):
...
@@ -134,12 +133,12 @@ class ResultBase(object):
doc
=
"The storage associated with this result"
)
doc
=
"The storage associated with this result"
)
def
filter
(
self
,
data
):
def
filter
(
self
,
data
):
"""
(abstract) Raise an exception if the data is not of an
"""
acceptable type.
Raise an exception if the data is not of an
acceptable type.
If a subclass overrides this function, __set_data will use
If a subclass overrides this function, __set_data will use
it
it to check that the argument can be used properly. This gives
to check that the argument can be used properly. This gives a
a
subclass the opportunity to ensure that the contents of
subclass the opportunity to ensure that the contents of
self._data remain sensible.
self._data remain sensible.
Returns data or an appropriately wrapped data.
Returns data or an appropriately wrapped data.
...
@@ -152,6 +151,11 @@ class ResultBase(object):
...
@@ -152,6 +151,11 @@ class ResultBase(object):
#
#
def
c_is_simple
(
self
):
def
c_is_simple
(
self
):
"""
A hint to tell the compiler that this type is a builtin C
type or a small struct and that its memory footprint is
negligible.
"""
return
False
return
False
def
c_declare
(
self
):
def
c_declare
(
self
):
...
@@ -167,8 +171,8 @@ class ResultBase(object):
...
@@ -167,8 +171,8 @@ class ResultBase(object):
call this Result. The Python object self.data is in a
call this Result. The Python object self.data is in a
variable called "py_
%(name)
s" and this code must set the
variable called "py_
%(name)
s" and this code must set the
variables declared by c_declare to something representative
variables declared by c_declare to something representative
of py_
%(name)
s. If the data is improper, set an appropriate
error
of py_
%(name)
s. If the data is improper, set an appropriate
message
and insert "
%(fail)
s".
exception
and insert "
%(fail)
s".
"""
"""
raise
AbstractFunctionError
()
raise
AbstractFunctionError
()
...
@@ -177,8 +181,6 @@ class ResultBase(object):
...
@@ -177,8 +181,6 @@ class ResultBase(object):
This returns C code that should deallocate whatever
This returns C code that should deallocate whatever
c_data_extract allocated or decrease the reference counts. Do
c_data_extract allocated or decrease the reference counts. Do
not decrease py_
%(name)
s's reference count.
not decrease py_
%(name)
s's reference count.
Note: EITHER c_cleanup OR c_sync will be called.
"""
"""
raise
AbstractFunctionError
()
raise
AbstractFunctionError
()
...
@@ -188,7 +190,7 @@ class ResultBase(object):
...
@@ -188,7 +190,7 @@ class ResultBase(object):
representing the name that the caller wants to call this Result.
representing the name that the caller wants to call this Result.
The returned code may set "py_
%(name)
s" to a PyObject* and that PyObject*
The returned code may set "py_
%(name)
s" to a PyObject* and that PyObject*
will be accessible from Python via result.data. Do not forget to adjust
will be accessible from Python via result.data. Do not forget to adjust
reference counts if "py_
%(name)
s" is changed from its original value
!
reference counts if "py_
%(name)
s" is changed from its original value
.
"""
"""
raise
AbstractFunctionError
()
raise
AbstractFunctionError
()
...
@@ -273,6 +275,10 @@ class ResultBase(object):
...
@@ -273,6 +275,10 @@ class ResultBase(object):
class
PythonResult
(
ResultBase
):
class
PythonResult
(
ResultBase
):
"""
Represents a generic Python object. The object is available
through
%(name)
s.
"""
def
c_declare
(
self
):
def
c_declare
(
self
):
return
"""
return
"""
...
@@ -296,6 +302,7 @@ class PythonResult(ResultBase):
...
@@ -296,6 +302,7 @@ class PythonResult(ResultBase):
py_
%(name)
s =
%(name)
s;
py_
%(name)
s =
%(name)
s;
Py_XINCREF(py_
%(name)
s);
Py_XINCREF(py_
%(name)
s);
"""
"""
def
same_properties
(
self
,
other
):
def
same_properties
(
self
,
other
):
return
False
return
False
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论