|
2 | 2 |
|
3 | 3 | from conftest import assert_structure |
4 | 4 | from devito import ( |
5 | | - Eq, Function, Grid, Inc, Operator, SubDimension, SubDomain, TimeFunction, solve |
| 5 | + Buffer, Eq, Function, Grid, Inc, Operator, SubDimension, SubDomain, TimeFunction, |
| 6 | + solve |
6 | 7 | ) |
| 8 | +from devito.ir.iet import retrieve_iteration_tree |
| 9 | +from devito.ir.support.properties import PARALLEL |
7 | 10 |
|
8 | 11 |
|
9 | 12 | def test_issue_1725(): |
@@ -126,3 +129,66 @@ def test_issue_1921(): |
126 | 129 | op1.apply(time_m=1, time_M=5, g=g1) |
127 | 130 |
|
128 | 131 | assert np.all(g.data == g1.data) |
| 132 | + |
| 133 | + |
| 134 | +def test_buffer1_fissioning(): |
| 135 | + """ |
| 136 | + Tests an edge case whereby inability to spot the equivalence of |
| 137 | + `f.forward`/`backward` and `f` when using `Buffer(1)` would cause |
| 138 | + data dependance analysis to incorrectly determine that `x` and `y` |
| 139 | + loops should be sequential. |
| 140 | + """ |
| 141 | + so = 2 |
| 142 | + |
| 143 | + class SD0(SubDomain): |
| 144 | + name = 'sd0' |
| 145 | + |
| 146 | + def __init__(self, so, **kwargs): |
| 147 | + self.so = so |
| 148 | + super().__init__(**kwargs) |
| 149 | + |
| 150 | + def define(self, dimensions): |
| 151 | + map_d = {d: d for d in dimensions} |
| 152 | + map_d[dimensions[-1]] = ('left', self.so) |
| 153 | + return map_d |
| 154 | + |
| 155 | + grid = Grid(shape=(101, 101, 101)) |
| 156 | + z = grid.dimensions[-1] |
| 157 | + |
| 158 | + sd0 = SD0(so, grid=grid) |
| 159 | + iz = sd0.dimensions[-1] |
| 160 | + |
| 161 | + f0 = TimeFunction(name='f0', grid=grid, |
| 162 | + space_order=so, save=Buffer(1)) |
| 163 | + f1 = TimeFunction(name='f1', grid=grid, |
| 164 | + space_order=so, save=Buffer(1)) |
| 165 | + |
| 166 | + f2 = TimeFunction(name='f2', grid=grid, |
| 167 | + space_order=so, save=Buffer(1)) |
| 168 | + f3 = TimeFunction(name='f3', grid=grid, |
| 169 | + space_order=so, save=Buffer(1)) |
| 170 | + |
| 171 | + # Free-surface like conditions plus derivative creates a dependence |
| 172 | + eq0 = Eq(f0.backward.subs(z, iz-so), -f0.backward.subs(z, so-iz)) |
| 173 | + eq1 = Eq(f1.backward.subs(z, iz-so), -f1.backward.subs(z, so-iz)) |
| 174 | + |
| 175 | + eq2 = Eq(f2, f0.dx + f2) |
| 176 | + eq3 = Eq(f3, f1.dy + f3) |
| 177 | + |
| 178 | + eqs = [eq0, eq1, eq2, eq3] |
| 179 | + |
| 180 | + op = Operator(eqs) |
| 181 | + |
| 182 | + trees = retrieve_iteration_tree(op) |
| 183 | + |
| 184 | + # If the equivalence of f0.backward and f0 are not spotted by the |
| 185 | + # compiler, data dependence analysis will determine x and y loops |
| 186 | + # to be sequential. |
| 187 | + for tree in trees: |
| 188 | + for i in range(1, 3): |
| 189 | + assert PARALLEL in tree[i].properties |
| 190 | + |
| 191 | + # If parallelisation failed, then there will also be no blocking on |
| 192 | + # x and y |
| 193 | + assert 'x0_blk0_size' in str(op.parameters) |
| 194 | + assert 'y0_blk0_size' in str(op.parameters) |
0 commit comments