From db4194c177cf4b8faaf7facbb4928394aa18d6a4 Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Mon, 26 Mar 2012 00:33:36 -0400 Subject: [PATCH] Avoid write races when determining whether a temporary should be local. --- loopy/preprocess.py | 50 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/loopy/preprocess.py b/loopy/preprocess.py index 45d8c0a1e..97c3f3c44 100644 --- a/loopy/preprocess.py +++ b/loopy/preprocess.py @@ -51,18 +51,54 @@ def mark_local_temporaries(kernel): from loopy.symbolic import get_dependencies for temp_var in kernel.temporary_variables.itervalues(): + # Only fill out for variables that do not yet know if they're + # local. (I.e. those generated by implicit temporary generation.) + + if temp_var.is_local is not None: + new_temp_vars[temp_var.name] = temp_var + continue + my_writers = writers[temp_var.name] - has_local_parallel_write = False + wants_to_be_local_per_insn = [] for insn_id in my_writers: insn = kernel.id_to_insn[insn_id] - has_local_parallel_write = has_local_parallel_write or any( - isinstance(kernel.iname_to_tag.get(iname), LocalIndexTagBase) - for iname in get_dependencies(insn.get_assignee_indices()) - & kernel.all_inames()) - new_temp_vars[temp_var.name] = temp_var.copy( - is_local=has_local_parallel_write) + # A write race will emerge if: + # + # - the variable is local + # and + # - the instruction is run across more inames (locally) parallel + # than are reflected in the assignee indices. + + parallel_compute_inames = set(iname + for iname in kernel.insn_inames(insn_id) + if isinstance(kernel.iname_to_tag.get(iname), LocalIndexTagBase)) + + parallel_assignee_inames = set(iname + for iname in + get_dependencies(insn.get_assignee_indices()) + & kernel.all_inames() + if isinstance(kernel.iname_to_tag.get(iname), LocalIndexTagBase)) + + assert parallel_assignee_inames <= parallel_compute_inames + + wants_to_be_local_per_insn.append( + parallel_assignee_inames == parallel_compute_inames) + + if not wants_to_be_local_per_insn: + from warnings import warn + from loopy import LoopyAdvisory + warn("temporary variable '%s' never written, eliminating" + % temp_var.name, LoopyAdvisory) + + is_local = wants_to_be_local_per_insn[0] + from pytools import all + if not all(wtbl==is_local for wtbl in wants_to_be_local_per_insn): + raise RuntimeError("not all instructions agree on whether " + "temporary '%s' should be in local memory" % temp_var.name) + + new_temp_vars[temp_var.name] = temp_var.copy(is_local=is_local) return kernel.copy(temporary_variables=new_temp_vars) -- GitLab