diff --git a/doc/ref_transform.rst b/doc/ref_transform.rst index d293e3ebe998a632bd547f94a67e675ff0592bfb..8bdd17b6295e9328bbbb4acbadd2be7e14ae625b 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/__init__.py b/loopy/__init__.py index aa1d43172a4bd6472f5974c292c4256946fcf542..e48a8b3bdb77f2e2e10bb3546fafe7bf3ceb66c4 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 @@ -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 new file mode 100644 index 0000000000000000000000000000000000000000..00c99edce1ee741572e378d3610e533c6621ecfb --- /dev/null +++ b/loopy/transform/add_barrier.py @@ -0,0 +1,79 @@ +from __future__ import division, absolute_import + +__copyright__ = "Copyright (C) 2017 Kaushik Kulkarni" + +__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. +""" + + +from loopy.kernel.instruction import BarrierInstruction +from loopy.match import parse_match +from loopy.transform.instruction import add_dependency + +__doc__ = """ +.. currentmodule:: loopy + +.. autofunction:: add_barrier +""" + + +# {{{ add_barrier + +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 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_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, + insn)] + + 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]) + new_knl = add_dependency(kernel=new_knl, + insn_match=insn_after, + depends_on="id:"+id) + + return new_knl + +# }}} + +# vim: foldmethod=marker diff --git a/test/test_transform.py b/test/test_transform.py index d17f6c707d36214f0f6713da25c8be0691b58d2c..e50605b46672f8e9c1817431f1577742b1f6fb4c 100644 --- a/test/test_transform.py +++ b/test/test_transform.py @@ -105,6 +105,27 @@ 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) + knl = lp.make_kernel( + "{[i, j, ii, jj]: 0<=i,j, ii, jj