From 86d7ea9cd8067f8a127d8a5017c1ea1214eabb21 Mon Sep 17 00:00:00 2001 From: maelso Date: Thu, 10 Oct 2019 18:25:25 -0300 Subject: [PATCH 01/11] This solution checks all scopes created on the stack to see if the symbol has already been declared. --- devito/ir/iet/scheduler.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/devito/ir/iet/scheduler.py b/devito/ir/iet/scheduler.py index 51b72a4c83..11a4bf75a9 100644 --- a/devito/ir/iet/scheduler.py +++ b/devito/ir/iet/scheduler.py @@ -202,6 +202,14 @@ def push_object_on_stack(self, scope, obj): """Define an Array or a composite type (e.g., a struct) on the stack.""" handle = self.stack.setdefault(scope, OrderedDict()) + for k, v in self.stack.items(): + try: + if obj in self.stack[k]: + return + except TypeError: + # E.g., non-iterable argument + pass + if obj.is_LocalObject: handle[obj] = Element(c.Value(obj._C_typename, obj.name)) else: From df04a7f7bf71651d5d46f390954176689d04e3cc Mon Sep 17 00:00:00 2001 From: maelso Date: Fri, 11 Oct 2019 08:58:42 -0300 Subject: [PATCH 02/11] Using devito.tools.flatten --- devito/ir/iet/scheduler.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/devito/ir/iet/scheduler.py b/devito/ir/iet/scheduler.py index 11a4bf75a9..a2e67c1be6 100644 --- a/devito/ir/iet/scheduler.py +++ b/devito/ir/iet/scheduler.py @@ -7,7 +7,7 @@ ExpressionBundle, Transformer, FindNodes, FindSymbols, MapExprStmts, XSubs, iet_analyze) from devito.symbolics import IntDiv, ccode, xreplace_indices -from devito.tools import as_mapper, as_tuple +from devito.tools import as_mapper, as_tuple, flatten from devito.types import ConditionalDimension __all__ = ['iet_build', 'iet_insert_decls', 'iet_insert_casts'] @@ -202,13 +202,8 @@ def push_object_on_stack(self, scope, obj): """Define an Array or a composite type (e.g., a struct) on the stack.""" handle = self.stack.setdefault(scope, OrderedDict()) - for k, v in self.stack.items(): - try: - if obj in self.stack[k]: - return - except TypeError: - # E.g., non-iterable argument - pass + if obj in flatten(self.stack.values()): + return if obj.is_LocalObject: handle[obj] = Element(c.Value(obj._C_typename, obj.name)) From f8718b8c2eb885b8919bda4a8eb67f966f0444f5 Mon Sep 17 00:00:00 2001 From: maelso Date: Sat, 12 Oct 2019 08:28:13 -0300 Subject: [PATCH 03/11] Created push_array_on_stack --- devito/ir/iet/scheduler.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/devito/ir/iet/scheduler.py b/devito/ir/iet/scheduler.py index a2e67c1be6..a0f469c680 100644 --- a/devito/ir/iet/scheduler.py +++ b/devito/ir/iet/scheduler.py @@ -199,19 +199,21 @@ def __init__(self): self.stack = OrderedDict() def push_object_on_stack(self, scope, obj): - """Define an Array or a composite type (e.g., a struct) on the stack.""" + """Define a LocalObject on the stack.""" + handle = self.stack.setdefault(scope, OrderedDict()) + handle[obj] = Element(c.Value(obj._C_typename, obj.name)) + + def push_array_on_stack(self, scope, obj): + """Define an Array on the stack.""" handle = self.stack.setdefault(scope, OrderedDict()) if obj in flatten(self.stack.values()): return - if obj.is_LocalObject: - handle[obj] = Element(c.Value(obj._C_typename, obj.name)) - else: - shape = "".join("[%s]" % ccode(i) for i in obj.symbolic_shape) - alignment = "__attribute__((aligned(%d)))" % obj._data_alignment - value = "%s%s %s" % (obj.name, shape, alignment) - handle[obj] = Element(c.POD(obj.dtype, value)) + shape = "".join("[%s]" % ccode(i) for i in obj.symbolic_shape) + alignment = "__attribute__((aligned(%d)))" % obj._data_alignment + value = "%s%s %s" % (obj.name, shape, alignment) + handle[obj] = Element(c.POD(obj.dtype, value)) def push_scalar_on_stack(self, scope, expr): """Define a Scalar on the stack.""" From 29d8e4f420d12efa5c12c4f9eb0f03329c4cc200 Mon Sep 17 00:00:00 2001 From: maelso Date: Mon, 11 Nov 2019 17:57:41 -0300 Subject: [PATCH 04/11] git rebase --- devito/ir/iet/scheduler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devito/ir/iet/scheduler.py b/devito/ir/iet/scheduler.py index a0f469c680..ae8db93775 100644 --- a/devito/ir/iet/scheduler.py +++ b/devito/ir/iet/scheduler.py @@ -168,7 +168,7 @@ def iet_insert_decls(iet, external): continue elif i._mem_stack: # On the stack - allocator.push_object_on_stack(iet[0], i) + allocator.push_array_on_stack(iet[0], i) else: # On the heap allocator.push_array_on_heap(i) From 965681c5b9b4fe7a476f0e4efed62e3a8b330d39 Mon Sep 17 00:00:00 2001 From: maelso Date: Mon, 11 Nov 2019 19:18:02 -0300 Subject: [PATCH 05/11] Added test: single declaration --- tests/test_ops.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tests/test_ops.py b/tests/test_ops.py index 3b8693e030..348b3a443e 100644 --- a/tests/test_ops.py +++ b/tests/test_ops.py @@ -271,11 +271,24 @@ def test_create_ops_block(self, equation, expected): ]) def test_upper_bound(self, equation, expected): grid = Grid((5, 5)) - u = TimeFunction(name='u', grid=grid) # noqa + u = TimeFunction(name='u', grid=grid) # noqa op = Operator(eval(equation)) assert expected in str(op.ccode) + @pytest.mark.parametrize('equation, declaration', [ + ('Eq(u.forward, u+1)', + 'int OPS_Kernel_0_range[4]') + ]) + def test_single_declaration(self, equation, declaration): + grid = Grid((5, 5)) + u = TimeFunction(name='u', grid=grid) # noqa + op = Operator(eval(equation)) + + occurrences = [i for i in str(op.ccode).split('\n') if declaration in i] + + assert len(occurrences) == 1 + @pytest.mark.parametrize('equation,expected', [ ('Eq(u_2d.forward, u_2d + 1)', '[\'ops_dat_fetch_data(u_dat[(time_M)%(2)],0,&(u[(time_M)%(2)]));\',' From 24c55424bf5d0d73c5bbcf30734a249f33cb2c44 Mon Sep 17 00:00:00 2001 From: maelso Date: Tue, 12 Nov 2019 20:12:48 -0300 Subject: [PATCH 06/11] Testing declarations into conditionals --- tests/test_ops.py | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/tests/test_ops.py b/tests/test_ops.py index 348b3a443e..5e466b60d2 100644 --- a/tests/test_ops.py +++ b/tests/test_ops.py @@ -2,7 +2,7 @@ import pytest import numpy as np -from conftest import skipif +from conftest import skipif, x from sympy import Integer from sympy.core.numbers import Zero, One # noqa @@ -13,13 +13,15 @@ # thus invalidating all of the future tests. This is guaranteed by the # `pytestmark` above from devito import Eq, Function, Grid, Operator, TimeFunction, configuration # noqa +from devito.ir.equations import ClusterizedEq # noqa +from devito.ir.iet import Conditional, Expression, derive_parameters, iet_insert_decls, iet_insert_casts # noqa from devito.ops.node_factory import OPSNodeFactory # noqa from devito.ops.transformer import create_ops_arg, create_ops_dat, make_ops_ast, to_ops_stencil # noqa -from devito.ops.types import OpsAccessible, OpsDat, OpsStencil, OpsBlock # noqa +from devito.ops.types import Array, OpsAccessible, OpsDat, OpsStencil, OpsBlock # noqa from devito.ops.utils import namespace, AccessibleInfo, OpsDatDecl, OpsArgDecl # noqa -from devito.symbolics import Byref, Literal, indexify # noqa +from devito.symbolics import Byref, ListInitializer, Literal, indexify # noqa from devito.tools import dtype_to_cstr # noqa -from devito.types import Buffer, Constant, Symbol # noqa +from devito.types import Buffer, Constant, DefaultDimension, Symbol # noqa class TestOPSExpression(object): @@ -289,6 +291,38 @@ def test_single_declaration(self, equation, declaration): assert len(occurrences) == 1 + def test_conditional_declarations(self): + accesses = [[0, 0], [0, 1], [1, 0], [1, 1]] + dims = len(accesses[0]) + pts = len(accesses) + stencil_name = namespace['ops_stencil_name'](dims, 'name', pts) + + stencil_array = Array( + name=stencil_name, + dimensions=(DefaultDimension(name='len', default_value=dims * pts),), + dtype=np.int32, + scope='stack' + ) + + list_initialize = Expression(ClusterizedEq(Eq( + stencil_array, + ListInitializer(list(itertools.chain(*accesses))) + ))) + iet = Conditional(x < 3, list_initialize, list_initialize) + # Derive all Operator parameters based on the IET + parameters = derive_parameters(iet, True) + iet = iet_insert_decls(iet, parameters) + iet = iet_insert_casts(iet, parameters) + assert str(iet) == """\ +if (x < 3) +{ + int s2d_name_4pt[8] = {0, 0, 0, 1, 1, 0, 1, 1}; +} +else +{ + int s2d_name_4pt[8] = {0, 0, 0, 1, 1, 0, 1, 1}; +}""" + @pytest.mark.parametrize('equation,expected', [ ('Eq(u_2d.forward, u_2d + 1)', '[\'ops_dat_fetch_data(u_dat[(time_M)%(2)],0,&(u[(time_M)%(2)]));\',' From ff8cbe5fd8cba2c4abcd5ce16df53ce77574f0e3 Mon Sep 17 00:00:00 2001 From: maelso Date: Tue, 12 Nov 2019 20:15:56 -0300 Subject: [PATCH 07/11] code organization --- tests/test_ops.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/test_ops.py b/tests/test_ops.py index 5e466b60d2..0bc281d9a7 100644 --- a/tests/test_ops.py +++ b/tests/test_ops.py @@ -296,20 +296,19 @@ def test_conditional_declarations(self): dims = len(accesses[0]) pts = len(accesses) stencil_name = namespace['ops_stencil_name'](dims, 'name', pts) - stencil_array = Array( name=stencil_name, dimensions=(DefaultDimension(name='len', default_value=dims * pts),), dtype=np.int32, scope='stack' ) - list_initialize = Expression(ClusterizedEq(Eq( stencil_array, ListInitializer(list(itertools.chain(*accesses))) ))) + iet = Conditional(x < 3, list_initialize, list_initialize) - # Derive all Operator parameters based on the IET + parameters = derive_parameters(iet, True) iet = iet_insert_decls(iet, parameters) iet = iet_insert_casts(iet, parameters) From 0a4129dd3b6ce0de47131fdcbd01b34158e9f219 Mon Sep 17 00:00:00 2001 From: maelso Date: Wed, 13 Nov 2019 17:27:21 -0300 Subject: [PATCH 08/11] test_operator.py>test_conditional_declarations::TestDeclarator --- tests/test_operator.py | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/tests/test_operator.py b/tests/test_operator.py index ba610389d4..d13acf6d75 100644 --- a/tests/test_operator.py +++ b/tests/test_operator.py @@ -1,3 +1,4 @@ +import itertools import numpy as np import pytest @@ -6,12 +7,14 @@ SparseFunction, SparseTimeFunction, Dimension, error, SpaceDimension, NODE, CELL, dimensions, configuration, TensorFunction, TensorTimeFunction, VectorFunction, VectorTimeFunction) -from devito.ir.iet import (Expression, Iteration, FindNodes, IsPerfectIteration, - retrieve_iteration_tree) +from devito.ir.equations import ClusterizedEq +from devito.ir.iet import (Conditional, Expression, Iteration, FindNodes, + IsPerfectIteration, derive_parameters, iet_insert_decls, + iet_insert_casts, retrieve_iteration_tree) from devito.ir.support import Any, Backward, Forward -from devito.symbolics import indexify, retrieve_indexed +from devito.symbolics import ListInitializer, indexify, retrieve_indexed from devito.tools import flatten -from devito.types import Array, Scalar +from devito.types import Array, DefaultDimension, Scalar pytestmark = skipif(['yask', 'ops']) @@ -966,6 +969,37 @@ def test_incomplete_override(self): class TestDeclarator(object): + def test_conditional_declarations(self): + accesses = [[0, 0], [0, 1], [1, 0], [1, 1]] + dims = len(accesses[0]) + pts = len(accesses) + stencil_name = 's%dd_%s_%dpt' % (dims, 'name', pts) + stencil_array = Array( + name=stencil_name, + dimensions=(DefaultDimension(name='len', default_value=dims * pts),), + dtype=np.int32, + scope='stack' + ) + list_initialize = Expression(ClusterizedEq(Eq( + stencil_array, + ListInitializer(list(itertools.chain(*accesses))) + ))) + + iet = Conditional(x < 3, list_initialize, list_initialize) + + parameters = derive_parameters(iet, True) + iet = iet_insert_decls(iet, parameters) + iet = iet_insert_casts(iet, parameters) + assert str(iet) == """\ +if (x < 3) +{ + int s2d_name_4pt[8] = {0, 0, 0, 1, 1, 0, 1, 1}; +} +else +{ + int s2d_name_4pt[8] = {0, 0, 0, 1, 1, 0, 1, 1}; +}""" + def test_heap_1D_stencil(self): i, j = dimensions('i j') a = Array(name='a', dimensions=(i,)) From 9fe627861385578ca09c30e3770b5366dcbe798f Mon Sep 17 00:00:00 2001 From: maelso Date: Wed, 27 Nov 2019 15:33:02 -0300 Subject: [PATCH 09/11] minor changes --- tests/test_operator.py | 61 +++++++++++++++++++----------------------- tests/test_ops.py | 35 ++---------------------- 2 files changed, 30 insertions(+), 66 deletions(-) diff --git a/tests/test_operator.py b/tests/test_operator.py index d13acf6d75..ff3d163e9a 100644 --- a/tests/test_operator.py +++ b/tests/test_operator.py @@ -1,4 +1,3 @@ -import itertools import numpy as np import pytest @@ -10,7 +9,7 @@ from devito.ir.equations import ClusterizedEq from devito.ir.iet import (Conditional, Expression, Iteration, FindNodes, IsPerfectIteration, derive_parameters, iet_insert_decls, - iet_insert_casts, retrieve_iteration_tree) + retrieve_iteration_tree) from devito.ir.support import Any, Backward, Forward from devito.symbolics import ListInitializer, indexify, retrieve_indexed from devito.tools import flatten @@ -969,37 +968,6 @@ def test_incomplete_override(self): class TestDeclarator(object): - def test_conditional_declarations(self): - accesses = [[0, 0], [0, 1], [1, 0], [1, 1]] - dims = len(accesses[0]) - pts = len(accesses) - stencil_name = 's%dd_%s_%dpt' % (dims, 'name', pts) - stencil_array = Array( - name=stencil_name, - dimensions=(DefaultDimension(name='len', default_value=dims * pts),), - dtype=np.int32, - scope='stack' - ) - list_initialize = Expression(ClusterizedEq(Eq( - stencil_array, - ListInitializer(list(itertools.chain(*accesses))) - ))) - - iet = Conditional(x < 3, list_initialize, list_initialize) - - parameters = derive_parameters(iet, True) - iet = iet_insert_decls(iet, parameters) - iet = iet_insert_casts(iet, parameters) - assert str(iet) == """\ -if (x < 3) -{ - int s2d_name_4pt[8] = {0, 0, 0, 1, 1, 0, 1, 1}; -} -else -{ - int s2d_name_4pt[8] = {0, 0, 0, 1, 1, 0, 1, 1}; -}""" - def test_heap_1D_stencil(self): i, j = dimensions('i j') a = Array(name='a', dimensions=(i,)) @@ -1152,6 +1120,33 @@ def test_stack_vector_temporaries(self): timers->section0 += (double)(end_section0.tv_sec-start_section0.tv_sec)\ +(double)(end_section0.tv_usec-start_section0.tv_usec)/1000000;""" in str(operator) + def test_conditional_declarations(self): + accesses = [0, 0] + stencil_array = Array( + name='a', + dimensions=(DefaultDimension(name='x', default_value=len(accesses)),), + dtype=np.int32, + scope='stack' + ) + list_initialize = Expression(ClusterizedEq(Eq( + stencil_array, + ListInitializer(accesses) + ))) + + iet = Conditional(x < 3, list_initialize, list_initialize) + + parameters = derive_parameters(iet, True) + iet = iet_insert_decls(iet, parameters) + assert str(iet[0]) == """\ +if (x < 3) +{ + int a[2] = {0, 0}; +} +else +{ + int a[2] = {0, 0}; +}""" + class TestLoopScheduling(object): diff --git a/tests/test_ops.py b/tests/test_ops.py index 0bc281d9a7..d6e7104103 100644 --- a/tests/test_ops.py +++ b/tests/test_ops.py @@ -2,7 +2,7 @@ import pytest import numpy as np -from conftest import skipif, x +from conftest import skipif from sympy import Integer from sympy.core.numbers import Zero, One # noqa @@ -14,7 +14,7 @@ # `pytestmark` above from devito import Eq, Function, Grid, Operator, TimeFunction, configuration # noqa from devito.ir.equations import ClusterizedEq # noqa -from devito.ir.iet import Conditional, Expression, derive_parameters, iet_insert_decls, iet_insert_casts # noqa +from devito.ir.iet import Conditional, Expression, derive_parameters, iet_insert_decls # noqa from devito.ops.node_factory import OPSNodeFactory # noqa from devito.ops.transformer import create_ops_arg, create_ops_dat, make_ops_ast, to_ops_stencil # noqa from devito.ops.types import Array, OpsAccessible, OpsDat, OpsStencil, OpsBlock # noqa @@ -291,37 +291,6 @@ def test_single_declaration(self, equation, declaration): assert len(occurrences) == 1 - def test_conditional_declarations(self): - accesses = [[0, 0], [0, 1], [1, 0], [1, 1]] - dims = len(accesses[0]) - pts = len(accesses) - stencil_name = namespace['ops_stencil_name'](dims, 'name', pts) - stencil_array = Array( - name=stencil_name, - dimensions=(DefaultDimension(name='len', default_value=dims * pts),), - dtype=np.int32, - scope='stack' - ) - list_initialize = Expression(ClusterizedEq(Eq( - stencil_array, - ListInitializer(list(itertools.chain(*accesses))) - ))) - - iet = Conditional(x < 3, list_initialize, list_initialize) - - parameters = derive_parameters(iet, True) - iet = iet_insert_decls(iet, parameters) - iet = iet_insert_casts(iet, parameters) - assert str(iet) == """\ -if (x < 3) -{ - int s2d_name_4pt[8] = {0, 0, 0, 1, 1, 0, 1, 1}; -} -else -{ - int s2d_name_4pt[8] = {0, 0, 0, 1, 1, 0, 1, 1}; -}""" - @pytest.mark.parametrize('equation,expected', [ ('Eq(u_2d.forward, u_2d + 1)', '[\'ops_dat_fetch_data(u_dat[(time_M)%(2)],0,&(u[(time_M)%(2)]));\',' From 7767f8a9511ed8c5aa6b182f0f39f6d0f18fd739 Mon Sep 17 00:00:00 2001 From: maelso Date: Thu, 28 Nov 2019 16:32:15 -0300 Subject: [PATCH 10/11] DefaultDimension removed --- tests/test_operator.py | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/tests/test_operator.py b/tests/test_operator.py index ff3d163e9a..38d1d9e0a8 100644 --- a/tests/test_operator.py +++ b/tests/test_operator.py @@ -13,7 +13,7 @@ from devito.ir.support import Any, Backward, Forward from devito.symbolics import ListInitializer, indexify, retrieve_indexed from devito.tools import flatten -from devito.types import Array, DefaultDimension, Scalar +from devito.types import Array, Scalar pytestmark = skipif(['yask', 'ops']) @@ -1121,26 +1121,15 @@ def test_stack_vector_temporaries(self): +(double)(end_section0.tv_usec-start_section0.tv_usec)/1000000;""" in str(operator) def test_conditional_declarations(self): - accesses = [0, 0] - stencil_array = Array( - name='a', - dimensions=(DefaultDimension(name='x', default_value=len(accesses)),), - dtype=np.int32, - scope='stack' - ) - list_initialize = Expression(ClusterizedEq(Eq( - stencil_array, - ListInitializer(accesses) - ))) - + a = Array(name='a', dimensions=(x,), dtype=np.int32, scope='stack') + list_initialize = Expression(ClusterizedEq(Eq(a, ListInitializer([0, 0])))) iet = Conditional(x < 3, list_initialize, list_initialize) - parameters = derive_parameters(iet, True) iet = iet_insert_decls(iet, parameters) assert str(iet[0]) == """\ if (x < 3) { - int a[2] = {0, 0}; + int a[x_size] = {0, 0}; } else { From 5b65e19cf362e92f405800edfd6314b824b11658 Mon Sep 17 00:00:00 2001 From: maelso Date: Thu, 28 Nov 2019 16:35:34 -0300 Subject: [PATCH 11/11] Correcting the code --- tests/test_operator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_operator.py b/tests/test_operator.py index 38d1d9e0a8..324f66212c 100644 --- a/tests/test_operator.py +++ b/tests/test_operator.py @@ -1133,7 +1133,7 @@ def test_conditional_declarations(self): } else { - int a[2] = {0, 0}; + int a[x_size] = {0, 0}; }"""