/
test_symbol_caching.py
123 lines (95 loc) · 3.93 KB
/
test_symbol_caching.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import weakref
import numpy as np
import pytest
from devito import DenseData, TimeData, clear_cache
from devito.interfaces import _SymbolCache
@pytest.mark.xfail(reason="New function instances currently don't cache")
@pytest.mark.parametrize('FunctionType', [DenseData, TimeData])
def test_cache_function_new(FunctionType):
"""Test caching of a new u[x, y] instance"""
u0 = FunctionType(name='u', shape=(3, 4))
u0.data[:] = 6.
u = FunctionType(name='u', shape=(3, 4))
assert np.allclose(u.data, u0.data)
@pytest.mark.parametrize('FunctionType', [DenseData, TimeData])
def test_cache_function_same_indices(FunctionType):
"""Test caching of derived u[x, y] instance from derivative"""
u0 = FunctionType(name='u', shape=(3, 4))
u0.data[:] = 6.
# Pick u[x, y] from derivative
u = u0.dx.args[1].args[2]
assert np.allclose(u.data, u0.data)
@pytest.mark.parametrize('FunctionType', [DenseData, TimeData])
def test_cache_function_different_indices(FunctionType):
"""Test caching of u[x + h, y] instance from derivative"""
u0 = FunctionType(name='u', shape=(3, 4))
u0.data[:] = 6.
# Pick u[x + h, y] (different indices) from derivative
u = u0.dx.args[0].args[1]
assert np.allclose(u.data, u0.data)
def test_symbol_cache_aliasing():
"""Test to assert that our aiasing cache isn't defeated by sympys
non-aliasing symbol cache.
For further explanation consider the symbol u[x, y] and it's first
derivative in x, which includes the symbols u[x, y] and u[x + h, y].
The two functions are aliased in devito's caching mechanism to allow
multiple stencil indices pointing at the same data object u, but
SymPy treats these two instances as separate functions and thus is
allowed to delete one or the other when the cache is cleared.
The test below asserts that u[x + h, y] is deleted, the data on u
is still intact through our own caching mechanism."""
# Ensure a clean cache to start with
clear_cache()
# FIXME: Currently not working, presumably due to our
# failure to cache new instances?
# assert(len(_SymbolCache) == 0)
# Create first instance of u and fill its data
u = DenseData(name='u', shape=(3, 4))
u.data[:] = 6.
u_ref = weakref.ref(u.data)
# Create u[x + h, y] and delete it again
dx = u.dx # Contains two u symbols: u[x, y] and u[x + h, y]
del dx
clear_cache()
# FIXME: Unreliable cache sizes
# assert len(_SymbolCache) == 1 # We still have a reference to u
assert np.allclose(u.data, 6.) # u.data is alive and well
# Remove the final instance and ensure u.data got deallocated
del u
clear_cache()
assert u_ref() is None
def test_symbol_cache_aliasing_reverse():
"""Test to assert that removing he original u[x, y] instance does
not impede our alisaing cache or leaks memory.
"""
# Ensure a clean cache to start with
clear_cache()
# FIXME: Currently not working, presumably due to our
# failure to cache new instances?
# assert(len(_SymbolCache) == 0)
# Create first instance of u and fill its data
u = DenseData(name='u', shape=(3, 4))
u.data[:] = 6.
u_ref = weakref.ref(u.data)
# Create derivative and delete orignal u[x, y]
dx = u.dx
del u
clear_cache()
# We still have a references to u
# FIXME: Unreliable cache sizes
# assert len(_SymbolCache) == 1
# Ensure u[x + h, y] still holds valid data
assert np.allclose(dx.args[0].args[1].data, 6.)
del dx
clear_cache()
# FIXME: Unreliable cache sizes
# assert len(_SymbolCache) == 0 # We still have a reference to u_h
assert u_ref() is None
def test_clear_cache(nx=1000, ny=1000):
clear_cache()
cache_size = len(_SymbolCache)
for i in range(10):
assert(len(_SymbolCache) == cache_size)
DenseData(name='u', shape=(nx, ny), dtype=np.float64, space_order=2)
assert(len(_SymbolCache) == cache_size + 1)
clear_cache()