Skip to content
Snippets Groups Projects
Commit 94eec370 authored by Andreas Klöckner's avatar Andreas Klöckner
Browse files

Rename idempotent->boostable. Be more restrictive in marking insns boostable.

In particular, just touching a variable written to by a non-idempotent
instruction makes that instruction also not idempotent.
parent 7a368750
No related branches found
No related tags found
No related merge requests found
......@@ -42,9 +42,6 @@ Things to consider
To-do
^^^^^
- Just touching a variable written to by a non-idempotent
instruction makes that instruction also not idempotent
- user interface for dim length prescription
- Deal with equality constraints.
......@@ -89,6 +86,11 @@ Future ideas
Dealt with
^^^^^^^^^^
- Just touching a variable written to by a non-idempotent
instruction makes that instruction also not idempotent
-> Idempotent renamed to boostable.
-> Done.
- Give the user control over which reduction inames are
duplicated.
......
......@@ -223,8 +223,9 @@ class Instruction(Record):
:ivar insn_deps: a list of ids of :class:`Instruction` instances that
*must* be executed before this one. Note that loop scheduling augments this
by adding dependencies on any writes to temporaries read by this instruction.
:ivar idempotent: Whether the instruction may be executed repeatedly (while obeying
dependencies) without changing the meaning of the program.
:ivar boostable: Whether the instruction may safely be executed
inside more loops than advertised without changing the meaning
of the program. Allowed values are *None* (for unknwon), *True*, and *False*.
The following two instance variables are only used until :func:`loopy.kernel.make_kernel` is
finished:
......@@ -236,13 +237,13 @@ class Instruction(Record):
"""
def __init__(self,
id, assignee, expression,
forced_iname_deps=[], insn_deps=[], idempotent=None,
forced_iname_deps=[], insn_deps=[], boostable=None,
temp_var_type=None, duplicate_inames_and_tags=[]):
Record.__init__(self,
id=id, assignee=assignee, expression=expression,
forced_iname_deps=forced_iname_deps,
insn_deps=insn_deps, idempotent=idempotent,
insn_deps=insn_deps, boostable=boostable,
temp_var_type=temp_var_type, duplicate_inames_and_tags=duplicate_inames_and_tags)
@memoize_method
......@@ -268,14 +269,14 @@ class Instruction(Record):
result = "%s: %s <- %s\n [%s]" % (self.id,
self.assignee, self.expression, ", ".join(sorted(self.all_inames())))
if self.idempotent == True:
result += " (idempotent)"
elif self.idempotent == False:
result += " (not idempotent)"
elif self.idempotent is None:
result += " (idempotence unknown)"
if self.boostable == True:
result += " (boostable)"
elif self.boostable == False:
result += " (not boostable)"
elif self.boostable is None:
result += " (boostability unknown)"
else:
raise RuntimeError("unexpected value for Instruction.idempotent")
raise RuntimeError("unexpected value for Instruction.boostable")
if self.insn_deps:
result += "\n : " + ", ".join(self.insn_deps)
......
......@@ -98,7 +98,7 @@ def realize_reduction(kernel):
# }}}
# {{{ automatic dependencies, find idempotent instructions
# {{{ automatic dependencies, find boostability of instructions
def find_accessors(kernel, readers):
"""
......@@ -129,7 +129,7 @@ def find_accessors(kernel, readers):
def add_idempotence_and_automatic_dependencies(kernel):
def add_boostability_and_automatic_dependencies(kernel):
writer_map = find_accessors(kernel, readers=False)
arg_names = set(arg.name for arg in kernel.args)
......@@ -145,11 +145,14 @@ def add_idempotence_and_automatic_dependencies(kernel):
set(var.name for var in dm(insn.expression))
& var_names)
non_boostable_vars = set()
new_insns = []
for insn in kernel.instructions:
auto_deps = []
# {{{ add automatic dependencies
all_my_var_writers = set()
for var in dep_map[insn.id]:
var_writers = writer_map.get(var, set())
......@@ -171,7 +174,7 @@ def add_idempotence_and_automatic_dependencies(kernel):
# }}}
# {{{ find dependency loops, flag idempotence
# {{{ find dependency loops, flag boostability
while True:
last_all_my_var_writers = all_my_var_writers
......@@ -185,12 +188,30 @@ def add_idempotence_and_automatic_dependencies(kernel):
# }}}
boostable = insn.id not in all_my_var_writers
if not boostable:
non_boostable_vars.add(insn.get_assignee_var_name())
new_insns.append(
insn.copy(
insn_deps=insn.insn_deps + auto_deps,
idempotent=insn.id not in all_my_var_writers))
boostable=boostable))
# {{{ remove boostability from isns that access non-boostable vars
new2_insns = []
for insn in new_insns:
accessed_vars = (
set([insn.get_assignee_var_name()])
| insn.get_read_var_names())
boostable = insn.boostable and not bool(non_boostable_vars & accessed_vars)
new2_insns.append(insn.copy(boostable=boostable))
# }}}
return kernel.copy(instructions=new_insns)
return kernel.copy(instructions=new2_insns)
# }}}
......@@ -480,7 +501,7 @@ def preprocess_kernel(kernel):
# }}}
kernel = assign_automatic_axes(kernel)
kernel = add_idempotence_and_automatic_dependencies(kernel)
kernel = add_boostability_and_automatic_dependencies(kernel)
kernel = adjust_local_temp_var_storage(kernel)
import loopy.check as chk
......
......@@ -191,8 +191,8 @@ def generate_loop_schedules_internal(kernel, loop_priority, schedule=[]):
schedule_now = set(insn.insn_deps) <= scheduled_insn_ids
if insn.idempotent == True:
# If insn is idempotent, it may be placed inside a more deeply
if insn.boostable == True:
# If insn is boostable, it may be placed inside a more deeply
# nested loop without harm.
# But if it can be scheduled on the way *out* of the currently
......@@ -212,8 +212,8 @@ def generate_loop_schedules_internal(kernel, loop_priority, schedule=[]):
if schedulable_at_loop_levels != [len(active_inames)]:
schedule_now = False
elif insn.idempotent == False:
# If insn is not idempotent, we must insist that it is placed inside
elif insn.boostable == False:
# If insn is not boostable, we must insist that it is placed inside
# the exactly correct set of loops.
schedule_now = schedule_now and (
......@@ -222,7 +222,7 @@ def generate_loop_schedules_internal(kernel, loop_priority, schedule=[]):
active_inames_set - parallel_inames)
else:
raise RuntimeError("instruction '%s' has undetermined idempotence"
raise RuntimeError("instruction '%s' has undetermined boostability"
% insn.id)
if schedule_now:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment