From edb46124aee97df736d49706d1e6445fee0f2d0c Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner <inform@tiker.net> Date: Thu, 27 Oct 2016 13:07:24 -0500 Subject: [PATCH] Process single-writer heuristic early, deprecate late single-writer resolution --- loopy/kernel/__init__.py | 5 +-- loopy/kernel/creation.py | 71 ++++++++++++++++++++++++++++++++++++++++ loopy/kernel/tools.py | 4 +-- loopy/preprocess.py | 60 ++------------------------------- loopy/transform/diff.py | 4 +-- loopy/transform/subst.py | 4 +-- 6 files changed, 82 insertions(+), 66 deletions(-) diff --git a/loopy/kernel/__init__.py b/loopy/kernel/__init__.py index f811812da..f606057aa 100644 --- a/loopy/kernel/__init__.py +++ b/loopy/kernel/__init__.py @@ -1094,8 +1094,9 @@ class LoopKernel(RecordWithoutPickling): lines = [] - from loopy.preprocess import add_default_dependencies - kernel = add_default_dependencies(self) + from loopy.creation import apply_single_writer_depencency_heuristic + kernel = apply_single_writer_depencency_heuristic( + self, warn_if_used=False) sep = 75*"-" diff --git a/loopy/kernel/creation.py b/loopy/kernel/creation.py index 396b2b072..9859e0f14 100644 --- a/loopy/kernel/creation.py +++ b/loopy/kernel/creation.py @@ -1484,6 +1484,76 @@ def add_inferred_inames(knl): # }}} +# {{{ apply single-writer heuristic + +def apply_single_writer_depencency_heuristic(kernel, warn_if_used=True): + logger.debug("%s: default deps" % kernel.name) + + from loopy.transform.subst import expand_subst + expanded_kernel = expand_subst(kernel) + + writer_map = kernel.writer_map() + + arg_names = set(arg.name for arg in kernel.args) + + var_names = arg_names | set(six.iterkeys(kernel.temporary_variables)) + + dep_map = dict( + (insn.id, insn.read_dependency_names() & var_names) + for insn in expanded_kernel.instructions) + + new_insns = [] + for insn in kernel.instructions: + if not insn.depends_on_is_final: + auto_deps = set() + + # {{{ add automatic dependencies + + all_my_var_writers = set() + for var in dep_map[insn.id]: + var_writers = writer_map.get(var, set()) + all_my_var_writers |= var_writers + + if not var_writers and var not in arg_names: + tv = kernel.temporary_variables[var] + if tv.initializer is None: + warn_with_kernel(kernel, "read_no_write(%s)" % var, + "temporary variable '%s' is read, but never written." + % var) + + if len(var_writers) == 1: + auto_deps.update( + var_writers + - set([insn.id])) + + # }}} + + depends_on = insn.depends_on + if depends_on is None: + depends_on = frozenset() + + new_deps = frozenset(auto_deps) | depends_on + + if warn_if_used and new_deps != depends_on: + warn_with_kernel(kernel, "single_writer_after_creation", + "The single-writer dependency heuristic added dependencies " + "on instruction ID(s) '%s' to instruction ID '%s' after " + "kernel creation is complete. This is deprecated and " + "may stop working in the future. " + "To fix this, ensure that instruction dependencies " + "are added/resolved as soon as possible, ideally at kernel " + "creation time." + % (", ".join(new_deps - depends_on), insn.id)) + + insn = insn.copy(depends_on=new_deps) + + new_insns.append(insn) + + return kernel.copy(instructions=new_insns) + +# }}} + + # {{{ kernel creation top-level def make_kernel(domains, instructions, kernel_data=["..."], **kwargs): @@ -1711,6 +1781,7 @@ def make_kernel(domains, instructions, kernel_data=["..."], **kwargs): knl = guess_arg_shape_if_requested(knl, default_order) knl = apply_default_order_to_args(knl, default_order) knl = resolve_wildcard_deps(knl) + knl = apply_single_writer_depencency_heuristic(knl) # ------------------------------------------------------------------------- # Ordering dependency: diff --git a/loopy/kernel/tools.py b/loopy/kernel/tools.py index 350f4497c..66db79eff 100644 --- a/loopy/kernel/tools.py +++ b/loopy/kernel/tools.py @@ -438,8 +438,8 @@ def get_dot_dependency_graph(kernel, iname_cluster=True, use_insn_id=False): """ # make sure all automatically added stuff shows up - from loopy.preprocess import add_default_dependencies - kernel = add_default_dependencies(kernel) + from loopy.creation import apply_single_writer_depencency_heuristic + kernel = apply_single_writer_depencency_heuristic(kernel, warn_if_used=False) if iname_cluster and not kernel.schedule: try: diff --git a/loopy/preprocess.py b/loopy/preprocess.py index db3be65f1..09437f213 100644 --- a/loopy/preprocess.py +++ b/loopy/preprocess.py @@ -436,63 +436,6 @@ def find_temporary_scope(kernel): # }}} -# {{{ default dependencies - -def add_default_dependencies(kernel): - logger.debug("%s: default deps" % kernel.name) - - from loopy.transform.subst import expand_subst - expanded_kernel = expand_subst(kernel) - - writer_map = kernel.writer_map() - - arg_names = set(arg.name for arg in kernel.args) - - var_names = arg_names | set(six.iterkeys(kernel.temporary_variables)) - - dep_map = dict( - (insn.id, insn.read_dependency_names() & var_names) - for insn in expanded_kernel.instructions) - - new_insns = [] - for insn in kernel.instructions: - if not insn.depends_on_is_final: - auto_deps = set() - - # {{{ add automatic dependencies - - all_my_var_writers = set() - for var in dep_map[insn.id]: - var_writers = writer_map.get(var, set()) - all_my_var_writers |= var_writers - - if not var_writers and var not in arg_names: - tv = kernel.temporary_variables[var] - if tv.initializer is None: - warn_with_kernel(kernel, "read_no_write(%s)" % var, - "temporary variable '%s' is read, but never written." - % var) - - if len(var_writers) == 1: - auto_deps.update( - var_writers - - set([insn.id])) - - # }}} - - depends_on = insn.depends_on - if depends_on is None: - depends_on = frozenset() - - insn = insn.copy(depends_on=frozenset(auto_deps) | depends_on) - - new_insns.append(insn) - - return kernel.copy(instructions=new_insns) - -# }}} - - # {{{ rewrite reduction to imperative form def realize_reduction(kernel, insn_id_filter=None, unknown_types_ok=True): @@ -1119,7 +1062,8 @@ def preprocess_kernel(kernel, device=None): check_reduction_iname_uniqueness(kernel) - kernel = add_default_dependencies(kernel) + from loopy.kernel.creation import apply_single_writer_depencency_heuristic + kernel = apply_single_writer_depencency_heuristic(kernel) # Ordering restrictions: # diff --git a/loopy/transform/diff.py b/loopy/transform/diff.py index d972f44cf..a292cb666 100644 --- a/loopy/transform/diff.py +++ b/loopy/transform/diff.py @@ -370,8 +370,8 @@ def diff_kernel(knl, diff_outputs, by, diff_iname_prefix="diff_i", *diff_context.by_name*, or *None* if no dependency exists. """ - from loopy.preprocess import add_default_dependencies - knl = add_default_dependencies(knl) + from loopy.preprocess import apply_single_writer_depencency_heuristic + knl = apply_single_writer_depencency_heuristic(knl, warn_if_used=True) if isinstance(diff_outputs, str): diff_outputs = [ diff --git a/loopy/transform/subst.py b/loopy/transform/subst.py index 27e98383e..5f0db65d6 100644 --- a/loopy/transform/subst.py +++ b/loopy/transform/subst.py @@ -311,8 +311,8 @@ def assignment_to_subst(kernel, lhs_name, extra_arguments=(), within=None, # {{{ establish the relevant definition of lhs_name for each usage site dep_kernel = expand_subst(kernel) - from loopy.preprocess import add_default_dependencies - dep_kernel = add_default_dependencies(dep_kernel) + from loopy.preprocess import apply_single_writer_depencency_heuristic + dep_kernel = apply_single_writer_depencency_heuristic(dep_kernel) id_to_insn = dep_kernel.id_to_insn -- GitLab