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

Use loop nest maps to simplify scheduler.

parent 38ba6c3c
No related branches found
No related tags found
No related merge requests found
...@@ -87,6 +87,8 @@ Future ideas ...@@ -87,6 +87,8 @@ Future ideas
Dealt with Dealt with
^^^^^^^^^^ ^^^^^^^^^^
- Scheduler tries too many boostability-related options
- Automatically generate testing code vs. sequential. - Automatically generate testing code vs. sequential.
- If isl can prove that all operands are positive, may use '/' instead of - If isl can prove that all operands are positive, may use '/' instead of
...@@ -209,4 +211,3 @@ g: is tagged as group idx ...@@ -209,4 +211,3 @@ g: is tagged as group idx
Raise error if dl is targeting a private variable, regardless of whether it's Raise error if dl is targeting a private variable, regardless of whether it's
a dependency or not. a dependency or not.
...@@ -738,6 +738,16 @@ class LoopKernel(Record): ...@@ -738,6 +738,16 @@ class LoopKernel(Record):
else: else:
return self.all_insn_inames()[insn.id] return self.all_insn_inames()[insn.id]
@memoize_method
def iname_to_insns(self):
result = dict(
(iname, set()) for iname in self.all_inames())
for insn in self.instructions:
for iname in self.insn_inames(insn):
result[iname].add(insn.id)
return result
@property @property
@memoize_method @memoize_method
def sequential_inames(self): def sequential_inames(self):
...@@ -990,6 +1000,22 @@ class LoopKernel(Record): ...@@ -990,6 +1000,22 @@ class LoopKernel(Record):
return sum(lv.nbytes for lv in self.temporary_variables.itervalues() return sum(lv.nbytes for lv in self.temporary_variables.itervalues()
if lv.is_local) if lv.is_local)
@memoize_method
def loop_nest_map(self):
"""Returns a dictionary mapping inames to other inames that are
always nested around them.
"""
result = {}
iname_to_insns = self.iname_to_insns()
for inner_iname in self.all_inames():
result[inner_iname] = set()
for outer_iname in self.all_inames():
if iname_to_insns[inner_iname] < iname_to_insns[outer_iname]:
result[inner_iname].add(outer_iname)
return result
def __str__(self): def __str__(self):
lines = [] lines = []
......
...@@ -266,12 +266,12 @@ def generate_loop_schedules_internal(kernel, loop_priority, schedule=[], allow_b ...@@ -266,12 +266,12 @@ def generate_loop_schedules_internal(kernel, loop_priority, schedule=[], allow_b
and len(schedule) >= debug.debug_length): and len(schedule) >= debug.debug_length):
debug_mode = True debug_mode = True
#print dump_schedule(schedule), len(schedule)
if debug_mode: if debug_mode:
print kernel print kernel
print "--------------------------------------------" print "--------------------------------------------"
print "CURRENT SCHEDULE:" print "CURRENT SCHEDULE:"
print dump_schedule(schedule) print dump_schedule(schedule), len(schedule)
print "boost allowed:", allow_boost
print "--------------------------------------------" print "--------------------------------------------"
#if len(schedule) == 2: #if len(schedule) == 2:
...@@ -289,6 +289,8 @@ def generate_loop_schedules_internal(kernel, loop_priority, schedule=[], allow_b ...@@ -289,6 +289,8 @@ def generate_loop_schedules_internal(kernel, loop_priority, schedule=[], allow_b
reachable_insn_ids = set() reachable_insn_ids = set()
for insn_id in all_insn_ids - scheduled_insn_ids: for insn_id in all_insn_ids - scheduled_insn_ids:
if debug_mode:
print insn_id
insn = kernel.id_to_insn[insn_id] insn = kernel.id_to_insn[insn_id]
schedule_now = set(insn.insn_deps) <= scheduled_insn_ids schedule_now = set(insn.insn_deps) <= scheduled_insn_ids
...@@ -299,52 +301,28 @@ def generate_loop_schedules_internal(kernel, loop_priority, schedule=[], allow_b ...@@ -299,52 +301,28 @@ def generate_loop_schedules_internal(kernel, loop_priority, schedule=[], allow_b
insn.id, ",".join(set(insn.insn_deps) - scheduled_insn_ids)) insn.id, ",".join(set(insn.insn_deps) - scheduled_insn_ids))
continue continue
want = kernel.insn_inames(insn) - parallel_inames
have = active_inames_set - parallel_inames
# If insn is boostable, it may be placed inside a more deeply # If insn is boostable, it may be placed inside a more deeply
# nested loop without harm. # nested loop without harm.
# But if it can be scheduled on the way *out* of the currently
# active loops, now is not the right moment.
schedulable_at_loop_levels = []
if allow_boost: if allow_boost:
try_loop_counts = xrange(len(active_inames), -1, -1) have = have - insn.boostable_into
else:
try_loop_counts = [len(active_inames)]
for active_loop_count in try_loop_counts:
outer_active_inames = set(active_inames[:active_loop_count])
want = kernel.insn_inames(insn) - parallel_inames
have = outer_active_inames - parallel_inames - insn.boostable_into
if allow_boost:
have -= insn.boostable_into
if want == have: if want != have:
schedulable_at_loop_levels.append(active_loop_count)
if schedulable_at_loop_levels != [len(active_inames)]:
schedule_now = False schedule_now = False
if debug_mode: if debug_mode:
if schedulable_at_loop_levels: if want-have:
print ("instruction '%s' will be scheduled when more " print ("instruction '%s' is missing inames '%s'"
"loops have been exited" % insn.id) % (insn.id, ",".join(want-have)))
else: if have-want:
want = (kernel.insn_inames(insn) - parallel_inames) print ("instruction '%s' won't work under inames '%s'"
have = (active_inames_set - parallel_inames) % (insn.id, ",".join(have-want)))
if want-have:
print ("instruction '%s' is missing inames '%s'"
% (insn.id, ",".join(want-have)))
if have-want:
print ("instruction '%s' won't work under inames '%s'"
% (insn.id, ",".join(have-want)))
# {{{ determine reachability # {{{ determine reachability
want = kernel.insn_inames(insn) - parallel_inames
have = active_inames_set - parallel_inames
if (not schedule_now and have <= want): if (not schedule_now and have <= want):
reachable_insn_ids.add(insn_id) reachable_insn_ids.add(insn_id)
else: else:
...@@ -355,6 +333,8 @@ def generate_loop_schedules_internal(kernel, loop_priority, schedule=[], allow_b ...@@ -355,6 +333,8 @@ def generate_loop_schedules_internal(kernel, loop_priority, schedule=[], allow_b
# }}} # }}}
if schedule_now: if schedule_now:
if debug_mode:
print "scheduling '%s'" % insn.id
scheduled_insn_ids.add(insn.id) scheduled_insn_ids.add(insn.id)
schedule = schedule + [RunInstruction(insn_id=insn.id)] schedule = schedule + [RunInstruction(insn_id=insn.id)]
made_progress = True made_progress = True
...@@ -408,6 +388,9 @@ def generate_loop_schedules_internal(kernel, loop_priority, schedule=[], allow_b ...@@ -408,6 +388,9 @@ def generate_loop_schedules_internal(kernel, loop_priority, schedule=[], allow_b
useful_loops = [] useful_loops = []
for iname in available_loops: for iname in available_loops:
if not kernel.loop_nest_map()[iname] <= active_inames_set | parallel_inames:
continue
# {{{ determine if that gets us closer to being able to schedule an insn # {{{ determine if that gets us closer to being able to schedule an insn
useful = False useful = False
...@@ -415,8 +398,10 @@ def generate_loop_schedules_internal(kernel, loop_priority, schedule=[], allow_b ...@@ -415,8 +398,10 @@ def generate_loop_schedules_internal(kernel, loop_priority, schedule=[], allow_b
hypothetically_active_loops = active_inames_set | set([iname]) hypothetically_active_loops = active_inames_set | set([iname])
for insn_id in reachable_insn_ids: for insn_id in reachable_insn_ids:
insn = kernel.id_to_insn[insn_id] insn = kernel.id_to_insn[insn_id]
if (hypothetically_active_loops
<= (kernel.insn_inames(insn) | insn.boostable_into)): want = kernel.insn_inames(insn) | insn.boostable_into
if hypothetically_active_loops <= want:
useful = True useful = True
break break
......
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