From 208987796e4db8fb8b1ab388bd3adb5d3b59dbcb Mon Sep 17 00:00:00 2001 From: Kaushik Kulkarni Date: Sun, 5 Nov 2017 13:44:06 -0600 Subject: [PATCH 1/8] Added the transformation add_barrier --- loopy/__init__.py | 2 +- loopy/transform/add_barrier.py | 80 ++++++++++++++++++++++++++++++++++ test/test_transform.py | 13 ++++++ 3 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 loopy/transform/add_barrier.py diff --git a/loopy/__init__.py b/loopy/__init__.py index aa1d43172..b45649e21 100644 --- a/loopy/__init__.py +++ b/loopy/__init__.py @@ -112,7 +112,7 @@ from loopy.transform.ilp import realize_ilp from loopy.transform.batch import to_batched from loopy.transform.parameter import assume, fix_parameters from loopy.transform.save import save_and_reload_temporaries - +from loopy.transform.add_barrier import add_barrier # }}} from loopy.type_inference import infer_unknown_types diff --git a/loopy/transform/add_barrier.py b/loopy/transform/add_barrier.py new file mode 100644 index 000000000..e88630411 --- /dev/null +++ b/loopy/transform/add_barrier.py @@ -0,0 +1,80 @@ +from __future__ import division, absolute_import + +__copyright__ = "Copyright (C) 2017 Andreas Kloeckner" + +__license__ = """ +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +""" + + +import six + +from loopy.symbolic import (RuleAwareIdentityMapper, SubstitutionRuleMappingContext) +from loopy.kernel.data import ValueArg, GlobalArg +from loopy.kernel.instruction import BarrierInstruction +from loopy.match import parse_match +from loopy.transform.instruction import add_dependency +from loopy.diagnostic import LoopyError +import islpy as isl + +__doc__ = """ +.. currentmodule:: loopy + +.. autofunction:: add_barrier +""" + + +# {{{ add_barrier + +def add_barrier(knl, id, insn0_expr, insn1_expr, tags=None, kind='global'): + """Takes in a kernel that needs to be added a barrier and returns a kernel + which has a barrier inserted into it. It takes input of 2 instructions and + then adds a barrier in between those 2 instructions. + + :arg id: String which would be the id of the barrier + :arg id_insn0: String expression that specifies the first instruction + :arg id_insn1: String expression that specifies the second instruction + :arg tags: The tag of the group to which the barrier must be added + :arg kind: Specifies whether the barrier is a local or a global one + """ + + match0 = parse_match(insn0_expr) + insn0_set = [insn.id for insn in knl.instructions if match0(knl, insn)] + match1 = parse_match(insn1_expr) + insn1_set = [insn for insn in knl.instructions if match1(knl, insn)] + + if len(insn0_set)!=1 or len(insn1_set)!=1: + raise LoopyError("The instruction expressions should match only 1 instruction.") + + barrier_to_add = BarrierInstruction(depends_on = frozenset(insn0_set), + depends_on_is_final=True, + id = id, + tags = tags, + kind = kind) + new_knl = knl.copy(instructions=knl.instructions + [barrier_to_add]) + print("id:"+id) + new_knl = add_dependency(kernel=new_knl, + insn_match=insn1_expr, + depends_on="id:"+id) + + return new_knl + +# }}} + +# vim: foldmethod=marker diff --git a/test/test_transform.py b/test/test_transform.py index d17f6c707..bff0c6cb4 100644 --- a/test/test_transform.py +++ b/test/test_transform.py @@ -104,6 +104,19 @@ def test_to_batched(ctx_factory): bknl(queue, a=a, x=x) +def test_add_barrier(ctx_factory): + ctx = ctx_factory() + queue = cl.CommandQueue(ctx) + kernel = lp.make_kernel( + "{[i, j, ii, jj]: 0<=i,j, ii, jj Date: Sun, 5 Nov 2017 15:49:57 -0600 Subject: [PATCH 2/8] Modified according to PEP8 --- loopy/transform/add_barrier.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/loopy/transform/add_barrier.py b/loopy/transform/add_barrier.py index e88630411..28d434d22 100644 --- a/loopy/transform/add_barrier.py +++ b/loopy/transform/add_barrier.py @@ -62,15 +62,15 @@ def add_barrier(knl, id, insn0_expr, insn1_expr, tags=None, kind='global'): if len(insn0_set)!=1 or len(insn1_set)!=1: raise LoopyError("The instruction expressions should match only 1 instruction.") - barrier_to_add = BarrierInstruction(depends_on = frozenset(insn0_set), + barrier_to_add = BarrierInstruction(depends_on=frozenset(insn0_set), depends_on_is_final=True, - id = id, - tags = tags, - kind = kind) + id=id, + tags=tags, + kind=kind) new_knl = knl.copy(instructions=knl.instructions + [barrier_to_add]) print("id:"+id) - new_knl = add_dependency(kernel=new_knl, - insn_match=insn1_expr, + new_knl = add_dependency(kernel=new_knl, + insn_match=insn1_expr, depends_on="id:"+id) return new_knl -- GitLab From 328890ebe0f7c85e80008088c7f36a51c2b48ad4 Mon Sep 17 00:00:00 2001 From: Kaushik Kulkarni Date: Sun, 5 Nov 2017 15:51:12 -0600 Subject: [PATCH 3/8] modifications adhering to PEP8 --- test/test_transform.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/test_transform.py b/test/test_transform.py index bff0c6cb4..02cd6b895 100644 --- a/test/test_transform.py +++ b/test/test_transform.py @@ -104,6 +104,7 @@ def test_to_batched(ctx_factory): bknl(queue, a=a, x=x) + def test_add_barrier(ctx_factory): ctx = ctx_factory() queue = cl.CommandQueue(ctx) @@ -118,6 +119,7 @@ def test_add_barrier(ctx_factory): evt, (out,) = new_kernel(queue, a=a) assert (np.linalg.norm(out-2*a.T) < 1e-16) + def test_rename_argument(ctx_factory): ctx = ctx_factory() queue = cl.CommandQueue(ctx) -- GitLab From 62dae28d9165ca3e479a86a22d8c569e3b6f9231 Mon Sep 17 00:00:00 2001 From: Kaushik Kulkarni Date: Sun, 5 Nov 2017 16:04:55 -0600 Subject: [PATCH 4/8] Added documentation support --- doc/ref_transform.rst | 2 ++ loopy/transform/add_barrier.py | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/ref_transform.rst b/doc/ref_transform.rst index d293e3ebe..8bdd17b62 100644 --- a/doc/ref_transform.rst +++ b/doc/ref_transform.rst @@ -74,6 +74,8 @@ Manipulating Instructions .. autofunction:: add_nosync +.. autofunction:: add_barrier + Registering Library Routines ---------------------------- diff --git a/loopy/transform/add_barrier.py b/loopy/transform/add_barrier.py index 28d434d22..f5f97de87 100644 --- a/loopy/transform/add_barrier.py +++ b/loopy/transform/add_barrier.py @@ -45,10 +45,11 @@ __doc__ = """ def add_barrier(knl, id, insn0_expr, insn1_expr, tags=None, kind='global'): """Takes in a kernel that needs to be added a barrier and returns a kernel which has a barrier inserted into it. It takes input of 2 instructions and - then adds a barrier in between those 2 instructions. + then adds a barrier in between those 2 instructions. See **parse_match()** + for the expected format of expression. :arg id: String which would be the id of the barrier - :arg id_insn0: String expression that specifies the first instruction + :arg id_insn0: String expression that specifies the first instruction :arg id_insn1: String expression that specifies the second instruction :arg tags: The tag of the group to which the barrier must be added :arg kind: Specifies whether the barrier is a local or a global one -- GitLab From 5c3ee13ea1b2c8a45085b89b2924b54145562a69 Mon Sep 17 00:00:00 2001 From: Kaushik Kulkarni Date: Sun, 5 Nov 2017 16:19:47 -0600 Subject: [PATCH 5/8] PEP 8 formatting --- loopy/transform/add_barrier.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/loopy/transform/add_barrier.py b/loopy/transform/add_barrier.py index f5f97de87..6ee49efc6 100644 --- a/loopy/transform/add_barrier.py +++ b/loopy/transform/add_barrier.py @@ -23,15 +23,10 @@ THE SOFTWARE. """ -import six - -from loopy.symbolic import (RuleAwareIdentityMapper, SubstitutionRuleMappingContext) -from loopy.kernel.data import ValueArg, GlobalArg from loopy.kernel.instruction import BarrierInstruction from loopy.match import parse_match from loopy.transform.instruction import add_dependency from loopy.diagnostic import LoopyError -import islpy as isl __doc__ = """ .. currentmodule:: loopy @@ -61,11 +56,12 @@ def add_barrier(knl, id, insn0_expr, insn1_expr, tags=None, kind='global'): insn1_set = [insn for insn in knl.instructions if match1(knl, insn)] if len(insn0_set)!=1 or len(insn1_set)!=1: - raise LoopyError("The instruction expressions should match only 1 instruction.") + raise LoopyError("The instruction expressions should match only 1\ +instruction.") barrier_to_add = BarrierInstruction(depends_on=frozenset(insn0_set), depends_on_is_final=True, - id=id, + id = id, tags=tags, kind=kind) new_knl = knl.copy(instructions=knl.instructions + [barrier_to_add]) -- GitLab From 694a602de0254c368e4197356f288cf497cffd80 Mon Sep 17 00:00:00 2001 From: Kaushik Kulkarni Date: Sun, 5 Nov 2017 16:37:38 -0600 Subject: [PATCH 6/8] More PEP 8 modifications --- loopy/__init__.py | 2 ++ loopy/transform/add_barrier.py | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/loopy/__init__.py b/loopy/__init__.py index b45649e21..e48a8b3bd 100644 --- a/loopy/__init__.py +++ b/loopy/__init__.py @@ -215,6 +215,8 @@ __all__ = [ "save_and_reload_temporaries", + "add_barrier", + # }}} "get_dot_dependency_graph", diff --git a/loopy/transform/add_barrier.py b/loopy/transform/add_barrier.py index 6ee49efc6..ec68348c9 100644 --- a/loopy/transform/add_barrier.py +++ b/loopy/transform/add_barrier.py @@ -55,13 +55,13 @@ def add_barrier(knl, id, insn0_expr, insn1_expr, tags=None, kind='global'): match1 = parse_match(insn1_expr) insn1_set = [insn for insn in knl.instructions if match1(knl, insn)] - if len(insn0_set)!=1 or len(insn1_set)!=1: + if len(insn0_set) != 1 or len(insn1_set) != 1: raise LoopyError("The instruction expressions should match only 1\ instruction.") barrier_to_add = BarrierInstruction(depends_on=frozenset(insn0_set), depends_on_is_final=True, - id = id, + id=id, tags=tags, kind=kind) new_knl = knl.copy(instructions=knl.instructions + [barrier_to_add]) -- GitLab From f1aabf8f28799e401de6f1e71796ae60d4b50b70 Mon Sep 17 00:00:00 2001 From: Kaushik Kulkarni Date: Mon, 6 Nov 2017 21:50:56 -0600 Subject: [PATCH 7/8] Changes done according to comments received after the merge request. --- loopy/transform/add_barrier.py | 32 +++++++++++++++----------------- test/test_transform.py | 12 +++++++++--- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/loopy/transform/add_barrier.py b/loopy/transform/add_barrier.py index ec68348c9..0718b9a3e 100644 --- a/loopy/transform/add_barrier.py +++ b/loopy/transform/add_barrier.py @@ -1,6 +1,6 @@ from __future__ import division, absolute_import -__copyright__ = "Copyright (C) 2017 Andreas Kloeckner" +__copyright__ = "Copyright (C) 2017 Kaushik Kulkarni" __license__ = """ Permission is hereby granted, free of charge, to any person obtaining a copy @@ -26,7 +26,6 @@ THE SOFTWARE. from loopy.kernel.instruction import BarrierInstruction from loopy.match import parse_match from loopy.transform.instruction import add_dependency -from loopy.diagnostic import LoopyError __doc__ = """ .. currentmodule:: loopy @@ -37,38 +36,37 @@ __doc__ = """ # {{{ add_barrier -def add_barrier(knl, id, insn0_expr, insn1_expr, tags=None, kind='global'): +def add_barrier(knl, id="", insn_before="", insn_after="", tags=None, + kind="global"): """Takes in a kernel that needs to be added a barrier and returns a kernel which has a barrier inserted into it. It takes input of 2 instructions and - then adds a barrier in between those 2 instructions. See **parse_match()** - for the expected format of expression. + then adds a barrier in between those 2 instructions. The expressions can + be any inputs that are understood by :func:`loopy.match.parse_match`. :arg id: String which would be the id of the barrier :arg id_insn0: String expression that specifies the first instruction :arg id_insn1: String expression that specifies the second instruction :arg tags: The tag of the group to which the barrier must be added - :arg kind: Specifies whether the barrier is a local or a global one + :arg kind: Kind of barrier to be added. May be "global" or "local". """ - match0 = parse_match(insn0_expr) - insn0_set = [insn.id for insn in knl.instructions if match0(knl, insn)] - match1 = parse_match(insn1_expr) - insn1_set = [insn for insn in knl.instructions if match1(knl, insn)] + if id == "": + id = knl.make_unique_instruction_id(based_on=kind[0]+"_barrier") - if len(insn0_set) != 1 or len(insn1_set) != 1: - raise LoopyError("The instruction expressions should match only 1\ -instruction.") + match = parse_match(insn_before) + insn_before_list = [insn.id for insn in knl.instructions if match(knl, + insn)] - barrier_to_add = BarrierInstruction(depends_on=frozenset(insn0_set), + barrier_to_add = BarrierInstruction(depends_on=frozenset(insn_before_list), depends_on_is_final=True, id=id, tags=tags, kind=kind) + new_knl = knl.copy(instructions=knl.instructions + [barrier_to_add]) - print("id:"+id) new_knl = add_dependency(kernel=new_knl, - insn_match=insn1_expr, - depends_on="id:"+id) + insn_match=insn_after, + depends_on="id:"+id) return new_knl diff --git a/test/test_transform.py b/test/test_transform.py index 02cd6b895..f747105d3 100644 --- a/test/test_transform.py +++ b/test/test_transform.py @@ -108,15 +108,21 @@ def test_to_batched(ctx_factory): def test_add_barrier(ctx_factory): ctx = ctx_factory() queue = cl.CommandQueue(ctx) - kernel = lp.make_kernel( + knl = lp.make_kernel( "{[i, j, ii, jj]: 0<=i,j, ii, jj Date: Wed, 8 Nov 2017 00:25:18 -0600 Subject: [PATCH 8/8] makes changes from `id` to `id_based_on` --- loopy/transform/add_barrier.py | 16 ++++++++++------ test/test_transform.py | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/loopy/transform/add_barrier.py b/loopy/transform/add_barrier.py index 0718b9a3e..00c99edce 100644 --- a/loopy/transform/add_barrier.py +++ b/loopy/transform/add_barrier.py @@ -36,22 +36,26 @@ __doc__ = """ # {{{ add_barrier -def add_barrier(knl, id="", insn_before="", insn_after="", tags=None, - kind="global"): +def add_barrier(knl, insn_before="", insn_after="", id_based_on=None, + tags=None, kind="global"): """Takes in a kernel that needs to be added a barrier and returns a kernel which has a barrier inserted into it. It takes input of 2 instructions and then adds a barrier in between those 2 instructions. The expressions can be any inputs that are understood by :func:`loopy.match.parse_match`. - :arg id: String which would be the id of the barrier - :arg id_insn0: String expression that specifies the first instruction - :arg id_insn1: String expression that specifies the second instruction + :arg insn_before: String expression that specifies the instruction(s) + before the barrier which is to be added + :arg insn_after: String expression that specifies the instruction(s) after + the barrier which is to be added + :arg id: String on which the id of the barrier would be based on. :arg tags: The tag of the group to which the barrier must be added :arg kind: Kind of barrier to be added. May be "global" or "local". """ - if id == "": + if id_based_on is None: id = knl.make_unique_instruction_id(based_on=kind[0]+"_barrier") + else: + id = knl.make_unique_instruction_id(based_on=id_based_on) match = parse_match(insn_before) insn_before_list = [insn.id for insn in knl.instructions if match(knl, diff --git a/test/test_transform.py b/test/test_transform.py index f747105d3..e50605b46 100644 --- a/test/test_transform.py +++ b/test/test_transform.py @@ -115,7 +115,7 @@ def test_add_barrier(ctx_factory): out[ii, jj] = 2*out[ii, jj]{id=double} """) a = np.random.randn(16, 16) - knl = lp.add_barrier(knl, "gb1", "id:transpose", "id:double") + knl = lp.add_barrier(knl, "id:transpose", "id:double", "gb1") knl = lp.split_iname(knl, "i", 2, outer_tag="g.0", inner_tag="l.0") knl = lp.split_iname(knl, "j", 2, outer_tag="g.1", inner_tag="l.1") -- GitLab