def test_collapsing(self, eqns, expected, blocking): grid = Grid(shape=(3, 3, 3)) f = Function(name='f', grid=grid) # noqa u = TimeFunction(name='u', grid=grid) # noqa eqns = eval(eqns) if blocking: op = Operator(eqns, opt=('blocking', 'simd', 'openmp', { 'blockinner': True, 'par-collapse-ncores': 1, 'par-collapse-work': 0 })) assert_structure(op, ['t,x0_blk0,y0_blk0,z0_blk0,x,y,z']) else: op = Operator(eqns, opt=('simd', 'openmp', { 'par-collapse-ncores': 1, 'par-collapse-work': 0 })) iterations = FindNodes(Iteration).visit(op) assert len(iterations) == len(expected) # Check for presence of pragma omp + collapse clause for i, j in zip(iterations, expected): if j > 0: assert len(i.pragmas) == 1 pragma = i.pragmas[0] assert 'omp for collapse(%d)' % j in pragma.value else: for k in i.pragmas: assert 'omp for collapse' not in k.value
def test_issue_1725(): class ToyPMLLeft(SubDomain): name = 'toypmlleft' def define(self, dimensions): x, y = dimensions return {x: x, y: ('left', 2)} class ToyPMLRight(SubDomain): name = 'toypmlright' def define(self, dimensions): x, y = dimensions return {x: x, y: ('right', 2)} subdomains = [ToyPMLLeft(), ToyPMLRight()] grid = Grid(shape=(20, 20), subdomains=subdomains) u = TimeFunction(name='u', grid=grid, time_order=2, space_order=2) eqns = [ Eq(u.forward, solve(u.dt2 - u.laplace, u.forward), subdomain=sd) for sd in subdomains ] op = Operator(eqns, opt='fission') # Note the `x` loop is fissioned, so now both loop nests can be collapsed # for maximum parallelism assert_structure(op, ['t,x,i1y', 't,x,i2y'], 't,x,i1y,x,i2y')
def test_issue_1761(self): """ MFE for issue #1761. """ class DummySubdomains(SubDomainSet): name = 'dummydomain' dummy = DummySubdomains(N=1, bounds=(1, 1, 1, 1)) grid = Grid(shape=(10, 10), subdomains=(dummy,)) f = TimeFunction(name='f', grid=grid) g = TimeFunction(name='g', grid=grid) theta = Function(name='theta', grid=grid) phi = Function(name='phi', grid=grid) eqns = [Eq(f.forward, f*sin(phi), subdomain=grid.subdomains['dummydomain']), Eq(g.forward, g*sin(theta), subdomain=grid.subdomains['dummydomain'])] op = Operator(eqns) # Make sure it jit-compiles op.cfunction assert_structure(op, ['x,y', 't,n', 't,n,xi_n,yi_n'], 'x,y,t,n,xi_n,yi_n')
def test_nofission_as_illegal(): """ Test there's no fission if dependencies would break. """ grid = Grid(shape=(20, 20)) x, y = grid.dimensions f = Function(name='f', grid=grid, dimensions=(y, ), shape=(20, )) u = TimeFunction(name='u', grid=grid) v = TimeFunction(name='v', grid=grid) eqns = [Inc(f, v + 1.), Eq(u.forward, f[y + 1] + 1.)] op = Operator(eqns, opt='fission') assert_structure(op, ['t,x,y', 't,x,y'], 't,x,y,y')
def test_cache_blocking_structure(blockinner, openmp, expected): # Check code structure _, op = _new_operator2((10, 31, 45), time_order=2, opt=('blocking', { 'openmp': openmp, 'blockinner': blockinner, 'par-collapse-ncores': 1 })) assert_structure(op, [expected]) # Check presence of openmp pragmas at the right place if openmp: trees = retrieve_iteration_tree(op) assert len(trees[0][1].pragmas) == 1 assert 'omp for' in trees[0][1].pragmas[0].value
def test_collapsing_v2(self): """ MFE from issue #1478. """ n = 8 m = 8 nx, ny, nchi, ncho = 12, 12, 1, 1 x, y = SpaceDimension("x"), SpaceDimension("y") ci, co = Dimension("ci"), Dimension("co") i, j = Dimension("i"), Dimension("j") grid = Grid((nx, ny), dtype=np.float32, dimensions=(x, y)) X = Function(name="xin", dimensions=(ci, x, y), shape=(nchi, nx, ny), grid=grid, space_order=n // 2) dy = Function(name="dy", dimensions=(co, x, y), shape=(ncho, nx, ny), grid=grid, space_order=n // 2) dW = Function(name="dW", dimensions=(co, ci, i, j), shape=(ncho, nchi, n, m), grid=grid) eq = [ Eq( dW[co, ci, i, j], dW[co, ci, i, j] + dy[co, x, y] * X[ci, x + i - n // 2, y + j - m // 2]) for i in range(n) for j in range(m) ] op = Operator(eq, opt=('advanced', {'openmp': True})) assert_structure(op, ['co,ci,x,y']) iterations = FindNodes(Iteration).visit(op) assert iterations[0].ncollapsed == 1 assert iterations[1].is_Vectorized assert iterations[2].is_Sequential assert iterations[3].is_Sequential
def test_nofission_as_unprofitable(): """ Test there's no fission if not gonna increase number of collapsable loops. """ grid = Grid(shape=(20, 20)) x, y = grid.dimensions t = grid.stepping_dim yl = SubDimension.left(name='yl', parent=y, thickness=4) yr = SubDimension.right(name='yr', parent=y, thickness=4) u = TimeFunction(name='u', grid=grid) eqns = [ Eq(u.forward, u[t + 1, x, y + 1] + 1.).subs(y, yl), Eq(u.forward, u[t + 1, x, y - 1] + 1.).subs(y, yr) ] op = Operator(eqns, opt='fission') assert_structure(op, ['t,x,yl', 't,x,yr'], 't,x,yl,yr')
def test_issue_1761_b(self): """ Follow-up issue emerged after patching #1761. The thicknesses assigments were missing before the third equation. """ n = Dimension(name='n') m = Dimension(name='m') class DummySubdomains(SubDomainSet): name = 'dummydomain' implicit_dimension = m dummy = DummySubdomains(N=1, bounds=(1, 1, 1, 1)) class DummySubdomains2(SubDomainSet): name = 'dummydomain2' implicit_dimension = n dummy2 = DummySubdomains2(N=1, bounds=(1, 1, 1, 1)) grid = Grid(shape=(10, 10), subdomains=(dummy, dummy2)) f = TimeFunction(name='f', grid=grid) g = TimeFunction(name='g', grid=grid) theta = Function(name='theta', grid=grid) phi = Function(name='phi', grid=grid) eqns = [Eq(f.forward, f*sin(phi), subdomain=grid.subdomains['dummydomain']), Eq(g.forward, g*sin(theta), subdomain=grid.subdomains['dummydomain2']), Eq(f.forward, f*tan(phi), subdomain=grid.subdomains['dummydomain'])] op = Operator(eqns) # Make sure it jit-compiles op.cfunction assert_structure(op, ['x,y', 't,m', 't,m,xi_m,yi_m', 't,n', 't,n,xi_n,yi_n', 't,m', 't,m,xi_m,yi_m'], 'x,y,t,m,xi_m,yi_m,n,xi_n,yi_n,m,xi_m,yi_m')