From a834aeef0fa2f1c1182b1e61696af2c22380e28e Mon Sep 17 00:00:00 2001 From: Matt Wala <wala1@illinois.edu> Date: Fri, 23 Dec 2016 12:40:15 -0600 Subject: [PATCH] Implement a syntax for no_sync_with_scopes. (closes #67 on github) --- loopy/kernel/__init__.py | 5 ++--- loopy/kernel/creation.py | 38 ++++++++++++++++++++++++++++--------- loopy/kernel/instruction.py | 4 +--- test/test_loopy.py | 19 +++++++++++++++++++ 4 files changed, 51 insertions(+), 15 deletions(-) diff --git a/loopy/kernel/__init__.py b/loopy/kernel/__init__.py index 5dff5e53c..e48b83935 100644 --- a/loopy/kernel/__init__.py +++ b/loopy/kernel/__init__.py @@ -1226,9 +1226,8 @@ class LoopKernel(ImmutableRecordWithoutPickling): options.append( "conflicts=%s" % ":".join(insn.conflicts_with_groups)) if insn.no_sync_with: - # FIXME: Find a syntax to express scopes. - options.append("no_sync_with=%s" % ":".join(id for id, _ in - insn.no_sync_with)) + options.append("no_sync_with=%s" % ":".join( + "%s@%s" % entry for entry in sorted(insn.no_sync_with))) if lhs: core = "%s <- %s" % ( diff --git a/loopy/kernel/creation.py b/loopy/kernel/creation.py index 0a030b108..9a05408bb 100644 --- a/loopy/kernel/creation.py +++ b/loopy/kernel/creation.py @@ -167,6 +167,11 @@ def get_default_insn_options_dict(): } +from collections import namedtuple + +_NosyncParseResult = namedtuple("_NosyncParseResult", "expr, scope") + + def parse_insn_options(opt_dict, options_str, assignee_names=None): if options_str is None: return opt_dict @@ -175,6 +180,20 @@ def parse_insn_options(opt_dict, options_str, assignee_names=None): result = opt_dict.copy() + def parse_nosync_option(opt_value): + if "@" in opt_value: + expr, scope = opt_value.split("@") + else: + expr = opt_value + scope = "any" + allowable_scopes = ("local", "global", "any") + if scope not in allowable_scopes: + raise ValueError( + "unknown scope for nosync option: '%s' " + "(allowable scopes are %s)" % + (scope, ', '.join("'%s'" % s for s in allowable_scopes))) + return _NosyncParseResult(expr, scope) + for option in options_str.split(","): option = option.strip() if not option: @@ -242,23 +261,24 @@ def parse_insn_options(opt_dict, options_str, assignee_names=None): raise LoopyError("'nosync' option may not be specified " "in a 'with' block") - # TODO: Come up with a syntax that allows the user to express - # different synchronization scopes. result["no_sync_with"] = result["no_sync_with"].union(frozenset( - (intern(dep.strip()), "any") - for dep in opt_value.split(":") if dep.strip())) + (option.expr.strip(), option.scope) + for option in ( + parse_nosync_option(entry) + for entry in opt_value.split(":")) + if option.expr.strip())) elif opt_key == "nosync_query" and opt_value is not None: if is_with_block: raise LoopyError("'nosync' option may not be specified " "in a 'with' block") + match_expr, scope = parse_nosync_option(opt_value) + from loopy.match import parse_match - match = parse_match(opt_value) - # TODO: Come up with a syntax that allows the user to express - # different synchronization scopes. + match = parse_match(match_expr) result["no_sync_with"] = result["no_sync_with"].union( - frozenset([(match, "any")])) + frozenset([(match, scope)])) elif opt_key == "groups" and opt_value is not None: result["groups"] = frozenset( @@ -1627,7 +1647,7 @@ def resolve_dependencies(knl): (resolved_insn_id, nosync_scope) for nosync_dep, nosync_scope in insn.no_sync_with for resolved_insn_id in - _resolve_dependencies(knl, insn, nosync_dep)), + _resolve_dependencies(knl, insn, (nosync_dep,))), )) return knl.copy(instructions=new_insns) diff --git a/loopy/kernel/instruction.py b/loopy/kernel/instruction.py index 4477f5baf..2e81c2e38 100644 --- a/loopy/kernel/instruction.py +++ b/loopy/kernel/instruction.py @@ -388,10 +388,8 @@ class InstructionBase(ImmutableRecord): if self.depends_on: result.append("dep="+":".join(self.depends_on)) if self.no_sync_with: - # TODO: Come up with a syntax to express different kinds of - # synchronization scopes. result.append("nosync="+":".join( - insn_id for insn_id, _ in self.no_sync_with)) + "%s@%s" % entry for entry in self.no_sync_with)) if self.groups: result.append("groups=%s" % ":".join(self.groups)) if self.conflicts_with_groups: diff --git a/test/test_loopy.py b/test/test_loopy.py index 48ccd8ee0..6ef28f676 100644 --- a/test/test_loopy.py +++ b/test/test_loopy.py @@ -1995,6 +1995,25 @@ def test_integer_reduction(ctx_factory): assert function(out) +def test_nosync_option_parsing(): + knl = lp.make_kernel( + "{[i]: 0 <= i < 10}", + """ + <>t = 1 {id=insn1,nosync=insn1} + t = 2 {id=insn2,nosync=insn1:insn2} + t = 3 {id=insn3,nosync=insn1@local:insn2@global:insn3@any} + t = 4 {id=insn4,nosync_query=id:insn*@local} + t = 5 {id=insn5,nosync_query=id:insn1} + """, + options=lp.Options(allow_terminal_colors=False)) + kernel_str = str(knl) + assert "# insn1,no_sync_with=insn1@any" in kernel_str + assert "# insn2,no_sync_with=insn1@any:insn2@any" in kernel_str + assert "# insn3,no_sync_with=insn1@local:insn2@global:insn3@any" in kernel_str + assert "# insn4,no_sync_with=insn1@local:insn2@local:insn3@local" in kernel_str + assert "# insn5,no_sync_with=insn1@any" in kernel_str + + def assert_barrier_between(knl, id1, id2): from loopy.schedule import RunInstruction, Barrier watch_for_barrier = False -- GitLab