Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
P
pytensor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
testgroup
pytensor
Commits
b19e53c1
提交
b19e53c1
authored
3月 07, 2012
作者:
Olivier Delalleau
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #513 from lamblin/fix_error_type
Fix tests following usage of new exceptions.
上级
941ea07c
f050cdf5
隐藏空白字符变更
内嵌
并排
正在显示
1 个修改的文件
包含
258 行增加
和
243 行删除
+258
-243
test_pfunc.py
theano/compile/tests/test_pfunc.py
+258
-243
没有找到文件。
theano/compile/tests/test_pfunc.py
浏览文件 @
b19e53c1
import
copy
import
unittest
from
nose.plugins.skip
import
SkipTest
...
...
@@ -25,7 +24,7 @@ class Test_pfunc(unittest.TestCase):
# Example #1.
a
=
lscalar
()
b
=
shared
(
1
)
f1
=
pfunc
([
a
],
a
+
b
)
f1
=
pfunc
([
a
],
(
a
+
b
)
)
f2
=
pfunc
([
Param
(
a
,
default
=
44
)],
a
+
b
,
updates
=
{
b
:
b
+
1
})
self
.
assertTrue
(
b
.
get_value
()
==
1
)
self
.
assertTrue
(
f1
(
3
)
==
4
)
...
...
@@ -48,22 +47,24 @@ class Test_pfunc(unittest.TestCase):
def
test_shared
(
self
):
# CHECK: two functions (f1 and f2) can share w
w
=
shared
(
numpy
.
random
.
rand
(
2
,
2
),
'w'
)
w
=
shared
(
numpy
.
random
.
rand
(
2
,
2
),
'w'
)
wval
=
w
.
get_value
(
borrow
=
False
)
x
=
dmatrix
()
out1
=
w
+
x
out2
=
w
*
x
f1
=
pfunc
([
x
],[
out1
])
f2
=
pfunc
([
x
],[
out2
])
xval
=
numpy
.
random
.
rand
(
2
,
2
)
f1
=
pfunc
([
x
],
[
out1
])
f2
=
pfunc
([
x
],
[
out2
])
xval
=
numpy
.
random
.
rand
(
2
,
2
)
assert
numpy
.
all
(
f1
(
xval
)
==
xval
+
wval
)
assert
numpy
.
all
(
f2
(
xval
)
==
xval
*
wval
)
# CHECK: updating a shared value
f3
=
pfunc
([
x
],
out1
,
updates
=
[(
w
,
w
-
1
)])
assert
numpy
.
all
(
f3
(
xval
)
==
xval
+
wval
)
# f3 changes the value of w
assert
numpy
.
all
(
f1
(
xval
)
==
xval
+
(
wval
-
1
))
# this same value is read by f1
f3
=
pfunc
([
x
],
out1
,
updates
=
[(
w
,
(
w
-
1
))])
# f3 changes the value of w
assert
numpy
.
all
(
f3
(
xval
)
==
xval
+
wval
)
# this same value is read by f1
assert
numpy
.
all
(
f1
(
xval
)
==
xval
+
(
wval
-
1
))
w
.
set_value
(
w
.
get_value
(
borrow
=
True
)
*
10
,
borrow
=
True
)
# this same value is read by f1
...
...
@@ -71,10 +72,10 @@ class Test_pfunc(unittest.TestCase):
def
test_no_shared_as_input
(
self
):
"""Test that shared variables cannot be used as function inputs."""
w_init
=
numpy
.
random
.
rand
(
2
,
2
)
w_init
=
numpy
.
random
.
rand
(
2
,
2
)
w
=
shared
(
w_init
.
copy
(),
'w'
)
try
:
f
=
pfunc
([
w
],
theano
.
tensor
.
sum
(
w
*
w
))
pfunc
([
w
],
theano
.
tensor
.
sum
(
w
*
w
))
assert
False
except
TypeError
,
e
:
msg
=
'Cannot use a shared variable (w) as explicit input'
...
...
@@ -88,13 +89,13 @@ class Test_pfunc(unittest.TestCase):
rng
=
numpy
.
random
.
RandomState
(
1827
)
w_init
=
rng
.
rand
(
5
)
w
=
shared
(
w_init
.
copy
(),
'w'
)
reg
=
theano
.
tensor
.
sum
(
w
*
w
)
reg
=
theano
.
tensor
.
sum
(
w
*
w
)
f
=
pfunc
([],
reg
)
assert
f
()
==
numpy
.
sum
(
w_init
*
w_init
)
# Change the value of w and ensure the output changes accordingly.
w
.
set_value
(
w
.
get_value
(
borrow
=
True
)
+
1.0
,
borrow
=
True
)
assert
f
()
==
numpy
.
sum
((
w_init
+
1
)
**
2
)
assert
f
()
==
numpy
.
sum
((
w_init
+
1
)
**
2
)
def
test_default_scalar_container
(
self
):
# Similar in spirit to test_default_container, but updating a scalar
...
...
@@ -112,77 +113,79 @@ class Test_pfunc(unittest.TestCase):
out
=
a
+
b
f
=
pfunc
([
Param
(
a
,
strict
=
False
)],
[
out
])
f
(
numpy
.
random
.
rand
(
8
))
# works, rand generates float64 by default
f
(
numpy
.
array
([
1
,
2
,
3
,
4
],
dtype
=
'int32'
))
# works, casting is allowed
# works, rand generates float64 by default
f
(
numpy
.
random
.
rand
(
8
))
# works, casting is allowed
f
(
numpy
.
array
([
1
,
2
,
3
,
4
],
dtype
=
'int32'
))
f
=
pfunc
([
Param
(
a
,
strict
=
True
)],
[
out
])
try
:
f
(
numpy
.
array
([
1
,
2
,
3
,
4
],
dtype
=
'int32'
))
# fails, f expects float64
# fails, f expects float64
f
(
numpy
.
array
([
1
,
2
,
3
,
4
],
dtype
=
'int32'
))
except
TypeError
:
pass
def
test_param_mutable
(
self
):
a
=
tensor
.
dvector
()
b
=
shared
(
7
)
out
=
a
+
b
a_out
=
a
*
2
# assuming the op which makes this "in place" triggers
a_out
=
a
*
2
# assuming the op which makes this "in place" triggers
# using mutable=True will let fip change the value in aval
fip
=
pfunc
([
Param
(
a
,
mutable
=
True
)],
[
a_out
],
mode
=
'FAST_RUN'
)
aval
=
numpy
.
random
.
rand
(
10
)
aval2
=
aval
.
copy
()
assert
numpy
.
all
(
fip
(
aval
)
==
aval2
*
2
)
assert
not
numpy
.
all
(
aval
==
aval2
)
assert
numpy
.
all
(
fip
(
aval
)
==
(
aval2
*
2
)
)
assert
not
numpy
.
all
(
aval
==
aval2
)
# using mutable=False should leave the input untouched
f
=
pfunc
([
Param
(
a
,
mutable
=
False
)],
[
a_out
],
mode
=
'FAST_RUN'
)
aval
=
numpy
.
random
.
rand
(
10
)
aval2
=
aval
.
copy
()
assert
numpy
.
all
(
f
(
aval
)
==
aval2
*
2
)
assert
numpy
.
all
(
aval
==
aval2
)
assert
numpy
.
all
(
f
(
aval
)
==
(
aval2
*
2
)
)
assert
numpy
.
all
(
aval
==
aval2
)
def
test_shared_mutable
(
self
):
bval
=
numpy
.
arange
(
5
)
b
=
shared
(
bval
)
b_out
=
b
*
2
assert
b
.
get_value
(
borrow
=
True
)
is
not
bval
# shared vars copy args.
bval
=
data_of
(
b
)
# so we do this to get at the underlying data
# shared vars copy args.
assert
b
.
get_value
(
borrow
=
True
)
is
not
bval
# so we do this to get at the underlying data
bval
=
data_of
(
b
)
# by default, shared are not mutable unless doing an explicit update
f
=
pfunc
([],
[
b_out
],
mode
=
'FAST_RUN'
)
assert
(
f
()
==
numpy
.
arange
(
5
)
*
2
)
.
all
()
assert
(
f
()
==
numpy
.
arange
(
5
)
*
2
)
.
all
()
assert
numpy
.
all
(
b
.
get_value
(
borrow
=
True
)
==
numpy
.
arange
(
5
))
# using updates, b is now a mutable parameter
f
=
pfunc
([],
[
b_out
],
updates
=
[(
b
,
b_out
)],
mode
=
'FAST_RUN'
)
assert
(
f
()
==
numpy
.
arange
(
5
)
*
2
)
.
all
()
assert
(
f
()
==
(
numpy
.
arange
(
5
)
*
2
)
)
.
all
()
# because of the update
assert
(
b
.
get_value
(
borrow
=
True
)
==
numpy
.
arange
(
5
)
*
2
)
.
all
()
assert
(
bval
==
numpy
.
arange
(
5
)
*
2
)
.
all
()
# because of mutable=True
assert
(
b
.
get_value
(
borrow
=
True
)
==
(
numpy
.
arange
(
5
)
*
2
)
)
.
all
()
assert
(
bval
==
(
numpy
.
arange
(
5
)
*
2
))
.
all
()
# because of mutable=True
# do not depend on updates being in-place though!
bval
=
numpy
.
arange
(
5
)
b
.
set_value
(
bval
,
borrow
=
True
)
bval
=
data_of
(
b
)
f
=
pfunc
([],
[
b_out
],
updates
=
[(
b
,
b_out
+
3
)],
mode
=
'FAST_RUN'
)
assert
(
f
()
==
numpy
.
arange
(
5
)
*
2
)
.
all
()
f
=
pfunc
([],
[
b_out
],
updates
=
[(
b
,
(
b_out
+
3
)
)],
mode
=
'FAST_RUN'
)
assert
(
f
()
==
(
numpy
.
arange
(
5
)
*
2
)
)
.
all
()
# because of the update
assert
(
b
.
get_value
(
borrow
=
True
)
==
((
numpy
.
arange
(
5
)
*
2
)
+
3
))
.
all
()
assert
(
b
.
get_value
(
borrow
=
True
)
==
((
numpy
.
arange
(
5
)
*
2
)
+
3
))
.
all
()
# bval got modified to something...
assert
not
(
bval
==
numpy
.
arange
(
5
))
.
all
()
# ... but not to b.value !
assert
not
(
bval
==
b
.
get_value
(
borrow
=
True
))
.
all
()
def
test_param_allow_downcast_int
(
self
):
a
=
tensor
.
wvector
(
'a'
)
# int16
b
=
tensor
.
bvector
(
'b'
)
# int8
c
=
tensor
.
bscalar
(
'c'
)
# int8
a
=
tensor
.
wvector
(
'a'
)
# int16
b
=
tensor
.
bvector
(
'b'
)
# int8
c
=
tensor
.
bscalar
(
'c'
)
# int8
f
=
pfunc
([
Param
(
a
,
allow_downcast
=
True
),
Param
(
b
,
allow_downcast
=
False
),
Param
(
c
,
allow_downcast
=
None
)],
a
+
b
+
c
)
(
a
+
b
+
c
)
)
# Both values are in range. Since they're not ndarrays (but lists),
# they will be converted, and their value checked.
...
...
@@ -195,7 +198,7 @@ class Test_pfunc(unittest.TestCase):
[
3
],
numpy
.
array
([
6
],
dtype
=
'int16'
),
1
)
# Value too big for a, silently ignored
assert
numpy
.
all
(
f
([
2
**
20
],
numpy
.
ones
(
1
,
dtype
=
'int8'
),
1
)
==
2
)
assert
numpy
.
all
(
f
([
2
**
20
],
numpy
.
ones
(
1
,
dtype
=
'int8'
),
1
)
==
2
)
# Value too big for b, raises TypeError
self
.
assertRaises
(
TypeError
,
f
,
[
3
],
[
312
],
1
)
...
...
@@ -211,7 +214,7 @@ class Test_pfunc(unittest.TestCase):
f
=
pfunc
([
Param
(
a
,
allow_downcast
=
True
),
Param
(
b
,
allow_downcast
=
False
),
Param
(
c
,
allow_downcast
=
None
)],
a
+
b
+
c
)
(
a
+
b
+
c
)
)
# If the values can be accurately represented, everything is OK
assert
numpy
.
all
(
f
(
0
,
0
,
0
)
==
0
)
...
...
@@ -236,7 +239,7 @@ class Test_pfunc(unittest.TestCase):
f
=
pfunc
([
Param
(
a
,
allow_downcast
=
True
),
Param
(
b
,
allow_downcast
=
False
),
Param
(
c
,
allow_downcast
=
None
)],
a
+
b
+
c
)
(
a
+
b
+
c
)
)
# If the values can be accurately represented, everything is OK
z
=
[
0
]
...
...
@@ -252,17 +255,17 @@ class Test_pfunc(unittest.TestCase):
self
.
assertRaises
(
TypeError
,
f
,
z
,
z
,
[
0.1
])
def
test_allow_input_downcast_int
(
self
):
a
=
tensor
.
wvector
(
'a'
)
# int16
b
=
tensor
.
bvector
(
'b'
)
# int8
c
=
tensor
.
bscalar
(
'c'
)
# int8
a
=
tensor
.
wvector
(
'a'
)
# int16
b
=
tensor
.
bvector
(
'b'
)
# int8
c
=
tensor
.
bscalar
(
'c'
)
# int8
f
=
pfunc
([
a
,
b
,
c
],
a
+
b
+
c
,
allow_input_downcast
=
True
)
f
=
pfunc
([
a
,
b
,
c
],
(
a
+
b
+
c
)
,
allow_input_downcast
=
True
)
# Value too big for a, b, or c, silently ignored
assert
f
([
2
**
20
],
[
1
],
0
)
==
1
assert
f
([
2
**
20
],
[
1
],
0
)
==
1
assert
f
([
3
],
[
312
],
0
)
==
59
assert
f
([
3
],
[
1
],
806
)
==
42
g
=
pfunc
([
a
,
b
,
c
],
a
+
b
+
c
,
allow_input_downcast
=
False
)
g
=
pfunc
([
a
,
b
,
c
],
(
a
+
b
+
c
)
,
allow_input_downcast
=
False
)
# All values are in range. Since they're not ndarrays (but lists
# or scalars), they will be converted, and their value checked.
assert
numpy
.
all
(
g
([
3
],
[
6
],
0
)
==
9
)
...
...
@@ -276,7 +279,7 @@ class Test_pfunc(unittest.TestCase):
# Value too big for b, raises TypeError
self
.
assertRaises
(
TypeError
,
g
,
[
3
],
[
312
],
0
)
h
=
pfunc
([
a
,
b
,
c
],
a
+
b
+
c
)
# Default: allow_input_downcast=None
h
=
pfunc
([
a
,
b
,
c
],
(
a
+
b
+
c
))
# Default: allow_input_downcast=None
# Everything here should behave like with False
assert
numpy
.
all
(
h
([
3
],
[
6
],
0
)
==
9
)
self
.
assertRaises
(
TypeError
,
h
,
...
...
@@ -287,9 +290,9 @@ class Test_pfunc(unittest.TestCase):
a
=
tensor
.
fscalar
(
'a'
)
b
=
tensor
.
fvector
(
'b'
)
f
=
pfunc
([
a
,
b
],
a
+
b
,
allow_input_downcast
=
True
)
g
=
pfunc
([
a
,
b
],
a
+
b
,
allow_input_downcast
=
False
)
h
=
pfunc
([
a
,
b
],
a
+
b
,
allow_input_downcast
=
None
)
f
=
pfunc
([
a
,
b
],
(
a
+
b
)
,
allow_input_downcast
=
True
)
g
=
pfunc
([
a
,
b
],
(
a
+
b
)
,
allow_input_downcast
=
False
)
h
=
pfunc
([
a
,
b
],
(
a
+
b
)
,
allow_input_downcast
=
None
)
# If the values can be accurately represented, OK
assert
numpy
.
all
(
f
(
0
,
[
0
])
==
0
)
...
...
@@ -315,60 +318,65 @@ class Test_pfunc(unittest.TestCase):
# Simple value assignment.
x
=
shared
(
0
)
assign
=
pfunc
([],
[],
updates
=
{
x
:
3
})
assign
=
pfunc
([],
[],
updates
=
{
x
:
3
})
assign
()
self
.
assertTrue
(
x
.
get_value
()
==
3
)
# Basic increment function.
x
.
set_value
(
0
)
inc
=
pfunc
([],
[],
updates
=
{
x
:
x
+
1
})
inc
=
pfunc
([],
[],
updates
=
{
x
:
x
+
1
})
inc
()
self
.
assertTrue
(
x
.
get_value
()
==
1
)
# Increment by a constant value.
x
.
set_value
(
-
1
)
y
=
shared
(
2
)
inc_by_y
=
pfunc
([],
[],
updates
=
{
x
:
x
+
y
})
inc_by_y
=
pfunc
([],
[],
updates
=
{
x
:
x
+
y
})
inc_by_y
()
self
.
assertTrue
(
x
.
get_value
()
==
1
)
def
test_duplicate_updates
(
self
):
x
,
y
=
dmatrices
(
'x'
,
'y'
)
z
=
shared
(
numpy
.
ones
((
2
,
3
)))
self
.
assertRaises
(
ValueError
,
theano
.
function
,
[
x
,
y
],
[
z
],
updates
=
[(
z
,
z
+
x
+
y
),
(
z
,
z
-
x
)])
z
=
shared
(
numpy
.
ones
((
2
,
3
)))
self
.
assertRaises
(
ValueError
,
theano
.
function
,
[
x
,
y
],
[
z
],
updates
=
[(
z
,
(
z
+
x
+
y
)),
(
z
,
(
z
-
x
))])
def
test_givens
(
self
):
x
=
shared
(
0
)
assign
=
pfunc
([],
x
,
givens
=
{
x
:
3
})
assign
=
pfunc
([],
x
,
givens
=
{
x
:
3
})
assert
assign
()
==
3
assert
x
.
get_value
(
borrow
=
True
)
==
0
y
=
tensor
.
ivector
()
f
=
pfunc
([
y
],
y
*
x
,
givens
=
{
x
:
6
})
assert
numpy
.
all
(
f
([
1
,
1
,
1
])
==
[
6
,
6
,
6
])
f
=
pfunc
([
y
],
(
y
*
x
),
givens
=
{
x
:
6
})
assert
numpy
.
all
(
f
([
1
,
1
,
1
])
==
[
6
,
6
,
6
])
assert
x
.
get_value
()
==
0
z
=
tensor
.
ivector
()
c
=
z
*
y
f
=
pfunc
([
y
],
c
+
7
,
givens
=
{
z
:
theano
.
_asarray
([
4
,
4
,
4
],
dtype
=
'int32'
)})
assert
numpy
.
all
(
f
([
1
,
1
,
1
])
==
[
11
,
11
,
11
])
c
=
z
*
y
f
=
pfunc
([
y
],
(
c
+
7
),
givens
=
{
z
:
theano
.
_asarray
([
4
,
4
,
4
],
dtype
=
'int32'
)})
assert
numpy
.
all
(
f
([
1
,
1
,
1
])
==
[
11
,
11
,
11
])
assert
x
.
get_value
()
==
0
def
test_clone0
(
self
):
x
=
shared
(
numpy
.
asarray
([
4
,
4
,
4
]))
y
=
shared
(
numpy
.
asarray
([
4
,
4
,
4
]))
z
=
shared
(
numpy
.
asarray
([
2
,
2
,
2
]))
up
=
pfunc
([],
[],
updates
=
{
x
:
(
x
*
5
),
y
:(
x
*
5
)
+
y
,
z
:
((
x
*
5
)
+
y
)
**
z
})
x
=
shared
(
numpy
.
asarray
([
4
,
4
,
4
]))
y
=
shared
(
numpy
.
asarray
([
4
,
4
,
4
]))
z
=
shared
(
numpy
.
asarray
([
2
,
2
,
2
]))
up
=
pfunc
([],
[],
updates
=
{
x
:
(
x
*
5
),
y
:
((
x
*
5
)
+
y
),
z
:
(((
x
*
5
)
+
y
)
**
z
)})
up
()
print
x
.
get_value
(
borrow
=
True
)
assert
numpy
.
all
(
x
.
get_value
()
==
20
)
assert
numpy
.
all
(
y
.
get_value
()
==
24
)
assert
numpy
.
all
(
z
.
get_value
()
==
24
**
2
)
assert
numpy
.
all
(
x
.
get_value
()
==
20
)
assert
numpy
.
all
(
y
.
get_value
()
==
24
)
assert
numpy
.
all
(
z
.
get_value
()
==
(
24
**
2
)
)
def
test_default_updates
(
self
):
x
=
shared
(
0
)
x
.
default_update
=
x
+
1
x
.
default_update
=
x
+
1
f
=
pfunc
([],
[
x
])
f
()
...
...
@@ -386,7 +394,7 @@ class Test_pfunc(unittest.TestCase):
def
test_no_default_updates
(
self
):
x
=
shared
(
0
)
y
=
shared
(
1
)
x
.
default_update
=
x
+
2
x
.
default_update
=
x
+
2
# Test that the default update is taken into account in the right cases
f1
=
pfunc
([],
[
x
],
no_default_updates
=
True
)
...
...
@@ -421,35 +429,36 @@ class Test_pfunc(unittest.TestCase):
self
.
assertRaises
(
TypeError
,
pfunc
,
[],
[
x
],
no_default_updates
=
(
x
))
self
.
assertRaises
(
TypeError
,
pfunc
,
[],
[
x
],
no_default_updates
=
x
)
self
.
assertRaises
(
TypeError
,
pfunc
,
[],
[
x
],
no_default_updates
=
'canard'
)
self
.
assertRaises
(
TypeError
,
pfunc
,
[],
[
x
],
no_default_updates
=
'canard'
)
# Mix explicit updates and no_default_updates
g1
=
pfunc
([],
[
x
],
updates
=
[(
x
,
x
-
1
)],
no_default_updates
=
True
)
g1
=
pfunc
([],
[
x
],
updates
=
[(
x
,
(
x
-
1
)
)],
no_default_updates
=
True
)
g1
()
print
x
.
get_value
()
assert
x
.
get_value
()
==
5
g2
=
pfunc
([],
[
x
],
updates
=
[(
x
,
x
-
1
)],
no_default_updates
=
[
x
])
g2
=
pfunc
([],
[
x
],
updates
=
[(
x
,
(
x
-
1
)
)],
no_default_updates
=
[
x
])
g2
()
print
x
.
get_value
()
assert
x
.
get_value
()
==
4
g3
=
pfunc
([],
[
x
],
updates
=
[(
x
,
x
-
1
)],
no_default_updates
=
[
x
,
y
])
g3
=
pfunc
([],
[
x
],
updates
=
[(
x
,
(
x
-
1
)
)],
no_default_updates
=
[
x
,
y
])
g3
()
print
x
.
get_value
()
assert
x
.
get_value
()
==
3
g4
=
pfunc
([],
[
x
],
updates
=
[(
x
,
x
-
1
)],
no_default_updates
=
[
y
])
g4
=
pfunc
([],
[
x
],
updates
=
[(
x
,
(
x
-
1
)
)],
no_default_updates
=
[
y
])
g4
()
print
x
.
get_value
()
assert
x
.
get_value
()
==
2
g5
=
pfunc
([],
[
x
],
updates
=
[(
x
,
x
-
1
)],
no_default_updates
=
[])
g5
=
pfunc
([],
[
x
],
updates
=
[(
x
,
(
x
-
1
)
)],
no_default_updates
=
[])
g5
()
print
x
.
get_value
()
assert
x
.
get_value
()
==
1
g5
=
pfunc
([],
[
x
],
updates
=
[(
x
,
x
-
1
)],
no_default_updates
=
False
)
g5
=
pfunc
([],
[
x
],
updates
=
[(
x
,
(
x
-
1
)
)],
no_default_updates
=
False
)
g5
()
print
x
.
get_value
()
assert
x
.
get_value
()
==
0
...
...
@@ -459,8 +468,8 @@ class Test_pfunc(unittest.TestCase):
y
=
shared
(
1
)
a
=
lscalar
(
'a'
)
z
=
a
*
x
x
.
default_update
=
x
+
y
z
=
a
*
x
x
.
default_update
=
x
+
y
f1
=
pfunc
([
a
],
z
)
f1
(
12
)
...
...
@@ -481,25 +490,25 @@ class Test_pfunc(unittest.TestCase):
x
=
shared
(
0
)
y
=
shared
(
1
)
x
.
default_update
=
x
-
1
y
.
default_update
=
y
+
1
x
.
default_update
=
x
-
1
y
.
default_update
=
y
+
1
f1
=
pfunc
([],
[
x
,
y
])
f1
=
pfunc
([],
[
x
,
y
])
f1
()
assert
x
.
get_value
()
==
-
1
assert
y
.
get_value
()
==
2
f2
=
pfunc
([],
[
x
,
y
],
updates
=
[(
x
,
x
-
2
)],
no_default_updates
=
[
y
])
f2
=
pfunc
([],
[
x
,
y
],
updates
=
[(
x
,
(
x
-
2
)
)],
no_default_updates
=
[
y
])
f2
()
assert
x
.
get_value
()
==
-
3
assert
y
.
get_value
()
==
2
f3
=
pfunc
([],
[
x
,
y
],
updates
=
[(
x
,
x
-
2
)],
no_default_updates
=
True
)
f3
=
pfunc
([],
[
x
,
y
],
updates
=
[(
x
,
(
x
-
2
)
)],
no_default_updates
=
True
)
f3
()
assert
x
.
get_value
()
==
-
5
assert
y
.
get_value
()
==
2
f4
=
pfunc
([],
[
x
,
y
],
updates
=
[(
y
,
y
-
2
)])
f4
=
pfunc
([],
[
x
,
y
],
updates
=
[(
y
,
(
y
-
2
)
)])
f4
()
assert
x
.
get_value
()
==
-
6
assert
y
.
get_value
()
==
0
...
...
@@ -509,9 +518,9 @@ class Test_pfunc(unittest.TestCase):
y
=
shared
(
1
)
z
=
shared
(
-
1
)
x
.
default_update
=
x
-
y
x
.
default_update
=
x
-
y
y
.
default_update
=
z
z
.
default_update
=
z
-
1
z
.
default_update
=
z
-
1
f1
=
pfunc
([],
[
x
])
f1
()
...
...
@@ -532,29 +541,28 @@ class Test_pfunc(unittest.TestCase):
assert
y
.
get_value
()
==
-
3
assert
z
.
get_value
()
==
-
4
f4
=
pfunc
([],
[
x
,
y
],
no_default_updates
=
[
x
])
f4
=
pfunc
([],
[
x
,
y
],
no_default_updates
=
[
x
])
f4
()
assert
x
.
get_value
()
==
2
assert
y
.
get_value
()
==
-
4
assert
z
.
get_value
()
==
-
5
f5
=
pfunc
([],
[
x
,
y
,
z
],
no_default_updates
=
[
z
])
f5
=
pfunc
([],
[
x
,
y
,
z
],
no_default_updates
=
[
z
])
f5
()
assert
x
.
get_value
()
==
6
assert
y
.
get_value
()
==
-
5
assert
z
.
get_value
()
==
-
5
def
test_default_updates_input
(
self
):
x
=
shared
(
0
)
y
=
shared
(
1
)
if
theano
.
gof
.
cmodule
.
local_bitwidth
()
==
32
:
if
theano
.
gof
.
cmodule
.
local_bitwidth
()
==
32
:
a
=
iscalar
(
'a'
)
else
:
a
=
lscalar
(
'a'
)
x
.
default_update
=
y
y
.
default_update
=
y
+
a
y
.
default_update
=
y
+
a
f1
=
pfunc
([],
x
,
no_default_updates
=
True
)
f1
()
...
...
@@ -576,18 +584,18 @@ class Test_pfunc(unittest.TestCase):
assert
x
.
get_value
()
==
1
assert
y
.
get_value
()
==
3
f5
=
pfunc
([],
x
,
updates
=
{
y
:
y
-
1
})
f5
=
pfunc
([],
x
,
updates
=
{
y
:
(
y
-
1
)
})
f5
()
assert
x
.
get_value
()
==
3
assert
y
.
get_value
()
==
2
# a is needed as input if y.default_update is used
self
.
assertRaises
(
Type
Error
,
pfunc
,
[],
x
)
self
.
assertRaises
(
theano
.
gof
.
MissingInput
Error
,
pfunc
,
[],
x
)
def
test_default_updates_partial_graph
(
self
):
a
=
shared
(
0
)
a
.
default_update
=
a
+
1
# Increment a each time it is used
b
=
2
*
a
a
.
default_update
=
a
+
1
# Increment a each time it is used
b
=
2
*
a
# Use only the tip of the graph, a is not used
f
=
pfunc
([
b
],
b
)
print
'a.get_value() ='
,
a
.
get_value
()
...
...
@@ -596,54 +604,53 @@ class Test_pfunc(unittest.TestCase):
print
'a.get_value() ='
,
a
.
get_value
()
assert
a
.
get_value
()
==
0
def
test_givens_replaces_shared_variable
(
self
):
a
=
shared
(
1.
,
'a'
)
a
.
default_update
=
a
+
3.
a
=
shared
(
1.
,
'a'
)
a
.
default_update
=
a
+
3.
b
=
tensor
.
dscalar
(
'b'
)
c
=
a
+
10
f
=
pfunc
([
b
],
c
,
givens
=
{
a
:
b
})
f
=
pfunc
([
b
],
c
,
givens
=
{
a
:
b
})
assert
len
(
f
.
maker
.
env
.
inputs
)
==
1
assert
len
(
f
.
maker
.
env
.
outputs
)
==
1
def
test_givens_replaces_shared_variable2
(
self
):
a
=
shared
(
1.
,
'a'
)
a
.
default_update
=
a
+
3
c
=
a
+
10
f
=
pfunc
([],
c
,
givens
=
{
a
:
a
+
10
}
)
a
=
shared
(
1.
,
'a'
)
a
.
default_update
=
a
+
3
c
=
a
+
10
f
=
pfunc
([],
c
,
givens
=
{
a
:
(
a
+
10
)}
)
assert
f
()
==
21
assert
f
()
==
34
def
test_duplicate_inputs
(
self
):
x
=
theano
.
tensor
.
lscalar
(
'x'
)
self
.
assertRaises
(
ValueError
,
theano
.
function
,
[
x
,
x
,
x
],
x
)
self
.
assertRaises
(
theano
.
compile
.
UnusedInputError
,
theano
.
function
,
[
x
,
x
,
x
],
x
)
class
Test_aliasing_rules
(
unittest
.
TestCase
):
"""
1. Theano manages its own memory space, which typically does not overlap
with the memory of
normal python variables that the user uses.
1. Theano manages its own memory space, which typically does not overlap
with the memory of
normal python variables that the user uses.
2. shared variables are allocated in this memory space, as are the
temporaries used for
Function evalution.
2. shared variables are allocated in this memory space, as are the
temporaries used for
Function evalution.
3. Physically, this managed memory space may be spread across the host,
on a GPU device(s),
or even on a remote machine.
3. Physically, this managed memory space may be spread across the host,
o
n a GPU device(s), o
r even on a remote machine.
4. Theano assumes that shared variables are never aliased to one another,
and tries to make
it impossible to accidentally alias them.
4. Theano assumes that shared variables are never aliased to one another,
and tries to make
it impossible to accidentally alias them.
5. Theano's managed data is constant while Theano Functions are not running
and theano
library code is not running.
5. Theano's managed data is constant while Theano Functions are not running
and theano
library code is not running.
6. The default behaviour of Function is to return user-space values for outputs, but this
can be overridden (borrow=True) for better performance, in which case the returned value
may be aliased to managed memory, and potentially invalidated by the next Theano Function
call or call to theano library code.
6. The default behaviour of Function is to return user-space values for
outputs, but this can be overridden (borrow=True) for better performance,
in which case the returned value may be aliased to managed memory, and
potentially invalidated by the next Theano Function call or call to theano
library code.
"""
def
shared
(
self
,
x
):
...
...
@@ -652,12 +659,13 @@ class Test_aliasing_rules(unittest.TestCase):
def
test_shared_constructor_copies
(
self
):
# shared constructor makes copy
# (rule #2)
orig_a
=
numpy
.
zeros
((
2
,
2
))
orig_a
=
numpy
.
zeros
((
2
,
2
))
A
=
self
.
shared
(
orig_a
)
assert
not
numpy
.
may_share_memory
(
orig_a
,
data_of
(
A
))
# rule #2 reading back from theano-managed memory
assert
not
numpy
.
may_share_memory
(
A
.
get_value
(
borrow
=
False
),
data_of
(
A
))
assert
not
numpy
.
may_share_memory
(
A
.
get_value
(
borrow
=
False
),
data_of
(
A
))
def
test_sparse_input_aliasing_affecting_inplace_operations
(
self
):
##
...
...
@@ -680,30 +688,32 @@ class Test_aliasing_rules(unittest.TestCase):
# operations are used) and to break the elemwise composition
# with some non-elemwise op (here dot)
x
=
sparse
.
SparseType
(
'csc'
,
dtype
=
'float64'
)()
y
=
sparse
.
SparseType
(
'csc'
,
dtype
=
'float64'
)()
f
=
theano
.
function
(
[
theano
.
In
(
x
,
mutable
=
True
),
theano
.
In
(
y
,
mutable
=
True
)],
(
x
+
y
)
+
(
x
+
y
))
x
=
sparse
.
SparseType
(
'csc'
,
dtype
=
'float64'
)()
y
=
sparse
.
SparseType
(
'csc'
,
dtype
=
'float64'
)()
f
=
theano
.
function
(
[
theano
.
In
(
x
,
mutable
=
True
),
theano
.
In
(
y
,
mutable
=
True
)],
(
x
+
y
)
+
(
x
+
y
))
## Test 1. If the same variable is given twice
# Compute bogus values
m
=
sp
.
csc_matrix
(
numpy
.
asarray
([[
1
,
0
,
0
,
0
,
0
],
[
0
,
1
,
0
,
0
,
0
],
[
0
,
0
,
1
,
0
,
0
],
[
0
,
0
,
0
,
1
,
0
],
[
0
,
0
,
0
,
0
,
1
]],
dtype
=
'float64'
))
bogus_vals
=
f
(
m
,
m
)
m
=
sp
.
csc_matrix
(
numpy
.
asarray
(
[[
1
,
0
,
0
,
0
,
0
],
[
0
,
1
,
0
,
0
,
0
],
[
0
,
0
,
1
,
0
,
0
],
[
0
,
0
,
0
,
1
,
0
],
[
0
,
0
,
0
,
0
,
1
]],
dtype
=
'float64'
))
bogus_vals
=
f
(
m
,
m
)
# Since we used inplace operation v and m may be corrupted
# so we need to recreate them
m
=
sp
.
csc_matrix
(
numpy
.
asarray
([[
1
,
0
,
0
,
0
,
0
],
[
0
,
1
,
0
,
0
,
0
],
[
0
,
0
,
1
,
0
,
0
],
[
0
,
0
,
0
,
1
,
0
],
[
0
,
0
,
0
,
0
,
1
]],
dtype
=
'float64'
))
m
=
sp
.
csc_matrix
(
numpy
.
asarray
(
[[
1
,
0
,
0
,
0
,
0
],
[
0
,
1
,
0
,
0
,
0
],
[
0
,
0
,
1
,
0
,
0
],
[
0
,
0
,
0
,
1
,
0
],
[
0
,
0
,
0
,
0
,
1
]],
dtype
=
'float64'
))
m_copy
=
m
.
copy
()
vals
=
f
(
m
,
m_copy
)
vals
=
f
(
m
,
m_copy
)
assert
numpy
.
allclose
(
vals
.
todense
(),
bogus_vals
.
todense
())
...
...
@@ -713,37 +723,37 @@ class Test_aliasing_rules(unittest.TestCase):
# you need to make in inputs mutable (so that inplace
# operations are used) and to break the elemwise composition
# with some non-elemwise op (here dot)
x
=
theano
.
tensor
.
dvector
()
y
=
theano
.
tensor
.
dvector
()
x
=
theano
.
tensor
.
dvector
()
y
=
theano
.
tensor
.
dvector
()
m1
=
theano
.
tensor
.
dmatrix
()
m2
=
theano
.
tensor
.
dmatrix
()
f
=
theano
.
function
(
[
theano
.
In
(
x
,
mutable
=
True
),
theano
.
In
(
y
,
mutable
=
True
),
theano
.
In
(
m1
,
mutable
=
True
),
theano
.
In
(
m2
,
mutable
=
True
)],
theano
.
dot
(
x
*
2
,
m1
)
+
theano
.
dot
(
y
*
3
,
m2
))
f
=
theano
.
function
(
[
theano
.
In
(
x
,
mutable
=
True
),
theano
.
In
(
y
,
mutable
=
True
),
theano
.
In
(
m1
,
mutable
=
True
),
theano
.
In
(
m2
,
mutable
=
True
)],
theano
.
dot
(
(
x
*
2
),
m1
)
+
theano
.
dot
((
y
*
3
),
m2
))
## Test 1. If the same variable is given twice
# Compute bogus values
v
=
numpy
.
asarray
(
[
1
,
2
,
3
,
4
,
5
],
dtype
=
'float64'
)
m
=
numpy
.
asarray
([[
1
,
0
,
0
,
0
,
0
],
[
0
,
1
,
0
,
0
,
0
],
[
0
,
0
,
1
,
0
,
0
],
[
0
,
0
,
0
,
1
,
0
],
[
0
,
0
,
0
,
0
,
1
]],
dtype
=
'float64'
)
bogus_vals
=
f
(
v
,
v
,
m
,
m
)
v
=
numpy
.
asarray
(
[
1
,
2
,
3
,
4
,
5
],
dtype
=
'float64'
)
m
=
numpy
.
asarray
([[
1
,
0
,
0
,
0
,
0
],
[
0
,
1
,
0
,
0
,
0
],
[
0
,
0
,
1
,
0
,
0
],
[
0
,
0
,
0
,
1
,
0
],
[
0
,
0
,
0
,
0
,
1
]],
dtype
=
'float64'
)
bogus_vals
=
f
(
v
,
v
,
m
,
m
)
# Since we used inplace operation v and m may be corrupted
# so we need to recreate them
v
=
numpy
.
asarray
(
[
1
,
2
,
3
,
4
,
5
],
dtype
=
'float64'
)
m
=
numpy
.
asarray
([[
1
,
0
,
0
,
0
,
0
],
[
0
,
1
,
0
,
0
,
0
],
[
0
,
0
,
1
,
0
,
0
],
[
0
,
0
,
0
,
1
,
0
],
[
0
,
0
,
0
,
0
,
1
]],
dtype
=
'float64'
)
v
=
numpy
.
asarray
(
[
1
,
2
,
3
,
4
,
5
],
dtype
=
'float64'
)
m
=
numpy
.
asarray
([[
1
,
0
,
0
,
0
,
0
],
[
0
,
1
,
0
,
0
,
0
],
[
0
,
0
,
1
,
0
,
0
],
[
0
,
0
,
0
,
1
,
0
],
[
0
,
0
,
0
,
0
,
1
]],
dtype
=
'float64'
)
m_copy
=
m
.
copy
()
v_copy
=
v
.
copy
()
vals
=
f
(
v
,
v_copy
,
m
,
m_copy
)
vals
=
f
(
v
,
v_copy
,
m
,
m_copy
)
assert
numpy
.
allclose
(
vals
,
bogus_vals
)
...
...
@@ -753,9 +763,9 @@ class Test_aliasing_rules(unittest.TestCase):
# you need to make in inputs mutable ( so that inplace
# operations are used) and to break the elemwise composition
# with some non-elemwise op ( here dot )
x
=
theano
.
tensor
.
dvector
()
y
=
theano
.
tensor
.
dvector
()
z
=
theano
.
tensor
.
dvector
()
x
=
theano
.
tensor
.
dvector
()
y
=
theano
.
tensor
.
dvector
()
z
=
theano
.
tensor
.
dvector
()
m1
=
theano
.
tensor
.
dmatrix
()
m2
=
theano
.
tensor
.
dmatrix
()
m3
=
theano
.
tensor
.
dmatrix
()
...
...
@@ -765,118 +775,121 @@ class Test_aliasing_rules(unittest.TestCase):
# and a shares memory with b, b shares memory with c, but
# c does not share memory with a
f
=
theano
.
function
(
[
theano
.
In
(
x
,
mutable
=
True
),
theano
.
In
(
y
,
mutable
=
True
),
theano
.
In
(
z
,
mutable
=
True
),
theano
.
In
(
m1
,
mutable
=
True
),
theano
.
In
(
m2
,
mutable
=
True
),
theano
.
In
(
m3
,
mutable
=
True
)],
(
theano
.
dot
((
x
*
2
),
m1
)
+
theano
.
dot
((
y
*
3
),
m2
)
+
theano
.
dot
((
z
*
4
),
m3
)))
f
=
theano
.
function
(
[
theano
.
In
(
x
,
mutable
=
True
),
theano
.
In
(
y
,
mutable
=
True
),
theano
.
In
(
z
,
mutable
=
True
),
theano
.
In
(
m1
,
mutable
=
True
),
theano
.
In
(
m2
,
mutable
=
True
),
theano
.
In
(
m3
,
mutable
=
True
)],
theano
.
dot
(
x
*
2
,
m1
)
+
theano
.
dot
(
y
*
3
,
m2
)
+
theano
.
dot
(
z
*
4
,
m3
))
# Compute bogus values
v
=
numpy
.
asarray
(
[
1
,
2
,
3
,
4
,
5
],
dtype
=
'float64'
)
m
=
numpy
.
asarray
([[
1
,
0
],
[
0
,
1
]],
dtype
=
'float64'
)
bogus_vals
=
f
(
v
[:
2
],
v
[
1
:
3
],
v
[
2
:
4
],
m
,
m
,
m
)
v
=
numpy
.
asarray
(
[
1
,
2
,
3
,
4
,
5
],
dtype
=
'float64'
)
m
=
numpy
.
asarray
([[
1
,
0
],
[
0
,
1
]],
dtype
=
'float64'
)
bogus_vals
=
f
(
v
[:
2
],
v
[
1
:
3
],
v
[
2
:
4
],
m
,
m
,
m
)
# Since we used inplace operation v and m may be corrupted
# so we need to recreate them
v
=
numpy
.
asarray
(
[
1
,
2
,
3
,
4
,
5
],
dtype
=
'float64'
)
m
=
numpy
.
asarray
([[
1
,
0
],
[
0
,
1
]],
dtype
=
'float64'
)
v
=
numpy
.
asarray
(
[
1
,
2
,
3
,
4
,
5
],
dtype
=
'float64'
)
m
=
numpy
.
asarray
([[
1
,
0
],
[
0
,
1
]],
dtype
=
'float64'
)
m_copy1
=
m
.
copy
()
v_copy1
=
v
.
copy
()
m_copy2
=
m
.
copy
()
v_copy2
=
v
.
copy
()
vals
=
f
(
v
[:
2
],
v_copy1
[
1
:
3
],
v_copy2
[
2
:
4
],
m
,
m_copy1
,
m_copy2
)
vals
=
f
(
v
[:
2
],
v_copy1
[
1
:
3
],
v_copy2
[
2
:
4
],
m
,
m_copy1
,
m_copy2
)
assert
numpy
.
allclose
(
vals
,
bogus_vals
)
def
test_potential_output_aliasing_induced_by_updates
(
self
):
A
=
self
.
shared
(
numpy
.
zeros
((
2
,
2
)))
B
=
self
.
shared
(
numpy
.
zeros
((
2
,
2
)))
C
=
numpy
.
zeros
((
2
,
2
))
A
=
self
.
shared
(
numpy
.
zeros
((
2
,
2
)))
B
=
self
.
shared
(
numpy
.
zeros
((
2
,
2
)))
C
=
numpy
.
zeros
((
2
,
2
))
D
=
tensor
.
dmatrix
()
DD
=
D
+
5
f
=
pfunc
([
D
],
[],
updates
=
[
(
A
,
D
),
(
B
,
D
)
])
f
=
pfunc
([
D
],
[],
updates
=
[
(
A
,
D
),
(
B
,
D
)
])
f
(
C
)
assert
not
numpy
.
may_share_memory
(
data_of
(
A
),
data_of
(
B
))
f
=
pfunc
([
D
],
[],
updates
=
[
(
A
,
D
[:]),
(
B
,
D
)
])
assert
not
numpy
.
may_share_memory
(
data_of
(
A
),
data_of
(
B
))
f
=
pfunc
([
D
],
[],
updates
=
[
(
A
,
D
[:]),
(
B
,
D
)
])
f
(
C
)
assert
not
numpy
.
may_share_memory
(
data_of
(
A
),
data_of
(
B
))
f
=
pfunc
([
D
],
[],
updates
=
[
(
A
,
D
+
5
),
(
B
,
D
[:])
])
assert
not
numpy
.
may_share_memory
(
data_of
(
A
),
data_of
(
B
))
f
=
pfunc
([
D
],
[],
updates
=
[
(
A
,
(
D
+
5
)),
(
B
,
D
[:])
])
f
(
C
)
assert
not
numpy
.
may_share_memory
(
data_of
(
A
),
data_of
(
B
))
assert
not
numpy
.
may_share_memory
(
data_of
(
A
),
data_of
(
B
))
f
=
pfunc
([
D
],
[],
updates
=
[
(
A
,
D
+
5
),
(
B
,
D
)
])
f
=
pfunc
([
D
],
[],
updates
=
[
(
A
,
(
D
+
5
)),
(
B
,
D
)
])
f
(
C
)
assert
not
numpy
.
may_share_memory
(
data_of
(
A
),
data_of
(
B
))
f
=
pfunc
([
D
],
DD
,
updates
=
[
(
A
,
DD
[:
1
]),
(
B
,
DD
)
])
R
=
f
(
C
)
assert
not
numpy
.
may_share_memory
(
data_of
(
A
),
data_of
(
B
))
assert
not
numpy
.
may_share_memory
(
R
,
data_of
(
B
))
assert
not
numpy
.
may_share_memory
(
R
,
data_of
(
A
))
f
=
pfunc
([
D
],
DD
,
updates
=
[
(
A
,
DD
[:
1
]),
(
B
,
DD
[:
1
]
*
2
)
])
R
=
f
(
C
)
assert
not
numpy
.
may_share_memory
(
data_of
(
A
),
data_of
(
B
))
assert
not
numpy
.
may_share_memory
(
R
,
data_of
(
B
))
assert
not
numpy
.
may_share_memory
(
R
,
data_of
(
A
))
f
=
pfunc
([
D
],
DD
*
4
,
updates
=
[
(
A
,
DD
[:
1
]
*
3
),
(
B
,
DD
[:
1
]
*
2
)
])
R
=
f
(
C
)
assert
not
numpy
.
may_share_memory
(
data_of
(
A
),
data_of
(
B
))
assert
not
numpy
.
may_share_memory
(
R
,
data_of
(
B
))
assert
not
numpy
.
may_share_memory
(
R
,
data_of
(
A
))
f
=
pfunc
([
D
],
DD
*
4
,
updates
=
[
(
A
,
DD
[:
1
]
*
3
),
(
B
,
DD
[:
1
]
*
3
)
])
R
=
f
(
C
)
assert
not
numpy
.
may_share_memory
(
data_of
(
A
),
data_of
(
B
))
assert
not
numpy
.
may_share_memory
(
R
,
data_of
(
B
))
assert
not
numpy
.
may_share_memory
(
R
,
data_of
(
A
))
assert
not
numpy
.
may_share_memory
(
data_of
(
A
),
data_of
(
B
))
f
=
pfunc
([
D
],
DD
,
updates
=
[(
A
,
DD
[:
1
]),
(
B
,
DD
)])
R
=
f
(
C
)
assert
not
numpy
.
may_share_memory
(
data_of
(
A
),
data_of
(
B
))
assert
not
numpy
.
may_share_memory
(
R
,
data_of
(
B
))
assert
not
numpy
.
may_share_memory
(
R
,
data_of
(
A
))
f
=
pfunc
([
D
],
DD
,
updates
=
[(
A
,
DD
[:
1
]),
(
B
,
(
DD
[:
1
]
*
2
))])
R
=
f
(
C
)
assert
not
numpy
.
may_share_memory
(
data_of
(
A
),
data_of
(
B
))
assert
not
numpy
.
may_share_memory
(
R
,
data_of
(
B
))
assert
not
numpy
.
may_share_memory
(
R
,
data_of
(
A
))
f
=
pfunc
([
D
],
(
DD
*
4
),
updates
=
[(
A
,
(
DD
[:
1
]
*
3
)),
(
B
,
(
DD
[:
1
]
*
2
))])
R
=
f
(
C
)
assert
not
numpy
.
may_share_memory
(
data_of
(
A
),
data_of
(
B
))
assert
not
numpy
.
may_share_memory
(
R
,
data_of
(
B
))
assert
not
numpy
.
may_share_memory
(
R
,
data_of
(
A
))
f
=
pfunc
([
D
],
(
DD
*
4
),
updates
=
[(
A
,
(
DD
[:
1
]
*
3
)),
(
B
,
(
DD
[:
1
]
*
3
))])
R
=
f
(
C
)
assert
not
numpy
.
may_share_memory
(
data_of
(
A
),
data_of
(
B
))
assert
not
numpy
.
may_share_memory
(
R
,
data_of
(
B
))
assert
not
numpy
.
may_share_memory
(
R
,
data_of
(
A
))
def
test_no_aliasing_0
(
self
):
# B is a shared variable, A is updated with B's contents
# we need A to be copied to avoid aliasing
A
=
self
.
shared
(
numpy
.
zeros
((
2
,
2
))
+
.
5
)
B
=
self
.
shared
(
numpy
.
zeros
((
2
,
2
))
-
.
5
)
f
=
pfunc
([],
[],
updates
=
[(
A
,
B
)])
A
=
self
.
shared
(
numpy
.
zeros
((
2
,
2
))
+
.
5
)
B
=
self
.
shared
(
numpy
.
zeros
((
2
,
2
))
-
.
5
)
f
=
pfunc
([],
[],
updates
=
[(
A
,
B
)])
f
()
assert
not
numpy
.
may_share_memory
(
data_of
(
A
),
data_of
(
B
))
def
test_no_aliasing_1
(
self
):
# B is a shared variable, A is updated with B's contents
# since B is being updated as well, we don't need to copy anything
to avoid aliasing
# shared variables.
A
=
self
.
shared
(
numpy
.
zeros
((
2
,
2
))
+
.
5
)
B
=
self
.
shared
(
numpy
.
zeros
((
2
,
2
))
-
.
5
)
# since B is being updated as well, we don't need to copy anything
#
to avoid aliasing
shared variables.
A
=
self
.
shared
(
numpy
.
zeros
((
2
,
2
))
+
.
5
)
B
=
self
.
shared
(
numpy
.
zeros
((
2
,
2
))
-
.
5
)
C
=
tensor
.
dmatrix
()
f
=
pfunc
([
C
],
[],
updates
=
[
(
A
,
B
),
(
B
,
C
)
])
z
=
numpy
.
zeros
((
2
,
2
))
f
=
pfunc
([
C
],
[],
updates
=
[
(
A
,
B
),
(
B
,
C
)
])
z
=
numpy
.
zeros
((
2
,
2
))
f
(
z
)
assert
not
numpy
.
may_share_memory
(
data_of
(
A
),
data_of
(
B
))
assert
not
numpy
.
may_share_memory
(
z
,
data_of
(
B
))
# Theano tries to maintain its own memory space.
assert
not
numpy
.
may_share_memory
(
data_of
(
A
),
data_of
(
B
))
# Theano tries to maintain its own memory space.
assert
not
numpy
.
may_share_memory
(
z
,
data_of
(
B
))
assert
numpy
.
all
(
data_of
(
B
)
==
z
)
def
test_no_aliasing_2
(
self
):
# B and A take one another's values
# no copying is necessary since each one is updated.
orig_a
=
numpy
.
zeros
((
2
,
2
))
+
.
5
orig_b
=
numpy
.
zeros
((
2
,
2
))
-
.
5
orig_a
=
numpy
.
zeros
((
2
,
2
))
+
.
5
orig_b
=
numpy
.
zeros
((
2
,
2
))
-
.
5
A
=
self
.
shared
(
orig_a
)
B
=
self
.
shared
(
orig_b
)
data_of_a
=
data_of
(
A
)
data_of_b
=
data_of
(
B
)
f
=
pfunc
([],
[],
updates
=
[(
A
,
B
),(
B
,
A
)])
f
=
pfunc
([],
[],
updates
=
[(
A
,
B
),
(
B
,
A
)])
f
()
# correctness
assert
numpy
.
all
(
data_of
(
A
)
==
-.
5
)
...
...
@@ -892,18 +905,18 @@ class Test_aliasing_rules(unittest.TestCase):
def
test_no_aliasing_2b
(
self
):
# B and A take one another's values
# no copying is necessary since each one is updated.
# The twist one `test_no_aliasing_2` is that each shared var is updated
with a view of
# the other one.
# The twist one `test_no_aliasing_2` is that each shared var is updated
#
with a view of
the other one.
orig_a
=
numpy
.
zeros
((
2
,
2
))
+
.
5
orig_b
=
numpy
.
zeros
((
2
,
2
))
-
.
5
orig_a
=
numpy
.
zeros
((
2
,
2
))
+
.
5
orig_b
=
numpy
.
zeros
((
2
,
2
))
-
.
5
A
=
self
.
shared
(
orig_a
)
B
=
self
.
shared
(
orig_b
)
data_of_a
=
data_of
(
A
)
data_of_b
=
data_of
(
B
)
f
=
pfunc
([],
[],
updates
=
[(
A
,
B
[:,::
-
1
]),(
B
,
A
.
T
)])
f
=
pfunc
([],
[],
updates
=
[(
A
,
B
[:,
::
-
1
]),
(
B
,
A
.
T
)])
theano
.
printing
.
debugprint
(
f
)
f
()
# correctness (doesn't actually test the view...)
...
...
@@ -914,8 +927,10 @@ class Test_aliasing_rules(unittest.TestCase):
assert
not
numpy
.
may_share_memory
(
data_of
(
A
),
data_of
(
B
))
# theano should have been smart enough to not make copies
if
theano
.
config
.
mode
not
in
[
'DebugMode'
,
'DEBUG_MODE'
,
'FAST_COMPILE'
]:
#we don't ask DebugMode and FAST_COMPILE to don't make copy. We have the right to do so.
if
theano
.
config
.
mode
not
in
[
'DebugMode'
,
'DEBUG_MODE'
,
'FAST_COMPILE'
]:
# We don't ask DebugMode and FAST_COMPILE not to make copy.
# We have the right to do so.
assert
numpy
.
all
(
data_of
(
A
)
<
5
)
data_of_b
+=
10
assert
numpy
.
all
(
data_of
(
A
)
>
5
)
...
...
@@ -931,11 +946,11 @@ class Test_aliasing_rules(unittest.TestCase):
assert
numpy
.
may_share_memory
(
data_of
(
A
),
data_of_b
)
assert
numpy
.
may_share_memory
(
data_of
(
B
),
data_of_a
)
# N.B. This pattern could form a memory leak - each shared
variable always points to a
# v
iew, and that view gets further and further from the (e.g. data_of_a) with each
#
call. The memory leak is in the increasing number of view objects forming a chain to
#
the underlying data.
# N.B. This pattern could form a memory leak - each shared
# v
ariable always points to a view, and that view gets
#
further and further from the (e.g. data_of_a) with each
#
call. The memory leak is in the increasing number of view
# objects forming a chain to the underlying data.
if
__name__
==
'__main__'
:
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论