def test_offsets(self): sdfg = dace.SDFG('mapfission_offsets') sdfg.add_array('A', [20], dace.float64) sdfg.add_scalar('interim', dace.float64, transient=True) state = sdfg.add_state() me, mx = state.add_map('outer', dict(i='10:20')) t1 = state.add_tasklet('addone', {'a'}, {'b'}, 'b = a + 1') t2 = state.add_tasklet('addtwo', {'a'}, {'b'}, 'b = a + 2') aread = state.add_read('A') awrite = state.add_write('A') state.add_memlet_path(aread, me, t1, dst_conn='a', memlet=dace.Memlet.simple('A', 'i')) state.add_edge(t1, 'b', t2, 'a', dace.Memlet.simple('interim', '0')) state.add_memlet_path(t2, mx, awrite, src_conn='b', memlet=dace.Memlet.simple('A', 'i')) self.assertGreater(sdfg.apply_transformations(MapFission), 0) dace.propagate_memlets_sdfg(sdfg) sdfg.validate() # Test A = np.random.rand(20) expected = A.copy() expected[10:] += 3 sdfg(A=A) self.assertTrue(np.allclose(A, expected))
def test_offsets_array(): sdfg = dace.SDFG('mapfission_offsets2') sdfg.add_array('A', [20], dace.float64) sdfg.add_array('interim', [1], dace.float64, transient=True) state = sdfg.add_state() me, mx = state.add_map('outer', dict(i='10:20')) t1 = state.add_tasklet('addone', {'a'}, {'b'}, 'b = a + 1') interim = state.add_access('interim') t2 = state.add_tasklet('addtwo', {'a'}, {'b'}, 'b = a + 2') aread = state.add_read('A') awrite = state.add_write('A') state.add_memlet_path(aread, me, t1, dst_conn='a', memlet=dace.Memlet.simple('A', 'i')) state.add_edge(t1, 'b', interim, None, dace.Memlet.simple('interim', '0')) state.add_edge(interim, None, t2, 'a', dace.Memlet.simple('interim', '0')) state.add_memlet_path(t2, mx, awrite, src_conn='b', memlet=dace.Memlet.simple('A', 'i')) sdfg.apply_transformations(MapFission) dace.propagate_memlets_sdfg(sdfg) sdfg.validate() # Test A = np.random.rand(20) expected = A.copy() expected[10:] += 3 A_cpy = A.copy() csdfg = sdfg.compile() csdfg(A=A_cpy) del csdfg print(np.linalg.norm(A_cpy)) print(np.linalg.norm(expected)) assert (np.allclose(A_cpy, expected)) subgraph = SubgraphView(sdfg.nodes()[0], sdfg.nodes()[0].nodes()) sf = SubgraphFusion(subgraph) assert sf.can_be_applied(sdfg, subgraph) fusion(sdfg, sdfg.nodes()[0], None) A_cpy = A.copy() csdfg = sdfg.compile() csdfg(A=A_cpy) assert (np.allclose(A_cpy, expected))
def test(): print('Constant specialization test') N = dp.symbol('N') M = dp.symbol('M') N.set(20) M.set(30) fullrange = '1:N-1,0:M' irange = '1:N-1' jrange = '0:M' input = np.random.rand(N.get(), M.get()).astype(np.float32) output = dp.ndarray([N, M], dtype=dp.float32) output[:] = dp.float32(0) ########################################################################## spec_sdfg = SDFG('spectest') state = spec_sdfg.add_state() A = state.add_array('A', [N, M], dp.float32) Atrans = state.add_transient('At', [N - 2, M], dp.float32) B = state.add_array('B', [N, M], dp.float32) state.add_edge(A, None, Atrans, None, Memlet.simple(A, fullrange)) _, me, mx = state.add_mapped_tasklet( 'compute', dict(i=irange, j=jrange), dict(a=Memlet.simple(Atrans, 'i-1,j')), 'b = math.exp(a)', dict(b=Memlet.simple(B, 'i,j'))) state.add_edge(Atrans, None, me, None, Memlet.simple(Atrans, fullrange)) state.add_edge(mx, None, B, None, Memlet.simple(B, fullrange)) spec_sdfg.fill_scope_connectors() dp.propagate_memlets_sdfg(spec_sdfg) spec_sdfg.validate() ########################################################################## code_nonspec = spec_sdfg.generate_code() assert 'Dynamic' in code_nonspec[0].code spec_sdfg.specialize(dict(N=N, M=M)) code_spec = spec_sdfg.generate_code() assert 'Dynamic' not in code_spec[0].code func = spec_sdfg.compile() func(A=input, B=output, N=N, M=M) diff = np.linalg.norm( np.exp(input[1:(N.get() - 1), 0:M.get()]) - output[1:-1, :]) / N.get() print("Difference:", diff) assert diff <= 1e-5
def test_uneven(self): # For testing uneven decomposition, use longer buffer and ensure # it's not filled over output = np.ones(20, np.int32) sdfg = arange.to_sdfg() sdfg.apply_transformations([MapTiling, OutLocalStorage], options=[{ 'tile_sizes': [5] }, {}]) dace.propagate_memlets_sdfg(sdfg) sdfg(N=16, __return=output) self.assertTrue( np.array_equal(output[:16], np.arange(16, dtype=np.int32))) self.assertTrue(np.array_equal(output[16:], np.ones(4, np.int32)))
spec_sdfg = SDFG('spectest') state = spec_sdfg.add_state() A = state.add_array('A', [N, M], dp.float32) Atrans = state.add_transient('At', [N - 2, M], dp.float32) B = state.add_array('B', [N, M], dp.float32) state.add_edge(A, None, Atrans, None, Memlet.simple(A, fullrange)) _, me, mx = state.add_mapped_tasklet('compute', dict(i=irange, j=jrange), dict(a=Memlet.simple(Atrans, 'i-1,j')), 'b = math.exp(a)', dict(b=Memlet.simple(B, 'i,j'))) state.add_edge(Atrans, None, me, None, Memlet.simple(Atrans, fullrange)) state.add_edge(mx, None, B, None, Memlet.simple(B, fullrange)) spec_sdfg.fill_scope_connectors() dp.propagate_memlets_sdfg(spec_sdfg) spec_sdfg.validate() ########################################################################## code_nonspec = spec_sdfg.generate_code() if 'Dynamic' not in code_nonspec[0].code: print('ERROR: Constants were needlessly specialized') exit(1) spec_sdfg.specialize(dict(N=N, M=M)) code_spec = spec_sdfg.generate_code() if 'Dynamic' in code_spec[0].code: print('ERROR: Constants were not properly specialized') exit(2)
# Copyright 2019-2021 ETH Zurich and the DaCe authors. All rights reserved. import dace import sys import time print(time.time(), 'loading') a = dace.SDFG.from_file(sys.argv[1]) print(time.time(), 'propagating') dace.propagate_memlets_sdfg(a) print(time.time(), 'strict transformations') a.apply_strict_transformations() print(time.time(), 'saving') a.save('strict.sdfg') print(time.time(), 'compiling') a.compile()