Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
P
pytensor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
testgroup
pytensor
Commits
8f0b0888
提交
8f0b0888
authored
9月 30, 2016
作者:
Frédéric Bastien
提交者:
GitHub
9月 30, 2016
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #4039 from Sentient07/gpu_optimization
Making DimShuffles view by default
上级
8682627a
3da3054e
隐藏空白字符变更
内嵌
并排
正在显示
12 个修改的文件
包含
106 行增加
和
222 行删除
+106
-222
graphstructures.txt
doc/extending/graphstructures.txt
+1
-1
printing.txt
doc/library/printing.txt
+1
-1
basic.txt
doc/library/tensor/basic.txt
+4
-4
printing_drawing.txt
doc/tutorial/printing_drawing.txt
+4
-4
basic_ops.py
theano/sandbox/cuda/basic_ops.py
+17
-59
blas.py
theano/sandbox/cuda/blas.py
+2
-8
opt.py
theano/sandbox/cuda/opt.py
+20
-31
basic.py
theano/tensor/basic.py
+1
-1
elemwise.py
theano/tensor/elemwise.py
+10
-35
opt.py
theano/tensor/opt.py
+4
-33
test_opt.py
theano/tensor/tests/test_opt.py
+31
-34
test_printing.py
theano/tests/test_printing.py
+11
-11
没有找到文件。
doc/extending/graphstructures.txt
浏览文件 @
8f0b0888
...
...
@@ -99,7 +99,7 @@ multiplication is done between the inputs:
>>> y.owner.inputs[0]
x
>>> y.owner.inputs[1]
DimShuffle{x,x}.0
Inplace
DimShuffle{x,x}.0
Note that the second input is not 2 as we would have expected. This is
because 2 was first :term:`broadcasted <broadcasting>` to a matrix of
...
...
doc/library/printing.txt
浏览文件 @
8f0b0888
...
...
@@ -118,7 +118,7 @@ Elemwise{mul} [id A] ''
|x [id E]
|Elemwise{sub} [id I] ''
|TensorConstant{2} [id F]
|DimShuffle{} [id J] ''
|
Inplace
DimShuffle{} [id J] ''
|TensorConstant{1} [id K]
>>> theano.printing.debugprint(gy, depth=2) # doctest: +NORMALIZE_WHITESPACE
...
...
doc/library/tensor/basic.txt
浏览文件 @
8f0b0888
...
...
@@ -615,13 +615,13 @@ dimensions, see :meth:`_tensor_py_operators.dimshuffle`.
>>> tensor = theano.tensor.tensor3()
>>> theano.tensor.shape_padaxis(tensor, axis=0)
DimShuffle{x,0,1,2}.0
Inplace
DimShuffle{x,0,1,2}.0
>>> theano.tensor.shape_padaxis(tensor, axis=1)
DimShuffle{0,x,1,2}.0
Inplace
DimShuffle{0,x,1,2}.0
>>> theano.tensor.shape_padaxis(tensor, axis=3)
DimShuffle{0,1,2,x}.0
Inplace
DimShuffle{0,1,2,x}.0
>>> theano.tensor.shape_padaxis(tensor, axis=-1)
DimShuffle{0,1,2,x}.0
Inplace
DimShuffle{0,1,2,x}.0
.. autofunction:: unbroadcast(x, *axes)
...
...
doc/tutorial/printing_drawing.txt
浏览文件 @
8f0b0888
...
...
@@ -69,10 +69,10 @@ The pre-compilation graph:
>>> theano.printing.debugprint(prediction) # doctest: +NORMALIZE_WHITESPACE, +ELLIPSIS
Elemwise{gt,no_inplace} [id A] ''
|Elemwise{true_div,no_inplace} [id B] ''
| |DimShuffle{x} [id C] ''
| |
Inplace
DimShuffle{x} [id C] ''
| | |TensorConstant{1} [id D]
| |Elemwise{add,no_inplace} [id E] ''
| |DimShuffle{x} [id F] ''
| |
Inplace
DimShuffle{x} [id F] ''
| | |TensorConstant{1} [id D]
| |Elemwise{exp,no_inplace} [id G] ''
| |Elemwise{sub,no_inplace} [id H] ''
...
...
@@ -80,9 +80,9 @@ Elemwise{gt,no_inplace} [id A] ''
| | |dot [id J] ''
| | |x [id K]
| | |w [id L]
| |DimShuffle{x} [id M] ''
| |
Inplace
DimShuffle{x} [id M] ''
| |b [id N]
|DimShuffle{x} [id O] ''
|
Inplace
DimShuffle{x} [id O] ''
|TensorConstant{0.5} [id P]
The post-compilation graph:
...
...
theano/sandbox/cuda/basic_ops.py
浏览文件 @
8f0b0888
...
...
@@ -121,14 +121,7 @@ class GpuFromHost(GpuOp):
check_input
=
False
def
__eq__
(
self
,
other
):
return
type
(
self
)
==
type
(
other
)
def
__hash__
(
self
):
return
hash
(
type
(
self
))
def
__str__
(
self
):
return
'GpuFromHost'
__props__
=
()
def
make_node
(
self
,
x
):
if
not
isinstance
(
x
.
type
,
tensor
.
TensorType
):
...
...
@@ -220,12 +213,6 @@ class GpuElemwise(GpuOp):
self
.
sync
=
d
.
get
(
'sync'
,
True
)
self
.
_rehash
()
def
__eq__
(
self
,
other
):
return
(
type
(
self
)
==
type
(
other
)
and
self
.
scalar_op
==
other
.
scalar_op
and
self
.
inplace_pattern
==
other
.
inplace_pattern
and
self
.
sync
==
other
.
sync
)
def
_rehash
(
self
):
items
=
list
(
self
.
inplace_pattern
.
items
())
items
.
sort
()
...
...
@@ -242,6 +229,12 @@ class GpuElemwise(GpuOp):
assert
h
==
getattr
(
self
,
'_hashval'
,
h
)
self
.
_hashval
=
h
def
__eq__
(
self
,
other
):
return
(
type
(
self
)
==
type
(
other
)
and
self
.
scalar_op
==
other
.
scalar_op
and
self
.
inplace_pattern
==
other
.
inplace_pattern
and
self
.
sync
==
other
.
sync
)
def
__hash__
(
self
):
return
self
.
_hashval
...
...
@@ -320,6 +313,8 @@ class GpuDimShuffle(GpuOp):
check_broadcast
=
False
__props__
=
(
"input_broadcastable"
,
"new_order"
)
def
__init__
(
self
,
input_broadcastable
,
new_order
):
input_broadcastable
=
tuple
(
input_broadcastable
)
self
.
input_broadcastable
=
input_broadcastable
...
...
@@ -342,17 +337,6 @@ class GpuDimShuffle(GpuOp):
self
.
view_map
=
{
0
:
[
0
]}
self
.
_rehash
()
def
__getstate__
(
self
):
d
=
dict
(
self
.
__dict__
)
del
d
[
'_hashval'
]
return
d
def
__setstate__
(
self
,
d
):
self
.
__dict__
.
update
(
d
)
self
.
_rehash
()
def
make_node
(
self
,
input
):
ib
=
tuple
(
input
.
type
.
broadcastable
)
if
not
ib
==
self
.
input_broadcastable
:
...
...
@@ -379,21 +363,6 @@ class GpuDimShuffle(GpuOp):
ob
.
append
(
ib
[
value
])
return
Apply
(
self
,
[
input
],
[
CudaNdarrayType
(
broadcastable
=
ob
)()])
def
__eq__
(
self
,
other
):
# it's probably not necessary to compare input_broadcastable
return
type
(
self
)
==
type
(
other
)
\
and
self
.
new_order
==
other
.
new_order
\
and
self
.
input_broadcastable
==
other
.
input_broadcastable
def
_rehash
(
self
):
self
.
_hashval
=
(
hash
(
type
(
self
)
.
__name__
)
^
hash
(
type
(
self
)
.
__module__
)
^
hash
(
self
.
new_order
)
^
hash
(
self
.
input_broadcastable
))
def
__hash__
(
self
):
return
self
.
_hashval
def
__str__
(
self
):
return
"GpuDimShuffle{
%
s}"
%
","
.
join
(
str
(
x
)
for
x
in
self
.
new_order
)
...
...
@@ -568,6 +537,8 @@ class GpuCAReduce(GpuOp):
"""
__props__
=
(
"reduce_mask"
,
"scalar_op"
,
"pre_scalar_op"
,
)
def
__init__
(
self
,
reduce_mask
,
scalar_op
,
pre_scalar_op
=
None
):
self
.
reduce_mask
=
tuple
(
reduce_mask
)
self
.
scalar_op
=
scalar_op
...
...
@@ -578,17 +549,11 @@ class GpuCAReduce(GpuOp):
if
pre_scalar_op
:
assert
pre_scalar_op
.
nin
==
1
def
__eq__
(
self
,
other
):
return
(
type
(
self
)
==
type
(
other
)
and
self
.
reduce_mask
==
other
.
reduce_mask
and
self
.
scalar_op
==
other
.
scalar_op
and
self
.
pre_scalar_op
==
other
.
pre_scalar_op
)
def
__hash__
(
self
):
return
(
hash
(
type
(
self
))
^
hash
(
self
.
reduce_mask
)
^
hash
(
type
(
self
.
scalar_op
))
^
hash
(
type
(
self
.
pre_scalar_op
)))
def
__setstate__
(
self
,
d
):
self
.
__dict__
.
update
(
d
)
# For unpickling of old ops.
if
not
hasattr
(
self
,
"pre_scalar_op"
):
self
.
pre_scalar_op
=
None
def
__str__
(
self
):
pre
=
""
...
...
@@ -598,12 +563,6 @@ class GpuCAReduce(GpuOp):
pre
,
str
(
self
.
scalar_op
),
','
.
join
(
str
(
i
)
for
i
in
self
.
reduce_mask
))
def
__setstate__
(
self
,
d
):
self
.
__dict__
.
update
(
d
)
# For unpickling of old ops.
if
not
hasattr
(
self
,
"pre_scalar_op"
):
self
.
pre_scalar_op
=
None
def
make_node
(
self
,
x
):
x
=
as_cuda_ndarray_variable
(
x
)
if
(
x
.
type
.
ndim
!=
len
(
self
.
reduce_mask
)):
...
...
@@ -3655,7 +3614,6 @@ class GpuAllocEmpty(GpuOp):
Implement Alloc on the gpu, but without initializing memory.
"""
__props__
=
()
def
make_node
(
self
,
*
shape
):
...
...
@@ -3852,10 +3810,10 @@ class CopyOnNegativeStrides(GpuOp):
If it does, returns a c contiguous copy.
"""
__props__
=
()
view_map
=
{
0
:
[
0
]}
check_input
=
False
__props__
=
()
def
grad
(
self
,
inputs
,
dout
):
...
...
theano/sandbox/cuda/blas.py
浏览文件 @
8f0b0888
...
...
@@ -2207,18 +2207,12 @@ class GpuDownsampleFactorMax(GpuOp):
Implement downsample with max on the gpu.
"""
__props__
=
(
'ds'
,
'ignore_border'
)
def
__init__
(
self
,
ds
,
ignore_border
=
False
):
self
.
ds
=
tuple
(
ds
)
self
.
ignore_border
=
ignore_border
def
__eq__
(
self
,
other
):
return
(
type
(
self
)
==
type
(
other
)
and
self
.
ds
==
other
.
ds
and
self
.
ignore_border
==
other
.
ignore_border
)
def
__hash__
(
self
):
return
hash
(
type
(
self
))
^
hash
(
self
.
ds
)
^
hash
(
self
.
ignore_border
)
def
__str__
(
self
):
return
'
%
s{
%
s,
%
s}'
%
(
self
.
__class__
.
__name__
,
self
.
ds
,
...
...
theano/sandbox/cuda/opt.py
浏览文件 @
8f0b0888
...
...
@@ -379,7 +379,7 @@ def local_gpu_split(node):
if
(
input
.
owner
and
isinstance
(
input
.
owner
.
op
,
HostFromGpu
)
or
any
(
c
!=
'output'
and
isinstance
(
c
.
op
,
GpuFromHost
)
for
c
,
idx
in
outs_clients
)):
new_op
=
GpuSplit
(
node
.
op
.
len_splits
)
new_op
=
GpuSplit
(
**
node
.
op
.
_props_dict
()
)
split_res
=
new_op
(
as_cuda_ndarray_variable
(
input
),
*
node
.
inputs
[
1
:],
return_list
=
True
)
return
[
host_from_gpu
(
o
)
for
o
in
split_res
]
...
...
@@ -398,16 +398,18 @@ def local_gpu_dimshuffle_0(node):
input
,
=
node
.
inputs
if
input
.
owner
and
isinstance
(
input
.
owner
.
op
,
HostFromGpu
):
# move the add to a GpuAdd
new_op
=
GpuDimShuffle
(
node
.
op
.
input_broadcastable
,
node
.
op
.
new_order
)
p_dict
=
node
.
op
.
_props_dict
()
p_dict
.
pop
(
'inplace'
,
None
)
new_op
=
GpuDimShuffle
(
**
p_dict
)
return
[
host_from_gpu
(
new_op
(
as_cuda_ndarray_variable
(
input
)))]
if
isinstance
(
node
.
op
,
GpuFromHost
):
host_input
=
node
.
inputs
[
0
]
if
host_input
.
owner
and
isinstance
(
host_input
.
owner
.
op
,
tensor
.
DimShuffle
):
dimshuffle_node
=
host_input
.
owner
new_op
=
GpuDimShuffle
(
dimshuffle_node
.
op
.
input_broadcastable
,
dimshuffle_node
.
op
.
new_order
)
p_dict
=
dimshuffle_node
.
op
.
_props_dict
()
p_dict
.
pop
(
'inplace'
,
None
)
new_op
=
GpuDimShuffle
(
**
p_dict
)
return
[
new_op
(
as_cuda_ndarray_variable
(
dimshuffle_node
.
inputs
[
0
]))]
return
False
...
...
@@ -995,10 +997,8 @@ def local_gpu_reshape(node):
host_input
=
node
.
inputs
[
0
]
if
host_input
.
owner
and
\
isinstance
(
host_input
.
owner
.
op
,
tensor
.
Reshape
):
rshp
=
host_input
.
owner
.
op
x
,
shp
=
host_input
.
owner
.
inputs
gpu_reshape
=
GpuReshape
(
rshp
.
ndim
)(
as_cuda_ndarray_variable
(
x
),
shp
)
gpu_reshape
=
GpuReshape
(
**
host_input
.
owner
.
op
.
_props_dict
())(
as_cuda_ndarray_variable
(
x
),
shp
)
if
gpu_reshape
.
broadcastable
!=
node
.
outputs
[
0
]
.
broadcastable
:
# this can happen as we always return False for all broadcast
# dim in GpuReshape but not for Reshape
...
...
@@ -1011,7 +1011,7 @@ def local_gpu_reshape(node):
x
,
shp
=
node
.
inputs
if
x
.
owner
and
isinstance
(
x
.
owner
.
op
,
HostFromGpu
):
gpu_x
,
=
x
.
owner
.
inputs
gpu_reshape
=
GpuReshape
(
node
.
op
.
ndim
)(
gpu_x
,
shp
)
gpu_reshape
=
GpuReshape
(
**
node
.
op
.
_props_dict
()
)(
gpu_x
,
shp
)
if
gpu_reshape
.
broadcastable
!=
node
.
outputs
[
0
]
.
broadcastable
:
# this can happen as we always return False for all broadcast
# dim in GpuReshape but not for Reshape
...
...
@@ -1082,7 +1082,7 @@ def local_gpu_subtensor(node):
gpu_x
,
=
x
.
owner
.
inputs
coords
=
node
.
inputs
[
1
:]
return
[
host_from_gpu
(
GpuSubtensor
(
node
.
op
.
idx_list
)(
gpu_x
,
*
coords
))]
**
node
.
op
.
_props_dict
()
)(
gpu_x
,
*
coords
))]
return
False
...
...
@@ -1131,11 +1131,9 @@ def local_gpu_advanced_incsubtensor1(node):
compute_capability
=
device_properties
(
active_device_no
)[
'major'
]
if
(
compute_capability
<
2
or
y
.
ndim
!=
2
or
x
.
ndim
!=
2
):
gpu_op
=
GpuAdvancedIncSubtensor1
(
set_instead_of_inc
=
set_instead_of_inc
)
gpu_op
=
GpuAdvancedIncSubtensor1
(
**
node
.
op
.
_props_dict
())
else
:
gpu_op
=
GpuAdvancedIncSubtensor1_dev20
(
set_instead_of_inc
=
set_instead_of_inc
)
gpu_op
=
GpuAdvancedIncSubtensor1_dev20
(
**
node
.
op
.
_props_dict
())
return
[
gpu_op
(
as_cuda_ndarray_variable
(
x
),
as_cuda_ndarray_variable
(
y
),
*
coords
)]
...
...
@@ -1171,11 +1169,9 @@ def local_gpu_advanced_incsubtensor1(node):
active_device_no
=
theano
.
sandbox
.
cuda
.
active_device_number
()
compute_capability
=
device_properties
(
active_device_no
)[
'major'
]
if
(
compute_capability
<
2
or
y
.
ndim
!=
2
or
x
.
ndim
!=
2
):
gpu_op
=
GpuAdvancedIncSubtensor1
(
set_instead_of_inc
=
set_instead_of_inc
)
gpu_op
=
GpuAdvancedIncSubtensor1
(
**
node
.
op
.
_props_dict
())
else
:
gpu_op
=
GpuAdvancedIncSubtensor1_dev20
(
set_instead_of_inc
=
set_instead_of_inc
)
gpu_op
=
GpuAdvancedIncSubtensor1_dev20
(
**
node
.
op
.
_props_dict
())
return
[
host_from_gpu
(
gpu_op
(
gpu_x
,
gpu_y
,
*
coords
))]
return
False
...
...
@@ -1196,13 +1192,9 @@ def local_gpu_incsubtensor(node):
# The IncSubtensor upcast to float32 y, so we do it
# explicitly to move it to the GPU.
y
=
y
.
astype
(
'float32'
)
ret
=
GpuIncSubtensor
(
incsubt
.
idx_list
,
inplace
=
incsubt
.
inplace
,
set_instead_of_inc
=
incsubt
.
set_instead_of_inc
)(
as_cuda_ndarray_variable
(
x
),
as_cuda_ndarray_variable
(
y
),
*
coords
)
ret
=
GpuIncSubtensor
(
**
incsubt
.
_props_dict
())(
as_cuda_ndarray_variable
(
x
),
as_cuda_ndarray_variable
(
y
),
*
coords
)
ret
.
tag
.
nan_guard_mode_check
=
getattr
(
host_output
.
tag
,
'nan_guard_mode_check'
,
True
)
return
[
ret
]
...
...
@@ -1229,10 +1221,7 @@ def local_gpu_incsubtensor(node):
y
=
tensor
.
cast
(
y
,
'float32'
)
gpu_y
=
as_cuda_ndarray_variable
(
y
)
if
go_gpu
:
ret
=
GpuIncSubtensor
(
node
.
op
.
idx_list
,
inplace
=
node
.
op
.
inplace
,
set_instead_of_inc
=
node
.
op
.
set_instead_of_inc
)(
gpu_x
,
gpu_y
,
*
coords
)
ret
=
GpuIncSubtensor
(
**
node
.
op
.
_props_dict
())(
gpu_x
,
gpu_y
,
*
coords
)
val
=
getattr
(
node
.
outputs
[
0
]
.
tag
,
'nan_guard_mode_check'
,
True
)
ret
.
tag
.
nan_guard_mode_check
=
val
...
...
@@ -2690,7 +2679,7 @@ def gpu_sparse_block_outer_opt(node):
inputs
=
_clear_host_from_gpu
(
node
.
inputs
)
return
[
host_from_gpu
(
GpuSparseBlockOuter
(
node
.
op
.
inplace
)(
*
inputs
))]
return
[
host_from_gpu
(
GpuSparseBlockOuter
()(
*
inputs
))]
elif
isinstance
(
node
.
op
,
GpuFromHost
)
and
\
_owner_isinstance
(
node
.
inputs
[
0
],
SparseBlockOuter
):
...
...
@@ -2698,7 +2687,7 @@ def gpu_sparse_block_outer_opt(node):
meta_node
=
node
.
inputs
[
0
]
.
owner
inputs
=
_clear_host_from_gpu
(
meta_node
.
inputs
)
return
[
GpuSparseBlockOuter
(
meta_node
.
op
.
inplace
)(
*
inputs
)]
return
[
GpuSparseBlockOuter
()(
*
inputs
)]
@local_optimizer
([
GpuSparseBlockGemv
],
inplace
=
True
)
...
...
theano/tensor/basic.py
浏览文件 @
8f0b0888
...
...
@@ -3517,7 +3517,7 @@ def transpose(x, axes=None):
"""
if
axes
is
None
:
axes
=
list
(
range
((
x
.
ndim
-
1
),
-
1
,
-
1
))
ret
=
DimShuffle
(
x
.
broadcastable
,
axes
,
inplace
=
False
)(
x
)
ret
=
DimShuffle
(
x
.
broadcastable
,
axes
)(
x
)
if
x
.
name
and
axes
==
list
(
range
((
x
.
ndim
-
1
),
-
1
,
-
1
)):
ret
.
name
=
x
.
name
+
'.T'
return
ret
...
...
theano/tensor/elemwise.py
浏览文件 @
8f0b0888
...
...
@@ -73,8 +73,7 @@ class DimShuffle(Op):
list can either be an index or 'x'. Indices must be encoded
as python integers, not theano symbolic integers.
inplace : bool, optional
If True, the output will be a view of the input.
If False (default), the output will be a copy of the input.
If True (default), the output will be a view of the input.
Note
----
...
...
@@ -134,13 +133,17 @@ class DimShuffle(Op):
_f16_ok
=
True
check_input
=
False
__props__
=
(
"input_broadcastable"
,
"new_order"
,
"inplace"
)
def
__init__
(
self
,
input_broadcastable
,
new_order
,
inplace
=
Fals
e
):
def
__init__
(
self
,
input_broadcastable
,
new_order
,
inplace
=
Tru
e
):
input_broadcastable
=
tuple
(
input_broadcastable
)
self
.
input_broadcastable
=
input_broadcastable
new_order
=
tuple
(
new_order
)
self
.
new_order
=
new_order
self
.
inplace
=
inplace
if
inplace
is
True
:
self
.
inplace
=
inplace
else
:
raise
ValueError
(
"DimShuffle is inplace by default and hence the inplace for DimShuffle must be true"
)
for
i
,
j
in
enumerate
(
new_order
):
if
j
!=
'x'
:
...
...
@@ -186,17 +189,6 @@ class DimShuffle(Op):
if
self
.
inplace
:
self
.
view_map
=
{
0
:
[
0
]}
self
.
_rehash
()
def
__getstate__
(
self
):
d
=
dict
(
self
.
__dict__
)
del
d
[
'_hashval'
]
return
d
def
__setstate__
(
self
,
d
):
self
.
__dict__
.
update
(
d
)
self
.
_rehash
()
def
make_node
(
self
,
_input
):
input
=
as_tensor_variable
(
_input
)
ib
=
tuple
(
input
.
type
.
broadcastable
)
...
...
@@ -227,23 +219,6 @@ class DimShuffle(Op):
return
Apply
(
self
,
[
input
],
[
output
])
def
__eq__
(
self
,
other
):
# it's probably not necessary to compare input_broadcastable
return
type
(
self
)
==
type
(
other
)
\
and
self
.
inplace
==
other
.
inplace
\
and
self
.
new_order
==
other
.
new_order
\
and
self
.
input_broadcastable
==
other
.
input_broadcastable
def
_rehash
(
self
):
self
.
_hashval
=
(
hash
(
type
(
self
)
.
__name__
)
^
hash
(
type
(
self
)
.
__module__
)
^
hash
(
self
.
inplace
)
^
hash
(
self
.
new_order
)
^
hash
(
self
.
input_broadcastable
))
def
__hash__
(
self
):
return
self
.
_hashval
def
__str__
(
self
):
if
self
.
inplace
:
return
"InplaceDimShuffle{
%
s}"
%
","
.
join
(
str
(
x
)
...
...
@@ -564,8 +539,7 @@ second dimension
# TODO: use LComplete instead
args
.
append
(
dim_shuffle
(
input
.
type
.
broadcastable
,
[
'x'
]
*
difference
+
list
(
range
(
length
)),
inplace
=
False
)(
input
))
[
'x'
]
*
difference
+
list
(
range
(
length
)))(
input
))
inputs
=
args
# HERE: all the broadcast dims have the same length now
...
...
@@ -798,7 +772,8 @@ second dimension
# dimensions
res
=
theano
.
tensor
.
constant
(
numpy
.
asarray
(
r
.
data
),
dtype
=
r
.
type
.
dtype
)
return
DimShuffle
((),
[
'x'
]
*
nd
,
inplace
=
False
)(
res
)
return
DimShuffle
((),
[
'x'
]
*
nd
)(
res
)
new_r
=
Elemwise
(
node
.
op
,
{})(
*
[
transform
(
ipt
)
for
ipt
in
node
.
inputs
])
return
new_r
...
...
theano/tensor/opt.py
浏览文件 @
8f0b0888
...
...
@@ -600,8 +600,7 @@ def local_dimshuffle_lift(node):
new_inputs
=
[]
for
inp
in
inode
.
inputs
:
new_inp
=
op
.
__class__
(
inp
.
type
.
broadcastable
,
op
.
new_order
,
op
.
inplace
)(
inp
)
op
.
new_order
)(
inp
)
new_inputs
.
append
(
apply_local_dimshuffle_lift
(
new_inp
))
copy_stack_trace
(
node
.
outputs
[
0
],
new_inputs
)
ret
=
inode
.
op
(
*
new_inputs
,
**
dict
(
return_list
=
True
))
...
...
@@ -609,14 +608,12 @@ def local_dimshuffle_lift(node):
if
inode
and
isinstance
(
inode
.
op
,
DimShuffle
):
new_order
=
[
x
==
'x'
and
'x'
or
inode
.
op
.
new_order
[
x
]
for
x
in
new_order
]
inplace
=
op
.
inplace
and
inode
.
op
.
inplace
input
=
inode
.
inputs
[
0
]
if
is_dimshuffle_useless
(
new_order
,
input
):
return
[
input
]
elif
inode
and
isinstance
(
inode
.
op
,
DimShuffle
):
ret
=
op
.
__class__
(
input
.
type
.
broadcastable
,
new_order
,
inplace
)(
input
)
ret
=
op
.
__class__
(
input
.
type
.
broadcastable
,
new_order
)(
input
)
ret
=
apply_local_dimshuffle_lift
(
ret
)
copy_stack_trace
(
node
.
outputs
[
0
],
ret
)
return
[
ret
]
...
...
@@ -659,7 +656,7 @@ def local_useless_dimshuffle_in_reshape(node):
@register_canonicalize
@gof.local_optimizer
([
T
.
DimShuffle
])
@gof.local_optimizer
([
DimShuffle
])
def
local_lift_transpose_through_dot
(
node
):
"""
dot(x,y).T -> dot(y.T, x.T)
...
...
@@ -688,40 +685,14 @@ def local_lift_transpose_through_dot(node):
copy_stack_trace
(
node
.
inputs
[
0
],
ret
)
return
ret
@gof.local_optimizer
([
DimShuffle
])
def
dimshuffle_as_view
(
node
):
op
=
node
.
op
if
not
isinstance
(
op
,
DimShuffle
)
or
op
.
inplace
:
return
False
new_op
=
op
.
__class__
(
op
.
input_broadcastable
,
op
.
new_order
,
inplace
=
True
)
v
=
new_op
(
*
node
.
inputs
)
copy_stack_trace
(
node
.
outputs
[
0
],
v
)
return
[
v
]
# Step 60 is the inplace optimization stage.
compile
.
optdb
.
register
(
'dimshuffle_as_view'
,
TopoOptimizer
(
dimshuffle_as_view
,
failure_callback
=
TopoOptimizer
.
warn_inplace
),
60
,
'fast_run'
,
'inplace'
)
register_canonicalize
(
local_dimshuffle_lift
)
register_specialize
(
local_dimshuffle_lift
)
@register_canonicalize
@gof.local_optimizer
([
T
.
DimShuffle
])
def
local_dimshuffle_no_inplace_at_canonicalize
(
node
):
if
isinstance
(
node
.
op
,
T
.
DimShuffle
)
and
node
.
op
.
inplace
:
return
[
T
.
DimShuffle
(
node
.
op
.
input_broadcastable
,
node
.
op
.
new_order
,
inplace
=
False
)(
node
.
inputs
[
0
])]
######################
# Casting operations #
######################
@register_canonicalize
@register_specialize
@gof.local_optimizer
([
T
.
TensorFromScalar
])
...
...
theano/tensor/tests/test_opt.py
浏览文件 @
8f0b0888
...
...
@@ -117,7 +117,7 @@ class test_dimshuffle_lift(unittest.TestCase):
x
,
y
,
z
=
inputs
()
e
=
ds
(
ds
(
x
,
(
1
,
0
)),
(
1
,
0
))
g
=
FunctionGraph
([
x
],
[
e
])
self
.
assertTrue
(
str
(
g
)
==
"[
DimShuffle{1,0}(
DimShuffle{1,0}(x))]"
)
self
.
assertTrue
(
str
(
g
)
==
"[
InplaceDimShuffle{1,0}(Inplace
DimShuffle{1,0}(x))]"
)
dimshuffle_lift
.
optimize
(
g
)
self
.
assertTrue
(
str
(
g
)
==
"[x]"
)
# no need to check_stack_trace as graph is supposed to be empty
...
...
@@ -126,11 +126,10 @@ class test_dimshuffle_lift(unittest.TestCase):
x
,
y
,
z
=
inputs
()
e
=
ds
(
ds
(
x
,
(
1
,
'x'
,
0
)),
(
2
,
0
,
'x'
,
1
))
g
=
FunctionGraph
([
x
],
[
e
])
self
.
assertTrue
(
str
(
g
)
==
"[DimShuffle{2,0,x,1}(DimShuffle{1,x,0}(x))]"
,
str
(
g
))
self
.
assertTrue
(
str
(
g
)
==
"[InplaceDimShuffle{2,0,x,1}(InplaceDimShuffle{1,x,0}(x))]"
,
str
(
g
))
dimshuffle_lift
.
optimize
(
g
)
self
.
assertTrue
(
str
(
g
)
==
"[DimShuffle{0,1,x,x}(x)]"
,
str
(
g
))
self
.
assertTrue
(
str
(
g
)
==
"[
Inplace
DimShuffle{0,1,x,x}(x)]"
,
str
(
g
))
# Check stacktrace was copied over correctly after opt was applied
self
.
assertTrue
(
check_stack_trace
(
g
,
ops_to_check
=
'all'
))
...
...
@@ -138,10 +137,9 @@ class test_dimshuffle_lift(unittest.TestCase):
x
,
y
,
z
=
inputs
()
e
=
ds
(
ds
(
ds
(
x
,
(
0
,
'x'
,
1
)),
(
2
,
0
,
'x'
,
1
)),
(
1
,
0
))
g
=
FunctionGraph
([
x
],
[
e
])
self
.
assertTrue
(
str
(
g
)
==
"[DimShuffle{1,0}(DimShuffle{2,0,x,1}"
"(DimShuffle{0,x,1}(x)))]"
,
str
(
g
))
self
.
assertTrue
(
str
(
g
)
==
"[InplaceDimShuffle{1,0}(InplaceDimShuffle{2,0,x,1}"
"(InplaceDimShuffle{0,x,1}(x)))]"
,
str
(
g
))
dimshuffle_lift
.
optimize
(
g
)
self
.
assertTrue
(
str
(
g
)
==
"[x]"
,
str
(
g
))
# no need to check_stack_trace as graph is supposed to be empty
...
...
@@ -179,24 +177,22 @@ class test_dimshuffle_lift(unittest.TestCase):
m
=
T
.
matrix
(
dtype
=
"float64"
)
out
=
((
v
+
42
)
*
(
m
+
84
))
.
T
g
=
FunctionGraph
([
v
,
m
],
[
out
])
init_str_g
=
(
"[DimShuffle{1,0}(Elemwise{mul,no_inplace}"
"(DimShuffle{x,0}(Elemwise{add,no_inplace}"
init_str_g
=
(
"[
Inplace
DimShuffle{1,0}(Elemwise{mul,no_inplace}"
"(
Inplace
DimShuffle{x,0}(Elemwise{add,no_inplace}"
"(<TensorType(float64, vector)>, "
"DimShuffle{x}(TensorConstant{42}))), "
"
Inplace
DimShuffle{x}(TensorConstant{42}))), "
"Elemwise{add,no_inplace}"
"(<TensorType(float64, matrix)>, "
"DimShuffle{x,x}(TensorConstant{84}))))]"
)
"InplaceDimShuffle{x,x}(TensorConstant{84}))))]"
)
self
.
assertTrue
(
str
(
g
)
==
init_str_g
)
new_out
=
local_dimshuffle_lift
.
transform
(
g
.
outputs
[
0
]
.
owner
)[
0
]
new_g
=
FunctionGraph
(
g
.
inputs
,
[
new_out
])
opt_str_g
=
(
"[Elemwise{mul,no_inplace}(Elemwise{add,no_inplace}"
"(DimShuffle{0,x}(<TensorType(float64, vector)>), "
"DimShuffle{x,x}(TensorConstant{42})), "
"Elemwise{add,no_inplace}(DimShuffle{1,0}"
"(
Inplace
DimShuffle{0,x}(<TensorType(float64, vector)>), "
"
Inplace
DimShuffle{x,x}(TensorConstant{42})), "
"Elemwise{add,no_inplace}(
Inplace
DimShuffle{1,0}"
"(<TensorType(float64, matrix)>), "
"DimShuffle{x,x}(TensorConstant{84})))]"
)
"InplaceDimShuffle{x,x}(TensorConstant{84})))]"
)
self
.
assertTrue
(
str
(
new_g
)
==
opt_str_g
)
# Check stacktrace was copied over correctly after opt was applied
self
.
assertTrue
(
check_stack_trace
(
new_g
,
ops_to_check
=
'all'
))
...
...
@@ -205,7 +201,7 @@ class test_dimshuffle_lift(unittest.TestCase):
x
,
_
,
_
=
inputs
()
e
=
ds
(
x
,
(
0
,
1
))
g
=
FunctionGraph
([
x
],
[
e
])
self
.
assertTrue
(
str
(
g
)
==
"[DimShuffle{0,1}(x)]"
)
self
.
assertTrue
(
str
(
g
)
==
"[
Inplace
DimShuffle{0,1}(x)]"
)
dimshuffle_lift
.
optimize
(
g
)
self
.
assertTrue
(
str
(
g
)
==
"[x]"
)
# Check stacktrace was copied over correctly after opt was applied
...
...
@@ -219,9 +215,9 @@ class test_dimshuffle_lift(unittest.TestCase):
ds_z
=
ds
(
z
,
(
2
,
1
,
0
))
# usefull
ds_u
=
ds
(
u
,
(
'x'
))
# usefull
g
=
FunctionGraph
([
x
,
y
,
z
,
u
],
[
ds_x
,
ds_y
,
ds_z
,
ds_u
])
self
.
assertTrue
(
str
(
g
)
==
"[
DimShuffle{0,x}(x), DimShuffle{2,1,0}(y), DimShuffle{2,1,0}(z),
DimShuffle{x}(TensorConstant{1})]"
)
self
.
assertTrue
(
str
(
g
)
==
"[
InplaceDimShuffle{0,x}(x), InplaceDimShuffle{2,1,0}(y), InplaceDimShuffle{2,1,0}(z), Inplace
DimShuffle{x}(TensorConstant{1})]"
)
dimshuffle_lift
.
optimize
(
g
)
self
.
assertTrue
(
str
(
g
)
==
"[x, y,
DimShuffle{2,1,0}(z),
DimShuffle{x}(TensorConstant{1})]"
)
self
.
assertTrue
(
str
(
g
)
==
"[x, y,
InplaceDimShuffle{2,1,0}(z), Inplace
DimShuffle{x}(TensorConstant{1})]"
)
# Check stacktrace was copied over correctly after opt was applied
self
.
assertTrue
(
hasattr
(
g
.
outputs
[
0
]
.
tag
,
'trace'
))
...
...
@@ -241,10 +237,11 @@ def test_local_useless_dimshuffle_in_reshape():
[
reshape_dimshuffle_vector
,
reshape_dimshuffle_mat
,
reshape_dimshuffle_row
,
reshape_dimshuffle_col
])
assert_true
(
str
(
g
)
==
"[Reshape{1}(DimShuffle{x,0}(vector), Shape(vector)), "
"Reshape{2}(DimShuffle{x,0,x,1}(mat), Shape(mat)), "
"Reshape{2}(DimShuffle{1,x}(row), Shape(row)), "
"Reshape{2}(DimShuffle{0}(col), Shape(col))]"
)
print
(
str
(
g
))
assert_true
(
str
(
g
)
==
"[Reshape{1}(InplaceDimShuffle{x,0}(vector), Shape(vector)), "
"Reshape{2}(InplaceDimShuffle{x,0,x,1}(mat), Shape(mat)), "
"Reshape{2}(InplaceDimShuffle{1,x}(row), Shape(row)), "
"Reshape{2}(InplaceDimShuffle{0}(col), Shape(col))]"
)
useless_dimshuffle_in_reshape
=
out2in
(
local_useless_dimshuffle_in_reshape
)
useless_dimshuffle_in_reshape
.
optimize
(
g
)
assert_true
(
str
(
g
)
==
"[Reshape{1}(vector, Shape(vector)), "
...
...
@@ -3766,15 +3763,15 @@ class Test_local_canonicalize_alloc(unittest.TestCase):
"TensorConstant{2})]"
))
alloc_lift
.
optimize
(
g
)
self
.
assertTrue
(
str
(
g
)
==
"[DimShuffle{x,0,1}"
self
.
assertTrue
(
str
(
g
)
==
"[
Inplace
DimShuffle{x,0,1}"
"(Alloc(<TensorType(float64, vector)>, "
"TensorConstant{3}, "
"TensorConstant{2})), "
"DimShuffle{x,x}"
"
Inplace
DimShuffle{x,x}"
"(<TensorType(float64, scalar)>), "
"DimShuffle{x,0,1}"
"
Inplace
DimShuffle{x,0,1}"
"(Alloc(<TensorType(float64, matrix)>, "
"TensorConstant{1}, "
"TensorConstant{2})), "
...
...
@@ -6268,9 +6265,9 @@ class Test_local_reshape_to_dimshuffle(unittest.TestCase):
reshape_lift
.
optimize
(
g
)
useless_reshape
.
optimize
(
g
)
self
.
assertTrue
(
str
(
g
)
==
"[DimShuffle{x,0}"
self
.
assertTrue
(
str
(
g
)
==
"[
Inplace
DimShuffle{x,0}"
"(<TensorType(float64, vector)>), "
"DimShuffle{x,0,x,1,x,x}"
"
Inplace
DimShuffle{x,0,x,1,x,x}"
"(Reshape{2}(<TensorType(float64, matrix)>, "
"TensorConstant{[5 6]}))]"
)
...
...
@@ -6301,7 +6298,7 @@ class Test_lift_transpose_through_dot(unittest.TestCase):
def
test_matrix_matrix
(
self
):
a
,
b
=
matrices
(
'ab'
)
g
=
self
.
simple_optimize
(
FunctionGraph
([
a
,
b
],
[
tensor
.
dot
(
a
,
b
)
.
T
]))
sg
=
'[dot(
DimShuffle{1,0}(b),
DimShuffle{1,0}(a))]'
sg
=
'[dot(
InplaceDimShuffle{1,0}(b), Inplace
DimShuffle{1,0}(a))]'
assert
str
(
g
)
==
sg
,
(
str
(
g
),
sg
)
# Check stacktrace was copied over correctly after opt was applied
self
.
assertTrue
(
check_stack_trace
(
g
,
ops_to_check
=
'all'
))
...
...
@@ -6313,7 +6310,7 @@ class Test_lift_transpose_through_dot(unittest.TestCase):
[
a
,
b
],
[
tensor
.
dot
(
a
.
dimshuffle
(
'x'
,
0
),
b
)
.
T
]),
level
=
'stabilize'
)
sg
=
'[dot(
DimShuffle{1,0}(b),
DimShuffle{0,x}(a))]'
sg
=
'[dot(
InplaceDimShuffle{1,0}(b), Inplace
DimShuffle{0,x}(a))]'
assert
str
(
g
)
==
sg
,
(
str
(
g
),
sg
)
# Check stacktrace was copied over correctly after opt was applied
self
.
assertTrue
(
check_stack_trace
(
g
,
ops_to_check
=
'all'
))
...
...
@@ -6325,7 +6322,7 @@ class Test_lift_transpose_through_dot(unittest.TestCase):
[
a
,
b
],
[
tensor
.
dot
(
b
,
a
.
dimshuffle
(
0
,
'x'
))
.
T
]),
level
=
'stabilize'
)
sg
=
'[dot(
DimShuffle{x,0}(a),
DimShuffle{1,0}(b))]'
sg
=
'[dot(
InplaceDimShuffle{x,0}(a), Inplace
DimShuffle{1,0}(b))]'
assert
str
(
g
)
==
sg
,
(
str
(
g
),
sg
)
# Check stacktrace was copied over correctly after opt was applied
self
.
assertTrue
(
check_stack_trace
(
g
,
ops_to_check
=
'all'
))
...
...
theano/tests/test_printing.py
浏览文件 @
8f0b0888
...
...
@@ -321,10 +321,10 @@ def test_scan_debugprint1():
| | | | | |Subtensor{int64} [id H] ''
| | | | | |Shape [id I] ''
| | | | | | |Rebroadcast{0} [id J] ''
| | | | | | |DimShuffle{x,0} [id K] ''
| | | | | | |
Inplace
DimShuffle{x,0} [id K] ''
| | | | | | |Elemwise{second,no_inplace} [id L] ''
| | | | | | |A [id M]
| | | | | | |DimShuffle{x} [id N] ''
| | | | | | |
Inplace
DimShuffle{x} [id N] ''
| | | | | | |TensorConstant{1.0} [id O]
| | | | | |Constant{0} [id P]
| | | | |Subtensor{int64} [id Q] ''
...
...
@@ -490,7 +490,7 @@ def test_scan_debugprint3():
for{cpu,scan_fn} [id B] ''
>Elemwise{mul,no_inplace} [id Y] ''
> |DimShuffle{x} [id Z] ''
> |
Inplace
DimShuffle{x} [id Z] ''
> | |coefficients[t] [id BA] -> [id S]
> |Elemwise{pow,no_inplace} [id BB] ''
> |Subtensor{int64} [id BC] ''
...
...
@@ -504,10 +504,10 @@ def test_scan_debugprint3():
> | | | | | | |Subtensor{int64} [id BJ] ''
> | | | | | | |Shape [id BK] ''
> | | | | | | | |Rebroadcast{0} [id BL] ''
> | | | | | | | |DimShuffle{x,0} [id BM] ''
> | | | | | | | |
Inplace
DimShuffle{x,0} [id BM] ''
> | | | | | | | |Elemwise{second,no_inplace} [id BN] ''
> | | | | | | | |A_copy [id BO] -> [id W]
> | | | | | | | |DimShuffle{x} [id BP] ''
> | | | | | | | |
Inplace
DimShuffle{x} [id BP] ''
> | | | | | | | |TensorConstant{1.0} [id BQ]
> | | | | | | |Constant{0} [id BR]
> | | | | | |Subtensor{int64} [id BS] ''
...
...
@@ -520,7 +520,7 @@ def test_scan_debugprint3():
> | | | |A_copy [id BO] -> [id W]
> | | |Constant{1} [id BW]
> | |Constant{-1} [id BX]
> |DimShuffle{x} [id BY] ''
> |
Inplace
DimShuffle{x} [id BY] ''
> |<TensorType(int64, scalar)> [id BZ] -> [id U]
for{cpu,scan_fn} [id BE] ''
...
...
@@ -636,10 +636,10 @@ def test_scan_debugprint5():
| | | | | | | |Subtensor{int64} [id K] ''
| | | | | | | |Shape [id L] ''
| | | | | | | | |Rebroadcast{0} [id M] ''
| | | | | | | | |DimShuffle{x,0} [id N] ''
| | | | | | | | |
Inplace
DimShuffle{x,0} [id N] ''
| | | | | | | | |Elemwise{second,no_inplace} [id O] ''
| | | | | | | | |A [id P]
| | | | | | | | |DimShuffle{x} [id Q] ''
| | | | | | | | |
Inplace
DimShuffle{x} [id Q] ''
| | | | | | | | |TensorConstant{1.0} [id R]
| | | | | | | |Constant{0} [id S]
| | | | | | |Subtensor{int64} [id T] ''
...
...
@@ -675,20 +675,20 @@ def test_scan_debugprint5():
| | | | | |k [id G]
| | | | | |IncSubtensor{Set;:int64:} [id H] ''
| | | | | |A [id P]
| | | | |DimShuffle{x,x} [id BP] ''
| | | | |
Inplace
DimShuffle{x,x} [id BP] ''
| | | | |TensorConstant{0.0} [id BQ]
| | | |IncSubtensor{Inc;int64} [id BR] ''
| | | | |Elemwise{second,no_inplace} [id BS] ''
| | | | | |Subtensor{int64::} [id BT] ''
| | | | | | |for{cpu,scan_fn} [id BO] ''
| | | | | | |Constant{1} [id BU]
| | | | | |DimShuffle{x,x} [id BV] ''
| | | | | |
Inplace
DimShuffle{x,x} [id BV] ''
| | | | | |TensorConstant{0.0} [id BQ]
| | | | |Elemwise{second} [id BW] ''
| | | | | |Subtensor{int64} [id BX] ''
| | | | | | |Subtensor{int64::} [id BT] ''
| | | | | | |Constant{-1} [id BY]
| | | | | |DimShuffle{x} [id BZ] ''
| | | | | |
Inplace
DimShuffle{x} [id BZ] ''
| | | | | |Elemwise{second,no_inplace} [id CA] ''
| | | | | |Sum{acc_dtype=float64} [id CB] ''
| | | | | | |Subtensor{int64} [id BX] ''
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论