From ad45361773c7df95760504b8d5a9b375f9564b76 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 13 Apr 2020 22:12:19 -0500 Subject: [PATCH 001/136] improved encapsulation approach for LexSchedule and map creation; improved algorithm for LexSchedule creation so that integer lex dims are not incremented unnecessarily when a block of code didn't contain any statements; fixed minor bugs in LexSchedule/item str methods; extracted only code related to LexSchedule/map creation (removed dependency stuff, for example) to shrink scope of this MR --- .../checker/lexicographic_order_map.py | 159 ++++++ loopy/schedule/checker/schedule.py | 493 ++++++++++++++++++ loopy/schedule/checker/utils.py | 335 ++++++++++++ 3 files changed, 987 insertions(+) create mode 100644 loopy/schedule/checker/lexicographic_order_map.py create mode 100644 loopy/schedule/checker/schedule.py create mode 100644 loopy/schedule/checker/utils.py diff --git a/loopy/schedule/checker/lexicographic_order_map.py b/loopy/schedule/checker/lexicographic_order_map.py new file mode 100644 index 000000000..2e063e7d7 --- /dev/null +++ b/loopy/schedule/checker/lexicographic_order_map.py @@ -0,0 +1,159 @@ +__copyright__ = "Copyright (C) 2019 James Stevens" + +__license__ = """ +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +""" + +import islpy as isl + + +def get_statement_ordering_map( + sched_map_before, sched_map_after, lex_map, before_marker="'"): + """Return a mapping that maps each statement instance to + all statement instances occuring later. + + :arg sched_map_before: An :class:`islpy.Map` representing instruction + instance order for the dependee as a mapping from each statement + instance to a point in the lexicographic ordering. + + :arg sched_map_after: An :class:`islpy.Map` representing instruction + instance order for the depender as a mapping from each statement + instance to a point in the lexicographic ordering. + + :arg lex_map: An :class:`islpy.Map` representing a lexicographic + ordering as a mapping from each point in lexicographic time + to every point that occurs later in lexicographic time. E.g.:: + + {[i0', i1', i2', ...] -> [i0, i1, i2, ...] : + i0' < i0 or (i0' = i0 and i1' < i1) + or (i0' = i0 and i1' = i1 and i2' < i2) ...} + + :returns: An :class:`islpy.Map` representing the lex schedule as + a mapping from each statement instance to all statement instances + occuring later. I.e., we compose B -> L -> A^-1, where B + is sched_map_before, A is sched_map_after, and L is the + lexicographic ordering map. + + """ + + sio = sched_map_before.apply_range( + lex_map).apply_range(sched_map_after.reverse()) + # append marker to in names + for i in range(sio.dim(isl.dim_type.in_)): + sio = sio.set_dim_name(isl.dim_type.in_, i, sio.get_dim_name( + isl.dim_type.in_, i)+before_marker) + return sio + + +def get_lex_order_constraint(islvars, before_names, after_names): + """Return a constraint represented as an :class:`islpy.Set` + defining a 'happens before' relationship in a lexicographic + ordering. + + :arg islvars: A dictionary from variable names to :class:`islpy.PwAff` + instances that represent each of the variables + (islvars may be produced by `islpy.make_zero_and_vars`). The key + '0' is also include and represents a :class:`islpy.PwAff` zero constant. + This dictionary defines the space to be used for the set. + + :arg before_names: A list of :class:`str` variable names representing + the lexicographic space dimensions for a point in lexicographic + time that occurs before. (see example below) + + :arg after_names: A list of :class:`str` variable names representing + the lexicographic space dimensions for a point in lexicographic + time that occurs after. (see example below) + + :returns: An :class:`islpy.Set` representing a constraint that enforces a + lexicographic ordering. E.g., if ``before_names = [i0', i1', i2']`` and + ``after_names = [i0, i1, i2]``, return the set:: + + {[i0', i1', i2', i0, i1, i2] : + i0' < i0 or (i0' = i0 and i1' < i1) + or (i0' = i0 and i1' = i1 and i2' < i2)} + + """ + + lex_order_constraint = islvars[before_names[0]].lt_set(islvars[after_names[0]]) + for i in range(1, len(before_names)): + lex_order_constraint_conj = islvars[before_names[i]].lt_set( + islvars[after_names[i]]) + for j in range(i): + lex_order_constraint_conj = lex_order_constraint_conj & \ + islvars[before_names[j]].eq_set(islvars[after_names[j]]) + lex_order_constraint = lex_order_constraint | lex_order_constraint_conj + return lex_order_constraint + + +def create_lex_order_map( + n_dims, + before_names=None, + after_names=None, + ): + """Return a mapping that maps each point in a lexicographic + ordering to every point that occurs later in lexicographic + time. + + :arg n_dims: An :class:`int` representing the number of dimensions + in the lexicographic ordering. + + :arg before_names: A list of :class:`str` variable names representing + the lexicographic space dimensions for a point in lexicographic + time that occurs before. (see example below) + + :arg after_names: A list of :class:`str` variable names representing + the lexicographic space dimensions for a point in lexicographic + time that occurs after. (see example below) + + :returns: An :class:`islpy.Map` representing a lexicographic + ordering as a mapping from each point in lexicographic time + to every point that occurs later in lexicographic time. + E.g., if ``before_names = [i0', i1', i2']`` and + ``after_names = [i0, i1, i2]``, return the map:: + + {[i0', i1', i2'] -> [i0, i1, i2] : + i0' < i0 or (i0' = i0 and i1' < i1) + or (i0' = i0 and i1' = i1 and i2' < i2)} + + """ + + if before_names is None: + before_names = ["i%s" % (i) for i in range(n_dims)] + if after_names is None: + from loopy.schedule.checker.utils import ( + append_marker_to_strings, + ) + after_names = append_marker_to_strings(before_names, marker="_") + + assert len(before_names) == len(after_names) == n_dims + dim_type = isl.dim_type + + islvars = isl.make_zero_and_vars( + before_names+after_names, + []) + + lex_order_constraint = get_lex_order_constraint( + islvars, before_names, after_names) + + lex_map = isl.Map.from_domain(lex_order_constraint) + lex_map = lex_map.move_dims( + dim_type.out, 0, dim_type.in_, + len(before_names), len(after_names)) + + return lex_map diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py new file mode 100644 index 000000000..c395863ef --- /dev/null +++ b/loopy/schedule/checker/schedule.py @@ -0,0 +1,493 @@ +__copyright__ = "Copyright (C) 2019 James Stevens" + +__license__ = """ +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +""" + +import islpy as isl + + +class LexScheduleStatement(object): + """A representation of a :mod:`loopy` statement. + + .. attribute:: insn_id + + A :class:`str` specifying the instruction id. + + .. attribute:: int_id + + A :class:`int` uniquely identifying the instruction. + + .. attribute:: within_inames + + A :class:`list` of :class:`str` inames identifying the loops within + which this statement will be executed. + + """ + + def __init__( + self, + insn_id, # loopy insn id + int_id=None, # sid int (statement id within LexSchedule) + within_inames=None, # [string, ] + ): + self.insn_id = insn_id # string + self.int_id = int_id + self.within_inames = within_inames + + def __eq__(self, other): + return ( + self.insn_id == other.insn_id + and self.int_id == other.int_id + and self.within_inames == other.within_inames + ) + + def __hash__(self): + return hash(repr(self)) + + def update_persistent_hash(self, key_hash, key_builder): + """Custom hash computation function for use with + :class:`pytools.persistent_dict.PersistentDict`. + """ + + key_builder.rec(key_hash, self.insn_id) + key_builder.rec(key_hash, self.int_id) + key_builder.rec(key_hash, self.within_inames) + + def __str__(self): + if self.int_id is not None: + int_id = ":%d" % (self.int_id) + else: + int_id = "" + if self.within_inames: + within_inames = " {%s}" % (",".join(self.within_inames)) + else: + within_inames = "" + return "%s%s%s" % ( + self.insn_id, int_id, within_inames) + + +class LexScheduleStatementInstance(object): + """A representation of a :mod:`loopy` statement instance. + + .. attribute:: stmt + + A :class:`LexScheduleStatement`. + + .. attribute:: lex_pt + + A list of :class:`int` or as :class:`str` :mod:`loopy` inames representing + a point or set of points in a lexicographic ordering. + + """ + + def __init__( + self, + stmt, # a LexScheduleStatement + lex_pt, # [string/int, ] + ): + self.stmt = stmt + self.lex_pt = lex_pt + + def __str__(self): + return "{%s, %s}" % (self.stmt, self.lex_pt) + + +class LexSchedule(object): + """A program ordering represented as a mapping from statement + instances to points in a lexicographic ordering. + + .. attribute:: stmt_instance_before + + A :class:`LexScheduleStatementInstance` describing the dependee + statement's order relative to the depender statment by mapping + a statement to a point or set of points in a lexicographic + ordering. Points in lexicographic ordering are represented as + a list of :class:`int` or as :class:`str` :mod:`loopy` inames. + + .. attribute:: stmt_instance_after + + A :class:`LexScheduleStatementInstance` describing the depender + statement's order relative to the dependee statment by mapping + a statement to a point or set of points in a lexicographic + ordering. Points in lexicographic ordering are represented as + a list of :class:`int` or as :class:`str` :mod:`loopy` inames. + + .. attribute:: statement_var_name + + A :class:`str` specifying the name of the isl variable used + to represent the unique :class:`int` statement id. + + .. attribute:: lex_var_prefix + + A :class:`str` specifying the prefix to be used for the variables + representing the dimensions in the lexicographic ordering. E.g., + a prefix of "lex" might yield variables "lex0", "lex1", "lex2". + + """ + + statement_var_name = "statement" + lex_var_prefix = "l" + + def __init__( + self, + linearization_items_ordered, + before_insn_id, + after_insn_id, + prohibited_var_names=[], + loops_to_ignore=set(), + ): + """ + :arg linearization_items_ordered: A list of :class:`ScheduleItem` whose + order will be described by this :class:`LexSchedule`. + + :arg before_insn_id: A :class:`str` instruction id specifying + the dependee in this pair of instructions. + + :arg after_insn_id: A :class:`str` instruction id specifying + the depender in this pair of instructions. + + :arg prohibited_var_names: A list of :class:`str` variable names + that may not be used as the statement variable name (e.g., + because they are already being used as inames). + + """ + + # LexScheduleStatements + self.stmt_instance_before = None + self.stmt_instance_after = None + + # make sure we don't have an iname name conflict + # TODO use loopy's existing tool for ensuring unique var names + assert not any( + iname == self.statement_var_name for iname in prohibited_var_names) + + from loopy.schedule import (EnterLoop, LeaveLoop, Barrier, RunInstruction) + + # go through linearization_items_ordered and generate self.lex_schedule + + # keep track of the next point in our lexicographic ordering + # initially this as a 1-d point with value 0 + next_insn_lex_pt = [0] + stmt_since_last_block_at_tier = [False] + next_sid = 0 + stmt_added_since_last_EnterLoop = False + stmt_added_since_last_LeaveLoop = False + #stmt_added_since_last_new_block = False # blocks start at open/close loop + for linearization_item in linearization_items_ordered: + if isinstance(linearization_item, EnterLoop): + iname = linearization_item.iname + if iname in loops_to_ignore: + continue + + # We could always increment next_insn_lex_pt[-1] here since this new + # section of code comes after the previous section (statements + # since last opened/closed loop), but if we have not added any statements + # within this block yet, we don't have to + # (effectively ignoring that section of code). + if stmt_since_last_block_at_tier[-1]: + next_insn_lex_pt[-1] = next_insn_lex_pt[-1]+1 + stmt_since_last_block_at_tier[-1] = False + + # upon entering a loop, we enter a new (deeper) tier, + # add one lex dimension for the loop variable, + # add second lex dim to enumerate code blocks within new loop, and + # append a dim to stmt_since_last_block_at_tier to represent new tier + next_insn_lex_pt.append(iname) + next_insn_lex_pt.append(0) + stmt_since_last_block_at_tier.append(False) + elif isinstance(linearization_item, LeaveLoop): + if linearization_item.iname in loops_to_ignore: + continue + # upon leaving a loop, + # pop lex dimension for enumerating code blocks within this loop, and + # pop lex dimension for the loop variable, and + # increment lex dim val enumerating items in current code block + next_insn_lex_pt.pop() + next_insn_lex_pt.pop() + + # We could always increment next_insn_lex_pt[-1] here since this new + # block of code comes after the previous block (all statements + # since last opened/closed loop), but if we have not added any statements + # within this block yet, we don't have to + # (effectively ignoring that section of code). + stmt_since_last_block_at_tier.pop() + if stmt_since_last_block_at_tier[-1]: + next_insn_lex_pt[-1] = next_insn_lex_pt[-1]+1 + stmt_since_last_block_at_tier[-1] = False + elif isinstance(linearization_item, (RunInstruction, Barrier)): + from loopy.schedule.checker.utils import ( + _get_insn_id_from_linearization_item, + ) + lp_insn_id = _get_insn_id_from_linearization_item(linearization_item) + if lp_insn_id is None: + # TODO make sure it's okay to ignore barriers without id + # (because they'll never be part of a dependency?) + # matmul example has barrier that fails this assertion... + # assert linearization_item.originating_insn_id is not None + continue + + # only process before/after insns, otherwise ignore + if lp_insn_id == before_insn_id and lp_insn_id == after_insn_id: + # add before sched item + self.stmt_instance_before = LexScheduleStatementInstance( + LexScheduleStatement( + insn_id=lp_insn_id, + int_id=next_sid, # int representing insn + ), + next_insn_lex_pt[:]) + # add after sched item + self.stmt_instance_after = LexScheduleStatementInstance( + LexScheduleStatement( + insn_id=lp_insn_id, + int_id=next_sid, # int representing insn + ), + next_insn_lex_pt[:]) + + # increment lex dim val enumerating items in current code block + next_insn_lex_pt[-1] = next_insn_lex_pt[-1] + 1 + next_sid += 1 + + # all current (nested) blocks now contain a statement + stmt_since_last_block_at_tier = [True]*len(stmt_since_last_block_at_tier) + elif lp_insn_id == before_insn_id: + # add before sched item + self.stmt_instance_before = LexScheduleStatementInstance( + LexScheduleStatement( + insn_id=lp_insn_id, + int_id=next_sid, # int representing insn + ), + next_insn_lex_pt[:]) + + # increment lex dim val enumerating items in current code block + next_insn_lex_pt[-1] = next_insn_lex_pt[-1] + 1 + next_sid += 1 + + # all current (nested) blocks now contain a statement + stmt_since_last_block_at_tier = [True]*len(stmt_since_last_block_at_tier) + elif lp_insn_id == after_insn_id: + # add after sched item + self.stmt_instance_after = LexScheduleStatementInstance( + LexScheduleStatement( + insn_id=lp_insn_id, + int_id=next_sid, # int representing insn + ), + next_insn_lex_pt[:]) + + # increment lex dim val enumerating items in current code block + next_insn_lex_pt[-1] = next_insn_lex_pt[-1] + 1 + next_sid += 1 + + # all current (nested) blocks now contain a statement + stmt_since_last_block_at_tier = [True]*len(stmt_since_last_block_at_tier) + else: + pass + # to save time, stop when we've created both statements + if self.stmt_instance_before and self.stmt_instance_after: + break + + # at this point, lex_schedule may contain lex points missing dimensions, + # the values in these missing dims should be zero, so add them + self.pad_lex_pts_with_zeros() + + def loopy_insn_id_to_lex_sched_id(self): + """Return a dictionary mapping insn_id to int_id, where ``insn_id`` and + ``int_id`` refer to the ``insn_id`` and ``int_id`` attributes of + :class:`LexScheduleStatement`. + """ + return { + self.stmt_instance_before.stmt.insn_id: + self.stmt_instance_before.stmt.int_id, + self.stmt_instance_after.stmt.insn_id: + self.stmt_instance_after.stmt.int_id, + } + + def max_lex_dims(self): + return max([ + len(self.stmt_instance_before.lex_pt), + len(self.stmt_instance_after.lex_pt)]) + + def pad_lex_pts_with_zeros(self): + """Find the maximum number of lexicographic dimensions represented + in the lexicographic ordering, and if any + :class:`LexScheduleStatement` maps to a point in lexicographic + time with fewer dimensions, add a zero for each of the missing + dimensions. + """ + + max_lex_dim = self.max_lex_dims() + self.stmt_instance_before = LexScheduleStatementInstance( + self.stmt_instance_before.stmt, + self.stmt_instance_before.lex_pt[:] + [0]*( + max_lex_dim-len(self.stmt_instance_before.lex_pt)) + ) + self.stmt_instance_after = LexScheduleStatementInstance( + self.stmt_instance_after.stmt, + self.stmt_instance_after.lex_pt[:] + [0]*( + max_lex_dim-len(self.stmt_instance_after.lex_pt)) + ) + + def create_isl_maps( + self, + dom_before, + dom_after, + dom_inames_ordered_before=None, + dom_inames_ordered_after=None, + ): + """Create two isl maps representing lex schedule as two mappings + from statement instances to lexicographic time, one for + the dependee and one for the depender. + + :arg dom_before: A :class:`islpy.BasicSet` representing the + domain for the dependee statement. + + :arg dom_after: A :class:`islpy.BasicSet` representing the + domain for the dependee statement. + + :arg dom_inames_ordered_before: A list of :class:`str` + representing the union of inames used in instances of the + dependee statement. ``statement_var_name`` and + ``dom_inames_ordered_before`` are the names of the dims of + the space of the ISL map domain for the dependee. + + :arg dom_inames_ordered_after: A list of :class:`str` + representing the union of inames used in instances of the + depender statement. ``statement_var_name`` and + ``dom_inames_ordered_after`` are the names of the dims of + the space of the ISL map domain for the depender. + + :returns: A two-tuple containing two :class:`islpy.Map`s + representing the schedule as two mappings + from statement instances to lexicographic time, one for + the dependee and one for the depender. + + """ + + from loopy.schedule.checker.utils import ( + create_symbolic_isl_map_from_tuples, + add_dims_to_isl_set + ) + + from loopy.schedule.checker.utils import ( + list_var_names_in_isl_sets, + ) + if dom_inames_ordered_before is None: + dom_inames_ordered_before = list_var_names_in_isl_sets( + [dom_before]) + if dom_inames_ordered_after is None: + dom_inames_ordered_after = list_var_names_in_isl_sets( + [dom_after]) + + # create an isl space + # {('statement', used in >=1 statement domain>) -> + # (lexicographic ordering dims)} + from loopy.schedule.checker.utils import ( + get_isl_space + ) + params_sched = [] + out_names_sched = self.get_lex_var_names() + + in_names_sched_before = [ + self.statement_var_name] + dom_inames_ordered_before[:] + sched_space_before = get_isl_space( + params_sched, in_names_sched_before, out_names_sched) + in_names_sched_after = [ + self.statement_var_name] + dom_inames_ordered_after[:] + sched_space_after = get_isl_space( + params_sched, in_names_sched_after, out_names_sched) + + # Insert 'statement' dim into domain so that its space allows for + # intersection with sched map later + doms_to_intersect_before = [ + add_dims_to_isl_set( + dom_before, isl.dim_type.set, + [self.statement_var_name], 0), + ] + doms_to_intersect_after = [ + add_dims_to_isl_set( + dom_after, isl.dim_type.set, + [self.statement_var_name], 0), + ] + + # Each isl map representing the schedule maps + # statement instances -> lex time + + # Right now, statement tuples consist of single int. + # Add all inames from domains to map domain tuples. + + # create isl map + return ( + create_symbolic_isl_map_from_tuples( + zip( + [( + (self.stmt_instance_before.stmt.int_id,) + + tuple(dom_inames_ordered_before), + self.stmt_instance_before.lex_pt + )], + doms_to_intersect_before + ), + sched_space_before, self.statement_var_name), + create_symbolic_isl_map_from_tuples( + zip( + [( + (self.stmt_instance_after.stmt.int_id,) + + tuple(dom_inames_ordered_after), + self.stmt_instance_after.lex_pt)], + doms_to_intersect_after + ), + sched_space_after, self.statement_var_name) + ) + + def get_lex_var_names(self): + return [self.lex_var_prefix+str(i) + for i in range(self.max_lex_dims())] + + def get_lex_order_map_for_sched_space(self): + """Return an :class:`islpy.BasicMap` that maps each point in a + lexicographic ordering to every point that is + lexocigraphically greater. + """ + + from loopy.schedule.checker.lexicographic_order_map import ( + create_lex_order_map, + ) + n_dims = self.max_lex_dims() + return create_lex_order_map( + n_dims, before_names=self.get_lex_var_names()) + + def __eq__(self, other): + return ( + self.stmt_instance_before == other.stmt_instance_before + and self.stmt_instance_after == other.stmt_instance_after) + + def __str__(self): + sched_str = "Before: {\n" + domain_elem = "[%s=%s,]" % ( + self.statement_var_name, + self.stmt_instance_before.stmt.int_id) + sched_str += "%s -> %s;\n" % (domain_elem, self.stmt_instance_before.lex_pt) + sched_str += "}\n" + + sched_str += "After: {\n" + domain_elem = "[%s=%s,]" % ( + self.statement_var_name, + self.stmt_instance_after.stmt.int_id) + sched_str += "%s -> %s;\n" % (domain_elem, self.stmt_instance_after.lex_pt) + sched_str += "}" + return sched_str diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py new file mode 100644 index 000000000..8757406b7 --- /dev/null +++ b/loopy/schedule/checker/utils.py @@ -0,0 +1,335 @@ +__copyright__ = "Copyright (C) 2019 James Stevens" + +__license__ = """ +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +""" + +import islpy as isl + + +def prettier_map_string(isl_map): + return str(isl_map + ).replace("{ ", "{\n").replace(" }", "\n}").replace("; ", ";\n") + + +def get_islvars_from_space(space): + param_names = space.get_var_names(isl.dim_type.param) + in_names = space.get_var_names(isl.dim_type.in_) + out_names = space.get_var_names(isl.dim_type.out) + return isl.make_zero_and_vars(in_names+out_names, param_names) + + +def add_dims_to_isl_set(isl_set, dim_type, names, new_pose_start): + new_set = isl_set.insert_dims( + dim_type, new_pose_start, len(names) + ).set_dim_name(dim_type, new_pose_start, names[0]) + for i, name in enumerate(names[1:]): + new_set = new_set.set_dim_name(dim_type, new_pose_start+1+i, name) + return new_set + + +def reorder_dims_by_name( + isl_set, dim_type, desired_dims_ordered, + add_missing=False, new_names_are_permutation_only=False): + """Return an isl_set with the dimensions in the specified order. + + :arg isl_set: A :class:`islpy.Set` whose dimensions are + to be reordered. + + :arg dim_type: A :class:`islpy.dim_type`, i.e., an :class:`int`, + specifying the dimension to be reordered. + + :arg desired_dims_ordered: A :class:`list` of :class:`str` elements + representing the desired dimensions order by dimension name. + + :arg add_missing: A :class:`bool` specifying whether to insert + dimensions (by name) found in `desired_dims_ordered` that are not + present in `isl_set`. + + :arg new_names_are_permutation_only: A :class:`bool` indicating that + `desired_dims_ordered` contains the same names as the specified + dimensions in `isl_set`, and does not, e.g., contain additional + dimension names not found in `isl_set`. If set to True, and these + two sets of names do not match, an error is produced. + + :returns: An :class:`islpy.Set` matching `isl_set` with the + dimension order matching `desired_dims_ordered`, optionally + including additional dimensions present in `desred_dims_ordered` + that are not present in `isl_set`. + + """ + + assert set(isl_set.get_var_names(dim_type)).issubset(desired_dims_ordered) + assert dim_type != isl.dim_type.param + + if new_names_are_permutation_only and ( + set(isl_set.get_var_names(dim_type)) + != set(desired_dims_ordered)): + raise ValueError( + "Var name sets must match with new_names_are_permutation_only=True. " + "isl vars: %s, desired dims: %s" + % (isl_set.get_var_names(dim_type), desired_dims_ordered)) + + other_dim_type = isl.dim_type.param + other_dim_len = len(isl_set.get_var_names(other_dim_type)) + + new_set = isl_set.copy() + for desired_pose, name in enumerate(desired_dims_ordered): + # if iname doesn't exist in set, add dim: + if name not in new_set.get_var_names(dim_type): + if add_missing: + # insert missing dim in correct location + new_set = new_set.insert_dims( + dim_type, desired_pose, 1 + ).set_dim_name( + dim_type, desired_pose, name) + else: # iname exists in set + current_pose = new_set.find_dim_by_name(dim_type, name) + if current_pose != desired_pose: + # move_dims(dst_type, dst_pose, src_type, src_pose, n) + + # first move to other dim because isl is stupid + new_set = new_set.move_dims( + other_dim_type, other_dim_len, dim_type, current_pose, 1) + + # now move it where we actually want it + new_set = new_set.move_dims( + dim_type, desired_pose, other_dim_type, other_dim_len, 1) + + return new_set + + +def align_isl_maps_by_var_names(input_map, target_map): + + # align params + aligned_input_map = input_map.align_params(target_map.space) + + # align in_ dims + target_map_in_names = target_map.space.get_var_names(isl.dim_type.in_) + aligned_input_map = reorder_dims_by_name( + aligned_input_map, + isl.dim_type.in_, + target_map_in_names, + add_missing=False, + new_names_are_permutation_only=True, + ) + + # align out dims + target_map_out_names = target_map.space.get_var_names(isl.dim_type.out) + aligned_input_map = reorder_dims_by_name( + aligned_input_map, + isl.dim_type.out, + target_map_out_names, + add_missing=False, + new_names_are_permutation_only=True, + ) + + return aligned_input_map + + +def append_marker_to_strings(strings, marker="'"): + if not isinstance(strings, list): + raise ValueError("append_marker_to_strings did not receive a list") + else: + return [s+marker for s in strings] + + +def _union_of_isl_sets_or_maps(set_list): + union = set_list[0] + for s in set_list[1:]: + union = union.union(s) + return union + + +def list_var_names_in_isl_sets( + isl_sets, + set_dim=isl.dim_type.set): + inames = set() + for isl_set in isl_sets: + inames.update(isl_set.get_var_names(set_dim)) + return list(inames) + + +def create_symbolic_isl_map_from_tuples( + tuple_pairs_with_domains, + space, + statement_var_name, + ): + """Return an :class:`islpy.Map` constructed using the provided space, + mapping input->output tuples provided in `tuple_pairs_with_domains`, + with each set of tuple variables constrained by the domains provided. + + :arg tuple_pairs_with_domains: A :class:`list` with each element being + a tuple of the form `((tup_in, tup_out), domain)`. + `tup_in` and `tup_out` are tuples containing elements of type + :class:`int` and :class:`str` representing values for the + input and output dimensions in `space`, and `domain` is a + :class:`islpy.Set` constraining variable bounds. + + :arg space: A :class:`islpy.Space` to be used to create the map. + + :arg statement_var_name: A :class:`str` specifying the name of the + isl variable used to represent the unique :class:`int` statement id. + + :returns: A :class:`islpy.Map` constructed using the provided space + as follows. For each `((tup_in, tup_out), domain)` in + `tuple_pairs_with_domains`, map + `(tup_in)->(tup_out) : domain`, where `tup_in` and `tup_out` are + numeric or symbolic values assigned to the input and output + dimension variables in `space`, and `domain` specifies constraints + on these values. + + """ + # TODO allow None for domains + + dim_type = isl.dim_type + + #param_names = space.get_var_names(isl.dim_type.param) + space_out_names = space.get_var_names(dim_type.out) + space_in_names = space.get_var_names(isl.dim_type.in_) + + islvars = get_islvars_from_space(space) + + # loop through pairs and create a set that will later be converted to a map + + all_maps = [] + for (tup_in, tup_out), dom in tuple_pairs_with_domains: + + # initialize constraint with true + constraint = islvars[0].eq_set(islvars[0]) + + # set values for 'in' dimension using tuple vals + assert len(tup_in) == len(space_in_names) + for dim_name, val_in in zip(space_in_names, tup_in): + if isinstance(val_in, int): + constraint = constraint \ + & islvars[dim_name].eq_set(islvars[0]+val_in) + else: + constraint = constraint \ + & islvars[dim_name].eq_set(islvars[val_in]) + + # set values for 'out' dimension using tuple vals + assert len(tup_out) == len(space_out_names) + for dim_name, val_out in zip(space_out_names, tup_out): + if isinstance(val_out, int): + constraint = constraint \ + & islvars[dim_name].eq_set(islvars[0]+val_out) + else: + constraint = constraint \ + & islvars[dim_name].eq_set(islvars[val_out]) + + # convert set to map by moving dimensions around + map_from_set = isl.Map.from_domain(constraint) + map_from_set = map_from_set.move_dims( + dim_type.out, 0, dim_type.in_, + len(space_in_names), len(space_out_names)) + + assert space_in_names == map_from_set.get_var_names( + isl.dim_type.in_) + + # if there are any dimensions in dom that are missing from + # map_from_set, we have a problem I think? + # (assertion checks this in add_missing... + dom_with_all_inames = reorder_dims_by_name( + dom, isl.dim_type.set, + space_in_names, + add_missing=True, + new_names_are_permutation_only=False, + ) + + # intersect domain with this map + all_maps.append( + map_from_set.intersect_domain(dom_with_all_inames)) + + return _union_of_isl_sets_or_maps(all_maps) + + +def set_all_isl_space_names( + isl_space, param_names=None, in_names=None, out_names=None): + """Return a copy of `isl_space` with the specified dimension names. + If no names are provided, use `p0, p1, ...` for parameters, + `i0, i1, ...`, for in_ dimensions, and `o0, o1, ...` for out + dimensions. + + """ + + new_space = isl_space.copy() + dim_type = isl.dim_type + if param_names: + for i, p in enumerate(param_names): + new_space = new_space.set_dim_name(dim_type.param, i, p) + else: + for i in range(len(isl_space.get_var_names(dim_type.param))): + new_space = new_space.set_dim_name(dim_type.param, i, "p%d" % (i)) + if in_names: + for i, p in enumerate(in_names): + new_space = new_space.set_dim_name(dim_type.in_, i, p) + else: + for i in range(len(isl_space.get_var_names(dim_type.in_))): + new_space = new_space.set_dim_name(dim_type.in_, i, "i%d" % (i)) + if out_names: + for i, p in enumerate(out_names): + new_space = new_space.set_dim_name(dim_type.out, i, p) + else: + for i in range(len(isl_space.get_var_names(dim_type.out))): + new_space = new_space.set_dim_name(dim_type.out, i, "o%d" % (i)) + return new_space + + +def get_isl_space(param_names, in_names, out_names): + """Return an :class:`islpy.Space` with the specified dimension names. + """ + + space = isl.Space.alloc( + isl.DEFAULT_CONTEXT, len(param_names), len(in_names), len(out_names)) + return set_all_isl_space_names( + space, param_names=param_names, in_names=in_names, out_names=out_names) + + +def get_concurrent_inames(knl): + from loopy.kernel.data import ConcurrentTag + conc_inames = set() + non_conc_inames = set() + + all_inames = knl.all_inames() + for iname in all_inames: + if knl.iname_tags_of_type(iname, ConcurrentTag): + conc_inames.add(iname) + else: + non_conc_inames.add(iname) + + return conc_inames, all_inames-conc_inames + + +def _get_insn_id_from_linearization_item(linearization_item): + # TODO could use loopy's sched_item_to_insn_id() + from loopy.schedule import Barrier + if isinstance(linearization_item, Barrier): + return linearization_item.originating_insn_id + else: + return linearization_item.insn_id + + +def _get_EnterLoop_inames(linearization_items, knl): + from loopy.schedule import EnterLoop + loop_inames = set() + for linearization_item in linearization_items: + if isinstance(linearization_item, EnterLoop): + loop_inames.add(linearization_item.iname) + return loop_inames -- GitLab From 1ce81703127df9bddcfe841ee3663373a8369a7c Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 13 Apr 2020 22:14:00 -0500 Subject: [PATCH 002/136] adding updated and stripped down checker/__init__ (with aforementioned encapsulation improvements) --- loopy/schedule/checker/__init__.py | 104 +++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 loopy/schedule/checker/__init__.py diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py new file mode 100644 index 000000000..1acee56b9 --- /dev/null +++ b/loopy/schedule/checker/__init__.py @@ -0,0 +1,104 @@ +__copyright__ = "Copyright (C) 2019 James Stevens" + +__license__ = """ +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +""" + + +def get_schedule_for_statement_pair( + knl, + linearization_items, + insn_id_before, + insn_id_after, + prohibited_var_names=set(), + ): + """A set of dependencies between two statements. + + .. arg insn_id_before: An instruction identifier that is unique within + a :class:`loopy.kernel.LoopKernel`. + + .. arg insn_id_after: An instruction identifier that is unique within + a :class:`loopy.kernel.LoopKernel`. + + """ + + # We don't retrieve linearization items from knl because knl may not be + # (fully) linearized yet. This function may be called part way through the + # linearization process and receive the current (unfinished) set of + # linearization items + + # Preprocess if not already preprocessed + from loopy import preprocess_kernel + preproc_knl = preprocess_kernel(knl) + + if not prohibited_var_names: + prohibited_var_names = preproc_knl.all_inames() + + # Get EnterLoop inames tagged as concurrent so LexSchedule can ignore + # (In the future, this shouldn't be necessary because there + # won't be any inames with ConcurrentTags in EnterLoop linearization items. + # Test exercising this: test_linearization_checker_with_stroud_bernstein()) + from loopy.schedule.checker.utils import ( + get_concurrent_inames, + _get_EnterLoop_inames, + ) + conc_inames, _ = get_concurrent_inames(preproc_knl) + enterloop_inames = _get_EnterLoop_inames(linearization_items, preproc_knl) + conc_loop_inames = conc_inames & enterloop_inames + if conc_loop_inames: + from warnings import warn + warn( + "get_schedule_for_statement_pair encountered EnterLoop for inames %s " + "with ConcurrentTag(s) in linearization for kernel %s. " + "Ignoring these loops." % (conc_loop_inames, preproc_knl.name)) + + # Create LexSchedule: mapping of {statement instance: lex point} + # include only instructions involved in this dependency + from loopy.schedule.checker.schedule import LexSchedule + return LexSchedule( + linearization_items, + insn_id_before, + insn_id_after, + prohibited_var_names=prohibited_var_names, + loops_to_ignore=conc_loop_inames, + ) + + +def get_isl_maps_for_LexSchedule( + lex_sched, + knl, + insn_id_before, + insn_id_after, + ): + # Get two isl maps representing the LexSchedule, + # one for the 'before' linearization item and one for 'after'; + # this requires the iname domains + + insn_before_inames = knl.id_to_insn[insn_id_before].within_inames + insn_after_inames = knl.id_to_insn[insn_id_after].within_inames + dom_before = knl.get_inames_domain(insn_before_inames) + dom_after = knl.get_inames_domain(insn_after_inames) + + isl_sched_map_before, isl_sched_map_after = \ + lex_sched.create_isl_maps( + dom_before, + dom_after, + ) + + return isl_sched_map_before, isl_sched_map_after -- GitLab From 387a8f12ef594cdf6d0fc221305bbc0bb9692b4a Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 13 Apr 2020 22:25:05 -0500 Subject: [PATCH 003/136] add test for LexSchedule creation and conversion of LexSchedule into isl map --- test/test_linearization_checker.py | 367 +++++++++++++++++++++++++++++ 1 file changed, 367 insertions(+) create mode 100644 test/test_linearization_checker.py diff --git a/test/test_linearization_checker.py b/test/test_linearization_checker.py new file mode 100644 index 000000000..7e145ce1d --- /dev/null +++ b/test/test_linearization_checker.py @@ -0,0 +1,367 @@ +from __future__ import division, print_function + +__copyright__ = "Copyright (C) 2019 James Stevens" + +__license__ = """ +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +""" + +import six # noqa: F401 +import sys +import numpy as np +import loopy as lp +from pyopencl.tools import ( # noqa + pytest_generate_tests_for_pyopencl + as pytest_generate_tests) +from loopy.version import LOOPY_USE_LANGUAGE_VERSION_2018_2 # noqa +import logging +from loopy.kernel import KernelState +from loopy import ( + preprocess_kernel, + get_one_linearized_kernel, +) + +logger = logging.getLogger(__name__) + +try: + import faulthandler +except ImportError: + pass +else: + faulthandler.enable() + + +def test_lexschedule_and_islmap_creation(): + import islpy as isl + from loopy.schedule.checker import ( + get_schedule_for_statement_pair, + get_isl_maps_for_LexSchedule, + ) + from loopy.schedule.checker.utils import ( + align_isl_maps_by_var_names, + ) + + # example kernel + knl = lp.make_kernel( + [ + "{[i]: 0<=itemp = b[i,k] {id=insn_a} + end + for j + a[i,j] = temp + 1 {id=insn_b,dep=insn_a} + c[i,j] = d[i,j] {id=insn_c} + end + end + for t + e[t] = f[t] {id=insn_d} + end + """, + name="example", + assumptions="pi,pj,pk,pt >= 1", + lang_version=(2018, 2) + ) + knl = lp.add_and_infer_dtypes( + knl, + {"b": np.float32, "d": np.float32, "f": np.float32}) + knl = lp.prioritize_loops(knl, "i,k") + knl = lp.prioritize_loops(knl, "i,j") + + # get a linearization + knl = preprocess_kernel(knl) + knl = get_one_linearized_kernel(knl) + linearization_items = knl.linearization + + # Create LexSchedule: mapping of {statement instance: lex point} + lex_sched_AB = get_schedule_for_statement_pair( + knl, + linearization_items, + "insn_a", + "insn_b", + ) + lex_sched_AC = get_schedule_for_statement_pair( + knl, + linearization_items, + "insn_a", + "insn_c", + ) + lex_sched_AD = get_schedule_for_statement_pair( + knl, + linearization_items, + "insn_a", + "insn_d", + ) + lex_sched_BC = get_schedule_for_statement_pair( + knl, + linearization_items, + "insn_b", + "insn_c", + ) + lex_sched_BD = get_schedule_for_statement_pair( + knl, + linearization_items, + "insn_b", + "insn_d", + ) + lex_sched_CD = get_schedule_for_statement_pair( + knl, + linearization_items, + "insn_c", + "insn_d", + ) + + # Relationship between insn_a and insn_b --------------------------------------- + + assert lex_sched_AB.stmt_instance_before.lex_pt == [0, 'i', 0, 'k', 0] + assert lex_sched_AB.stmt_instance_after.lex_pt == [0, 'i', 1, 'j', 0] + + # Get two isl maps representing the LexSchedule + + isl_sched_map_before, isl_sched_map_after = \ + get_isl_maps_for_LexSchedule(lex_sched_AB, knl, "insn_a", "insn_b") + + # Create expected maps, align, compare + + isl_sched_map_before_expected = isl.Map( + "[pi, pk] -> { " + "[statement = 0, i, k] -> [l0 = 0, l1 = i, l2 = 0, l3 = k, l4 = 0] : " + "0 <= i < pi and 0 <= k < pk }" + ) + isl_sched_map_before_expected = align_isl_maps_by_var_names( + isl_sched_map_before_expected, isl_sched_map_before) + + isl_sched_map_after_expected = isl.Map( + "[pi, pj] -> { " + "[statement = 1, i, j] -> [l0 = 0, l1 = i, l2 = 1, l3 = j, l4 = 0] : " + "0 <= i < pi and 0 <= j < pj }" + ) + isl_sched_map_after_expected = align_isl_maps_by_var_names( + isl_sched_map_after_expected, isl_sched_map_after) + + assert isl_sched_map_before == isl_sched_map_before_expected + assert isl_sched_map_after == isl_sched_map_after_expected + + # ------------------------------------------------------------------------------ + # Relationship between insn_a and insn_c --------------------------------------- + + assert lex_sched_AC.stmt_instance_before.lex_pt == [0, 'i', 0, 'k', 0] + assert lex_sched_AC.stmt_instance_after.lex_pt == [0, 'i', 1, 'j', 0] + + # Get two isl maps representing the LexSchedule + + isl_sched_map_before, isl_sched_map_after = \ + get_isl_maps_for_LexSchedule(lex_sched_AC, knl, "insn_a", "insn_c") + + # Create expected maps, align, compare + + isl_sched_map_before_expected = isl.Map( + "[pi, pk] -> { " + "[statement = 0, i, k] -> [l0 = 0, l1 = i, l2 = 0, l3 = k, l4 = 0] : " + "0 <= i < pi and 0 <= k < pk }" + ) + isl_sched_map_before_expected = align_isl_maps_by_var_names( + isl_sched_map_before_expected, isl_sched_map_before) + + isl_sched_map_after_expected = isl.Map( + "[pi, pj] -> { " + "[statement = 1, i, j] -> [l0 = 0, l1 = i, l2 = 1, l3 = j, l4 = 0] : " + "0 <= i < pi and 0 <= j < pj }" + ) + isl_sched_map_after_expected = align_isl_maps_by_var_names( + isl_sched_map_after_expected, isl_sched_map_after) + + assert isl_sched_map_before == isl_sched_map_before_expected + assert isl_sched_map_after == isl_sched_map_after_expected + + # ------------------------------------------------------------------------------ + # Relationship between insn_a and insn_d --------------------------------------- + + assert lex_sched_AD.stmt_instance_before.lex_pt == [0, 'i', 0, 'k', 0] + assert lex_sched_AD.stmt_instance_after.lex_pt == [1, 't', 0, 0, 0] + + # Get two isl maps representing the LexSchedule + + isl_sched_map_before, isl_sched_map_after = \ + get_isl_maps_for_LexSchedule(lex_sched_AD, knl, "insn_a", "insn_d") + + # Create expected maps, align, compare + + isl_sched_map_before_expected = isl.Map( + "[pi, pk] -> { " + "[statement = 0, i, k] -> [l0 = 0, l1 = i, l2 = 0, l3 = k, l4 = 0] : " + "0 <= i < pi and 0 <= k < pk }" + ) + isl_sched_map_before_expected = align_isl_maps_by_var_names( + isl_sched_map_before_expected, isl_sched_map_before) + + isl_sched_map_after_expected = isl.Map( + "[pt] -> { " + "[statement = 1, t] -> [l0 = 1, l1 = t, l2 = 0, l3 = 0, l4 = 0] : " + "0 <= t < pt }" + ) + isl_sched_map_after_expected = align_isl_maps_by_var_names( + isl_sched_map_after_expected, isl_sched_map_after) + + assert isl_sched_map_before == isl_sched_map_before_expected + assert isl_sched_map_after == isl_sched_map_after_expected + + # ------------------------------------------------------------------------------ + # Relationship between insn_b and insn_c --------------------------------------- + + # insn_b and insn_c could have been linearized in either order + if lex_sched_BC.stmt_instance_before.stmt.int_id == 0: + # insn_c comes first + assert lex_sched_BC.stmt_instance_before.lex_pt == [0, 'i', 0, 'j', 0] + assert lex_sched_BC.stmt_instance_after.lex_pt == [0, 'i', 0, 'j', 1] + + # Get two isl maps representing the LexSchedule + + isl_sched_map_before, isl_sched_map_after = \ + get_isl_maps_for_LexSchedule(lex_sched_BC, knl, "insn_b", "insn_c") + + # Create expected maps, align, compare + + isl_sched_map_before_expected = isl.Map( + "[pi, pj] -> { " + "[statement = 0, i, j] -> [l0 = 0, l1 = i, l2 = 0, l3 = j, l4 = 1] : " + "0 <= i < pi and 0 <= j < pj }" + ) + isl_sched_map_before_expected = align_isl_maps_by_var_names( + isl_sched_map_before_expected, isl_sched_map_before) + + isl_sched_map_after_expected = isl.Map( + "[pi, pj] -> { " + "[statement = 1, i, j] -> [l0 = 0, l1 = i, l2 = 0, l3 = j, l4 = 0] : " + "0 <= i < pi and 0 <= j < pj }" + ) + isl_sched_map_after_expected = align_isl_maps_by_var_names( + isl_sched_map_after_expected, isl_sched_map_after) + + assert isl_sched_map_before == isl_sched_map_before_expected + assert isl_sched_map_after == isl_sched_map_after_expected + elif lex_sched_BC.stmt_instance_before.stmt.int_id == 1: + # insn_c comes first + assert lex_sched_BC.stmt_instance_before.lex_pt == [0, 'i', 0, 'j', 1] + assert lex_sched_BC.stmt_instance_after.lex_pt == [0, 'i', 0, 'j', 0] + + # Get two isl maps representing the LexSchedule + + isl_sched_map_before, isl_sched_map_after = \ + get_isl_maps_for_LexSchedule(lex_sched_BC, knl, "insn_b", "insn_c") + + # Create expected maps, align, compare + + isl_sched_map_before_expected = isl.Map( + "[pi, pj] -> { " + "[statement = 1, i, j] -> [l0 = 0, l1 = i, l2 = 0, l3 = j, l4 = 1] : " + "0 <= i < pi and 0 <= j < pj }" + ) + isl_sched_map_before_expected = align_isl_maps_by_var_names( + isl_sched_map_before_expected, isl_sched_map_before) + + isl_sched_map_after_expected = isl.Map( + "[pi, pj] -> { " + "[statement = 0, i, j] -> [l0 = 0, l1 = i, l2 = 0, l3 = j, l4 = 0] : " + "0 <= i < pi and 0 <= j < pj }" + ) + isl_sched_map_after_expected = align_isl_maps_by_var_names( + isl_sched_map_after_expected, isl_sched_map_after) + + assert isl_sched_map_before == isl_sched_map_before_expected + assert isl_sched_map_after == isl_sched_map_after_expected + + # ------------------------------------------------------------------------------ + # Relationship between insn_b and insn_d --------------------------------------- + + assert lex_sched_BD.stmt_instance_before.lex_pt == [0, 'i', 0, 'j', 0] + assert lex_sched_BD.stmt_instance_after.lex_pt == [1, 't', 0, 0, 0] + + # Get two isl maps representing the LexSchedule + + isl_sched_map_before, isl_sched_map_after = \ + get_isl_maps_for_LexSchedule(lex_sched_BD, knl, "insn_b", "insn_d") + + # Create expected maps, align, compare + + isl_sched_map_before_expected = isl.Map( + "[pi, pj] -> { " + "[statement = 0, i, j] -> [l0 = 0, l1 = i, l2 = 0, l3 = j, l4 = 0] : " + "0 <= i < pi and 0 <= j < pj }" + ) + isl_sched_map_before_expected = align_isl_maps_by_var_names( + isl_sched_map_before_expected, isl_sched_map_before) + + isl_sched_map_after_expected = isl.Map( + "[pt] -> { " + "[statement = 1, t] -> [l0 = 1, l1 = t, l2 = 0, l3 = 0, l4 = 0] : " + "0 <= t < pt }" + ) + isl_sched_map_after_expected = align_isl_maps_by_var_names( + isl_sched_map_after_expected, isl_sched_map_after) + + assert isl_sched_map_before == isl_sched_map_before_expected + assert isl_sched_map_after == isl_sched_map_after_expected + + # ------------------------------------------------------------------------------ + # Relationship between insn_c and insn_d --------------------------------------- + + assert lex_sched_CD.stmt_instance_before.lex_pt == [0, 'i', 0, 'j', 0] + assert lex_sched_CD.stmt_instance_after.lex_pt == [1, 't', 0, 0, 0] + + # Get two isl maps representing the LexSchedule + + isl_sched_map_before, isl_sched_map_after = \ + get_isl_maps_for_LexSchedule(lex_sched_CD, knl, "insn_c", "insn_d") + + # Create expected maps, align, compare + + isl_sched_map_before_expected = isl.Map( + "[pi, pj] -> { " + "[statement = 0, i, j] -> [l0 = 0, l1 = i, l2 = 0, l3 = j, l4 = 0] : " + "0 <= i < pi and 0 <= j < pj }" + ) + isl_sched_map_before_expected = align_isl_maps_by_var_names( + isl_sched_map_before_expected, isl_sched_map_before) + + isl_sched_map_after_expected = isl.Map( + "[pt] -> { " + "[statement = 1, t] -> [l0 = 1, l1 = t, l2 = 0, l3 = 0, l4 = 0] : " + "0 <= t < pt }" + ) + isl_sched_map_after_expected = align_isl_maps_by_var_names( + isl_sched_map_after_expected, isl_sched_map_after) + + assert isl_sched_map_before == isl_sched_map_before_expected + assert isl_sched_map_after == isl_sched_map_after_expected + + +if __name__ == "__main__": + if len(sys.argv) > 1: + exec(sys.argv[1]) + else: + from pytest import main + main([__file__]) + +# vim: foldmethod=marker -- GitLab From 17e14b19e0c59c4854e60b0509ba665b870e468e Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 13 Apr 2020 23:01:23 -0500 Subject: [PATCH 004/136] add docstrings for get_schedule_for_statement_pair() and get_isl_maps_for_LexSchedule() --- loopy/schedule/checker/__init__.py | 86 ++++++++++++++++++++++++------ 1 file changed, 70 insertions(+), 16 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 1acee56b9..99a555e00 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -20,6 +20,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ +# {{{ Create LexSchedule for statement pair def get_schedule_for_statement_pair( knl, @@ -28,32 +29,52 @@ def get_schedule_for_statement_pair( insn_id_after, prohibited_var_names=set(), ): - """A set of dependencies between two statements. - - .. arg insn_id_before: An instruction identifier that is unique within + """Create a :class:`loopy.schedule.checker.schedule.LexSchedule` + representing the order of two statements as a mapping from + :class:`loopy.schedule.checker.LexScheduleStatementInstance` + to lexicographic time. + + :arg knl: A :class:`loopy.kernel.LoopKernel` containing the + linearization items that will be used to create a schedule. + + :arg linearization_items: A list of :class:`loopy.schedule.ScheduleItem` + (to be renamed to `loopy.schedule.LinearizationItem`) containing + the two linearization items for which a schedule will be + created. This list may be a partial linearization for a + kernel since this function may be used during the linearization + process. + + :arg insn_id_before: An instruction identifier that is unique within a :class:`loopy.kernel.LoopKernel`. - .. arg insn_id_after: An instruction identifier that is unique within + :arg insn_id_after: An instruction identifier that is unique within a :class:`loopy.kernel.LoopKernel`. - """ + :arg prohibited_var_names: A set of :class:`str` representing + variable names that should not be used when creating names for + dimensions in a :class:`loopy.schedule.checker.LexSchedule`. - # We don't retrieve linearization items from knl because knl may not be - # (fully) linearized yet. This function may be called part way through the - # linearization process and receive the current (unfinished) set of - # linearization items + :returns: A :class:`loopy.schedule.checker.schedule.LexSchedule` + representing the order of two statements as a mapping from + :class:`loopy.schedule.checker.LexScheduleStatementInstance` + to lexicographic time. + """ - # Preprocess if not already preprocessed + # {{{ Preprocess if not already preprocessed from loopy import preprocess_kernel preproc_knl = preprocess_kernel(knl) + # }}} + # {{{ By default, don't create LexSchedule variables matching existing inames if not prohibited_var_names: prohibited_var_names = preproc_knl.all_inames() + # }}} - # Get EnterLoop inames tagged as concurrent so LexSchedule can ignore + # {{{ Find any EnterLoop inames that are tagged as concurrent + # so that LexSchedule knows to ignore them # (In the future, this shouldn't be necessary because there # won't be any inames with ConcurrentTags in EnterLoop linearization items. - # Test exercising this: test_linearization_checker_with_stroud_bernstein()) + # Test which exercises this: test_linearization_checker_with_stroud_bernstein()) from loopy.schedule.checker.utils import ( get_concurrent_inames, _get_EnterLoop_inames, @@ -67,8 +88,9 @@ def get_schedule_for_statement_pair( "get_schedule_for_statement_pair encountered EnterLoop for inames %s " "with ConcurrentTag(s) in linearization for kernel %s. " "Ignoring these loops." % (conc_loop_inames, preproc_knl.name)) + # }}} - # Create LexSchedule: mapping of {statement instance: lex point} + # {{{ Create LexSchedule: mapping of {statement instance: lex point} # include only instructions involved in this dependency from loopy.schedule.checker.schedule import LexSchedule return LexSchedule( @@ -78,27 +100,59 @@ def get_schedule_for_statement_pair( prohibited_var_names=prohibited_var_names, loops_to_ignore=conc_loop_inames, ) + # }}} + +# }}} +# {{{ Get isl map pair for LexSchedule + def get_isl_maps_for_LexSchedule( lex_sched, knl, insn_id_before, insn_id_after, ): - # Get two isl maps representing the LexSchedule, - # one for the 'before' linearization item and one for 'after'; - # this requires the iname domains + """Create a pair of :class:`islpy.Map`s representing a + :class:`loopy.schedule.checker.LexSchedule` as two mappings + from statement instances to lexicographic time, one for + the dependee statement and one for the depender. + + :arg lex_sched: A :class:`loopy.schedule.checker.schedule.LexSchedule` + representing the order of two statements as a mapping from + :class:`loopy.schedule.checker.LexScheduleStatementInstance` + to lexicographic time. + + :arg knl: A :class:`loopy.kernel.LoopKernel` containing the + linearization items that will be used to create a schedule. + :arg insn_id_before: An instruction identifier that is unique within + a :class:`loopy.kernel.LoopKernel`. + + :arg insn_id_after: An instruction identifier that is unique within + a :class:`loopy.kernel.LoopKernel`. + + :returns: A two-tuple containing two :class:`islpy.Map`s + representing the schedule as two mappings + from statement instances to lexicographic time, one for + the dependee and one for the depender. + """ + + # {{{ Get iname domains insn_before_inames = knl.id_to_insn[insn_id_before].within_inames insn_after_inames = knl.id_to_insn[insn_id_after].within_inames dom_before = knl.get_inames_domain(insn_before_inames) dom_after = knl.get_inames_domain(insn_after_inames) + # }}} + # {{{ Get isl maps isl_sched_map_before, isl_sched_map_after = \ lex_sched.create_isl_maps( dom_before, dom_after, ) + # }}} return isl_sched_map_before, isl_sched_map_after + +# }}} -- GitLab From dc45709e6e9b117940f375c5fba8aeeb53f0d3b6 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 13 Apr 2020 23:03:14 -0500 Subject: [PATCH 005/136] remove get_statement_ordering_map() (won't be part of this MR) --- .../checker/lexicographic_order_map.py | 38 ------------------- 1 file changed, 38 deletions(-) diff --git a/loopy/schedule/checker/lexicographic_order_map.py b/loopy/schedule/checker/lexicographic_order_map.py index 2e063e7d7..399add0b3 100644 --- a/loopy/schedule/checker/lexicographic_order_map.py +++ b/loopy/schedule/checker/lexicographic_order_map.py @@ -23,44 +23,6 @@ THE SOFTWARE. import islpy as isl -def get_statement_ordering_map( - sched_map_before, sched_map_after, lex_map, before_marker="'"): - """Return a mapping that maps each statement instance to - all statement instances occuring later. - - :arg sched_map_before: An :class:`islpy.Map` representing instruction - instance order for the dependee as a mapping from each statement - instance to a point in the lexicographic ordering. - - :arg sched_map_after: An :class:`islpy.Map` representing instruction - instance order for the depender as a mapping from each statement - instance to a point in the lexicographic ordering. - - :arg lex_map: An :class:`islpy.Map` representing a lexicographic - ordering as a mapping from each point in lexicographic time - to every point that occurs later in lexicographic time. E.g.:: - - {[i0', i1', i2', ...] -> [i0, i1, i2, ...] : - i0' < i0 or (i0' = i0 and i1' < i1) - or (i0' = i0 and i1' = i1 and i2' < i2) ...} - - :returns: An :class:`islpy.Map` representing the lex schedule as - a mapping from each statement instance to all statement instances - occuring later. I.e., we compose B -> L -> A^-1, where B - is sched_map_before, A is sched_map_after, and L is the - lexicographic ordering map. - - """ - - sio = sched_map_before.apply_range( - lex_map).apply_range(sched_map_after.reverse()) - # append marker to in names - for i in range(sio.dim(isl.dim_type.in_)): - sio = sio.set_dim_name(isl.dim_type.in_, i, sio.get_dim_name( - isl.dim_type.in_, i)+before_marker) - return sio - - def get_lex_order_constraint(islvars, before_names, after_names): """Return a constraint represented as an :class:`islpy.Set` defining a 'happens before' relationship in a lexicographic -- GitLab From ee59915fb3d0c163ffddafa82eede6497fb348cf Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 13 Apr 2020 23:07:34 -0500 Subject: [PATCH 006/136] remove lexicographic_order_map (not used in this MR) --- .../checker/lexicographic_order_map.py | 121 ------------------ 1 file changed, 121 deletions(-) delete mode 100644 loopy/schedule/checker/lexicographic_order_map.py diff --git a/loopy/schedule/checker/lexicographic_order_map.py b/loopy/schedule/checker/lexicographic_order_map.py deleted file mode 100644 index 399add0b3..000000000 --- a/loopy/schedule/checker/lexicographic_order_map.py +++ /dev/null @@ -1,121 +0,0 @@ -__copyright__ = "Copyright (C) 2019 James Stevens" - -__license__ = """ -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" - -import islpy as isl - - -def get_lex_order_constraint(islvars, before_names, after_names): - """Return a constraint represented as an :class:`islpy.Set` - defining a 'happens before' relationship in a lexicographic - ordering. - - :arg islvars: A dictionary from variable names to :class:`islpy.PwAff` - instances that represent each of the variables - (islvars may be produced by `islpy.make_zero_and_vars`). The key - '0' is also include and represents a :class:`islpy.PwAff` zero constant. - This dictionary defines the space to be used for the set. - - :arg before_names: A list of :class:`str` variable names representing - the lexicographic space dimensions for a point in lexicographic - time that occurs before. (see example below) - - :arg after_names: A list of :class:`str` variable names representing - the lexicographic space dimensions for a point in lexicographic - time that occurs after. (see example below) - - :returns: An :class:`islpy.Set` representing a constraint that enforces a - lexicographic ordering. E.g., if ``before_names = [i0', i1', i2']`` and - ``after_names = [i0, i1, i2]``, return the set:: - - {[i0', i1', i2', i0, i1, i2] : - i0' < i0 or (i0' = i0 and i1' < i1) - or (i0' = i0 and i1' = i1 and i2' < i2)} - - """ - - lex_order_constraint = islvars[before_names[0]].lt_set(islvars[after_names[0]]) - for i in range(1, len(before_names)): - lex_order_constraint_conj = islvars[before_names[i]].lt_set( - islvars[after_names[i]]) - for j in range(i): - lex_order_constraint_conj = lex_order_constraint_conj & \ - islvars[before_names[j]].eq_set(islvars[after_names[j]]) - lex_order_constraint = lex_order_constraint | lex_order_constraint_conj - return lex_order_constraint - - -def create_lex_order_map( - n_dims, - before_names=None, - after_names=None, - ): - """Return a mapping that maps each point in a lexicographic - ordering to every point that occurs later in lexicographic - time. - - :arg n_dims: An :class:`int` representing the number of dimensions - in the lexicographic ordering. - - :arg before_names: A list of :class:`str` variable names representing - the lexicographic space dimensions for a point in lexicographic - time that occurs before. (see example below) - - :arg after_names: A list of :class:`str` variable names representing - the lexicographic space dimensions for a point in lexicographic - time that occurs after. (see example below) - - :returns: An :class:`islpy.Map` representing a lexicographic - ordering as a mapping from each point in lexicographic time - to every point that occurs later in lexicographic time. - E.g., if ``before_names = [i0', i1', i2']`` and - ``after_names = [i0, i1, i2]``, return the map:: - - {[i0', i1', i2'] -> [i0, i1, i2] : - i0' < i0 or (i0' = i0 and i1' < i1) - or (i0' = i0 and i1' = i1 and i2' < i2)} - - """ - - if before_names is None: - before_names = ["i%s" % (i) for i in range(n_dims)] - if after_names is None: - from loopy.schedule.checker.utils import ( - append_marker_to_strings, - ) - after_names = append_marker_to_strings(before_names, marker="_") - - assert len(before_names) == len(after_names) == n_dims - dim_type = isl.dim_type - - islvars = isl.make_zero_and_vars( - before_names+after_names, - []) - - lex_order_constraint = get_lex_order_constraint( - islvars, before_names, after_names) - - lex_map = isl.Map.from_domain(lex_order_constraint) - lex_map = lex_map.move_dims( - dim_type.out, 0, dim_type.in_, - len(before_names), len(after_names)) - - return lex_map -- GitLab From 5401383198da8c7ba6fc840d075a23297379e76a Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 13 Apr 2020 23:09:52 -0500 Subject: [PATCH 007/136] remove get_lex_order_map_for_sched_space() (not part of this MR) --- loopy/schedule/checker/schedule.py | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index c395863ef..199a5deda 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -458,19 +458,6 @@ class LexSchedule(object): return [self.lex_var_prefix+str(i) for i in range(self.max_lex_dims())] - def get_lex_order_map_for_sched_space(self): - """Return an :class:`islpy.BasicMap` that maps each point in a - lexicographic ordering to every point that is - lexocigraphically greater. - """ - - from loopy.schedule.checker.lexicographic_order_map import ( - create_lex_order_map, - ) - n_dims = self.max_lex_dims() - return create_lex_order_map( - n_dims, before_names=self.get_lex_var_names()) - def __eq__(self, other): return ( self.stmt_instance_before == other.stmt_instance_before -- GitLab From 7e94f4beafa84aa525a7eb5c6177c7f12b498d19 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 13 Apr 2020 23:14:12 -0500 Subject: [PATCH 008/136] remove more methods from LexSchedule that are not used in this MR (loopy_insn_id_to_lex_sched_id and __eq__) --- loopy/schedule/checker/schedule.py | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 199a5deda..ed168ae5b 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -306,18 +306,6 @@ class LexSchedule(object): # the values in these missing dims should be zero, so add them self.pad_lex_pts_with_zeros() - def loopy_insn_id_to_lex_sched_id(self): - """Return a dictionary mapping insn_id to int_id, where ``insn_id`` and - ``int_id`` refer to the ``insn_id`` and ``int_id`` attributes of - :class:`LexScheduleStatement`. - """ - return { - self.stmt_instance_before.stmt.insn_id: - self.stmt_instance_before.stmt.int_id, - self.stmt_instance_after.stmt.insn_id: - self.stmt_instance_after.stmt.int_id, - } - def max_lex_dims(self): return max([ len(self.stmt_instance_before.lex_pt), @@ -458,11 +446,6 @@ class LexSchedule(object): return [self.lex_var_prefix+str(i) for i in range(self.max_lex_dims())] - def __eq__(self, other): - return ( - self.stmt_instance_before == other.stmt_instance_before - and self.stmt_instance_after == other.stmt_instance_after) - def __str__(self): sched_str = "Before: {\n" domain_elem = "[%s=%s,]" % ( -- GitLab From 16afc55bec1d072783e7b2a0e5eae6963e7506fe Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 13 Apr 2020 23:21:08 -0500 Subject: [PATCH 009/136] remove another func from utils that is not used in this MR (append_marker_to_strings) --- loopy/schedule/checker/utils.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index 8757406b7..cb933de6f 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -143,13 +143,6 @@ def align_isl_maps_by_var_names(input_map, target_map): return aligned_input_map -def append_marker_to_strings(strings, marker="'"): - if not isinstance(strings, list): - raise ValueError("append_marker_to_strings did not receive a list") - else: - return [s+marker for s in strings] - - def _union_of_isl_sets_or_maps(set_list): union = set_list[0] for s in set_list[1:]: -- GitLab From d2f94b7cf6cee1d0f0a24b72209cff6be074852c Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 13 Apr 2020 23:41:53 -0500 Subject: [PATCH 010/136] remove LexScheduleStatement methods not needed in this MR --- loopy/schedule/checker/schedule.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index ed168ae5b..542c48f95 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -51,16 +51,6 @@ class LexScheduleStatement(object): self.int_id = int_id self.within_inames = within_inames - def __eq__(self, other): - return ( - self.insn_id == other.insn_id - and self.int_id == other.int_id - and self.within_inames == other.within_inames - ) - - def __hash__(self): - return hash(repr(self)) - def update_persistent_hash(self, key_hash, key_builder): """Custom hash computation function for use with :class:`pytools.persistent_dict.PersistentDict`. -- GitLab From aa44009f367adb810ee3686047d2fbbec13135e5 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 13 Apr 2020 23:47:49 -0500 Subject: [PATCH 011/136] fixing flake8 issues --- loopy/schedule/checker/__init__.py | 1 + loopy/schedule/checker/schedule.py | 20 +++++----- test/test_linearization_checker.py | 59 +++++++++++++++--------------- 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 99a555e00..2911351b2 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -20,6 +20,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ + # {{{ Create LexSchedule for statement pair def get_schedule_for_statement_pair( diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 542c48f95..39c8c1161 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -177,9 +177,6 @@ class LexSchedule(object): next_insn_lex_pt = [0] stmt_since_last_block_at_tier = [False] next_sid = 0 - stmt_added_since_last_EnterLoop = False - stmt_added_since_last_LeaveLoop = False - #stmt_added_since_last_new_block = False # blocks start at open/close loop for linearization_item in linearization_items_ordered: if isinstance(linearization_item, EnterLoop): iname = linearization_item.iname @@ -188,8 +185,8 @@ class LexSchedule(object): # We could always increment next_insn_lex_pt[-1] here since this new # section of code comes after the previous section (statements - # since last opened/closed loop), but if we have not added any statements - # within this block yet, we don't have to + # since last opened/closed loop), but if we have not added any + # statements within this block yet, we don't have to # (effectively ignoring that section of code). if stmt_since_last_block_at_tier[-1]: next_insn_lex_pt[-1] = next_insn_lex_pt[-1]+1 @@ -214,8 +211,8 @@ class LexSchedule(object): # We could always increment next_insn_lex_pt[-1] here since this new # block of code comes after the previous block (all statements - # since last opened/closed loop), but if we have not added any statements - # within this block yet, we don't have to + # since last opened/closed loop), but if we have not added any + # statements within this block yet, we don't have to # (effectively ignoring that section of code). stmt_since_last_block_at_tier.pop() if stmt_since_last_block_at_tier[-1]: @@ -255,7 +252,8 @@ class LexSchedule(object): next_sid += 1 # all current (nested) blocks now contain a statement - stmt_since_last_block_at_tier = [True]*len(stmt_since_last_block_at_tier) + stmt_since_last_block_at_tier = [True]*len( + stmt_since_last_block_at_tier) elif lp_insn_id == before_insn_id: # add before sched item self.stmt_instance_before = LexScheduleStatementInstance( @@ -270,7 +268,8 @@ class LexSchedule(object): next_sid += 1 # all current (nested) blocks now contain a statement - stmt_since_last_block_at_tier = [True]*len(stmt_since_last_block_at_tier) + stmt_since_last_block_at_tier = [True]*len( + stmt_since_last_block_at_tier) elif lp_insn_id == after_insn_id: # add after sched item self.stmt_instance_after = LexScheduleStatementInstance( @@ -285,7 +284,8 @@ class LexSchedule(object): next_sid += 1 # all current (nested) blocks now contain a statement - stmt_since_last_block_at_tier = [True]*len(stmt_since_last_block_at_tier) + stmt_since_last_block_at_tier = [True]*len( + stmt_since_last_block_at_tier) else: pass # to save time, stop when we've created both statements diff --git a/test/test_linearization_checker.py b/test/test_linearization_checker.py index 7e145ce1d..68688f0df 100644 --- a/test/test_linearization_checker.py +++ b/test/test_linearization_checker.py @@ -31,7 +31,6 @@ from pyopencl.tools import ( # noqa as pytest_generate_tests) from loopy.version import LOOPY_USE_LANGUAGE_VERSION_2018_2 # noqa import logging -from loopy.kernel import KernelState from loopy import ( preprocess_kernel, get_one_linearized_kernel, @@ -95,37 +94,37 @@ def test_lexschedule_and_islmap_creation(): linearization_items = knl.linearization # Create LexSchedule: mapping of {statement instance: lex point} - lex_sched_AB = get_schedule_for_statement_pair( + lex_sched_ab = get_schedule_for_statement_pair( knl, linearization_items, "insn_a", "insn_b", ) - lex_sched_AC = get_schedule_for_statement_pair( + lex_sched_ac = get_schedule_for_statement_pair( knl, linearization_items, "insn_a", "insn_c", ) - lex_sched_AD = get_schedule_for_statement_pair( + lex_sched_ad = get_schedule_for_statement_pair( knl, linearization_items, "insn_a", "insn_d", ) - lex_sched_BC = get_schedule_for_statement_pair( + lex_sched_bc = get_schedule_for_statement_pair( knl, linearization_items, "insn_b", "insn_c", ) - lex_sched_BD = get_schedule_for_statement_pair( + lex_sched_bd = get_schedule_for_statement_pair( knl, linearization_items, "insn_b", "insn_d", ) - lex_sched_CD = get_schedule_for_statement_pair( + lex_sched_cd = get_schedule_for_statement_pair( knl, linearization_items, "insn_c", @@ -134,13 +133,13 @@ def test_lexschedule_and_islmap_creation(): # Relationship between insn_a and insn_b --------------------------------------- - assert lex_sched_AB.stmt_instance_before.lex_pt == [0, 'i', 0, 'k', 0] - assert lex_sched_AB.stmt_instance_after.lex_pt == [0, 'i', 1, 'j', 0] + assert lex_sched_ab.stmt_instance_before.lex_pt == [0, 'i', 0, 'k', 0] + assert lex_sched_ab.stmt_instance_after.lex_pt == [0, 'i', 1, 'j', 0] # Get two isl maps representing the LexSchedule isl_sched_map_before, isl_sched_map_after = \ - get_isl_maps_for_LexSchedule(lex_sched_AB, knl, "insn_a", "insn_b") + get_isl_maps_for_LexSchedule(lex_sched_ab, knl, "insn_a", "insn_b") # Create expected maps, align, compare @@ -166,13 +165,13 @@ def test_lexschedule_and_islmap_creation(): # ------------------------------------------------------------------------------ # Relationship between insn_a and insn_c --------------------------------------- - assert lex_sched_AC.stmt_instance_before.lex_pt == [0, 'i', 0, 'k', 0] - assert lex_sched_AC.stmt_instance_after.lex_pt == [0, 'i', 1, 'j', 0] + assert lex_sched_ac.stmt_instance_before.lex_pt == [0, 'i', 0, 'k', 0] + assert lex_sched_ac.stmt_instance_after.lex_pt == [0, 'i', 1, 'j', 0] # Get two isl maps representing the LexSchedule isl_sched_map_before, isl_sched_map_after = \ - get_isl_maps_for_LexSchedule(lex_sched_AC, knl, "insn_a", "insn_c") + get_isl_maps_for_LexSchedule(lex_sched_ac, knl, "insn_a", "insn_c") # Create expected maps, align, compare @@ -198,13 +197,13 @@ def test_lexschedule_and_islmap_creation(): # ------------------------------------------------------------------------------ # Relationship between insn_a and insn_d --------------------------------------- - assert lex_sched_AD.stmt_instance_before.lex_pt == [0, 'i', 0, 'k', 0] - assert lex_sched_AD.stmt_instance_after.lex_pt == [1, 't', 0, 0, 0] + assert lex_sched_ad.stmt_instance_before.lex_pt == [0, 'i', 0, 'k', 0] + assert lex_sched_ad.stmt_instance_after.lex_pt == [1, 't', 0, 0, 0] # Get two isl maps representing the LexSchedule isl_sched_map_before, isl_sched_map_after = \ - get_isl_maps_for_LexSchedule(lex_sched_AD, knl, "insn_a", "insn_d") + get_isl_maps_for_LexSchedule(lex_sched_ad, knl, "insn_a", "insn_d") # Create expected maps, align, compare @@ -231,15 +230,15 @@ def test_lexschedule_and_islmap_creation(): # Relationship between insn_b and insn_c --------------------------------------- # insn_b and insn_c could have been linearized in either order - if lex_sched_BC.stmt_instance_before.stmt.int_id == 0: + if lex_sched_bc.stmt_instance_before.stmt.int_id == 0: # insn_c comes first - assert lex_sched_BC.stmt_instance_before.lex_pt == [0, 'i', 0, 'j', 0] - assert lex_sched_BC.stmt_instance_after.lex_pt == [0, 'i', 0, 'j', 1] + assert lex_sched_bc.stmt_instance_before.lex_pt == [0, 'i', 0, 'j', 0] + assert lex_sched_bc.stmt_instance_after.lex_pt == [0, 'i', 0, 'j', 1] # Get two isl maps representing the LexSchedule isl_sched_map_before, isl_sched_map_after = \ - get_isl_maps_for_LexSchedule(lex_sched_BC, knl, "insn_b", "insn_c") + get_isl_maps_for_LexSchedule(lex_sched_bc, knl, "insn_b", "insn_c") # Create expected maps, align, compare @@ -261,15 +260,15 @@ def test_lexschedule_and_islmap_creation(): assert isl_sched_map_before == isl_sched_map_before_expected assert isl_sched_map_after == isl_sched_map_after_expected - elif lex_sched_BC.stmt_instance_before.stmt.int_id == 1: + elif lex_sched_bc.stmt_instance_before.stmt.int_id == 1: # insn_c comes first - assert lex_sched_BC.stmt_instance_before.lex_pt == [0, 'i', 0, 'j', 1] - assert lex_sched_BC.stmt_instance_after.lex_pt == [0, 'i', 0, 'j', 0] + assert lex_sched_bc.stmt_instance_before.lex_pt == [0, 'i', 0, 'j', 1] + assert lex_sched_bc.stmt_instance_after.lex_pt == [0, 'i', 0, 'j', 0] # Get two isl maps representing the LexSchedule isl_sched_map_before, isl_sched_map_after = \ - get_isl_maps_for_LexSchedule(lex_sched_BC, knl, "insn_b", "insn_c") + get_isl_maps_for_LexSchedule(lex_sched_bc, knl, "insn_b", "insn_c") # Create expected maps, align, compare @@ -295,13 +294,13 @@ def test_lexschedule_and_islmap_creation(): # ------------------------------------------------------------------------------ # Relationship between insn_b and insn_d --------------------------------------- - assert lex_sched_BD.stmt_instance_before.lex_pt == [0, 'i', 0, 'j', 0] - assert lex_sched_BD.stmt_instance_after.lex_pt == [1, 't', 0, 0, 0] + assert lex_sched_bd.stmt_instance_before.lex_pt == [0, 'i', 0, 'j', 0] + assert lex_sched_bd.stmt_instance_after.lex_pt == [1, 't', 0, 0, 0] # Get two isl maps representing the LexSchedule isl_sched_map_before, isl_sched_map_after = \ - get_isl_maps_for_LexSchedule(lex_sched_BD, knl, "insn_b", "insn_d") + get_isl_maps_for_LexSchedule(lex_sched_bd, knl, "insn_b", "insn_d") # Create expected maps, align, compare @@ -327,13 +326,13 @@ def test_lexschedule_and_islmap_creation(): # ------------------------------------------------------------------------------ # Relationship between insn_c and insn_d --------------------------------------- - assert lex_sched_CD.stmt_instance_before.lex_pt == [0, 'i', 0, 'j', 0] - assert lex_sched_CD.stmt_instance_after.lex_pt == [1, 't', 0, 0, 0] + assert lex_sched_cd.stmt_instance_before.lex_pt == [0, 'i', 0, 'j', 0] + assert lex_sched_cd.stmt_instance_after.lex_pt == [1, 't', 0, 0, 0] # Get two isl maps representing the LexSchedule isl_sched_map_before, isl_sched_map_after = \ - get_isl_maps_for_LexSchedule(lex_sched_CD, knl, "insn_c", "insn_d") + get_isl_maps_for_LexSchedule(lex_sched_cd, knl, "insn_c", "insn_d") # Create expected maps, align, compare -- GitLab From 08e7342a919856a1f2eee7d1836c65fcdca61655 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 14 Apr 2020 00:29:02 -0500 Subject: [PATCH 012/136] adding LexScheduleStatement.__eq__ back in to see if it fixes caching error --- loopy/schedule/checker/schedule.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 39c8c1161..b5f9b4256 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -51,6 +51,13 @@ class LexScheduleStatement(object): self.int_id = int_id self.within_inames = within_inames + def __eq__(self, other): + return ( + self.insn_id == other.insn_id + and self.int_id == other.int_id + and self.within_inames == other.within_inames + ) + def update_persistent_hash(self, key_hash, key_builder): """Custom hash computation function for use with :class:`pytools.persistent_dict.PersistentDict`. -- GitLab From 5f53d50fe0b38c288c1fd1a5a681d24a317f6e8d Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Fri, 17 Apr 2020 03:26:18 -0500 Subject: [PATCH 013/136] eliminate duplicate code in sched.__str__ --- loopy/schedule/checker/schedule.py | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index b5f9b4256..af35bd68e 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -444,17 +444,13 @@ class LexSchedule(object): for i in range(self.max_lex_dims())] def __str__(self): - sched_str = "Before: {\n" - domain_elem = "[%s=%s,]" % ( - self.statement_var_name, - self.stmt_instance_before.stmt.int_id) - sched_str += "%s -> %s;\n" % (domain_elem, self.stmt_instance_before.lex_pt) - sched_str += "}\n" - - sched_str += "After: {\n" - domain_elem = "[%s=%s,]" % ( - self.statement_var_name, - self.stmt_instance_after.stmt.int_id) - sched_str += "%s -> %s;\n" % (domain_elem, self.stmt_instance_after.lex_pt) - sched_str += "}" - return sched_str + + def stringify_sched_stmt_instance(stmt_inst): + return "{\n[%s=%s,] -> %s;\n}" % ( + self.statement_var_name, + stmt_inst.stmt.int_id, + stmt_inst.lex_pt) + + return "Before: %s\nAfter: %s" % ( + stringify_sched_stmt_instance(self.stmt_instance_before), + stringify_sched_stmt_instance(self.stmt_instance_after)) -- GitLab From 5441bfa239a49567c63200ff24f1e0f2e45e4705 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Fri, 17 Apr 2020 04:27:41 -0500 Subject: [PATCH 014/136] eliminate duplicate code in sched.create_isl_maps --- loopy/schedule/checker/schedule.py | 110 ++++++++++++----------------- 1 file changed, 46 insertions(+), 64 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index af35bd68e..8ca42e83d 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -365,79 +365,61 @@ class LexSchedule(object): """ from loopy.schedule.checker.utils import ( + list_var_names_in_isl_sets, + get_isl_space, create_symbolic_isl_map_from_tuples, - add_dims_to_isl_set + add_dims_to_isl_set, ) - from loopy.schedule.checker.utils import ( - list_var_names_in_isl_sets, - ) - if dom_inames_ordered_before is None: - dom_inames_ordered_before = list_var_names_in_isl_sets( - [dom_before]) - if dom_inames_ordered_after is None: - dom_inames_ordered_after = list_var_names_in_isl_sets( - [dom_after]) - - # create an isl space - # {('statement', used in >=1 statement domain>) -> - # (lexicographic ordering dims)} - from loopy.schedule.checker.utils import ( - get_isl_space - ) params_sched = [] out_names_sched = self.get_lex_var_names() - in_names_sched_before = [ - self.statement_var_name] + dom_inames_ordered_before[:] - sched_space_before = get_isl_space( - params_sched, in_names_sched_before, out_names_sched) - in_names_sched_after = [ - self.statement_var_name] + dom_inames_ordered_after[:] - sched_space_after = get_isl_space( - params_sched, in_names_sched_after, out_names_sched) - - # Insert 'statement' dim into domain so that its space allows for - # intersection with sched map later - doms_to_intersect_before = [ - add_dims_to_isl_set( - dom_before, isl.dim_type.set, - [self.statement_var_name], 0), - ] - doms_to_intersect_after = [ - add_dims_to_isl_set( - dom_after, isl.dim_type.set, - [self.statement_var_name], 0), - ] + def _get_isl_map_for_stmt_inst( + stmt_inst, dom, dom_inames_ordered): - # Each isl map representing the schedule maps - # statement instances -> lex time + # create an isl space + # {('statement', used in statement domain>) -> + # (lexicographic ordering dims)} + if dom_inames_ordered is None: + dom_inames_ordered = list_var_names_in_isl_sets([dom]) - # Right now, statement tuples consist of single int. - # Add all inames from domains to map domain tuples. + in_names_sched = [ + self.statement_var_name] + dom_inames_ordered[:] + sched_space = get_isl_space( + params_sched, in_names_sched, out_names_sched) - # create isl map - return ( - create_symbolic_isl_map_from_tuples( - zip( - [( - (self.stmt_instance_before.stmt.int_id,) - + tuple(dom_inames_ordered_before), - self.stmt_instance_before.lex_pt - )], - doms_to_intersect_before - ), - sched_space_before, self.statement_var_name), - create_symbolic_isl_map_from_tuples( - zip( - [( - (self.stmt_instance_after.stmt.int_id,) - + tuple(dom_inames_ordered_after), - self.stmt_instance_after.lex_pt)], - doms_to_intersect_after - ), - sched_space_after, self.statement_var_name) - ) + # Insert 'statement' dim into domain so that its space allows + # for intersection with sched map later + dom_to_intersect = [ + add_dims_to_isl_set( + dom, isl.dim_type.set, [self.statement_var_name], 0), ] + + # Each isl map representing the schedule will map + # statement instances -> lex time. + # Right now, statement instance tuples consist of single int. + # Add all inames from domains to each map domain tuple. + tuple_pair = [( + (stmt_inst.stmt.int_id, ) + tuple(dom_inames_ordered), + stmt_inst.lex_pt + )] + + # create isl map + return create_symbolic_isl_map_from_tuples( + tuple_pairs_with_domains=zip(tuple_pair, dom_to_intersect), + space=sched_space, + statement_var_name=self.statement_var_name, + ) + + map_before = _get_isl_map_for_stmt_inst( + self.stmt_instance_before, + dom_before, + dom_inames_ordered_before) + map_after = _get_isl_map_for_stmt_inst( + self.stmt_instance_after, + dom_after, + dom_inames_ordered_after) + + return (map_before, map_after) def get_lex_var_names(self): return [self.lex_var_prefix+str(i) -- GitLab From 31c68b724c2c9d6bf1fdadc703b3e6a60c8a6cff Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Fri, 17 Apr 2020 04:34:33 -0500 Subject: [PATCH 015/136] eliminate duplicate code in sched.pad_lex_pts_with_zeros --- loopy/schedule/checker/schedule.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 8ca42e83d..4e59fdb7f 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -316,17 +316,18 @@ class LexSchedule(object): dimensions. """ + def _pad_lex_pt_with_zeros(stmt_inst, length): + return LexScheduleStatementInstance( + stmt_inst.stmt, + stmt_inst.lex_pt[:] + [0]*(length-len(stmt_inst.lex_pt)), + ) + max_lex_dim = self.max_lex_dims() - self.stmt_instance_before = LexScheduleStatementInstance( - self.stmt_instance_before.stmt, - self.stmt_instance_before.lex_pt[:] + [0]*( - max_lex_dim-len(self.stmt_instance_before.lex_pt)) - ) - self.stmt_instance_after = LexScheduleStatementInstance( - self.stmt_instance_after.stmt, - self.stmt_instance_after.lex_pt[:] + [0]*( - max_lex_dim-len(self.stmt_instance_after.lex_pt)) - ) + + self.stmt_instance_before = _pad_lex_pt_with_zeros( + self.stmt_instance_before, max_lex_dim) + self.stmt_instance_after = _pad_lex_pt_with_zeros( + self.stmt_instance_after, max_lex_dim) def create_isl_maps( self, -- GitLab From da919bfbe6cf9c5128d100caaf581f2b04c76ad0 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Fri, 17 Apr 2020 04:57:29 -0500 Subject: [PATCH 016/136] eliminate duplicate code in sched.__init__ --- loopy/schedule/checker/schedule.py | 65 ++++++++++-------------------- 1 file changed, 22 insertions(+), 43 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 4e59fdb7f..0aca588c3 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -182,7 +182,7 @@ class LexSchedule(object): # keep track of the next point in our lexicographic ordering # initially this as a 1-d point with value 0 next_insn_lex_pt = [0] - stmt_since_last_block_at_tier = [False] + stmt_added_since_prev_block_at_tier = [False] next_sid = 0 for linearization_item in linearization_items_ordered: if isinstance(linearization_item, EnterLoop): @@ -193,19 +193,20 @@ class LexSchedule(object): # We could always increment next_insn_lex_pt[-1] here since this new # section of code comes after the previous section (statements # since last opened/closed loop), but if we have not added any - # statements within this block yet, we don't have to + # statements within the previous section yet, we don't have to # (effectively ignoring that section of code). - if stmt_since_last_block_at_tier[-1]: + if stmt_added_since_prev_block_at_tier[-1]: next_insn_lex_pt[-1] = next_insn_lex_pt[-1]+1 - stmt_since_last_block_at_tier[-1] = False + stmt_added_since_prev_block_at_tier[-1] = False # upon entering a loop, we enter a new (deeper) tier, # add one lex dimension for the loop variable, # add second lex dim to enumerate code blocks within new loop, and - # append a dim to stmt_since_last_block_at_tier to represent new tier + # append a dim to stmt_added_since_prev_block_at_tier to represent + # new tier next_insn_lex_pt.append(iname) next_insn_lex_pt.append(0) - stmt_since_last_block_at_tier.append(False) + stmt_added_since_prev_block_at_tier.append(False) elif isinstance(linearization_item, LeaveLoop): if linearization_item.iname in loops_to_ignore: continue @@ -219,12 +220,12 @@ class LexSchedule(object): # We could always increment next_insn_lex_pt[-1] here since this new # block of code comes after the previous block (all statements # since last opened/closed loop), but if we have not added any - # statements within this block yet, we don't have to + # statements within the previous section yet, we don't have to # (effectively ignoring that section of code). - stmt_since_last_block_at_tier.pop() - if stmt_since_last_block_at_tier[-1]: + stmt_added_since_prev_block_at_tier.pop() + if stmt_added_since_prev_block_at_tier[-1]: next_insn_lex_pt[-1] = next_insn_lex_pt[-1]+1 - stmt_since_last_block_at_tier[-1] = False + stmt_added_since_prev_block_at_tier[-1] = False elif isinstance(linearization_item, (RunInstruction, Barrier)): from loopy.schedule.checker.utils import ( _get_insn_id_from_linearization_item, @@ -238,30 +239,9 @@ class LexSchedule(object): continue # only process before/after insns, otherwise ignore - if lp_insn_id == before_insn_id and lp_insn_id == after_insn_id: - # add before sched item - self.stmt_instance_before = LexScheduleStatementInstance( - LexScheduleStatement( - insn_id=lp_insn_id, - int_id=next_sid, # int representing insn - ), - next_insn_lex_pt[:]) - # add after sched item - self.stmt_instance_after = LexScheduleStatementInstance( - LexScheduleStatement( - insn_id=lp_insn_id, - int_id=next_sid, # int representing insn - ), - next_insn_lex_pt[:]) - - # increment lex dim val enumerating items in current code block - next_insn_lex_pt[-1] = next_insn_lex_pt[-1] + 1 - next_sid += 1 + stmt_added = False - # all current (nested) blocks now contain a statement - stmt_since_last_block_at_tier = [True]*len( - stmt_since_last_block_at_tier) - elif lp_insn_id == before_insn_id: + if lp_insn_id == before_insn_id: # add before sched item self.stmt_instance_before = LexScheduleStatementInstance( LexScheduleStatement( @@ -269,15 +249,9 @@ class LexSchedule(object): int_id=next_sid, # int representing insn ), next_insn_lex_pt[:]) + stmt_added = True - # increment lex dim val enumerating items in current code block - next_insn_lex_pt[-1] = next_insn_lex_pt[-1] + 1 - next_sid += 1 - - # all current (nested) blocks now contain a statement - stmt_since_last_block_at_tier = [True]*len( - stmt_since_last_block_at_tier) - elif lp_insn_id == after_insn_id: + if lp_insn_id == after_insn_id: # add after sched item self.stmt_instance_after = LexScheduleStatementInstance( LexScheduleStatement( @@ -285,14 +259,19 @@ class LexSchedule(object): int_id=next_sid, # int representing insn ), next_insn_lex_pt[:]) + stmt_added = True + + # Note: before/after may refer to same stmt, in which case + # both of the above conditionals execute + if stmt_added: # increment lex dim val enumerating items in current code block next_insn_lex_pt[-1] = next_insn_lex_pt[-1] + 1 next_sid += 1 # all current (nested) blocks now contain a statement - stmt_since_last_block_at_tier = [True]*len( - stmt_since_last_block_at_tier) + stmt_added_since_prev_block_at_tier = [True]*len( + stmt_added_since_prev_block_at_tier) else: pass # to save time, stop when we've created both statements -- GitLab From 7d291b0b49b878cc2c02767c717f6e652eb40cf2 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 19 Apr 2020 21:24:18 -0500 Subject: [PATCH 017/136] allow for all valid linearization orders in LexSchedule/map creation test --- test/test_linearization_checker.py | 187 +++++++++++++++-------------- 1 file changed, 97 insertions(+), 90 deletions(-) diff --git a/test/test_linearization_checker.py b/test/test_linearization_checker.py index 68688f0df..c112b40ae 100644 --- a/test/test_linearization_checker.py +++ b/test/test_linearization_checker.py @@ -197,43 +197,53 @@ def test_lexschedule_and_islmap_creation(): # ------------------------------------------------------------------------------ # Relationship between insn_a and insn_d --------------------------------------- - assert lex_sched_ad.stmt_instance_before.lex_pt == [0, 'i', 0, 'k', 0] - assert lex_sched_ad.stmt_instance_after.lex_pt == [1, 't', 0, 0, 0] + # insn_a and insn_d could have been linearized in either order + # (i loop could be before or after t loop) + def perform_insn_ad_checks_with(sid_a, sid_d): + assert lex_sched_ad.stmt_instance_before.lex_pt == [sid_a, 'i', 0, 'k', 0] + assert lex_sched_ad.stmt_instance_after.lex_pt == [sid_d, 't', 0, 0, 0] - # Get two isl maps representing the LexSchedule + # Get two isl maps representing the LexSchedule - isl_sched_map_before, isl_sched_map_after = \ - get_isl_maps_for_LexSchedule(lex_sched_ad, knl, "insn_a", "insn_d") + isl_sched_map_before, isl_sched_map_after = \ + get_isl_maps_for_LexSchedule(lex_sched_ad, knl, "insn_a", "insn_d") - # Create expected maps, align, compare + # Create expected maps, align, compare - isl_sched_map_before_expected = isl.Map( - "[pi, pk] -> { " - "[statement = 0, i, k] -> [l0 = 0, l1 = i, l2 = 0, l3 = k, l4 = 0] : " - "0 <= i < pi and 0 <= k < pk }" - ) - isl_sched_map_before_expected = align_isl_maps_by_var_names( - isl_sched_map_before_expected, isl_sched_map_before) + isl_sched_map_before_expected = isl.Map( + "[pi, pk] -> { " + "[statement = %d, i, k] -> [l0 = %d, l1 = i, l2 = 0, l3 = k, l4 = 0] : " + "0 <= i < pi and 0 <= k < pk }" + % (sid_a, sid_a) + ) + isl_sched_map_before_expected = align_isl_maps_by_var_names( + isl_sched_map_before_expected, isl_sched_map_before) - isl_sched_map_after_expected = isl.Map( - "[pt] -> { " - "[statement = 1, t] -> [l0 = 1, l1 = t, l2 = 0, l3 = 0, l4 = 0] : " - "0 <= t < pt }" - ) - isl_sched_map_after_expected = align_isl_maps_by_var_names( - isl_sched_map_after_expected, isl_sched_map_after) + isl_sched_map_after_expected = isl.Map( + "[pt] -> { " + "[statement = %d, t] -> [l0 = %d, l1 = t, l2 = 0, l3 = 0, l4 = 0] : " + "0 <= t < pt }" + % (sid_d, sid_d) + ) + isl_sched_map_after_expected = align_isl_maps_by_var_names( + isl_sched_map_after_expected, isl_sched_map_after) - assert isl_sched_map_before == isl_sched_map_before_expected - assert isl_sched_map_after == isl_sched_map_after_expected + assert isl_sched_map_before == isl_sched_map_before_expected + assert isl_sched_map_after == isl_sched_map_after_expected + + if lex_sched_ad.stmt_instance_before.stmt.int_id == 0: + perform_insn_ad_checks_with(0, 1) + else: + perform_insn_ad_checks_with(1, 0) # ------------------------------------------------------------------------------ # Relationship between insn_b and insn_c --------------------------------------- # insn_b and insn_c could have been linearized in either order - if lex_sched_bc.stmt_instance_before.stmt.int_id == 0: - # insn_c comes first - assert lex_sched_bc.stmt_instance_before.lex_pt == [0, 'i', 0, 'j', 0] - assert lex_sched_bc.stmt_instance_after.lex_pt == [0, 'i', 0, 'j', 1] + # (i loop could be before or after t loop) + def perform_insn_bc_checks_with(sid_b, sid_c): + assert lex_sched_bc.stmt_instance_before.lex_pt == [0, 'i', 0, 'j', sid_b] + assert lex_sched_bc.stmt_instance_after.lex_pt == [0, 'i', 0, 'j', sid_c] # Get two isl maps representing the LexSchedule @@ -244,46 +254,60 @@ def test_lexschedule_and_islmap_creation(): isl_sched_map_before_expected = isl.Map( "[pi, pj] -> { " - "[statement = 0, i, j] -> [l0 = 0, l1 = i, l2 = 0, l3 = j, l4 = 1] : " + "[statement = %d, i, j] -> [l0 = 0, l1 = i, l2 = 0, l3 = j, l4 = %d] : " "0 <= i < pi and 0 <= j < pj }" + % (sid_b, sid_b) ) isl_sched_map_before_expected = align_isl_maps_by_var_names( isl_sched_map_before_expected, isl_sched_map_before) isl_sched_map_after_expected = isl.Map( "[pi, pj] -> { " - "[statement = 1, i, j] -> [l0 = 0, l1 = i, l2 = 0, l3 = j, l4 = 0] : " + "[statement = %d, i, j] -> [l0 = 0, l1 = i, l2 = 0, l3 = j, l4 = %d] : " "0 <= i < pi and 0 <= j < pj }" + % (sid_c, sid_c) ) isl_sched_map_after_expected = align_isl_maps_by_var_names( isl_sched_map_after_expected, isl_sched_map_after) assert isl_sched_map_before == isl_sched_map_before_expected assert isl_sched_map_after == isl_sched_map_after_expected - elif lex_sched_bc.stmt_instance_before.stmt.int_id == 1: - # insn_c comes first - assert lex_sched_bc.stmt_instance_before.lex_pt == [0, 'i', 0, 'j', 1] - assert lex_sched_bc.stmt_instance_after.lex_pt == [0, 'i', 0, 'j', 0] + + if lex_sched_bc.stmt_instance_before.stmt.int_id == 0: + perform_insn_bc_checks_with(0, 1) + else: + perform_insn_bc_checks_with(1, 0) + + # ------------------------------------------------------------------------------ + # Relationship between insn_b and insn_d --------------------------------------- + + # insn_b and insn_d could have been linearized in either order + # (i loop could be before or after t loop) + def perform_insn_bd_checks_with(sid_b, sid_d): + assert lex_sched_bd.stmt_instance_before.lex_pt == [sid_b, 'i', 0, 'j', 0] + assert lex_sched_bd.stmt_instance_after.lex_pt == [sid_d, 't', 0, 0, 0] # Get two isl maps representing the LexSchedule isl_sched_map_before, isl_sched_map_after = \ - get_isl_maps_for_LexSchedule(lex_sched_bc, knl, "insn_b", "insn_c") + get_isl_maps_for_LexSchedule(lex_sched_bd, knl, "insn_b", "insn_d") # Create expected maps, align, compare isl_sched_map_before_expected = isl.Map( "[pi, pj] -> { " - "[statement = 1, i, j] -> [l0 = 0, l1 = i, l2 = 0, l3 = j, l4 = 1] : " + "[statement = %d, i, j] -> [l0 = %d, l1 = i, l2 = 0, l3 = j, l4 = 0] : " "0 <= i < pi and 0 <= j < pj }" + % (sid_b, sid_b) ) isl_sched_map_before_expected = align_isl_maps_by_var_names( isl_sched_map_before_expected, isl_sched_map_before) isl_sched_map_after_expected = isl.Map( - "[pi, pj] -> { " - "[statement = 0, i, j] -> [l0 = 0, l1 = i, l2 = 0, l3 = j, l4 = 0] : " - "0 <= i < pi and 0 <= j < pj }" + "[pt] -> { " + "[statement = %d, t] -> [l0 = %d, l1 = t, l2 = 0, l3 = 0, l4 = 0] : " + "0 <= t < pt }" + % (sid_d, sid_d) ) isl_sched_map_after_expected = align_isl_maps_by_var_names( isl_sched_map_after_expected, isl_sched_map_after) @@ -291,69 +315,52 @@ def test_lexschedule_and_islmap_creation(): assert isl_sched_map_before == isl_sched_map_before_expected assert isl_sched_map_after == isl_sched_map_after_expected - # ------------------------------------------------------------------------------ - # Relationship between insn_b and insn_d --------------------------------------- - - assert lex_sched_bd.stmt_instance_before.lex_pt == [0, 'i', 0, 'j', 0] - assert lex_sched_bd.stmt_instance_after.lex_pt == [1, 't', 0, 0, 0] - - # Get two isl maps representing the LexSchedule - - isl_sched_map_before, isl_sched_map_after = \ - get_isl_maps_for_LexSchedule(lex_sched_bd, knl, "insn_b", "insn_d") - - # Create expected maps, align, compare - - isl_sched_map_before_expected = isl.Map( - "[pi, pj] -> { " - "[statement = 0, i, j] -> [l0 = 0, l1 = i, l2 = 0, l3 = j, l4 = 0] : " - "0 <= i < pi and 0 <= j < pj }" - ) - isl_sched_map_before_expected = align_isl_maps_by_var_names( - isl_sched_map_before_expected, isl_sched_map_before) - - isl_sched_map_after_expected = isl.Map( - "[pt] -> { " - "[statement = 1, t] -> [l0 = 1, l1 = t, l2 = 0, l3 = 0, l4 = 0] : " - "0 <= t < pt }" - ) - isl_sched_map_after_expected = align_isl_maps_by_var_names( - isl_sched_map_after_expected, isl_sched_map_after) - - assert isl_sched_map_before == isl_sched_map_before_expected - assert isl_sched_map_after == isl_sched_map_after_expected + if lex_sched_bd.stmt_instance_before.stmt.int_id == 0: + perform_insn_bd_checks_with(0, 1) + else: + perform_insn_bd_checks_with(1, 0) # ------------------------------------------------------------------------------ # Relationship between insn_c and insn_d --------------------------------------- - assert lex_sched_cd.stmt_instance_before.lex_pt == [0, 'i', 0, 'j', 0] - assert lex_sched_cd.stmt_instance_after.lex_pt == [1, 't', 0, 0, 0] + # insn_c and insn_d could have been linearized in either order + # (i loop could be before or after t loop) + def perform_insn_cd_checks_with(sid_c, sid_d): + assert lex_sched_cd.stmt_instance_before.lex_pt == [sid_c, 'i', 0, 'j', 0] + assert lex_sched_cd.stmt_instance_after.lex_pt == [sid_d, 't', 0, 0, 0] - # Get two isl maps representing the LexSchedule + # Get two isl maps representing the LexSchedule - isl_sched_map_before, isl_sched_map_after = \ - get_isl_maps_for_LexSchedule(lex_sched_cd, knl, "insn_c", "insn_d") + isl_sched_map_before, isl_sched_map_after = \ + get_isl_maps_for_LexSchedule(lex_sched_cd, knl, "insn_c", "insn_d") - # Create expected maps, align, compare + # Create expected maps, align, compare - isl_sched_map_before_expected = isl.Map( - "[pi, pj] -> { " - "[statement = 0, i, j] -> [l0 = 0, l1 = i, l2 = 0, l3 = j, l4 = 0] : " - "0 <= i < pi and 0 <= j < pj }" - ) - isl_sched_map_before_expected = align_isl_maps_by_var_names( - isl_sched_map_before_expected, isl_sched_map_before) + isl_sched_map_before_expected = isl.Map( + "[pi, pj] -> { " + "[statement = %d, i, j] -> [l0 = %d, l1 = i, l2 = 0, l3 = j, l4 = 0] : " + "0 <= i < pi and 0 <= j < pj }" + % (sid_c, sid_c) + ) + isl_sched_map_before_expected = align_isl_maps_by_var_names( + isl_sched_map_before_expected, isl_sched_map_before) - isl_sched_map_after_expected = isl.Map( - "[pt] -> { " - "[statement = 1, t] -> [l0 = 1, l1 = t, l2 = 0, l3 = 0, l4 = 0] : " - "0 <= t < pt }" - ) - isl_sched_map_after_expected = align_isl_maps_by_var_names( - isl_sched_map_after_expected, isl_sched_map_after) + isl_sched_map_after_expected = isl.Map( + "[pt] -> { " + "[statement = %d, t] -> [l0 = %d, l1 = t, l2 = 0, l3 = 0, l4 = 0] : " + "0 <= t < pt }" + % (sid_d, sid_d) + ) + isl_sched_map_after_expected = align_isl_maps_by_var_names( + isl_sched_map_after_expected, isl_sched_map_after) - assert isl_sched_map_before == isl_sched_map_before_expected - assert isl_sched_map_after == isl_sched_map_after_expected + assert isl_sched_map_before == isl_sched_map_before_expected + assert isl_sched_map_after == isl_sched_map_after_expected + + if lex_sched_cd.stmt_instance_before.stmt.int_id == 0: + perform_insn_cd_checks_with(0, 1) + else: + perform_insn_cd_checks_with(1, 0) if __name__ == "__main__": -- GitLab From de3f00ce791dc98c884d6c705351f4bfd9beb9b8 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 26 Apr 2020 18:49:49 -0500 Subject: [PATCH 018/136] updated LexSchedule documentation --- loopy/schedule/checker/schedule.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 0aca588c3..e8e009169 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -107,8 +107,10 @@ class LexScheduleStatementInstance(object): class LexSchedule(object): - """A program ordering represented as a mapping from statement - instances to points in a lexicographic ordering. + """Given a pair of statements in a linearized kernel, LexSchedule + determines the (relative) order in which the instances are executed, + by creating a mapping from statement instances to points in a single + lexicographic ordering. .. attribute:: stmt_instance_before -- GitLab From 948ada80d26df2fec69eefb58d985c979524cdb9 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 26 Apr 2020 18:52:59 -0500 Subject: [PATCH 019/136] simplify+shorten code for getting+returning maps from schedule --- loopy/schedule/checker/__init__.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 2911351b2..260864aff 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -147,13 +147,7 @@ def get_isl_maps_for_LexSchedule( # }}} # {{{ Get isl maps - isl_sched_map_before, isl_sched_map_after = \ - lex_sched.create_isl_maps( - dom_before, - dom_after, - ) + return lex_sched.create_isl_maps(dom_before, dom_after) # }}} - return isl_sched_map_before, isl_sched_map_after - # }}} -- GitLab From 217d480ffc2222e8de0ff01638f4f6f78f51e26b Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 26 Apr 2020 19:01:30 -0500 Subject: [PATCH 020/136] remove underscores from function names if functions are used in separate module --- loopy/schedule/checker/__init__.py | 4 ++-- loopy/schedule/checker/schedule.py | 4 ++-- loopy/schedule/checker/utils.py | 5 ++--- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 260864aff..79fc2e0e8 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -78,10 +78,10 @@ def get_schedule_for_statement_pair( # Test which exercises this: test_linearization_checker_with_stroud_bernstein()) from loopy.schedule.checker.utils import ( get_concurrent_inames, - _get_EnterLoop_inames, + get_EnterLoop_inames, ) conc_inames, _ = get_concurrent_inames(preproc_knl) - enterloop_inames = _get_EnterLoop_inames(linearization_items, preproc_knl) + enterloop_inames = get_EnterLoop_inames(linearization_items, preproc_knl) conc_loop_inames = conc_inames & enterloop_inames if conc_loop_inames: from warnings import warn diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index e8e009169..e868f5b19 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -230,9 +230,9 @@ class LexSchedule(object): stmt_added_since_prev_block_at_tier[-1] = False elif isinstance(linearization_item, (RunInstruction, Barrier)): from loopy.schedule.checker.utils import ( - _get_insn_id_from_linearization_item, + get_insn_id_from_linearization_item, ) - lp_insn_id = _get_insn_id_from_linearization_item(linearization_item) + lp_insn_id = get_insn_id_from_linearization_item(linearization_item) if lp_insn_id is None: # TODO make sure it's okay to ignore barriers without id # (because they'll never be part of a dependency?) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index cb933de6f..b6a5487b0 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -310,8 +310,7 @@ def get_concurrent_inames(knl): return conc_inames, all_inames-conc_inames -def _get_insn_id_from_linearization_item(linearization_item): - # TODO could use loopy's sched_item_to_insn_id() +def get_insn_id_from_linearization_item(linearization_item): from loopy.schedule import Barrier if isinstance(linearization_item, Barrier): return linearization_item.originating_insn_id @@ -319,7 +318,7 @@ def _get_insn_id_from_linearization_item(linearization_item): return linearization_item.insn_id -def _get_EnterLoop_inames(linearization_items, knl): +def get_EnterLoop_inames(linearization_items, knl): from loopy.schedule import EnterLoop loop_inames = set() for linearization_item in linearization_items: -- GitLab From 70ec6a1bae5fbec9c1ef9b69415c24a079b8b385 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 26 Apr 2020 19:27:40 -0500 Subject: [PATCH 021/136] don't pass before/after insn_ids to get_isl_maps_for_LexSchedule(), instead get them from LexSchedule --- loopy/schedule/checker/__init__.py | 21 +++++---------------- test/test_linearization_checker.py | 24 ++++++++++++------------ 2 files changed, 17 insertions(+), 28 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 79fc2e0e8..68ca2e1a0 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -108,12 +108,7 @@ def get_schedule_for_statement_pair( # {{{ Get isl map pair for LexSchedule -def get_isl_maps_for_LexSchedule( - lex_sched, - knl, - insn_id_before, - insn_id_after, - ): +def get_isl_maps_for_LexSchedule(lex_sched, knl): """Create a pair of :class:`islpy.Map`s representing a :class:`loopy.schedule.checker.LexSchedule` as two mappings from statement instances to lexicographic time, one for @@ -127,12 +122,6 @@ def get_isl_maps_for_LexSchedule( :arg knl: A :class:`loopy.kernel.LoopKernel` containing the linearization items that will be used to create a schedule. - :arg insn_id_before: An instruction identifier that is unique within - a :class:`loopy.kernel.LoopKernel`. - - :arg insn_id_after: An instruction identifier that is unique within - a :class:`loopy.kernel.LoopKernel`. - :returns: A two-tuple containing two :class:`islpy.Map`s representing the schedule as two mappings from statement instances to lexicographic time, one for @@ -140,10 +129,10 @@ def get_isl_maps_for_LexSchedule( """ # {{{ Get iname domains - insn_before_inames = knl.id_to_insn[insn_id_before].within_inames - insn_after_inames = knl.id_to_insn[insn_id_after].within_inames - dom_before = knl.get_inames_domain(insn_before_inames) - dom_after = knl.get_inames_domain(insn_after_inames) + dom_before = knl.get_inames_domain( + knl.id_to_insn[lex_sched.stmt_instance_before.stmt.insn_id].within_inames) + dom_after = knl.get_inames_domain( + knl.id_to_insn[lex_sched.stmt_instance_after.stmt.insn_id].within_inames) # }}} # {{{ Get isl maps diff --git a/test/test_linearization_checker.py b/test/test_linearization_checker.py index c112b40ae..ed936a1ff 100644 --- a/test/test_linearization_checker.py +++ b/test/test_linearization_checker.py @@ -138,8 +138,8 @@ def test_lexschedule_and_islmap_creation(): # Get two isl maps representing the LexSchedule - isl_sched_map_before, isl_sched_map_after = \ - get_isl_maps_for_LexSchedule(lex_sched_ab, knl, "insn_a", "insn_b") + isl_sched_map_before, isl_sched_map_after = get_isl_maps_for_LexSchedule( + lex_sched_ab, knl) # Create expected maps, align, compare @@ -170,8 +170,8 @@ def test_lexschedule_and_islmap_creation(): # Get two isl maps representing the LexSchedule - isl_sched_map_before, isl_sched_map_after = \ - get_isl_maps_for_LexSchedule(lex_sched_ac, knl, "insn_a", "insn_c") + isl_sched_map_before, isl_sched_map_after = get_isl_maps_for_LexSchedule( + lex_sched_ac, knl) # Create expected maps, align, compare @@ -205,8 +205,8 @@ def test_lexschedule_and_islmap_creation(): # Get two isl maps representing the LexSchedule - isl_sched_map_before, isl_sched_map_after = \ - get_isl_maps_for_LexSchedule(lex_sched_ad, knl, "insn_a", "insn_d") + isl_sched_map_before, isl_sched_map_after = get_isl_maps_for_LexSchedule( + lex_sched_ad, knl) # Create expected maps, align, compare @@ -247,8 +247,8 @@ def test_lexschedule_and_islmap_creation(): # Get two isl maps representing the LexSchedule - isl_sched_map_before, isl_sched_map_after = \ - get_isl_maps_for_LexSchedule(lex_sched_bc, knl, "insn_b", "insn_c") + isl_sched_map_before, isl_sched_map_after = get_isl_maps_for_LexSchedule( + lex_sched_bc, knl) # Create expected maps, align, compare @@ -289,8 +289,8 @@ def test_lexschedule_and_islmap_creation(): # Get two isl maps representing the LexSchedule - isl_sched_map_before, isl_sched_map_after = \ - get_isl_maps_for_LexSchedule(lex_sched_bd, knl, "insn_b", "insn_d") + isl_sched_map_before, isl_sched_map_after = get_isl_maps_for_LexSchedule( + lex_sched_bd, knl) # Create expected maps, align, compare @@ -331,8 +331,8 @@ def test_lexschedule_and_islmap_creation(): # Get two isl maps representing the LexSchedule - isl_sched_map_before, isl_sched_map_after = \ - get_isl_maps_for_LexSchedule(lex_sched_cd, knl, "insn_c", "insn_d") + isl_sched_map_before, isl_sched_map_after = get_isl_maps_for_LexSchedule( + lex_sched_cd, knl) # Create expected maps, align, compare -- GitLab From af72169557b38b5bd26e69e80d657fb0d401aeac Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 27 Apr 2020 18:05:25 -0500 Subject: [PATCH 022/136] add TODO for future consideration of generalizing LexSchedule to allow more than two statements --- loopy/schedule/checker/schedule.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index e868f5b19..5edeecaab 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -171,6 +171,8 @@ class LexSchedule(object): # LexScheduleStatements self.stmt_instance_before = None self.stmt_instance_after = None + # TODO when/after dependencies are added, consider the possibility + # of removing the two-statements-per-LexSchedule limitation # make sure we don't have an iname name conflict # TODO use loopy's existing tool for ensuring unique var names -- GitLab From 98d744dda96fd835e38ba400d5dbc75f9f076a58 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 4 May 2020 23:25:37 -0500 Subject: [PATCH 023/136] remove no-longer-used arg from create_symbolic_isl_map_from_tuples() --- loopy/schedule/checker/schedule.py | 1 - loopy/schedule/checker/utils.py | 4 ---- 2 files changed, 5 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 5edeecaab..4138336b0 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -391,7 +391,6 @@ class LexSchedule(object): return create_symbolic_isl_map_from_tuples( tuple_pairs_with_domains=zip(tuple_pair, dom_to_intersect), space=sched_space, - statement_var_name=self.statement_var_name, ) map_before = _get_isl_map_for_stmt_inst( diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index b6a5487b0..0728e9686 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -162,7 +162,6 @@ def list_var_names_in_isl_sets( def create_symbolic_isl_map_from_tuples( tuple_pairs_with_domains, space, - statement_var_name, ): """Return an :class:`islpy.Map` constructed using the provided space, mapping input->output tuples provided in `tuple_pairs_with_domains`, @@ -177,9 +176,6 @@ def create_symbolic_isl_map_from_tuples( :arg space: A :class:`islpy.Space` to be used to create the map. - :arg statement_var_name: A :class:`str` specifying the name of the - isl variable used to represent the unique :class:`int` statement id. - :returns: A :class:`islpy.Map` constructed using the provided space as follows. For each `((tup_in, tup_out), domain)` in `tuple_pairs_with_domains`, map -- GitLab From ef79ff1deb95192dc2322b3b86aec3a3e1669f5a Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 5 May 2020 11:21:20 -0500 Subject: [PATCH 024/136] make var names begin wtih and remove variable/check --- loopy/schedule/checker/__init__.py | 11 --------- loopy/schedule/checker/schedule.py | 14 ++---------- test/test_linearization_checker.py | 36 ++++++++++++++++++++---------- 3 files changed, 26 insertions(+), 35 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 68ca2e1a0..3215201ae 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -28,7 +28,6 @@ def get_schedule_for_statement_pair( linearization_items, insn_id_before, insn_id_after, - prohibited_var_names=set(), ): """Create a :class:`loopy.schedule.checker.schedule.LexSchedule` representing the order of two statements as a mapping from @@ -51,10 +50,6 @@ def get_schedule_for_statement_pair( :arg insn_id_after: An instruction identifier that is unique within a :class:`loopy.kernel.LoopKernel`. - :arg prohibited_var_names: A set of :class:`str` representing - variable names that should not be used when creating names for - dimensions in a :class:`loopy.schedule.checker.LexSchedule`. - :returns: A :class:`loopy.schedule.checker.schedule.LexSchedule` representing the order of two statements as a mapping from :class:`loopy.schedule.checker.LexScheduleStatementInstance` @@ -66,11 +61,6 @@ def get_schedule_for_statement_pair( preproc_knl = preprocess_kernel(knl) # }}} - # {{{ By default, don't create LexSchedule variables matching existing inames - if not prohibited_var_names: - prohibited_var_names = preproc_knl.all_inames() - # }}} - # {{{ Find any EnterLoop inames that are tagged as concurrent # so that LexSchedule knows to ignore them # (In the future, this shouldn't be necessary because there @@ -98,7 +88,6 @@ def get_schedule_for_statement_pair( linearization_items, insn_id_before, insn_id_after, - prohibited_var_names=prohibited_var_names, loops_to_ignore=conc_loop_inames, ) # }}} diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 4138336b0..49c9e0a01 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -141,15 +141,14 @@ class LexSchedule(object): """ - statement_var_name = "statement" - lex_var_prefix = "l" + statement_var_name = "_lp_statement" + lex_var_prefix = "_lp_l" def __init__( self, linearization_items_ordered, before_insn_id, after_insn_id, - prohibited_var_names=[], loops_to_ignore=set(), ): """ @@ -162,10 +161,6 @@ class LexSchedule(object): :arg after_insn_id: A :class:`str` instruction id specifying the depender in this pair of instructions. - :arg prohibited_var_names: A list of :class:`str` variable names - that may not be used as the statement variable name (e.g., - because they are already being used as inames). - """ # LexScheduleStatements @@ -174,11 +169,6 @@ class LexSchedule(object): # TODO when/after dependencies are added, consider the possibility # of removing the two-statements-per-LexSchedule limitation - # make sure we don't have an iname name conflict - # TODO use loopy's existing tool for ensuring unique var names - assert not any( - iname == self.statement_var_name for iname in prohibited_var_names) - from loopy.schedule import (EnterLoop, LeaveLoop, Barrier, RunInstruction) # go through linearization_items_ordered and generate self.lex_schedule diff --git a/test/test_linearization_checker.py b/test/test_linearization_checker.py index ed936a1ff..39a73718f 100644 --- a/test/test_linearization_checker.py +++ b/test/test_linearization_checker.py @@ -145,7 +145,8 @@ def test_lexschedule_and_islmap_creation(): isl_sched_map_before_expected = isl.Map( "[pi, pk] -> { " - "[statement = 0, i, k] -> [l0 = 0, l1 = i, l2 = 0, l3 = k, l4 = 0] : " + "[_lp_statement=0, i, k] -> " + "[_lp_l0=0, _lp_l1=i, _lp_l2=0, _lp_l3=k, _lp_l4=0] : " "0 <= i < pi and 0 <= k < pk }" ) isl_sched_map_before_expected = align_isl_maps_by_var_names( @@ -153,7 +154,8 @@ def test_lexschedule_and_islmap_creation(): isl_sched_map_after_expected = isl.Map( "[pi, pj] -> { " - "[statement = 1, i, j] -> [l0 = 0, l1 = i, l2 = 1, l3 = j, l4 = 0] : " + "[_lp_statement=1, i, j] -> " + "[_lp_l0=0, _lp_l1=i, _lp_l2=1, _lp_l3=j, _lp_l4=0] : " "0 <= i < pi and 0 <= j < pj }" ) isl_sched_map_after_expected = align_isl_maps_by_var_names( @@ -177,7 +179,8 @@ def test_lexschedule_and_islmap_creation(): isl_sched_map_before_expected = isl.Map( "[pi, pk] -> { " - "[statement = 0, i, k] -> [l0 = 0, l1 = i, l2 = 0, l3 = k, l4 = 0] : " + "[_lp_statement=0, i, k] -> " + "[_lp_l0=0, _lp_l1=i, _lp_l2=0, _lp_l3=k, _lp_l4=0] : " "0 <= i < pi and 0 <= k < pk }" ) isl_sched_map_before_expected = align_isl_maps_by_var_names( @@ -185,7 +188,8 @@ def test_lexschedule_and_islmap_creation(): isl_sched_map_after_expected = isl.Map( "[pi, pj] -> { " - "[statement = 1, i, j] -> [l0 = 0, l1 = i, l2 = 1, l3 = j, l4 = 0] : " + "[_lp_statement=1, i, j] -> " + "[_lp_l0=0, _lp_l1=i, _lp_l2=1, _lp_l3=j, _lp_l4=0] : " "0 <= i < pi and 0 <= j < pj }" ) isl_sched_map_after_expected = align_isl_maps_by_var_names( @@ -212,7 +216,8 @@ def test_lexschedule_and_islmap_creation(): isl_sched_map_before_expected = isl.Map( "[pi, pk] -> { " - "[statement = %d, i, k] -> [l0 = %d, l1 = i, l2 = 0, l3 = k, l4 = 0] : " + "[_lp_statement=%d, i, k] -> " + "[_lp_l0=%d, _lp_l1=i, _lp_l2=0, _lp_l3=k, _lp_l4=0] : " "0 <= i < pi and 0 <= k < pk }" % (sid_a, sid_a) ) @@ -221,7 +226,8 @@ def test_lexschedule_and_islmap_creation(): isl_sched_map_after_expected = isl.Map( "[pt] -> { " - "[statement = %d, t] -> [l0 = %d, l1 = t, l2 = 0, l3 = 0, l4 = 0] : " + "[_lp_statement=%d, t] -> " + "[_lp_l0=%d, _lp_l1=t, _lp_l2=0, _lp_l3=0, _lp_l4=0] : " "0 <= t < pt }" % (sid_d, sid_d) ) @@ -254,7 +260,8 @@ def test_lexschedule_and_islmap_creation(): isl_sched_map_before_expected = isl.Map( "[pi, pj] -> { " - "[statement = %d, i, j] -> [l0 = 0, l1 = i, l2 = 0, l3 = j, l4 = %d] : " + "[_lp_statement=%d, i, j] -> " + "[_lp_l0=0, _lp_l1=i, _lp_l2=0, _lp_l3=j, _lp_l4=%d] : " "0 <= i < pi and 0 <= j < pj }" % (sid_b, sid_b) ) @@ -263,7 +270,8 @@ def test_lexschedule_and_islmap_creation(): isl_sched_map_after_expected = isl.Map( "[pi, pj] -> { " - "[statement = %d, i, j] -> [l0 = 0, l1 = i, l2 = 0, l3 = j, l4 = %d] : " + "[_lp_statement=%d, i, j] -> " + "[_lp_l0=0, _lp_l1=i, _lp_l2=0, _lp_l3=j, _lp_l4=%d] : " "0 <= i < pi and 0 <= j < pj }" % (sid_c, sid_c) ) @@ -296,7 +304,8 @@ def test_lexschedule_and_islmap_creation(): isl_sched_map_before_expected = isl.Map( "[pi, pj] -> { " - "[statement = %d, i, j] -> [l0 = %d, l1 = i, l2 = 0, l3 = j, l4 = 0] : " + "[_lp_statement=%d, i, j] -> " + "[_lp_l0=%d, _lp_l1=i, _lp_l2=0, _lp_l3=j, _lp_l4=0] : " "0 <= i < pi and 0 <= j < pj }" % (sid_b, sid_b) ) @@ -305,7 +314,8 @@ def test_lexschedule_and_islmap_creation(): isl_sched_map_after_expected = isl.Map( "[pt] -> { " - "[statement = %d, t] -> [l0 = %d, l1 = t, l2 = 0, l3 = 0, l4 = 0] : " + "[_lp_statement=%d, t] -> " + "[_lp_l0=%d, _lp_l1=t, _lp_l2=0, _lp_l3=0, _lp_l4=0] : " "0 <= t < pt }" % (sid_d, sid_d) ) @@ -338,7 +348,8 @@ def test_lexschedule_and_islmap_creation(): isl_sched_map_before_expected = isl.Map( "[pi, pj] -> { " - "[statement = %d, i, j] -> [l0 = %d, l1 = i, l2 = 0, l3 = j, l4 = 0] : " + "[_lp_statement=%d, i, j] -> " + "[_lp_l0=%d, _lp_l1=i, _lp_l2=0, _lp_l3=j, _lp_l4=0] : " "0 <= i < pi and 0 <= j < pj }" % (sid_c, sid_c) ) @@ -347,7 +358,8 @@ def test_lexschedule_and_islmap_creation(): isl_sched_map_after_expected = isl.Map( "[pt] -> { " - "[statement = %d, t] -> [l0 = %d, l1 = t, l2 = 0, l3 = 0, l4 = 0] : " + "[_lp_statement=%d, t] -> " + "[_lp_l0=%d, _lp_l1=t, _lp_l2=0, _lp_l3=0, _lp_l4=0] : " "0 <= t < pt }" % (sid_d, sid_d) ) -- GitLab From ec11b2f65f4825f2e0526e1418d8a8e7b0ad1355 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 5 May 2020 12:40:02 -0500 Subject: [PATCH 025/136] change _lp previx to _lp_sched (add sub-prefix) --- loopy/schedule/checker/schedule.py | 4 +- test/test_linearization_checker.py | 60 ++++++++++++++++++------------ 2 files changed, 38 insertions(+), 26 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 49c9e0a01..6cabaf1be 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -141,8 +141,8 @@ class LexSchedule(object): """ - statement_var_name = "_lp_statement" - lex_var_prefix = "_lp_l" + statement_var_name = "_lp_sched_statement" + lex_var_prefix = "_lp_sched_l" def __init__( self, diff --git a/test/test_linearization_checker.py b/test/test_linearization_checker.py index 39a73718f..0dfb2fc90 100644 --- a/test/test_linearization_checker.py +++ b/test/test_linearization_checker.py @@ -145,8 +145,9 @@ def test_lexschedule_and_islmap_creation(): isl_sched_map_before_expected = isl.Map( "[pi, pk] -> { " - "[_lp_statement=0, i, k] -> " - "[_lp_l0=0, _lp_l1=i, _lp_l2=0, _lp_l3=k, _lp_l4=0] : " + "[_lp_sched_statement=0, i, k] -> " + "[_lp_sched_l0=0, _lp_sched_l1=i, _lp_sched_l2=0, _lp_sched_l3=k, " + "_lp_sched_l4=0] : " "0 <= i < pi and 0 <= k < pk }" ) isl_sched_map_before_expected = align_isl_maps_by_var_names( @@ -154,8 +155,9 @@ def test_lexschedule_and_islmap_creation(): isl_sched_map_after_expected = isl.Map( "[pi, pj] -> { " - "[_lp_statement=1, i, j] -> " - "[_lp_l0=0, _lp_l1=i, _lp_l2=1, _lp_l3=j, _lp_l4=0] : " + "[_lp_sched_statement=1, i, j] -> " + "[_lp_sched_l0=0, _lp_sched_l1=i, _lp_sched_l2=1, _lp_sched_l3=j, " + "_lp_sched_l4=0] : " "0 <= i < pi and 0 <= j < pj }" ) isl_sched_map_after_expected = align_isl_maps_by_var_names( @@ -179,8 +181,9 @@ def test_lexschedule_and_islmap_creation(): isl_sched_map_before_expected = isl.Map( "[pi, pk] -> { " - "[_lp_statement=0, i, k] -> " - "[_lp_l0=0, _lp_l1=i, _lp_l2=0, _lp_l3=k, _lp_l4=0] : " + "[_lp_sched_statement=0, i, k] -> " + "[_lp_sched_l0=0, _lp_sched_l1=i, _lp_sched_l2=0, _lp_sched_l3=k, " + "_lp_sched_l4=0] : " "0 <= i < pi and 0 <= k < pk }" ) isl_sched_map_before_expected = align_isl_maps_by_var_names( @@ -188,8 +191,9 @@ def test_lexschedule_and_islmap_creation(): isl_sched_map_after_expected = isl.Map( "[pi, pj] -> { " - "[_lp_statement=1, i, j] -> " - "[_lp_l0=0, _lp_l1=i, _lp_l2=1, _lp_l3=j, _lp_l4=0] : " + "[_lp_sched_statement=1, i, j] -> " + "[_lp_sched_l0=0, _lp_sched_l1=i, _lp_sched_l2=1, _lp_sched_l3=j, " + "_lp_sched_l4=0] : " "0 <= i < pi and 0 <= j < pj }" ) isl_sched_map_after_expected = align_isl_maps_by_var_names( @@ -216,8 +220,9 @@ def test_lexschedule_and_islmap_creation(): isl_sched_map_before_expected = isl.Map( "[pi, pk] -> { " - "[_lp_statement=%d, i, k] -> " - "[_lp_l0=%d, _lp_l1=i, _lp_l2=0, _lp_l3=k, _lp_l4=0] : " + "[_lp_sched_statement=%d, i, k] -> " + "[_lp_sched_l0=%d, _lp_sched_l1=i, _lp_sched_l2=0, _lp_sched_l3=k, " + "_lp_sched_l4=0] : " "0 <= i < pi and 0 <= k < pk }" % (sid_a, sid_a) ) @@ -226,8 +231,9 @@ def test_lexschedule_and_islmap_creation(): isl_sched_map_after_expected = isl.Map( "[pt] -> { " - "[_lp_statement=%d, t] -> " - "[_lp_l0=%d, _lp_l1=t, _lp_l2=0, _lp_l3=0, _lp_l4=0] : " + "[_lp_sched_statement=%d, t] -> " + "[_lp_sched_l0=%d, _lp_sched_l1=t, _lp_sched_l2=0, _lp_sched_l3=0, " + "_lp_sched_l4=0] : " "0 <= t < pt }" % (sid_d, sid_d) ) @@ -260,8 +266,9 @@ def test_lexschedule_and_islmap_creation(): isl_sched_map_before_expected = isl.Map( "[pi, pj] -> { " - "[_lp_statement=%d, i, j] -> " - "[_lp_l0=0, _lp_l1=i, _lp_l2=0, _lp_l3=j, _lp_l4=%d] : " + "[_lp_sched_statement=%d, i, j] -> " + "[_lp_sched_l0=0, _lp_sched_l1=i, _lp_sched_l2=0, _lp_sched_l3=j, " + "_lp_sched_l4=%d] : " "0 <= i < pi and 0 <= j < pj }" % (sid_b, sid_b) ) @@ -270,8 +277,9 @@ def test_lexschedule_and_islmap_creation(): isl_sched_map_after_expected = isl.Map( "[pi, pj] -> { " - "[_lp_statement=%d, i, j] -> " - "[_lp_l0=0, _lp_l1=i, _lp_l2=0, _lp_l3=j, _lp_l4=%d] : " + "[_lp_sched_statement=%d, i, j] -> " + "[_lp_sched_l0=0, _lp_sched_l1=i, _lp_sched_l2=0, _lp_sched_l3=j, " + "_lp_sched_l4=%d] : " "0 <= i < pi and 0 <= j < pj }" % (sid_c, sid_c) ) @@ -304,8 +312,9 @@ def test_lexschedule_and_islmap_creation(): isl_sched_map_before_expected = isl.Map( "[pi, pj] -> { " - "[_lp_statement=%d, i, j] -> " - "[_lp_l0=%d, _lp_l1=i, _lp_l2=0, _lp_l3=j, _lp_l4=0] : " + "[_lp_sched_statement=%d, i, j] -> " + "[_lp_sched_l0=%d, _lp_sched_l1=i, _lp_sched_l2=0, _lp_sched_l3=j, " + "_lp_sched_l4=0] : " "0 <= i < pi and 0 <= j < pj }" % (sid_b, sid_b) ) @@ -314,8 +323,9 @@ def test_lexschedule_and_islmap_creation(): isl_sched_map_after_expected = isl.Map( "[pt] -> { " - "[_lp_statement=%d, t] -> " - "[_lp_l0=%d, _lp_l1=t, _lp_l2=0, _lp_l3=0, _lp_l4=0] : " + "[_lp_sched_statement=%d, t] -> " + "[_lp_sched_l0=%d, _lp_sched_l1=t, _lp_sched_l2=0, _lp_sched_l3=0, " + "_lp_sched_l4=0] : " "0 <= t < pt }" % (sid_d, sid_d) ) @@ -348,8 +358,9 @@ def test_lexschedule_and_islmap_creation(): isl_sched_map_before_expected = isl.Map( "[pi, pj] -> { " - "[_lp_statement=%d, i, j] -> " - "[_lp_l0=%d, _lp_l1=i, _lp_l2=0, _lp_l3=j, _lp_l4=0] : " + "[_lp_sched_statement=%d, i, j] -> " + "[_lp_sched_l0=%d, _lp_sched_l1=i, _lp_sched_l2=0, _lp_sched_l3=j, " + "_lp_sched_l4=0] : " "0 <= i < pi and 0 <= j < pj }" % (sid_c, sid_c) ) @@ -358,8 +369,9 @@ def test_lexschedule_and_islmap_creation(): isl_sched_map_after_expected = isl.Map( "[pt] -> { " - "[_lp_statement=%d, t] -> " - "[_lp_l0=%d, _lp_l1=t, _lp_l2=0, _lp_l3=0, _lp_l4=0] : " + "[_lp_sched_statement=%d, t] -> " + "[_lp_sched_l0=%d, _lp_sched_l1=t, _lp_sched_l2=0, _lp_sched_l3=0, " + "_lp_sched_l4=0] : " "0 <= t < pt }" % (sid_d, sid_d) ) -- GitLab From 767e821c7cc56331230c61e7d2193dbb6860394f Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 25 May 2020 02:22:26 -0500 Subject: [PATCH 026/136] in docstring for LexScheduleStatement, describe usage of int_id --- loopy/schedule/checker/schedule.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 6cabaf1be..bbea293a2 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -28,11 +28,17 @@ class LexScheduleStatement(object): .. attribute:: insn_id - A :class:`str` specifying the instruction id. + A :class:`str` specifying the :mod:`loopy` instruction id + for this statement. .. attribute:: int_id - A :class:`int` uniquely identifying the instruction. + A :class:`int` uniquely identifying the statement within a + :class:`LexSchedule`. A :class:`LexSchedule` describes a mapping + from points in a space of statement instances to points in a + lexicographic ordering. The `statement` dimension of a point + in the statement instance space representing an instance of this + statement is assigned this value (`int_id`). .. attribute:: within_inames -- GitLab From 9d52cc98da397f5ae0987cead564dc427e105459 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 25 May 2020 02:47:29 -0500 Subject: [PATCH 027/136] remove within_inames attribute from LexScheduleStatement() --- loopy/schedule/checker/schedule.py | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index bbea293a2..7f808abd5 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -40,28 +40,20 @@ class LexScheduleStatement(object): in the statement instance space representing an instance of this statement is assigned this value (`int_id`). - .. attribute:: within_inames - - A :class:`list` of :class:`str` inames identifying the loops within - which this statement will be executed. - """ def __init__( self, insn_id, # loopy insn id int_id=None, # sid int (statement id within LexSchedule) - within_inames=None, # [string, ] ): self.insn_id = insn_id # string self.int_id = int_id - self.within_inames = within_inames def __eq__(self, other): return ( self.insn_id == other.insn_id and self.int_id == other.int_id - and self.within_inames == other.within_inames ) def update_persistent_hash(self, key_hash, key_builder): @@ -71,19 +63,13 @@ class LexScheduleStatement(object): key_builder.rec(key_hash, self.insn_id) key_builder.rec(key_hash, self.int_id) - key_builder.rec(key_hash, self.within_inames) def __str__(self): if self.int_id is not None: int_id = ":%d" % (self.int_id) else: int_id = "" - if self.within_inames: - within_inames = " {%s}" % (",".join(self.within_inames)) - else: - within_inames = "" - return "%s%s%s" % ( - self.insn_id, int_id, within_inames) + return "%s%s" % (self.insn_id, int_id) class LexScheduleStatementInstance(object): -- GitLab From a19113153a84148545c08837c2055a774b5f3e75 Mon Sep 17 00:00:00 2001 From: James Stevens Date: Mon, 25 May 2020 10:19:25 +0200 Subject: [PATCH 028/136] Apply suggestion to loopy/schedule/checker/schedule.py --- loopy/schedule/checker/schedule.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 7f808abd5..ea3181b66 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -73,7 +73,7 @@ class LexScheduleStatement(object): class LexScheduleStatementInstance(object): - """A representation of a :mod:`loopy` statement instance. + """A representation of a statement instance. .. attribute:: stmt -- GitLab From bcef27aa953a07b5fcb49e1c92449bc041d22699 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 25 May 2020 21:12:31 -0500 Subject: [PATCH 029/136] rename {lex_pt->lex_points, pad_lex_pts_with_zeros->pad_lex_tuples_with_zeros, _pad_lex_pt_with_zeros->_pad_lex_tuple_with_zeros, next_insn_lex_pt->next_insn_lex_tuple}; lex_pt actually describes multiple points, not a single point --- loopy/schedule/checker/schedule.py | 70 +++++++++++++++--------------- test/test_linearization_checker.py | 56 ++++++++++++------------ 2 files changed, 63 insertions(+), 63 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index ea3181b66..052a47afe 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -79,7 +79,7 @@ class LexScheduleStatementInstance(object): A :class:`LexScheduleStatement`. - .. attribute:: lex_pt + .. attribute:: lex_points A list of :class:`int` or as :class:`str` :mod:`loopy` inames representing a point or set of points in a lexicographic ordering. @@ -89,13 +89,13 @@ class LexScheduleStatementInstance(object): def __init__( self, stmt, # a LexScheduleStatement - lex_pt, # [string/int, ] + lex_points, # [string/int, ] ): self.stmt = stmt - self.lex_pt = lex_pt + self.lex_points = lex_points def __str__(self): - return "{%s, %s}" % (self.stmt, self.lex_pt) + return "{%s, %s}" % (self.stmt, self.lex_points) class LexSchedule(object): @@ -167,7 +167,7 @@ class LexSchedule(object): # keep track of the next point in our lexicographic ordering # initially this as a 1-d point with value 0 - next_insn_lex_pt = [0] + next_insn_lex_tuple = [0] stmt_added_since_prev_block_at_tier = [False] next_sid = 0 for linearization_item in linearization_items_ordered: @@ -176,13 +176,13 @@ class LexSchedule(object): if iname in loops_to_ignore: continue - # We could always increment next_insn_lex_pt[-1] here since this new - # section of code comes after the previous section (statements - # since last opened/closed loop), but if we have not added any - # statements within the previous section yet, we don't have to - # (effectively ignoring that section of code). + # We could always increment next_insn_lex_tuple[-1] here since + # this new section of code comes after the previous section + # (statements since last opened/closed loop), but if we have + # not added any statements within the previous section yet, we + # don't have to (effectively ignoring that section of code). if stmt_added_since_prev_block_at_tier[-1]: - next_insn_lex_pt[-1] = next_insn_lex_pt[-1]+1 + next_insn_lex_tuple[-1] = next_insn_lex_tuple[-1]+1 stmt_added_since_prev_block_at_tier[-1] = False # upon entering a loop, we enter a new (deeper) tier, @@ -190,8 +190,8 @@ class LexSchedule(object): # add second lex dim to enumerate code blocks within new loop, and # append a dim to stmt_added_since_prev_block_at_tier to represent # new tier - next_insn_lex_pt.append(iname) - next_insn_lex_pt.append(0) + next_insn_lex_tuple.append(iname) + next_insn_lex_tuple.append(0) stmt_added_since_prev_block_at_tier.append(False) elif isinstance(linearization_item, LeaveLoop): if linearization_item.iname in loops_to_ignore: @@ -200,17 +200,17 @@ class LexSchedule(object): # pop lex dimension for enumerating code blocks within this loop, and # pop lex dimension for the loop variable, and # increment lex dim val enumerating items in current code block - next_insn_lex_pt.pop() - next_insn_lex_pt.pop() - - # We could always increment next_insn_lex_pt[-1] here since this new - # block of code comes after the previous block (all statements - # since last opened/closed loop), but if we have not added any - # statements within the previous section yet, we don't have to - # (effectively ignoring that section of code). + next_insn_lex_tuple.pop() + next_insn_lex_tuple.pop() + + # We could always increment next_insn_lex_tuple[-1] here since + # this new block of code comes after the previous block (all + # statements since last opened/closed loop), but if we have not + # added any statements within the previous section yet, we + # don't have to (effectively ignoring that section of code). stmt_added_since_prev_block_at_tier.pop() if stmt_added_since_prev_block_at_tier[-1]: - next_insn_lex_pt[-1] = next_insn_lex_pt[-1]+1 + next_insn_lex_tuple[-1] = next_insn_lex_tuple[-1]+1 stmt_added_since_prev_block_at_tier[-1] = False elif isinstance(linearization_item, (RunInstruction, Barrier)): from loopy.schedule.checker.utils import ( @@ -234,7 +234,7 @@ class LexSchedule(object): insn_id=lp_insn_id, int_id=next_sid, # int representing insn ), - next_insn_lex_pt[:]) + next_insn_lex_tuple[:]) stmt_added = True if lp_insn_id == after_insn_id: @@ -244,7 +244,7 @@ class LexSchedule(object): insn_id=lp_insn_id, int_id=next_sid, # int representing insn ), - next_insn_lex_pt[:]) + next_insn_lex_tuple[:]) stmt_added = True # Note: before/after may refer to same stmt, in which case @@ -252,7 +252,7 @@ class LexSchedule(object): if stmt_added: # increment lex dim val enumerating items in current code block - next_insn_lex_pt[-1] = next_insn_lex_pt[-1] + 1 + next_insn_lex_tuple[-1] = next_insn_lex_tuple[-1] + 1 next_sid += 1 # all current (nested) blocks now contain a statement @@ -266,14 +266,14 @@ class LexSchedule(object): # at this point, lex_schedule may contain lex points missing dimensions, # the values in these missing dims should be zero, so add them - self.pad_lex_pts_with_zeros() + self.pad_lex_tuples_with_zeros() def max_lex_dims(self): return max([ - len(self.stmt_instance_before.lex_pt), - len(self.stmt_instance_after.lex_pt)]) + len(self.stmt_instance_before.lex_points), + len(self.stmt_instance_after.lex_points)]) - def pad_lex_pts_with_zeros(self): + def pad_lex_tuples_with_zeros(self): """Find the maximum number of lexicographic dimensions represented in the lexicographic ordering, and if any :class:`LexScheduleStatement` maps to a point in lexicographic @@ -281,17 +281,17 @@ class LexSchedule(object): dimensions. """ - def _pad_lex_pt_with_zeros(stmt_inst, length): + def _pad_lex_tuple_with_zeros(stmt_inst, length): return LexScheduleStatementInstance( stmt_inst.stmt, - stmt_inst.lex_pt[:] + [0]*(length-len(stmt_inst.lex_pt)), + stmt_inst.lex_points[:] + [0]*(length-len(stmt_inst.lex_points)), ) max_lex_dim = self.max_lex_dims() - self.stmt_instance_before = _pad_lex_pt_with_zeros( + self.stmt_instance_before = _pad_lex_tuple_with_zeros( self.stmt_instance_before, max_lex_dim) - self.stmt_instance_after = _pad_lex_pt_with_zeros( + self.stmt_instance_after = _pad_lex_tuple_with_zeros( self.stmt_instance_after, max_lex_dim) def create_isl_maps( @@ -366,7 +366,7 @@ class LexSchedule(object): # Add all inames from domains to each map domain tuple. tuple_pair = [( (stmt_inst.stmt.int_id, ) + tuple(dom_inames_ordered), - stmt_inst.lex_pt + stmt_inst.lex_points )] # create isl map @@ -396,7 +396,7 @@ class LexSchedule(object): return "{\n[%s=%s,] -> %s;\n}" % ( self.statement_var_name, stmt_inst.stmt.int_id, - stmt_inst.lex_pt) + stmt_inst.lex_points) return "Before: %s\nAfter: %s" % ( stringify_sched_stmt_instance(self.stmt_instance_before), diff --git a/test/test_linearization_checker.py b/test/test_linearization_checker.py index 0dfb2fc90..aab9c8507 100644 --- a/test/test_linearization_checker.py +++ b/test/test_linearization_checker.py @@ -94,37 +94,37 @@ def test_lexschedule_and_islmap_creation(): linearization_items = knl.linearization # Create LexSchedule: mapping of {statement instance: lex point} - lex_sched_ab = get_schedule_for_statement_pair( + sched_ab = get_schedule_for_statement_pair( knl, linearization_items, "insn_a", "insn_b", ) - lex_sched_ac = get_schedule_for_statement_pair( + sched_ac = get_schedule_for_statement_pair( knl, linearization_items, "insn_a", "insn_c", ) - lex_sched_ad = get_schedule_for_statement_pair( + sched_ad = get_schedule_for_statement_pair( knl, linearization_items, "insn_a", "insn_d", ) - lex_sched_bc = get_schedule_for_statement_pair( + sched_bc = get_schedule_for_statement_pair( knl, linearization_items, "insn_b", "insn_c", ) - lex_sched_bd = get_schedule_for_statement_pair( + sched_bd = get_schedule_for_statement_pair( knl, linearization_items, "insn_b", "insn_d", ) - lex_sched_cd = get_schedule_for_statement_pair( + sched_cd = get_schedule_for_statement_pair( knl, linearization_items, "insn_c", @@ -133,13 +133,13 @@ def test_lexschedule_and_islmap_creation(): # Relationship between insn_a and insn_b --------------------------------------- - assert lex_sched_ab.stmt_instance_before.lex_pt == [0, 'i', 0, 'k', 0] - assert lex_sched_ab.stmt_instance_after.lex_pt == [0, 'i', 1, 'j', 0] + assert sched_ab.stmt_instance_before.lex_points == [0, 'i', 0, 'k', 0] + assert sched_ab.stmt_instance_after.lex_points == [0, 'i', 1, 'j', 0] # Get two isl maps representing the LexSchedule isl_sched_map_before, isl_sched_map_after = get_isl_maps_for_LexSchedule( - lex_sched_ab, knl) + sched_ab, knl) # Create expected maps, align, compare @@ -169,13 +169,13 @@ def test_lexschedule_and_islmap_creation(): # ------------------------------------------------------------------------------ # Relationship between insn_a and insn_c --------------------------------------- - assert lex_sched_ac.stmt_instance_before.lex_pt == [0, 'i', 0, 'k', 0] - assert lex_sched_ac.stmt_instance_after.lex_pt == [0, 'i', 1, 'j', 0] + assert sched_ac.stmt_instance_before.lex_points == [0, 'i', 0, 'k', 0] + assert sched_ac.stmt_instance_after.lex_points == [0, 'i', 1, 'j', 0] # Get two isl maps representing the LexSchedule isl_sched_map_before, isl_sched_map_after = get_isl_maps_for_LexSchedule( - lex_sched_ac, knl) + sched_ac, knl) # Create expected maps, align, compare @@ -208,13 +208,13 @@ def test_lexschedule_and_islmap_creation(): # insn_a and insn_d could have been linearized in either order # (i loop could be before or after t loop) def perform_insn_ad_checks_with(sid_a, sid_d): - assert lex_sched_ad.stmt_instance_before.lex_pt == [sid_a, 'i', 0, 'k', 0] - assert lex_sched_ad.stmt_instance_after.lex_pt == [sid_d, 't', 0, 0, 0] + assert sched_ad.stmt_instance_before.lex_points == [sid_a, 'i', 0, 'k', 0] + assert sched_ad.stmt_instance_after.lex_points == [sid_d, 't', 0, 0, 0] # Get two isl maps representing the LexSchedule isl_sched_map_before, isl_sched_map_after = get_isl_maps_for_LexSchedule( - lex_sched_ad, knl) + sched_ad, knl) # Create expected maps, align, compare @@ -243,7 +243,7 @@ def test_lexschedule_and_islmap_creation(): assert isl_sched_map_before == isl_sched_map_before_expected assert isl_sched_map_after == isl_sched_map_after_expected - if lex_sched_ad.stmt_instance_before.stmt.int_id == 0: + if sched_ad.stmt_instance_before.stmt.int_id == 0: perform_insn_ad_checks_with(0, 1) else: perform_insn_ad_checks_with(1, 0) @@ -254,13 +254,13 @@ def test_lexschedule_and_islmap_creation(): # insn_b and insn_c could have been linearized in either order # (i loop could be before or after t loop) def perform_insn_bc_checks_with(sid_b, sid_c): - assert lex_sched_bc.stmt_instance_before.lex_pt == [0, 'i', 0, 'j', sid_b] - assert lex_sched_bc.stmt_instance_after.lex_pt == [0, 'i', 0, 'j', sid_c] + assert sched_bc.stmt_instance_before.lex_points == [0, 'i', 0, 'j', sid_b] + assert sched_bc.stmt_instance_after.lex_points == [0, 'i', 0, 'j', sid_c] # Get two isl maps representing the LexSchedule isl_sched_map_before, isl_sched_map_after = get_isl_maps_for_LexSchedule( - lex_sched_bc, knl) + sched_bc, knl) # Create expected maps, align, compare @@ -289,7 +289,7 @@ def test_lexschedule_and_islmap_creation(): assert isl_sched_map_before == isl_sched_map_before_expected assert isl_sched_map_after == isl_sched_map_after_expected - if lex_sched_bc.stmt_instance_before.stmt.int_id == 0: + if sched_bc.stmt_instance_before.stmt.int_id == 0: perform_insn_bc_checks_with(0, 1) else: perform_insn_bc_checks_with(1, 0) @@ -300,13 +300,13 @@ def test_lexschedule_and_islmap_creation(): # insn_b and insn_d could have been linearized in either order # (i loop could be before or after t loop) def perform_insn_bd_checks_with(sid_b, sid_d): - assert lex_sched_bd.stmt_instance_before.lex_pt == [sid_b, 'i', 0, 'j', 0] - assert lex_sched_bd.stmt_instance_after.lex_pt == [sid_d, 't', 0, 0, 0] + assert sched_bd.stmt_instance_before.lex_points == [sid_b, 'i', 0, 'j', 0] + assert sched_bd.stmt_instance_after.lex_points == [sid_d, 't', 0, 0, 0] # Get two isl maps representing the LexSchedule isl_sched_map_before, isl_sched_map_after = get_isl_maps_for_LexSchedule( - lex_sched_bd, knl) + sched_bd, knl) # Create expected maps, align, compare @@ -335,7 +335,7 @@ def test_lexschedule_and_islmap_creation(): assert isl_sched_map_before == isl_sched_map_before_expected assert isl_sched_map_after == isl_sched_map_after_expected - if lex_sched_bd.stmt_instance_before.stmt.int_id == 0: + if sched_bd.stmt_instance_before.stmt.int_id == 0: perform_insn_bd_checks_with(0, 1) else: perform_insn_bd_checks_with(1, 0) @@ -346,13 +346,13 @@ def test_lexschedule_and_islmap_creation(): # insn_c and insn_d could have been linearized in either order # (i loop could be before or after t loop) def perform_insn_cd_checks_with(sid_c, sid_d): - assert lex_sched_cd.stmt_instance_before.lex_pt == [sid_c, 'i', 0, 'j', 0] - assert lex_sched_cd.stmt_instance_after.lex_pt == [sid_d, 't', 0, 0, 0] + assert sched_cd.stmt_instance_before.lex_points == [sid_c, 'i', 0, 'j', 0] + assert sched_cd.stmt_instance_after.lex_points == [sid_d, 't', 0, 0, 0] # Get two isl maps representing the LexSchedule isl_sched_map_before, isl_sched_map_after = get_isl_maps_for_LexSchedule( - lex_sched_cd, knl) + sched_cd, knl) # Create expected maps, align, compare @@ -381,7 +381,7 @@ def test_lexschedule_and_islmap_creation(): assert isl_sched_map_before == isl_sched_map_before_expected assert isl_sched_map_after == isl_sched_map_after_expected - if lex_sched_cd.stmt_instance_before.stmt.int_id == 0: + if sched_cd.stmt_instance_before.stmt.int_id == 0: perform_insn_cd_checks_with(0, 1) else: perform_insn_cd_checks_with(1, 0) -- GitLab From 7cc557eaeb4351cf23cf17b76c1648c3a4a0e9e1 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 25 May 2020 21:30:20 -0500 Subject: [PATCH 030/136] rename LexScheduleStatementInstance->LexScheduleStatementInstanceSet (will probably rename again) --- loopy/schedule/checker/__init__.py | 6 +++--- loopy/schedule/checker/schedule.py | 15 ++++++++------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 3215201ae..176b1399c 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -31,7 +31,7 @@ def get_schedule_for_statement_pair( ): """Create a :class:`loopy.schedule.checker.schedule.LexSchedule` representing the order of two statements as a mapping from - :class:`loopy.schedule.checker.LexScheduleStatementInstance` + :class:`loopy.schedule.checker.LexScheduleStatementInstanceSet` to lexicographic time. :arg knl: A :class:`loopy.kernel.LoopKernel` containing the @@ -52,7 +52,7 @@ def get_schedule_for_statement_pair( :returns: A :class:`loopy.schedule.checker.schedule.LexSchedule` representing the order of two statements as a mapping from - :class:`loopy.schedule.checker.LexScheduleStatementInstance` + :class:`loopy.schedule.checker.LexScheduleStatementInstanceSet` to lexicographic time. """ @@ -105,7 +105,7 @@ def get_isl_maps_for_LexSchedule(lex_sched, knl): :arg lex_sched: A :class:`loopy.schedule.checker.schedule.LexSchedule` representing the order of two statements as a mapping from - :class:`loopy.schedule.checker.LexScheduleStatementInstance` + :class:`loopy.schedule.checker.LexScheduleStatementInstanceSet` to lexicographic time. :arg knl: A :class:`loopy.kernel.LoopKernel` containing the diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 052a47afe..f839f45aa 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -72,8 +72,9 @@ class LexScheduleStatement(object): return "%s%s" % (self.insn_id, int_id) -class LexScheduleStatementInstance(object): - """A representation of a statement instance. +class LexScheduleStatementInstanceSet(object): + """A representation of a set of instances of a + :class:`LexScheduleStatement`. .. attribute:: stmt @@ -106,7 +107,7 @@ class LexSchedule(object): .. attribute:: stmt_instance_before - A :class:`LexScheduleStatementInstance` describing the dependee + A :class:`LexScheduleStatementInstanceSet` describing the dependee statement's order relative to the depender statment by mapping a statement to a point or set of points in a lexicographic ordering. Points in lexicographic ordering are represented as @@ -114,7 +115,7 @@ class LexSchedule(object): .. attribute:: stmt_instance_after - A :class:`LexScheduleStatementInstance` describing the depender + A :class:`LexScheduleStatementInstanceSet` describing the depender statement's order relative to the dependee statment by mapping a statement to a point or set of points in a lexicographic ordering. Points in lexicographic ordering are represented as @@ -229,7 +230,7 @@ class LexSchedule(object): if lp_insn_id == before_insn_id: # add before sched item - self.stmt_instance_before = LexScheduleStatementInstance( + self.stmt_instance_before = LexScheduleStatementInstanceSet( LexScheduleStatement( insn_id=lp_insn_id, int_id=next_sid, # int representing insn @@ -239,7 +240,7 @@ class LexSchedule(object): if lp_insn_id == after_insn_id: # add after sched item - self.stmt_instance_after = LexScheduleStatementInstance( + self.stmt_instance_after = LexScheduleStatementInstanceSet( LexScheduleStatement( insn_id=lp_insn_id, int_id=next_sid, # int representing insn @@ -282,7 +283,7 @@ class LexSchedule(object): """ def _pad_lex_tuple_with_zeros(stmt_inst, length): - return LexScheduleStatementInstance( + return LexScheduleStatementInstanceSet( stmt_inst.stmt, stmt_inst.lex_points[:] + [0]*(length-len(stmt_inst.lex_points)), ) -- GitLab From 2f6942632965b1406bce1b598ab7235dd2759bf7 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 25 May 2020 21:43:54 -0500 Subject: [PATCH 031/136] remove comments with redundant documentation --- loopy/schedule/checker/schedule.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index f839f45aa..aac9b5744 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -44,10 +44,10 @@ class LexScheduleStatement(object): def __init__( self, - insn_id, # loopy insn id - int_id=None, # sid int (statement id within LexSchedule) + insn_id, + int_id=None, ): - self.insn_id = insn_id # string + self.insn_id = insn_id self.int_id = int_id def __eq__(self, other): @@ -89,8 +89,8 @@ class LexScheduleStatementInstanceSet(object): def __init__( self, - stmt, # a LexScheduleStatement - lex_points, # [string/int, ] + stmt, + lex_points, ): self.stmt = stmt self.lex_points = lex_points -- GitLab From 2f494a2a02d15339ceb7662fee51ae0bcbb2a18e Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 25 May 2020 21:49:33 -0500 Subject: [PATCH 032/136] update more comments to clarify that the lex tuples represent *multiple* points, not a single point --- loopy/schedule/checker/schedule.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index aac9b5744..c40053869 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -166,8 +166,8 @@ class LexSchedule(object): # go through linearization_items_ordered and generate self.lex_schedule - # keep track of the next point in our lexicographic ordering - # initially this as a 1-d point with value 0 + # keep track of the next tuple of points in our lexicographic + # ordering, initially this as a 1-d point with value 0 next_insn_lex_tuple = [0] stmt_added_since_prev_block_at_tier = [False] next_sid = 0 @@ -265,8 +265,9 @@ class LexSchedule(object): if self.stmt_instance_before and self.stmt_instance_after: break - # at this point, lex_schedule may contain lex points missing dimensions, - # the values in these missing dims should be zero, so add them + # At this point, lex_schedule may contain lex point tuples + # missing dimensions; the values in these missing dims should + # be zero, so add them. self.pad_lex_tuples_with_zeros() def max_lex_dims(self): @@ -277,9 +278,8 @@ class LexSchedule(object): def pad_lex_tuples_with_zeros(self): """Find the maximum number of lexicographic dimensions represented in the lexicographic ordering, and if any - :class:`LexScheduleStatement` maps to a point in lexicographic - time with fewer dimensions, add a zero for each of the missing - dimensions. + :class:`LexScheduleStatement` maps to a lex point tuple with + fewer dimensions, add a zero for each of the missing dimensions. """ def _pad_lex_tuple_with_zeros(stmt_inst, length): -- GitLab From c71a0efb3182a50ccfad6d346d62abc93088d3f8 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 25 May 2020 22:13:38 -0500 Subject: [PATCH 033/136] clarify what a LexScheduleStatementInstanceSet is --- loopy/schedule/checker/schedule.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index c40053869..c4b4cfc78 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -73,8 +73,11 @@ class LexScheduleStatement(object): class LexScheduleStatementInstanceSet(object): - """A representation of a set of instances of a - :class:`LexScheduleStatement`. + """A representation of a set of (non-concurrent) instances of a + statement being executed. The ordering of the instances is described + by the `lex_points` attribute, a list representing points in a + lexicographic ordering of statements. Each field in the list + corresponds to a dimension in the lexicographic ordering. .. attribute:: stmt @@ -82,8 +85,9 @@ class LexScheduleStatementInstanceSet(object): .. attribute:: lex_points - A list of :class:`int` or as :class:`str` :mod:`loopy` inames representing - a point or set of points in a lexicographic ordering. + A list containing one value for each dimension in a lexicographic + ordering. These values describe the ordering of the statements, + and may be :class:`str` :mod:`loopy` inames or :class:`int`. """ -- GitLab From 492e1f7d66d837076592caeb20813a8df2fe5373 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 26 May 2020 10:16:32 -0500 Subject: [PATCH 034/136] rename LexScheduleStatement->PairwiseScheduleStatement, get_isl_maps_for_LexSchedule->get_isl_maps_from_PairwiseScheduleBuilder, LexSchedule->PairwiseScheduleBuilder --- loopy/schedule/checker/__init__.py | 32 +++---- loopy/schedule/checker/schedule.py | 42 ++++----- test/test_linearization_checker.py | 132 ++++++++++++++--------------- 3 files changed, 103 insertions(+), 103 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 176b1399c..1da7b1e16 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -21,7 +21,7 @@ THE SOFTWARE. """ -# {{{ Create LexSchedule for statement pair +# {{{ Create PairwiseScheduleBuilder for statement pair def get_schedule_for_statement_pair( knl, @@ -29,9 +29,9 @@ def get_schedule_for_statement_pair( insn_id_before, insn_id_after, ): - """Create a :class:`loopy.schedule.checker.schedule.LexSchedule` + """Create a :class:`loopy.schedule.checker.schedule.PairwiseScheduleBuilder` representing the order of two statements as a mapping from - :class:`loopy.schedule.checker.LexScheduleStatementInstanceSet` + :class:`loopy.schedule.checker.PairwiseScheduleStatementInstanceSet` to lexicographic time. :arg knl: A :class:`loopy.kernel.LoopKernel` containing the @@ -50,9 +50,9 @@ def get_schedule_for_statement_pair( :arg insn_id_after: An instruction identifier that is unique within a :class:`loopy.kernel.LoopKernel`. - :returns: A :class:`loopy.schedule.checker.schedule.LexSchedule` + :returns: A :class:`loopy.schedule.checker.schedule.PairwiseScheduleBuilder` representing the order of two statements as a mapping from - :class:`loopy.schedule.checker.LexScheduleStatementInstanceSet` + :class:`loopy.schedule.checker.PairwiseScheduleStatementInstanceSet` to lexicographic time. """ @@ -62,7 +62,7 @@ def get_schedule_for_statement_pair( # }}} # {{{ Find any EnterLoop inames that are tagged as concurrent - # so that LexSchedule knows to ignore them + # so that PairwiseScheduleBuilder knows to ignore them # (In the future, this shouldn't be necessary because there # won't be any inames with ConcurrentTags in EnterLoop linearization items. # Test which exercises this: test_linearization_checker_with_stroud_bernstein()) @@ -81,10 +81,10 @@ def get_schedule_for_statement_pair( "Ignoring these loops." % (conc_loop_inames, preproc_knl.name)) # }}} - # {{{ Create LexSchedule: mapping of {statement instance: lex point} + # {{{ Create PairwiseScheduleBuilder: mapping of {statement instance: lex point} # include only instructions involved in this dependency - from loopy.schedule.checker.schedule import LexSchedule - return LexSchedule( + from loopy.schedule.checker.schedule import PairwiseScheduleBuilder + return PairwiseScheduleBuilder( linearization_items, insn_id_before, insn_id_after, @@ -95,17 +95,17 @@ def get_schedule_for_statement_pair( # }}} -# {{{ Get isl map pair for LexSchedule +# {{{ Get isl map pair from PairwiseScheduleBuilder -def get_isl_maps_for_LexSchedule(lex_sched, knl): +def get_isl_maps_from_PairwiseScheduleBuilder(lex_sched, knl): """Create a pair of :class:`islpy.Map`s representing a - :class:`loopy.schedule.checker.LexSchedule` as two mappings - from statement instances to lexicographic time, one for - the dependee statement and one for the depender. + sub-schedule as two mappings from statement instances to lexicographic + time, one for the dependee statement and one for the depender. - :arg lex_sched: A :class:`loopy.schedule.checker.schedule.LexSchedule` + :arg lex_sched: A + :class:`loopy.schedule.checker.schedule.PairwiseScheduleBuilder` representing the order of two statements as a mapping from - :class:`loopy.schedule.checker.LexScheduleStatementInstanceSet` + :class:`loopy.schedule.checker.PairwiseScheduleStatementInstanceSet` to lexicographic time. :arg knl: A :class:`loopy.kernel.LoopKernel` containing the diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index c4b4cfc78..4d80d8945 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -23,7 +23,7 @@ THE SOFTWARE. import islpy as isl -class LexScheduleStatement(object): +class PairwiseScheduleStatement(object): """A representation of a :mod:`loopy` statement. .. attribute:: insn_id @@ -34,11 +34,11 @@ class LexScheduleStatement(object): .. attribute:: int_id A :class:`int` uniquely identifying the statement within a - :class:`LexSchedule`. A :class:`LexSchedule` describes a mapping - from points in a space of statement instances to points in a - lexicographic ordering. The `statement` dimension of a point - in the statement instance space representing an instance of this - statement is assigned this value (`int_id`). + :class:`PairwiseScheduleBuilder`. A :class:`PairwiseScheduleBuilder` + builds a mapping from points in a space of statement instances to + points in a lexicographic ordering. The `statement` dimension of a + point in the statement instance space representing an instance of + this statement is assigned this value (`int_id`). """ @@ -72,7 +72,7 @@ class LexScheduleStatement(object): return "%s%s" % (self.insn_id, int_id) -class LexScheduleStatementInstanceSet(object): +class PairwiseScheduleStatementInstanceSet(object): """A representation of a set of (non-concurrent) instances of a statement being executed. The ordering of the instances is described by the `lex_points` attribute, a list representing points in a @@ -81,7 +81,7 @@ class LexScheduleStatementInstanceSet(object): .. attribute:: stmt - A :class:`LexScheduleStatement`. + A :class:`PairwiseScheduleStatement`. .. attribute:: lex_points @@ -103,15 +103,15 @@ class LexScheduleStatementInstanceSet(object): return "{%s, %s}" % (self.stmt, self.lex_points) -class LexSchedule(object): - """Given a pair of statements in a linearized kernel, LexSchedule +class PairwiseScheduleBuilder(object): + """Given a pair of statements in a linearized kernel, PairwiseScheduleBuilder determines the (relative) order in which the instances are executed, by creating a mapping from statement instances to points in a single lexicographic ordering. .. attribute:: stmt_instance_before - A :class:`LexScheduleStatementInstanceSet` describing the dependee + A :class:`PairwiseScheduleStatementInstanceSet` describing the dependee statement's order relative to the depender statment by mapping a statement to a point or set of points in a lexicographic ordering. Points in lexicographic ordering are represented as @@ -119,7 +119,7 @@ class LexSchedule(object): .. attribute:: stmt_instance_after - A :class:`LexScheduleStatementInstanceSet` describing the depender + A :class:`PairwiseScheduleStatementInstanceSet` describing the depender statement's order relative to the dependee statment by mapping a statement to a point or set of points in a lexicographic ordering. Points in lexicographic ordering are represented as @@ -150,7 +150,7 @@ class LexSchedule(object): ): """ :arg linearization_items_ordered: A list of :class:`ScheduleItem` whose - order will be described by this :class:`LexSchedule`. + order will be described by this :class:`PairwiseScheduleBuilder`. :arg before_insn_id: A :class:`str` instruction id specifying the dependee in this pair of instructions. @@ -160,11 +160,11 @@ class LexSchedule(object): """ - # LexScheduleStatements + # PairwiseScheduleBuilder statements self.stmt_instance_before = None self.stmt_instance_after = None # TODO when/after dependencies are added, consider the possibility - # of removing the two-statements-per-LexSchedule limitation + # of removing the two-statements-per-PairwiseScheduleBuilder limitation from loopy.schedule import (EnterLoop, LeaveLoop, Barrier, RunInstruction) @@ -234,8 +234,8 @@ class LexSchedule(object): if lp_insn_id == before_insn_id: # add before sched item - self.stmt_instance_before = LexScheduleStatementInstanceSet( - LexScheduleStatement( + self.stmt_instance_before = PairwiseScheduleStatementInstanceSet( + PairwiseScheduleStatement( insn_id=lp_insn_id, int_id=next_sid, # int representing insn ), @@ -244,8 +244,8 @@ class LexSchedule(object): if lp_insn_id == after_insn_id: # add after sched item - self.stmt_instance_after = LexScheduleStatementInstanceSet( - LexScheduleStatement( + self.stmt_instance_after = PairwiseScheduleStatementInstanceSet( + PairwiseScheduleStatement( insn_id=lp_insn_id, int_id=next_sid, # int representing insn ), @@ -282,12 +282,12 @@ class LexSchedule(object): def pad_lex_tuples_with_zeros(self): """Find the maximum number of lexicographic dimensions represented in the lexicographic ordering, and if any - :class:`LexScheduleStatement` maps to a lex point tuple with + :class:`PairwiseScheduleStatement` maps to a lex point tuple with fewer dimensions, add a zero for each of the missing dimensions. """ def _pad_lex_tuple_with_zeros(stmt_inst, length): - return LexScheduleStatementInstanceSet( + return PairwiseScheduleStatementInstanceSet( stmt_inst.stmt, stmt_inst.lex_points[:] + [0]*(length-len(stmt_inst.lex_points)), ) diff --git a/test/test_linearization_checker.py b/test/test_linearization_checker.py index aab9c8507..a4696c3b2 100644 --- a/test/test_linearization_checker.py +++ b/test/test_linearization_checker.py @@ -50,7 +50,7 @@ def test_lexschedule_and_islmap_creation(): import islpy as isl from loopy.schedule.checker import ( get_schedule_for_statement_pair, - get_isl_maps_for_LexSchedule, + get_isl_maps_from_PairwiseScheduleBuilder, ) from loopy.schedule.checker.utils import ( align_isl_maps_by_var_names, @@ -93,7 +93,7 @@ def test_lexschedule_and_islmap_creation(): knl = get_one_linearized_kernel(knl) linearization_items = knl.linearization - # Create LexSchedule: mapping of {statement instance: lex point} + # Create PairwiseScheduleBuilder: mapping of {statement instance: lex point} sched_ab = get_schedule_for_statement_pair( knl, linearization_items, @@ -136,35 +136,35 @@ def test_lexschedule_and_islmap_creation(): assert sched_ab.stmt_instance_before.lex_points == [0, 'i', 0, 'k', 0] assert sched_ab.stmt_instance_after.lex_points == [0, 'i', 1, 'j', 0] - # Get two isl maps representing the LexSchedule + # Get two isl maps from the PairwiseScheduleBuilder - isl_sched_map_before, isl_sched_map_after = get_isl_maps_for_LexSchedule( + isl_sched_before, isl_sched_after = get_isl_maps_from_PairwiseScheduleBuilder( sched_ab, knl) # Create expected maps, align, compare - isl_sched_map_before_expected = isl.Map( + isl_sched_before_expected = isl.Map( "[pi, pk] -> { " "[_lp_sched_statement=0, i, k] -> " "[_lp_sched_l0=0, _lp_sched_l1=i, _lp_sched_l2=0, _lp_sched_l3=k, " "_lp_sched_l4=0] : " "0 <= i < pi and 0 <= k < pk }" ) - isl_sched_map_before_expected = align_isl_maps_by_var_names( - isl_sched_map_before_expected, isl_sched_map_before) + isl_sched_before_expected = align_isl_maps_by_var_names( + isl_sched_before_expected, isl_sched_before) - isl_sched_map_after_expected = isl.Map( + isl_sched_after_expected = isl.Map( "[pi, pj] -> { " "[_lp_sched_statement=1, i, j] -> " "[_lp_sched_l0=0, _lp_sched_l1=i, _lp_sched_l2=1, _lp_sched_l3=j, " "_lp_sched_l4=0] : " "0 <= i < pi and 0 <= j < pj }" ) - isl_sched_map_after_expected = align_isl_maps_by_var_names( - isl_sched_map_after_expected, isl_sched_map_after) + isl_sched_after_expected = align_isl_maps_by_var_names( + isl_sched_after_expected, isl_sched_after) - assert isl_sched_map_before == isl_sched_map_before_expected - assert isl_sched_map_after == isl_sched_map_after_expected + assert isl_sched_before == isl_sched_before_expected + assert isl_sched_after == isl_sched_after_expected # ------------------------------------------------------------------------------ # Relationship between insn_a and insn_c --------------------------------------- @@ -172,35 +172,35 @@ def test_lexschedule_and_islmap_creation(): assert sched_ac.stmt_instance_before.lex_points == [0, 'i', 0, 'k', 0] assert sched_ac.stmt_instance_after.lex_points == [0, 'i', 1, 'j', 0] - # Get two isl maps representing the LexSchedule + # Get two isl maps from the PairwiseScheduleBuilder - isl_sched_map_before, isl_sched_map_after = get_isl_maps_for_LexSchedule( + isl_sched_before, isl_sched_after = get_isl_maps_from_PairwiseScheduleBuilder( sched_ac, knl) # Create expected maps, align, compare - isl_sched_map_before_expected = isl.Map( + isl_sched_before_expected = isl.Map( "[pi, pk] -> { " "[_lp_sched_statement=0, i, k] -> " "[_lp_sched_l0=0, _lp_sched_l1=i, _lp_sched_l2=0, _lp_sched_l3=k, " "_lp_sched_l4=0] : " "0 <= i < pi and 0 <= k < pk }" ) - isl_sched_map_before_expected = align_isl_maps_by_var_names( - isl_sched_map_before_expected, isl_sched_map_before) + isl_sched_before_expected = align_isl_maps_by_var_names( + isl_sched_before_expected, isl_sched_before) - isl_sched_map_after_expected = isl.Map( + isl_sched_after_expected = isl.Map( "[pi, pj] -> { " "[_lp_sched_statement=1, i, j] -> " "[_lp_sched_l0=0, _lp_sched_l1=i, _lp_sched_l2=1, _lp_sched_l3=j, " "_lp_sched_l4=0] : " "0 <= i < pi and 0 <= j < pj }" ) - isl_sched_map_after_expected = align_isl_maps_by_var_names( - isl_sched_map_after_expected, isl_sched_map_after) + isl_sched_after_expected = align_isl_maps_by_var_names( + isl_sched_after_expected, isl_sched_after) - assert isl_sched_map_before == isl_sched_map_before_expected - assert isl_sched_map_after == isl_sched_map_after_expected + assert isl_sched_before == isl_sched_before_expected + assert isl_sched_after == isl_sched_after_expected # ------------------------------------------------------------------------------ # Relationship between insn_a and insn_d --------------------------------------- @@ -211,14 +211,14 @@ def test_lexschedule_and_islmap_creation(): assert sched_ad.stmt_instance_before.lex_points == [sid_a, 'i', 0, 'k', 0] assert sched_ad.stmt_instance_after.lex_points == [sid_d, 't', 0, 0, 0] - # Get two isl maps representing the LexSchedule + # Get two isl maps from the PairwiseScheduleBuilder - isl_sched_map_before, isl_sched_map_after = get_isl_maps_for_LexSchedule( - sched_ad, knl) + isl_sched_before, isl_sched_after = \ + get_isl_maps_from_PairwiseScheduleBuilder(sched_ad, knl) # Create expected maps, align, compare - isl_sched_map_before_expected = isl.Map( + isl_sched_before_expected = isl.Map( "[pi, pk] -> { " "[_lp_sched_statement=%d, i, k] -> " "[_lp_sched_l0=%d, _lp_sched_l1=i, _lp_sched_l2=0, _lp_sched_l3=k, " @@ -226,10 +226,10 @@ def test_lexschedule_and_islmap_creation(): "0 <= i < pi and 0 <= k < pk }" % (sid_a, sid_a) ) - isl_sched_map_before_expected = align_isl_maps_by_var_names( - isl_sched_map_before_expected, isl_sched_map_before) + isl_sched_before_expected = align_isl_maps_by_var_names( + isl_sched_before_expected, isl_sched_before) - isl_sched_map_after_expected = isl.Map( + isl_sched_after_expected = isl.Map( "[pt] -> { " "[_lp_sched_statement=%d, t] -> " "[_lp_sched_l0=%d, _lp_sched_l1=t, _lp_sched_l2=0, _lp_sched_l3=0, " @@ -237,11 +237,11 @@ def test_lexschedule_and_islmap_creation(): "0 <= t < pt }" % (sid_d, sid_d) ) - isl_sched_map_after_expected = align_isl_maps_by_var_names( - isl_sched_map_after_expected, isl_sched_map_after) + isl_sched_after_expected = align_isl_maps_by_var_names( + isl_sched_after_expected, isl_sched_after) - assert isl_sched_map_before == isl_sched_map_before_expected - assert isl_sched_map_after == isl_sched_map_after_expected + assert isl_sched_before == isl_sched_before_expected + assert isl_sched_after == isl_sched_after_expected if sched_ad.stmt_instance_before.stmt.int_id == 0: perform_insn_ad_checks_with(0, 1) @@ -257,14 +257,14 @@ def test_lexschedule_and_islmap_creation(): assert sched_bc.stmt_instance_before.lex_points == [0, 'i', 0, 'j', sid_b] assert sched_bc.stmt_instance_after.lex_points == [0, 'i', 0, 'j', sid_c] - # Get two isl maps representing the LexSchedule + # Get two isl maps from the PairwiseScheduleBuilder - isl_sched_map_before, isl_sched_map_after = get_isl_maps_for_LexSchedule( - sched_bc, knl) + isl_sched_before, isl_sched_after = \ + get_isl_maps_from_PairwiseScheduleBuilder(sched_bc, knl) # Create expected maps, align, compare - isl_sched_map_before_expected = isl.Map( + isl_sched_before_expected = isl.Map( "[pi, pj] -> { " "[_lp_sched_statement=%d, i, j] -> " "[_lp_sched_l0=0, _lp_sched_l1=i, _lp_sched_l2=0, _lp_sched_l3=j, " @@ -272,10 +272,10 @@ def test_lexschedule_and_islmap_creation(): "0 <= i < pi and 0 <= j < pj }" % (sid_b, sid_b) ) - isl_sched_map_before_expected = align_isl_maps_by_var_names( - isl_sched_map_before_expected, isl_sched_map_before) + isl_sched_before_expected = align_isl_maps_by_var_names( + isl_sched_before_expected, isl_sched_before) - isl_sched_map_after_expected = isl.Map( + isl_sched_after_expected = isl.Map( "[pi, pj] -> { " "[_lp_sched_statement=%d, i, j] -> " "[_lp_sched_l0=0, _lp_sched_l1=i, _lp_sched_l2=0, _lp_sched_l3=j, " @@ -283,11 +283,11 @@ def test_lexschedule_and_islmap_creation(): "0 <= i < pi and 0 <= j < pj }" % (sid_c, sid_c) ) - isl_sched_map_after_expected = align_isl_maps_by_var_names( - isl_sched_map_after_expected, isl_sched_map_after) + isl_sched_after_expected = align_isl_maps_by_var_names( + isl_sched_after_expected, isl_sched_after) - assert isl_sched_map_before == isl_sched_map_before_expected - assert isl_sched_map_after == isl_sched_map_after_expected + assert isl_sched_before == isl_sched_before_expected + assert isl_sched_after == isl_sched_after_expected if sched_bc.stmt_instance_before.stmt.int_id == 0: perform_insn_bc_checks_with(0, 1) @@ -303,14 +303,14 @@ def test_lexschedule_and_islmap_creation(): assert sched_bd.stmt_instance_before.lex_points == [sid_b, 'i', 0, 'j', 0] assert sched_bd.stmt_instance_after.lex_points == [sid_d, 't', 0, 0, 0] - # Get two isl maps representing the LexSchedule + # Get two isl maps from the PairwiseScheduleBuilder - isl_sched_map_before, isl_sched_map_after = get_isl_maps_for_LexSchedule( - sched_bd, knl) + isl_sched_before, isl_sched_after = \ + get_isl_maps_from_PairwiseScheduleBuilder(sched_bd, knl) # Create expected maps, align, compare - isl_sched_map_before_expected = isl.Map( + isl_sched_before_expected = isl.Map( "[pi, pj] -> { " "[_lp_sched_statement=%d, i, j] -> " "[_lp_sched_l0=%d, _lp_sched_l1=i, _lp_sched_l2=0, _lp_sched_l3=j, " @@ -318,10 +318,10 @@ def test_lexschedule_and_islmap_creation(): "0 <= i < pi and 0 <= j < pj }" % (sid_b, sid_b) ) - isl_sched_map_before_expected = align_isl_maps_by_var_names( - isl_sched_map_before_expected, isl_sched_map_before) + isl_sched_before_expected = align_isl_maps_by_var_names( + isl_sched_before_expected, isl_sched_before) - isl_sched_map_after_expected = isl.Map( + isl_sched_after_expected = isl.Map( "[pt] -> { " "[_lp_sched_statement=%d, t] -> " "[_lp_sched_l0=%d, _lp_sched_l1=t, _lp_sched_l2=0, _lp_sched_l3=0, " @@ -329,11 +329,11 @@ def test_lexschedule_and_islmap_creation(): "0 <= t < pt }" % (sid_d, sid_d) ) - isl_sched_map_after_expected = align_isl_maps_by_var_names( - isl_sched_map_after_expected, isl_sched_map_after) + isl_sched_after_expected = align_isl_maps_by_var_names( + isl_sched_after_expected, isl_sched_after) - assert isl_sched_map_before == isl_sched_map_before_expected - assert isl_sched_map_after == isl_sched_map_after_expected + assert isl_sched_before == isl_sched_before_expected + assert isl_sched_after == isl_sched_after_expected if sched_bd.stmt_instance_before.stmt.int_id == 0: perform_insn_bd_checks_with(0, 1) @@ -349,14 +349,14 @@ def test_lexschedule_and_islmap_creation(): assert sched_cd.stmt_instance_before.lex_points == [sid_c, 'i', 0, 'j', 0] assert sched_cd.stmt_instance_after.lex_points == [sid_d, 't', 0, 0, 0] - # Get two isl maps representing the LexSchedule + # Get two isl maps from the PairwiseScheduleBuilder - isl_sched_map_before, isl_sched_map_after = get_isl_maps_for_LexSchedule( - sched_cd, knl) + isl_sched_before, isl_sched_after = \ + get_isl_maps_from_PairwiseScheduleBuilder(sched_cd, knl) # Create expected maps, align, compare - isl_sched_map_before_expected = isl.Map( + isl_sched_before_expected = isl.Map( "[pi, pj] -> { " "[_lp_sched_statement=%d, i, j] -> " "[_lp_sched_l0=%d, _lp_sched_l1=i, _lp_sched_l2=0, _lp_sched_l3=j, " @@ -364,10 +364,10 @@ def test_lexschedule_and_islmap_creation(): "0 <= i < pi and 0 <= j < pj }" % (sid_c, sid_c) ) - isl_sched_map_before_expected = align_isl_maps_by_var_names( - isl_sched_map_before_expected, isl_sched_map_before) + isl_sched_before_expected = align_isl_maps_by_var_names( + isl_sched_before_expected, isl_sched_before) - isl_sched_map_after_expected = isl.Map( + isl_sched_after_expected = isl.Map( "[pt] -> { " "[_lp_sched_statement=%d, t] -> " "[_lp_sched_l0=%d, _lp_sched_l1=t, _lp_sched_l2=0, _lp_sched_l3=0, " @@ -375,11 +375,11 @@ def test_lexschedule_and_islmap_creation(): "0 <= t < pt }" % (sid_d, sid_d) ) - isl_sched_map_after_expected = align_isl_maps_by_var_names( - isl_sched_map_after_expected, isl_sched_map_after) + isl_sched_after_expected = align_isl_maps_by_var_names( + isl_sched_after_expected, isl_sched_after) - assert isl_sched_map_before == isl_sched_map_before_expected - assert isl_sched_map_after == isl_sched_map_after_expected + assert isl_sched_before == isl_sched_before_expected + assert isl_sched_after == isl_sched_after_expected if sched_cd.stmt_instance_before.stmt.int_id == 0: perform_insn_cd_checks_with(0, 1) -- GitLab From e5146b0cf846184562eac98a05f10fb35650d49c Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 26 May 2020 10:22:29 -0500 Subject: [PATCH 035/136] change a few variable names to be consistent with name changes for LexSchedule --- loopy/schedule/checker/__init__.py | 12 +++++++----- loopy/schedule/checker/schedule.py | 4 ++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 1da7b1e16..4ce370b4c 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -97,12 +97,12 @@ def get_schedule_for_statement_pair( # {{{ Get isl map pair from PairwiseScheduleBuilder -def get_isl_maps_from_PairwiseScheduleBuilder(lex_sched, knl): +def get_isl_maps_from_PairwiseScheduleBuilder(sched_builder, knl): """Create a pair of :class:`islpy.Map`s representing a sub-schedule as two mappings from statement instances to lexicographic time, one for the dependee statement and one for the depender. - :arg lex_sched: A + :arg sched_builder: A :class:`loopy.schedule.checker.schedule.PairwiseScheduleBuilder` representing the order of two statements as a mapping from :class:`loopy.schedule.checker.PairwiseScheduleStatementInstanceSet` @@ -119,13 +119,15 @@ def get_isl_maps_from_PairwiseScheduleBuilder(lex_sched, knl): # {{{ Get iname domains dom_before = knl.get_inames_domain( - knl.id_to_insn[lex_sched.stmt_instance_before.stmt.insn_id].within_inames) + knl.id_to_insn[ + sched_builder.stmt_instance_before.stmt.insn_id].within_inames) dom_after = knl.get_inames_domain( - knl.id_to_insn[lex_sched.stmt_instance_after.stmt.insn_id].within_inames) + knl.id_to_insn[ + sched_builder.stmt_instance_after.stmt.insn_id].within_inames) # }}} # {{{ Get isl maps - return lex_sched.create_isl_maps(dom_before, dom_after) + return sched_builder.create_isl_maps(dom_before, dom_after) # }}} # }}} diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 4d80d8945..aaef5de8e 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -168,7 +168,7 @@ class PairwiseScheduleBuilder(object): from loopy.schedule import (EnterLoop, LeaveLoop, Barrier, RunInstruction) - # go through linearization_items_ordered and generate self.lex_schedule + # go through linearization_items_ordered and generate pairwise sub-schedule # keep track of the next tuple of points in our lexicographic # ordering, initially this as a 1-d point with value 0 @@ -269,7 +269,7 @@ class PairwiseScheduleBuilder(object): if self.stmt_instance_before and self.stmt_instance_after: break - # At this point, lex_schedule may contain lex point tuples + # At this point, pairwise sub-schedule may contain lex point tuples # missing dimensions; the values in these missing dims should # be zero, so add them. self.pad_lex_tuples_with_zeros() -- GitLab From d06dd8980c6b39588cc63835bb040580f4dc764d Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 26 May 2020 10:53:52 -0500 Subject: [PATCH 036/136] remove dependee/depender language for now --- loopy/schedule/checker/schedule.py | 46 ++++++++++++++++-------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index aaef5de8e..27b76c847 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -111,19 +111,21 @@ class PairwiseScheduleBuilder(object): .. attribute:: stmt_instance_before - A :class:`PairwiseScheduleStatementInstanceSet` describing the dependee - statement's order relative to the depender statment by mapping - a statement to a point or set of points in a lexicographic - ordering. Points in lexicographic ordering are represented as - a list of :class:`int` or as :class:`str` :mod:`loopy` inames. + A :class:`PairwiseScheduleStatementInstanceSet` whose ordering relative + to `stmt_instance_after is described by PairwiseScheduleBuilder. This + is achieved by mapping the statement instances in both sets to points + in a single lexicographic ordering. Points in lexicographic ordering + are represented as a list of :class:`int` or as :class:`str` + :mod:`loopy` inames. .. attribute:: stmt_instance_after - A :class:`PairwiseScheduleStatementInstanceSet` describing the depender - statement's order relative to the dependee statment by mapping - a statement to a point or set of points in a lexicographic - ordering. Points in lexicographic ordering are represented as - a list of :class:`int` or as :class:`str` :mod:`loopy` inames. + A :class:`PairwiseScheduleStatementInstanceSet` whose ordering relative + to `stmt_instance_before is described by PairwiseScheduleBuilder. This + is achieved by mapping the statement instances in both sets to points + in a single lexicographic ordering. Points in lexicographic ordering + are represented as a list of :class:`int` or as :class:`str` + :mod:`loopy` inames. .. attribute:: statement_var_name @@ -153,10 +155,10 @@ class PairwiseScheduleBuilder(object): order will be described by this :class:`PairwiseScheduleBuilder`. :arg before_insn_id: A :class:`str` instruction id specifying - the dependee in this pair of instructions. + stmt_instance_before in this pair of instructions. :arg after_insn_id: A :class:`str` instruction id specifying - the depender in this pair of instructions. + stmt_instancce_after in this pair of instructions. """ @@ -308,30 +310,30 @@ class PairwiseScheduleBuilder(object): ): """Create two isl maps representing lex schedule as two mappings from statement instances to lexicographic time, one for - the dependee and one for the depender. + ``stmt_instance_before`` and one for ``stmt_instance_after``. :arg dom_before: A :class:`islpy.BasicSet` representing the - domain for the dependee statement. + domain for ``stmt_instance_before``. :arg dom_after: A :class:`islpy.BasicSet` representing the - domain for the dependee statement. + domain for ``stmt_instance_after``. :arg dom_inames_ordered_before: A list of :class:`str` - representing the union of inames used in instances of the - dependee statement. ``statement_var_name`` and + representing the union of inames used in + ``stmt_instance_before``. ``statement_var_name`` and ``dom_inames_ordered_before`` are the names of the dims of - the space of the ISL map domain for the dependee. + the space of the ISL map domain. :arg dom_inames_ordered_after: A list of :class:`str` - representing the union of inames used in instances of the - depender statement. ``statement_var_name`` and + representing the union of inames used in + ``stmt_instance_after``. ``statement_var_name`` and ``dom_inames_ordered_after`` are the names of the dims of - the space of the ISL map domain for the depender. + the space of the ISL map domain. :returns: A two-tuple containing two :class:`islpy.Map`s representing the schedule as two mappings from statement instances to lexicographic time, one for - the dependee and one for the depender. + each of the two :class:`PairwiseScheduleStatementInstanceSet`s. """ -- GitLab From 2574becdadd587f37deb26bad7131610bb50188c Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 31 May 2020 21:10:07 -0500 Subject: [PATCH 037/136] change identifier prefix for sched checker identifiers from _lp_sched_->lp_linchk_ --- loopy/schedule/checker/schedule.py | 4 +- test/test_linearization_checker.py | 72 +++++++++++++++--------------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 27b76c847..b3f21a6c3 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -140,8 +140,8 @@ class PairwiseScheduleBuilder(object): """ - statement_var_name = "_lp_sched_statement" - lex_var_prefix = "_lp_sched_l" + statement_var_name = "_lp_linchk_statement" + lex_var_prefix = "_lp_linchk_l" def __init__( self, diff --git a/test/test_linearization_checker.py b/test/test_linearization_checker.py index a4696c3b2..7a67ab824 100644 --- a/test/test_linearization_checker.py +++ b/test/test_linearization_checker.py @@ -145,9 +145,9 @@ def test_lexschedule_and_islmap_creation(): isl_sched_before_expected = isl.Map( "[pi, pk] -> { " - "[_lp_sched_statement=0, i, k] -> " - "[_lp_sched_l0=0, _lp_sched_l1=i, _lp_sched_l2=0, _lp_sched_l3=k, " - "_lp_sched_l4=0] : " + "[_lp_linchk_statement=0, i, k] -> " + "[_lp_linchk_l0=0, _lp_linchk_l1=i, _lp_linchk_l2=0, _lp_linchk_l3=k, " + "_lp_linchk_l4=0] : " "0 <= i < pi and 0 <= k < pk }" ) isl_sched_before_expected = align_isl_maps_by_var_names( @@ -155,9 +155,9 @@ def test_lexschedule_and_islmap_creation(): isl_sched_after_expected = isl.Map( "[pi, pj] -> { " - "[_lp_sched_statement=1, i, j] -> " - "[_lp_sched_l0=0, _lp_sched_l1=i, _lp_sched_l2=1, _lp_sched_l3=j, " - "_lp_sched_l4=0] : " + "[_lp_linchk_statement=1, i, j] -> " + "[_lp_linchk_l0=0, _lp_linchk_l1=i, _lp_linchk_l2=1, _lp_linchk_l3=j, " + "_lp_linchk_l4=0] : " "0 <= i < pi and 0 <= j < pj }" ) isl_sched_after_expected = align_isl_maps_by_var_names( @@ -181,9 +181,9 @@ def test_lexschedule_and_islmap_creation(): isl_sched_before_expected = isl.Map( "[pi, pk] -> { " - "[_lp_sched_statement=0, i, k] -> " - "[_lp_sched_l0=0, _lp_sched_l1=i, _lp_sched_l2=0, _lp_sched_l3=k, " - "_lp_sched_l4=0] : " + "[_lp_linchk_statement=0, i, k] -> " + "[_lp_linchk_l0=0, _lp_linchk_l1=i, _lp_linchk_l2=0, _lp_linchk_l3=k, " + "_lp_linchk_l4=0] : " "0 <= i < pi and 0 <= k < pk }" ) isl_sched_before_expected = align_isl_maps_by_var_names( @@ -191,9 +191,9 @@ def test_lexschedule_and_islmap_creation(): isl_sched_after_expected = isl.Map( "[pi, pj] -> { " - "[_lp_sched_statement=1, i, j] -> " - "[_lp_sched_l0=0, _lp_sched_l1=i, _lp_sched_l2=1, _lp_sched_l3=j, " - "_lp_sched_l4=0] : " + "[_lp_linchk_statement=1, i, j] -> " + "[_lp_linchk_l0=0, _lp_linchk_l1=i, _lp_linchk_l2=1, _lp_linchk_l3=j, " + "_lp_linchk_l4=0] : " "0 <= i < pi and 0 <= j < pj }" ) isl_sched_after_expected = align_isl_maps_by_var_names( @@ -220,9 +220,9 @@ def test_lexschedule_and_islmap_creation(): isl_sched_before_expected = isl.Map( "[pi, pk] -> { " - "[_lp_sched_statement=%d, i, k] -> " - "[_lp_sched_l0=%d, _lp_sched_l1=i, _lp_sched_l2=0, _lp_sched_l3=k, " - "_lp_sched_l4=0] : " + "[_lp_linchk_statement=%d, i, k] -> " + "[_lp_linchk_l0=%d, _lp_linchk_l1=i, _lp_linchk_l2=0, _lp_linchk_l3=k, " + "_lp_linchk_l4=0] : " "0 <= i < pi and 0 <= k < pk }" % (sid_a, sid_a) ) @@ -231,9 +231,9 @@ def test_lexschedule_and_islmap_creation(): isl_sched_after_expected = isl.Map( "[pt] -> { " - "[_lp_sched_statement=%d, t] -> " - "[_lp_sched_l0=%d, _lp_sched_l1=t, _lp_sched_l2=0, _lp_sched_l3=0, " - "_lp_sched_l4=0] : " + "[_lp_linchk_statement=%d, t] -> " + "[_lp_linchk_l0=%d, _lp_linchk_l1=t, _lp_linchk_l2=0, _lp_linchk_l3=0, " + "_lp_linchk_l4=0] : " "0 <= t < pt }" % (sid_d, sid_d) ) @@ -266,9 +266,9 @@ def test_lexschedule_and_islmap_creation(): isl_sched_before_expected = isl.Map( "[pi, pj] -> { " - "[_lp_sched_statement=%d, i, j] -> " - "[_lp_sched_l0=0, _lp_sched_l1=i, _lp_sched_l2=0, _lp_sched_l3=j, " - "_lp_sched_l4=%d] : " + "[_lp_linchk_statement=%d, i, j] -> " + "[_lp_linchk_l0=0, _lp_linchk_l1=i, _lp_linchk_l2=0, _lp_linchk_l3=j, " + "_lp_linchk_l4=%d] : " "0 <= i < pi and 0 <= j < pj }" % (sid_b, sid_b) ) @@ -277,9 +277,9 @@ def test_lexschedule_and_islmap_creation(): isl_sched_after_expected = isl.Map( "[pi, pj] -> { " - "[_lp_sched_statement=%d, i, j] -> " - "[_lp_sched_l0=0, _lp_sched_l1=i, _lp_sched_l2=0, _lp_sched_l3=j, " - "_lp_sched_l4=%d] : " + "[_lp_linchk_statement=%d, i, j] -> " + "[_lp_linchk_l0=0, _lp_linchk_l1=i, _lp_linchk_l2=0, _lp_linchk_l3=j, " + "_lp_linchk_l4=%d] : " "0 <= i < pi and 0 <= j < pj }" % (sid_c, sid_c) ) @@ -312,9 +312,9 @@ def test_lexschedule_and_islmap_creation(): isl_sched_before_expected = isl.Map( "[pi, pj] -> { " - "[_lp_sched_statement=%d, i, j] -> " - "[_lp_sched_l0=%d, _lp_sched_l1=i, _lp_sched_l2=0, _lp_sched_l3=j, " - "_lp_sched_l4=0] : " + "[_lp_linchk_statement=%d, i, j] -> " + "[_lp_linchk_l0=%d, _lp_linchk_l1=i, _lp_linchk_l2=0, _lp_linchk_l3=j, " + "_lp_linchk_l4=0] : " "0 <= i < pi and 0 <= j < pj }" % (sid_b, sid_b) ) @@ -323,9 +323,9 @@ def test_lexschedule_and_islmap_creation(): isl_sched_after_expected = isl.Map( "[pt] -> { " - "[_lp_sched_statement=%d, t] -> " - "[_lp_sched_l0=%d, _lp_sched_l1=t, _lp_sched_l2=0, _lp_sched_l3=0, " - "_lp_sched_l4=0] : " + "[_lp_linchk_statement=%d, t] -> " + "[_lp_linchk_l0=%d, _lp_linchk_l1=t, _lp_linchk_l2=0, _lp_linchk_l3=0, " + "_lp_linchk_l4=0] : " "0 <= t < pt }" % (sid_d, sid_d) ) @@ -358,9 +358,9 @@ def test_lexschedule_and_islmap_creation(): isl_sched_before_expected = isl.Map( "[pi, pj] -> { " - "[_lp_sched_statement=%d, i, j] -> " - "[_lp_sched_l0=%d, _lp_sched_l1=i, _lp_sched_l2=0, _lp_sched_l3=j, " - "_lp_sched_l4=0] : " + "[_lp_linchk_statement=%d, i, j] -> " + "[_lp_linchk_l0=%d, _lp_linchk_l1=i, _lp_linchk_l2=0, _lp_linchk_l3=j, " + "_lp_linchk_l4=0] : " "0 <= i < pi and 0 <= j < pj }" % (sid_c, sid_c) ) @@ -369,9 +369,9 @@ def test_lexschedule_and_islmap_creation(): isl_sched_after_expected = isl.Map( "[pt] -> { " - "[_lp_sched_statement=%d, t] -> " - "[_lp_sched_l0=%d, _lp_sched_l1=t, _lp_sched_l2=0, _lp_sched_l3=0, " - "_lp_sched_l4=0] : " + "[_lp_linchk_statement=%d, t] -> " + "[_lp_linchk_l0=%d, _lp_linchk_l1=t, _lp_linchk_l2=0, _lp_linchk_l3=0, " + "_lp_linchk_l4=0] : " "0 <= t < pt }" % (sid_d, sid_d) ) -- GitLab From 626140b832828432fd5e78b1511b5054d5819214 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 31 May 2020 21:17:29 -0500 Subject: [PATCH 038/136] rename PairwiseScheduleStatementInstanceSet->StatementInstanceSet --- loopy/schedule/checker/__init__.py | 6 +++--- loopy/schedule/checker/schedule.py | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 4ce370b4c..6769b56b7 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -31,7 +31,7 @@ def get_schedule_for_statement_pair( ): """Create a :class:`loopy.schedule.checker.schedule.PairwiseScheduleBuilder` representing the order of two statements as a mapping from - :class:`loopy.schedule.checker.PairwiseScheduleStatementInstanceSet` + :class:`loopy.schedule.checker.StatementInstanceSet` to lexicographic time. :arg knl: A :class:`loopy.kernel.LoopKernel` containing the @@ -52,7 +52,7 @@ def get_schedule_for_statement_pair( :returns: A :class:`loopy.schedule.checker.schedule.PairwiseScheduleBuilder` representing the order of two statements as a mapping from - :class:`loopy.schedule.checker.PairwiseScheduleStatementInstanceSet` + :class:`loopy.schedule.checker.StatementInstanceSet` to lexicographic time. """ @@ -105,7 +105,7 @@ def get_isl_maps_from_PairwiseScheduleBuilder(sched_builder, knl): :arg sched_builder: A :class:`loopy.schedule.checker.schedule.PairwiseScheduleBuilder` representing the order of two statements as a mapping from - :class:`loopy.schedule.checker.PairwiseScheduleStatementInstanceSet` + :class:`loopy.schedule.checker.StatementInstanceSet` to lexicographic time. :arg knl: A :class:`loopy.kernel.LoopKernel` containing the diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index b3f21a6c3..8f55eff39 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -72,7 +72,7 @@ class PairwiseScheduleStatement(object): return "%s%s" % (self.insn_id, int_id) -class PairwiseScheduleStatementInstanceSet(object): +class StatementInstanceSet(object): """A representation of a set of (non-concurrent) instances of a statement being executed. The ordering of the instances is described by the `lex_points` attribute, a list representing points in a @@ -111,7 +111,7 @@ class PairwiseScheduleBuilder(object): .. attribute:: stmt_instance_before - A :class:`PairwiseScheduleStatementInstanceSet` whose ordering relative + A :class:`StatementInstanceSet` whose ordering relative to `stmt_instance_after is described by PairwiseScheduleBuilder. This is achieved by mapping the statement instances in both sets to points in a single lexicographic ordering. Points in lexicographic ordering @@ -120,7 +120,7 @@ class PairwiseScheduleBuilder(object): .. attribute:: stmt_instance_after - A :class:`PairwiseScheduleStatementInstanceSet` whose ordering relative + A :class:`StatementInstanceSet` whose ordering relative to `stmt_instance_before is described by PairwiseScheduleBuilder. This is achieved by mapping the statement instances in both sets to points in a single lexicographic ordering. Points in lexicographic ordering @@ -236,7 +236,7 @@ class PairwiseScheduleBuilder(object): if lp_insn_id == before_insn_id: # add before sched item - self.stmt_instance_before = PairwiseScheduleStatementInstanceSet( + self.stmt_instance_before = StatementInstanceSet( PairwiseScheduleStatement( insn_id=lp_insn_id, int_id=next_sid, # int representing insn @@ -246,7 +246,7 @@ class PairwiseScheduleBuilder(object): if lp_insn_id == after_insn_id: # add after sched item - self.stmt_instance_after = PairwiseScheduleStatementInstanceSet( + self.stmt_instance_after = StatementInstanceSet( PairwiseScheduleStatement( insn_id=lp_insn_id, int_id=next_sid, # int representing insn @@ -289,7 +289,7 @@ class PairwiseScheduleBuilder(object): """ def _pad_lex_tuple_with_zeros(stmt_inst, length): - return PairwiseScheduleStatementInstanceSet( + return StatementInstanceSet( stmt_inst.stmt, stmt_inst.lex_points[:] + [0]*(length-len(stmt_inst.lex_points)), ) @@ -333,7 +333,7 @@ class PairwiseScheduleBuilder(object): :returns: A two-tuple containing two :class:`islpy.Map`s representing the schedule as two mappings from statement instances to lexicographic time, one for - each of the two :class:`PairwiseScheduleStatementInstanceSet`s. + each of the two :class:`StatementInstanceSet`s. """ -- GitLab From 132a1c699a6802714aa18a0c2031c9e469d94c77 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 31 May 2020 21:23:02 -0500 Subject: [PATCH 039/136] rename PairwiseScheduleStatement->StatementRef --- loopy/schedule/checker/schedule.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 8f55eff39..d80b64520 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -23,8 +23,8 @@ THE SOFTWARE. import islpy as isl -class PairwiseScheduleStatement(object): - """A representation of a :mod:`loopy` statement. +class StatementRef(object): + """A reference to a :mod:`loopy` statement. .. attribute:: insn_id @@ -81,7 +81,7 @@ class StatementInstanceSet(object): .. attribute:: stmt - A :class:`PairwiseScheduleStatement`. + A :class:`StatementRef`. .. attribute:: lex_points @@ -237,7 +237,7 @@ class PairwiseScheduleBuilder(object): if lp_insn_id == before_insn_id: # add before sched item self.stmt_instance_before = StatementInstanceSet( - PairwiseScheduleStatement( + StatementRef( insn_id=lp_insn_id, int_id=next_sid, # int representing insn ), @@ -247,7 +247,7 @@ class PairwiseScheduleBuilder(object): if lp_insn_id == after_insn_id: # add after sched item self.stmt_instance_after = StatementInstanceSet( - PairwiseScheduleStatement( + StatementRef( insn_id=lp_insn_id, int_id=next_sid, # int representing insn ), @@ -284,7 +284,7 @@ class PairwiseScheduleBuilder(object): def pad_lex_tuples_with_zeros(self): """Find the maximum number of lexicographic dimensions represented in the lexicographic ordering, and if any - :class:`PairwiseScheduleStatement` maps to a lex point tuple with + :class:`StatementRef` maps to a lex point tuple with fewer dimensions, add a zero for each of the missing dimensions. """ -- GitLab From 7a9a5bde0be356d90a012a1fab018c8d31520514 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 31 May 2020 21:28:23 -0500 Subject: [PATCH 040/136] rename StatementInstanceSet.stmt->StatementInstanceSet.stmt_ref --- loopy/schedule/checker/__init__.py | 4 ++-- loopy/schedule/checker/schedule.py | 14 +++++++------- test/test_linearization_checker.py | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 6769b56b7..7729dbbb1 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -120,10 +120,10 @@ def get_isl_maps_from_PairwiseScheduleBuilder(sched_builder, knl): # {{{ Get iname domains dom_before = knl.get_inames_domain( knl.id_to_insn[ - sched_builder.stmt_instance_before.stmt.insn_id].within_inames) + sched_builder.stmt_instance_before.stmt_ref.insn_id].within_inames) dom_after = knl.get_inames_domain( knl.id_to_insn[ - sched_builder.stmt_instance_after.stmt.insn_id].within_inames) + sched_builder.stmt_instance_after.stmt_ref.insn_id].within_inames) # }}} # {{{ Get isl maps diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index d80b64520..8963fb576 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -79,7 +79,7 @@ class StatementInstanceSet(object): lexicographic ordering of statements. Each field in the list corresponds to a dimension in the lexicographic ordering. - .. attribute:: stmt + .. attribute:: stmt_ref A :class:`StatementRef`. @@ -93,14 +93,14 @@ class StatementInstanceSet(object): def __init__( self, - stmt, + stmt_ref, lex_points, ): - self.stmt = stmt + self.stmt_ref = stmt_ref self.lex_points = lex_points def __str__(self): - return "{%s, %s}" % (self.stmt, self.lex_points) + return "{%s, %s}" % (self.stmt_ref, self.lex_points) class PairwiseScheduleBuilder(object): @@ -290,7 +290,7 @@ class PairwiseScheduleBuilder(object): def _pad_lex_tuple_with_zeros(stmt_inst, length): return StatementInstanceSet( - stmt_inst.stmt, + stmt_inst.stmt_ref, stmt_inst.lex_points[:] + [0]*(length-len(stmt_inst.lex_points)), ) @@ -372,7 +372,7 @@ class PairwiseScheduleBuilder(object): # Right now, statement instance tuples consist of single int. # Add all inames from domains to each map domain tuple. tuple_pair = [( - (stmt_inst.stmt.int_id, ) + tuple(dom_inames_ordered), + (stmt_inst.stmt_ref.int_id, ) + tuple(dom_inames_ordered), stmt_inst.lex_points )] @@ -402,7 +402,7 @@ class PairwiseScheduleBuilder(object): def stringify_sched_stmt_instance(stmt_inst): return "{\n[%s=%s,] -> %s;\n}" % ( self.statement_var_name, - stmt_inst.stmt.int_id, + stmt_inst.stmt_ref.int_id, stmt_inst.lex_points) return "Before: %s\nAfter: %s" % ( diff --git a/test/test_linearization_checker.py b/test/test_linearization_checker.py index 7a67ab824..396fccf4f 100644 --- a/test/test_linearization_checker.py +++ b/test/test_linearization_checker.py @@ -243,7 +243,7 @@ def test_lexschedule_and_islmap_creation(): assert isl_sched_before == isl_sched_before_expected assert isl_sched_after == isl_sched_after_expected - if sched_ad.stmt_instance_before.stmt.int_id == 0: + if sched_ad.stmt_instance_before.stmt_ref.int_id == 0: perform_insn_ad_checks_with(0, 1) else: perform_insn_ad_checks_with(1, 0) @@ -289,7 +289,7 @@ def test_lexschedule_and_islmap_creation(): assert isl_sched_before == isl_sched_before_expected assert isl_sched_after == isl_sched_after_expected - if sched_bc.stmt_instance_before.stmt.int_id == 0: + if sched_bc.stmt_instance_before.stmt_ref.int_id == 0: perform_insn_bc_checks_with(0, 1) else: perform_insn_bc_checks_with(1, 0) @@ -335,7 +335,7 @@ def test_lexschedule_and_islmap_creation(): assert isl_sched_before == isl_sched_before_expected assert isl_sched_after == isl_sched_after_expected - if sched_bd.stmt_instance_before.stmt.int_id == 0: + if sched_bd.stmt_instance_before.stmt_ref.int_id == 0: perform_insn_bd_checks_with(0, 1) else: perform_insn_bd_checks_with(1, 0) @@ -381,7 +381,7 @@ def test_lexschedule_and_islmap_creation(): assert isl_sched_before == isl_sched_before_expected assert isl_sched_after == isl_sched_after_expected - if sched_cd.stmt_instance_before.stmt.int_id == 0: + if sched_cd.stmt_instance_before.stmt_ref.int_id == 0: perform_insn_cd_checks_with(0, 1) else: perform_insn_cd_checks_with(1, 0) -- GitLab From 30054b19b0751045e4515a95420505cc57f99e3d Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 31 May 2020 21:34:58 -0500 Subject: [PATCH 041/136] keep docstring example consistent with identifier naming policy --- loopy/schedule/checker/schedule.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 8963fb576..26ceb49c4 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -136,7 +136,11 @@ class PairwiseScheduleBuilder(object): A :class:`str` specifying the prefix to be used for the variables representing the dimensions in the lexicographic ordering. E.g., - a prefix of "lex" might yield variables "lex0", "lex1", "lex2". + a prefix of "_lp_linchk_lex" might yield variables "_lp_linchk_lex0", + "_lp_linchk_lex1", "_lp_linchk_lex2". Note the identifier prefix + policies described in the documentation under + *Loopy's Model of a Kernel* -> *Identifiers*. + . """ -- GitLab From a9bbc92e840fe9deab63be773141d2be0bbabb17 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 31 May 2020 22:25:13 -0500 Subject: [PATCH 042/136] add example usage to docstring for get_schedule_for_statement_pair() and PairwiseScheduleBuilder() --- loopy/schedule/checker/__init__.py | 39 ++++++++++++++++++++++- loopy/schedule/checker/schedule.py | 50 +++++++++++++++++++++++++++++- 2 files changed, 87 insertions(+), 2 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 7729dbbb1..c454254f6 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -40,7 +40,7 @@ def get_schedule_for_statement_pair( :arg linearization_items: A list of :class:`loopy.schedule.ScheduleItem` (to be renamed to `loopy.schedule.LinearizationItem`) containing the two linearization items for which a schedule will be - created. This list may be a partial linearization for a + created. This list may be a *partial* linearization for a kernel since this function may be used during the linearization process. @@ -54,6 +54,43 @@ def get_schedule_for_statement_pair( representing the order of two statements as a mapping from :class:`loopy.schedule.checker.StatementInstanceSet` to lexicographic time. + + Example usage:: + + # Make kernel -------------------------------------------------------- + knl = lp.make_kernel( + "{[i,j,k]: 0<=i *Identifiers*. - . + + Example usage:: + + # Make kernel -------------------------------------------------------- + knl = lp.make_kernel( + "{[i,j,k]: 0<=i Date: Sun, 31 May 2020 22:33:59 -0500 Subject: [PATCH 043/136] add example schedule creation output to docstring examples --- loopy/schedule/checker/__init__.py | 16 ++++++++++++++++ loopy/schedule/checker/schedule.py | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index c454254f6..4489ca69b 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -91,6 +91,22 @@ def get_schedule_for_statement_pair( sched_a, sched_b = get_isl_maps_from_PairwiseScheduleBuilder( sched_builder_ab, knl) + print(sched_a) + print(sched_b) + + Example Output:: + + [pi, pj, pk] -> { + [_lp_linchk_statement = 0, i, j, k] -> + [_lp_linchk_l0 = 0, _lp_linchk_l1 = i, _lp_linchk_l2 = 0, + _lp_linchk_l3 = j, _lp_linchk_l4 = 0] : + 0 <= i < pi and 0 <= j < pj and 0 <= k < pk } + [pi, pj, pk] -> { + [_lp_linchk_statement = 1, i, j, k] -> + [_lp_linchk_l0 = 0, _lp_linchk_l1 = i, _lp_linchk_l2 = 1, + _lp_linchk_l3 = k, _lp_linchk_l4 = 0] : + 0 <= i < pi and 0 <= j < pj and 0 <= k < pk } + """ # {{{ Preprocess if not already preprocessed diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index d7cc7b454..fead079ac 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -190,6 +190,22 @@ class PairwiseScheduleBuilder(object): sched_a, sched_b = get_isl_maps_from_PairwiseScheduleBuilder( sched_builder_ab, knl) + print(sched_a) + print(sched_b) + + Example Output:: + + [pi, pj, pk] -> { + [_lp_linchk_statement = 0, i, j, k] -> + [_lp_linchk_l0 = 0, _lp_linchk_l1 = i, _lp_linchk_l2 = 0, + _lp_linchk_l3 = j, _lp_linchk_l4 = 0] : + 0 <= i < pi and 0 <= j < pj and 0 <= k < pk } + [pi, pj, pk] -> { + [_lp_linchk_statement = 1, i, j, k] -> + [_lp_linchk_l0 = 0, _lp_linchk_l1 = i, _lp_linchk_l2 = 1, + _lp_linchk_l3 = k, _lp_linchk_l4 = 0] : + 0 <= i < pi and 0 <= j < pj and 0 <= k < pk } + """ statement_var_name = "_lp_linchk_statement" -- GitLab From 8761fb2734364b27ef52ae28f3760bed18b05ea5 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 2 Jun 2020 04:18:13 -0500 Subject: [PATCH 044/136] for consistency between runs, sort var names extracted from isl sets --- loopy/schedule/checker/utils.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index 0728e9686..eb7707f67 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -156,7 +156,9 @@ def list_var_names_in_isl_sets( inames = set() for isl_set in isl_sets: inames.update(isl_set.get_var_names(set_dim)) - return list(inames) + + # sorting is not necessary, but keeps results consistent between runs + return sorted(list(inames)) def create_symbolic_isl_map_from_tuples( -- GitLab From 055be9744ec3a0377d3c142b0e89cb3f3a237e20 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 2 Jun 2020 12:40:21 -0500 Subject: [PATCH 045/136] fix docstring indentation --- loopy/schedule/checker/schedule.py | 64 +++++++++++++++--------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index fead079ac..459ab4fcb 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -28,17 +28,17 @@ class StatementRef(object): .. attribute:: insn_id - A :class:`str` specifying the :mod:`loopy` instruction id - for this statement. + A :class:`str` specifying the :mod:`loopy` instruction id + for this statement. .. attribute:: int_id - A :class:`int` uniquely identifying the statement within a - :class:`PairwiseScheduleBuilder`. A :class:`PairwiseScheduleBuilder` - builds a mapping from points in a space of statement instances to - points in a lexicographic ordering. The `statement` dimension of a - point in the statement instance space representing an instance of - this statement is assigned this value (`int_id`). + A :class:`int` uniquely identifying the statement within a + :class:`PairwiseScheduleBuilder`. A :class:`PairwiseScheduleBuilder` + builds a mapping from points in a space of statement instances to + points in a lexicographic ordering. The `statement` dimension of a + point in the statement instance space representing an instance of + this statement is assigned this value (`int_id`). """ @@ -81,13 +81,13 @@ class StatementInstanceSet(object): .. attribute:: stmt_ref - A :class:`StatementRef`. + A :class:`StatementRef`. .. attribute:: lex_points - A list containing one value for each dimension in a lexicographic - ordering. These values describe the ordering of the statements, - and may be :class:`str` :mod:`loopy` inames or :class:`int`. + A list containing one value for each dimension in a lexicographic + ordering. These values describe the ordering of the statements, + and may be :class:`str` :mod:`loopy` inames or :class:`int`. """ @@ -111,35 +111,35 @@ class PairwiseScheduleBuilder(object): .. attribute:: stmt_instance_before - A :class:`StatementInstanceSet` whose ordering relative - to `stmt_instance_after is described by PairwiseScheduleBuilder. This - is achieved by mapping the statement instances in both sets to points - in a single lexicographic ordering. Points in lexicographic ordering - are represented as a list of :class:`int` or as :class:`str` - :mod:`loopy` inames. + A :class:`StatementInstanceSet` whose ordering relative + to `stmt_instance_after is described by PairwiseScheduleBuilder. This + is achieved by mapping the statement instances in both sets to points + in a single lexicographic ordering. Points in lexicographic ordering + are represented as a list of :class:`int` or as :class:`str` + :mod:`loopy` inames. .. attribute:: stmt_instance_after - A :class:`StatementInstanceSet` whose ordering relative - to `stmt_instance_before is described by PairwiseScheduleBuilder. This - is achieved by mapping the statement instances in both sets to points - in a single lexicographic ordering. Points in lexicographic ordering - are represented as a list of :class:`int` or as :class:`str` - :mod:`loopy` inames. + A :class:`StatementInstanceSet` whose ordering relative + to `stmt_instance_before is described by PairwiseScheduleBuilder. This + is achieved by mapping the statement instances in both sets to points + in a single lexicographic ordering. Points in lexicographic ordering + are represented as a list of :class:`int` or as :class:`str` + :mod:`loopy` inames. .. attribute:: statement_var_name - A :class:`str` specifying the name of the isl variable used - to represent the unique :class:`int` statement id. + A :class:`str` specifying the name of the isl variable used + to represent the unique :class:`int` statement id. .. attribute:: lex_var_prefix - A :class:`str` specifying the prefix to be used for the variables - representing the dimensions in the lexicographic ordering. E.g., - a prefix of "_lp_linchk_lex" might yield variables "_lp_linchk_lex0", - "_lp_linchk_lex1", "_lp_linchk_lex2". Note the identifier prefix - policies described in the documentation under - *Loopy's Model of a Kernel* -> *Identifiers*. + A :class:`str` specifying the prefix to be used for the variables + representing the dimensions in the lexicographic ordering. E.g., + a prefix of "_lp_linchk_lex" might yield variables "_lp_linchk_lex0", + "_lp_linchk_lex1", "_lp_linchk_lex2". Note the identifier prefix + policies described in the documentation under + *Loopy's Model of a Kernel* -> *Identifiers*. Example usage:: -- GitLab From 6b0b01bd10aeffc7afbf9f0050b3e04e84710577 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 2 Jun 2020 12:49:20 -0500 Subject: [PATCH 046/136] remove redundant usage example and note that a PairwiseScheduleBuilder should be created using get_schedule_for_statement_pair --- loopy/schedule/checker/__init__.py | 2 +- loopy/schedule/checker/schedule.py | 68 +----------------------------- 2 files changed, 3 insertions(+), 67 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 4489ca69b..8c4b06b0d 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -71,7 +71,7 @@ def get_schedule_for_statement_pair( # Get a linearization knl = lp.get_one_linearized_kernel(lp.preprocess_kernel(knl)) - # Get a pairwise schedule* ------------------------------------------- + # Get a pairwise schedule -------------------------------------------- from loopy.schedule.checker import ( get_schedule_for_statement_pair, diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 459ab4fcb..12547d01c 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -107,7 +107,8 @@ class PairwiseScheduleBuilder(object): """Given a pair of statements in a linearized kernel, PairwiseScheduleBuilder determines the (relative) order in which the instances are executed, by creating a mapping from statement instances to points in a single - lexicographic ordering. + lexicographic ordering. To create a PairwiseScheduleBuilder, use + :func:`loopy.schedule.checker.get_schedule_for_statement_pair`. .. attribute:: stmt_instance_before @@ -141,71 +142,6 @@ class PairwiseScheduleBuilder(object): policies described in the documentation under *Loopy's Model of a Kernel* -> *Identifiers*. - Example usage:: - - # Make kernel -------------------------------------------------------- - knl = lp.make_kernel( - "{[i,j,k]: 0<=i { - [_lp_linchk_statement = 0, i, j, k] -> - [_lp_linchk_l0 = 0, _lp_linchk_l1 = i, _lp_linchk_l2 = 0, - _lp_linchk_l3 = j, _lp_linchk_l4 = 0] : - 0 <= i < pi and 0 <= j < pj and 0 <= k < pk } - [pi, pj, pk] -> { - [_lp_linchk_statement = 1, i, j, k] -> - [_lp_linchk_l0 = 0, _lp_linchk_l1 = i, _lp_linchk_l2 = 1, - _lp_linchk_l3 = k, _lp_linchk_l4 = 0] : - 0 <= i < pi and 0 <= j < pj and 0 <= k < pk } - """ statement_var_name = "_lp_linchk_statement" -- GitLab From bdef0a639f8a4dd9a6ceb9d58c74650437861831 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 2 Jun 2020 12:55:56 -0500 Subject: [PATCH 047/136] rephrase doc comment about using get_schedule_for_statement_pair to create a PairwiseScheduleBuilder --- loopy/schedule/checker/schedule.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 12547d01c..756b85628 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -107,8 +107,9 @@ class PairwiseScheduleBuilder(object): """Given a pair of statements in a linearized kernel, PairwiseScheduleBuilder determines the (relative) order in which the instances are executed, by creating a mapping from statement instances to points in a single - lexicographic ordering. To create a PairwiseScheduleBuilder, use - :func:`loopy.schedule.checker.get_schedule_for_statement_pair`. + lexicographic ordering. The function + :func:`loopy.schedule.checker.get_schedule_for_statement_pair` is the + preferred method of creating a PairwiseScheduleBuilder. .. attribute:: stmt_instance_before -- GitLab From 66283621373e8706b17795cb40e949dc2457c6a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Kl=C3=B6ckner?= Date: Wed, 3 Jun 2020 01:03:55 +0200 Subject: [PATCH 048/136] Some styling fixes for pairwise schedule representation --- doc/ref_kernel.rst | 2 ++ loopy/schedule/checker/__init__.py | 28 +++++++++++++++++----------- loopy/schedule/checker/schedule.py | 10 +++------- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/doc/ref_kernel.rst b/doc/ref_kernel.rst index af35221ad..1c4d8971d 100644 --- a/doc/ref_kernel.rst +++ b/doc/ref_kernel.rst @@ -154,6 +154,8 @@ Tag Meaning Identifiers ----------- +.. _reserved-identifiers: + Reserved Identifiers ^^^^^^^^^^^^^^^^^^^^ diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 8c4b06b0d..64d3d7c66 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -21,7 +21,7 @@ THE SOFTWARE. """ -# {{{ Create PairwiseScheduleBuilder for statement pair +# {{{ create PairwiseScheduleBuilder for statement pair def get_schedule_for_statement_pair( knl, @@ -30,9 +30,9 @@ def get_schedule_for_statement_pair( insn_id_after, ): """Create a :class:`loopy.schedule.checker.schedule.PairwiseScheduleBuilder` - representing the order of two statements as a mapping from - :class:`loopy.schedule.checker.StatementInstanceSet` - to lexicographic time. + representing the order of two statements as a mapping from + :class:`loopy.schedule.checker.StatementInstanceSet` + to lexicographic time. :arg knl: A :class:`loopy.kernel.LoopKernel` containing the linearization items that will be used to create a schedule. @@ -109,12 +109,15 @@ def get_schedule_for_statement_pair( """ - # {{{ Preprocess if not already preprocessed + # {{{ preprocess if not already preprocessed + from loopy import preprocess_kernel preproc_knl = preprocess_kernel(knl) + # }}} - # {{{ Find any EnterLoop inames that are tagged as concurrent + # {{{ find any EnterLoop inames that are tagged as concurrent + # so that PairwiseScheduleBuilder knows to ignore them # (In the future, this shouldn't be necessary because there # won't be any inames with ConcurrentTags in EnterLoop linearization items. @@ -132,9 +135,11 @@ def get_schedule_for_statement_pair( "get_schedule_for_statement_pair encountered EnterLoop for inames %s " "with ConcurrentTag(s) in linearization for kernel %s. " "Ignoring these loops." % (conc_loop_inames, preproc_knl.name)) + # }}} # {{{ Create PairwiseScheduleBuilder: mapping of {statement instance: lex point} + # include only instructions involved in this dependency from loopy.schedule.checker.schedule import PairwiseScheduleBuilder return PairwiseScheduleBuilder( @@ -143,17 +148,18 @@ def get_schedule_for_statement_pair( insn_id_after, loops_to_ignore=conc_loop_inames, ) + # }}} # }}} -# {{{ Get isl map pair from PairwiseScheduleBuilder +# {{{ get_isl_maps_from_PairwiseScheduleBuilder def get_isl_maps_from_PairwiseScheduleBuilder(sched_builder, knl): - """Create a pair of :class:`islpy.Map`s representing a - sub-schedule as two mappings from statement instances to lexicographic - time, one for the dependee statement and one for the depender. + """Create a pair of :class:`islpy.Map`\ s representing a + sub-schedule as two mappings from statement instances to lexicographic + time, one for the dependee statement and one for the depender. :arg sched_builder: A :class:`loopy.schedule.checker.schedule.PairwiseScheduleBuilder` @@ -164,7 +170,7 @@ def get_isl_maps_from_PairwiseScheduleBuilder(sched_builder, knl): :arg knl: A :class:`loopy.kernel.LoopKernel` containing the linearization items that will be used to create a schedule. - :returns: A two-tuple containing two :class:`islpy.Map`s + :returns: A two-tuple containing two :class:`islpy.Map`\ s representing the schedule as two mappings from statement instances to lexicographic time, one for the dependee and one for the depender. diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 756b85628..6dc091f9e 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -38,7 +38,7 @@ class StatementRef(object): builds a mapping from points in a space of statement instances to points in a lexicographic ordering. The `statement` dimension of a point in the statement instance space representing an instance of - this statement is assigned this value (`int_id`). + this statement is assigned this value. """ @@ -88,7 +88,6 @@ class StatementInstanceSet(object): A list containing one value for each dimension in a lexicographic ordering. These values describe the ordering of the statements, and may be :class:`str` :mod:`loopy` inames or :class:`int`. - """ def __init__( @@ -131,7 +130,7 @@ class PairwiseScheduleBuilder(object): .. attribute:: statement_var_name - A :class:`str` specifying the name of the isl variable used + A :class:`str` specifying the name of the variable used to represent the unique :class:`int` statement id. .. attribute:: lex_var_prefix @@ -139,10 +138,7 @@ class PairwiseScheduleBuilder(object): A :class:`str` specifying the prefix to be used for the variables representing the dimensions in the lexicographic ordering. E.g., a prefix of "_lp_linchk_lex" might yield variables "_lp_linchk_lex0", - "_lp_linchk_lex1", "_lp_linchk_lex2". Note the identifier prefix - policies described in the documentation under - *Loopy's Model of a Kernel* -> *Identifiers*. - + "_lp_linchk_lex1", "_lp_linchk_lex2". Cf. :ref:`reserved-identifiers`. """ statement_var_name = "_lp_linchk_statement" -- GitLab From 0bb444450e327a11aae08ce9e26c441e0d706057 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Kl=C3=B6ckner?= Date: Wed, 3 Jun 2020 01:32:19 +0200 Subject: [PATCH 049/136] Placate flake8 --- loopy/schedule/checker/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 64d3d7c66..790088d5c 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -117,7 +117,7 @@ def get_schedule_for_statement_pair( # }}} # {{{ find any EnterLoop inames that are tagged as concurrent - + # so that PairwiseScheduleBuilder knows to ignore them # (In the future, this shouldn't be necessary because there # won't be any inames with ConcurrentTags in EnterLoop linearization items. @@ -157,7 +157,7 @@ def get_schedule_for_statement_pair( # {{{ get_isl_maps_from_PairwiseScheduleBuilder def get_isl_maps_from_PairwiseScheduleBuilder(sched_builder, knl): - """Create a pair of :class:`islpy.Map`\ s representing a + r"""Create a pair of :class:`islpy.Map`\ s representing a sub-schedule as two mappings from statement instances to lexicographic time, one for the dependee statement and one for the depender. -- GitLab From 5dafc30ab3e7f189f80980d21064b6bc6dff2c5a Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Fri, 5 Jun 2020 06:27:08 -0500 Subject: [PATCH 050/136] remove get_isl_maps_from_PairwiseScheduleBuilder(); instead get j inames domains inside PairwiseScheduleBuilder.create_isl_maps() and just call PairwiseScheduleBuilder.create_isl_maps directly --- loopy/schedule/checker/__init__.py | 50 +++--------------------------- loopy/schedule/checker/schedule.py | 29 +++++++++-------- test/test_linearization_checker.py | 19 ++++-------- 3 files changed, 24 insertions(+), 74 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 8c4b06b0d..b287ca4b7 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -57,7 +57,7 @@ def get_schedule_for_statement_pair( Example usage:: - # Make kernel -------------------------------------------------------- + # Make kernel ------------------------------------------------------------ knl = lp.make_kernel( "{[i,j,k]: 0<=i used in statement domain>) -> @@ -389,11 +390,9 @@ class PairwiseScheduleBuilder(object): map_before = _get_isl_map_for_stmt_inst( self.stmt_instance_before, - dom_before, dom_inames_ordered_before) map_after = _get_isl_map_for_stmt_inst( self.stmt_instance_after, - dom_after, dom_inames_ordered_after) return (map_before, map_after) diff --git a/test/test_linearization_checker.py b/test/test_linearization_checker.py index 396fccf4f..02ac08592 100644 --- a/test/test_linearization_checker.py +++ b/test/test_linearization_checker.py @@ -50,7 +50,6 @@ def test_lexschedule_and_islmap_creation(): import islpy as isl from loopy.schedule.checker import ( get_schedule_for_statement_pair, - get_isl_maps_from_PairwiseScheduleBuilder, ) from loopy.schedule.checker.utils import ( align_isl_maps_by_var_names, @@ -138,8 +137,7 @@ def test_lexschedule_and_islmap_creation(): # Get two isl maps from the PairwiseScheduleBuilder - isl_sched_before, isl_sched_after = get_isl_maps_from_PairwiseScheduleBuilder( - sched_ab, knl) + isl_sched_before, isl_sched_after = sched_ab.create_isl_maps(knl) # Create expected maps, align, compare @@ -174,8 +172,7 @@ def test_lexschedule_and_islmap_creation(): # Get two isl maps from the PairwiseScheduleBuilder - isl_sched_before, isl_sched_after = get_isl_maps_from_PairwiseScheduleBuilder( - sched_ac, knl) + isl_sched_before, isl_sched_after = sched_ac.create_isl_maps(knl) # Create expected maps, align, compare @@ -213,8 +210,7 @@ def test_lexschedule_and_islmap_creation(): # Get two isl maps from the PairwiseScheduleBuilder - isl_sched_before, isl_sched_after = \ - get_isl_maps_from_PairwiseScheduleBuilder(sched_ad, knl) + isl_sched_before, isl_sched_after = sched_ad.create_isl_maps(knl) # Create expected maps, align, compare @@ -259,8 +255,7 @@ def test_lexschedule_and_islmap_creation(): # Get two isl maps from the PairwiseScheduleBuilder - isl_sched_before, isl_sched_after = \ - get_isl_maps_from_PairwiseScheduleBuilder(sched_bc, knl) + isl_sched_before, isl_sched_after = sched_bc.create_isl_maps(knl) # Create expected maps, align, compare @@ -305,8 +300,7 @@ def test_lexschedule_and_islmap_creation(): # Get two isl maps from the PairwiseScheduleBuilder - isl_sched_before, isl_sched_after = \ - get_isl_maps_from_PairwiseScheduleBuilder(sched_bd, knl) + isl_sched_before, isl_sched_after = sched_bd.create_isl_maps(knl) # Create expected maps, align, compare @@ -351,8 +345,7 @@ def test_lexschedule_and_islmap_creation(): # Get two isl maps from the PairwiseScheduleBuilder - isl_sched_before, isl_sched_after = \ - get_isl_maps_from_PairwiseScheduleBuilder(sched_cd, knl) + isl_sched_before, isl_sched_after = sched_cd.create_isl_maps(knl) # Create expected maps, align, compare -- GitLab From bb2ebcf84438be2678be35a3fb3cea2e543783ad Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Fri, 5 Jun 2020 09:09:09 -0500 Subject: [PATCH 051/136] print name of class in PairwiseScheduleBuilder.__str__() --- loopy/schedule/checker/schedule.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 37e5a5f4c..882bcc73f 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -405,6 +405,7 @@ class PairwiseScheduleBuilder(object): stmt_inst.stmt_ref.int_id, stmt_inst.lex_points) - return "Before: %s\nAfter: %s" % ( + return "%s(\nBefore: %s\nAfter: %s\n)" % ( + self.__class__.__name__, stringify_sched_stmt_instance(self.stmt_instance_before), stringify_sched_stmt_instance(self.stmt_instance_after)) -- GitLab From a87f101a6b6339319eb9129a040304792d821389 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Fri, 5 Jun 2020 09:11:15 -0500 Subject: [PATCH 052/136] rename pose->idx --- loopy/schedule/checker/utils.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index eb7707f67..af9e4aaef 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -35,12 +35,12 @@ def get_islvars_from_space(space): return isl.make_zero_and_vars(in_names+out_names, param_names) -def add_dims_to_isl_set(isl_set, dim_type, names, new_pose_start): +def add_dims_to_isl_set(isl_set, dim_type, names, new_idx_start): new_set = isl_set.insert_dims( - dim_type, new_pose_start, len(names) - ).set_dim_name(dim_type, new_pose_start, names[0]) + dim_type, new_idx_start, len(names) + ).set_dim_name(dim_type, new_idx_start, names[0]) for i, name in enumerate(names[1:]): - new_set = new_set.set_dim_name(dim_type, new_pose_start+1+i, name) + new_set = new_set.set_dim_name(dim_type, new_idx_start+1+i, name) return new_set @@ -90,27 +90,27 @@ def reorder_dims_by_name( other_dim_len = len(isl_set.get_var_names(other_dim_type)) new_set = isl_set.copy() - for desired_pose, name in enumerate(desired_dims_ordered): + for desired_idx, name in enumerate(desired_dims_ordered): # if iname doesn't exist in set, add dim: if name not in new_set.get_var_names(dim_type): if add_missing: # insert missing dim in correct location new_set = new_set.insert_dims( - dim_type, desired_pose, 1 + dim_type, desired_idx, 1 ).set_dim_name( - dim_type, desired_pose, name) + dim_type, desired_idx, name) else: # iname exists in set - current_pose = new_set.find_dim_by_name(dim_type, name) - if current_pose != desired_pose: - # move_dims(dst_type, dst_pose, src_type, src_pose, n) + current_idx = new_set.find_dim_by_name(dim_type, name) + if current_idx != desired_idx: + # move_dims(dst_type, dst_idx, src_type, src_idx, n) # first move to other dim because isl is stupid new_set = new_set.move_dims( - other_dim_type, other_dim_len, dim_type, current_pose, 1) + other_dim_type, other_dim_len, dim_type, current_idx, 1) # now move it where we actually want it new_set = new_set.move_dims( - dim_type, desired_pose, other_dim_type, other_dim_len, 1) + dim_type, desired_idx, other_dim_type, other_dim_len, 1) return new_set -- GitLab From 57669bc184019b3d8ee86f0600f2242aeb657504 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Fri, 5 Jun 2020 09:55:41 -0500 Subject: [PATCH 053/136] change __str__ to __repr__ in StatementInstanceSet() and include class name in string --- loopy/schedule/checker/schedule.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 882bcc73f..dbb2a7455 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -98,8 +98,9 @@ class StatementInstanceSet(object): self.stmt_ref = stmt_ref self.lex_points = lex_points - def __str__(self): - return "{%s, %s}" % (self.stmt_ref, self.lex_points) + def __repr__(self): + return "%s(%s, %s)" % ( + self.__class__.__name__, self.stmt_ref, self.lex_points) class PairwiseScheduleBuilder(object): -- GitLab From e3a4db902e49ee92b228219ac9cdce62a324137c Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 7 Jun 2020 15:24:42 -0500 Subject: [PATCH 054/136] rename _get_isl_map_for_stmt_inst()->_get_map_for_stmt_inst() --- loopy/schedule/checker/schedule.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index dbb2a7455..dc55a3bcd 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -347,7 +347,7 @@ class PairwiseScheduleBuilder(object): params_sched = [] out_names_sched = self.get_lex_var_names() - def _get_isl_map_for_stmt_inst(stmt_inst, dom_inames_ordered): + def _get_map_for_stmt_inst(stmt_inst, dom_inames_ordered): # Get inames domain for statement instance (a BasicSet) dom = knl.get_inames_domain( @@ -385,10 +385,10 @@ class PairwiseScheduleBuilder(object): space=sched_space, ) - map_before = _get_isl_map_for_stmt_inst( + map_before = _get_map_for_stmt_inst( self.stmt_instance_before, dom_inames_ordered_before) - map_after = _get_isl_map_for_stmt_inst( + map_after = _get_map_for_stmt_inst( self.stmt_instance_after, dom_inames_ordered_after) -- GitLab From 0e317270aeebd9e154c4e307d27cdb7b4375a07d Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 7 Jun 2020 15:30:34 -0500 Subject: [PATCH 055/136] rename create_isl_maps()->build_maps() --- loopy/schedule/checker/__init__.py | 2 +- loopy/schedule/checker/schedule.py | 2 +- test/test_linearization_checker.py | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 9698b95fc..6fd280a45 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -85,7 +85,7 @@ def get_schedule_for_statement_pair( # Get two isl maps from the PairwiseScheduleBuilder ---------------------- - sched_a, sched_b = sched_builder_ab.create_isl_maps(knl) + sched_a, sched_b = sched_builder_ab.build_maps(knl) print(sched_a) print(sched_b) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index dc55a3bcd..c9cc5981e 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -303,7 +303,7 @@ class PairwiseScheduleBuilder(object): self.stmt_instance_after = _pad_lex_tuple_with_zeros( self.stmt_instance_after, max_lex_dim) - def create_isl_maps( + def build_maps( self, knl, dom_inames_ordered_before=None, diff --git a/test/test_linearization_checker.py b/test/test_linearization_checker.py index 02ac08592..16c56274d 100644 --- a/test/test_linearization_checker.py +++ b/test/test_linearization_checker.py @@ -137,7 +137,7 @@ def test_lexschedule_and_islmap_creation(): # Get two isl maps from the PairwiseScheduleBuilder - isl_sched_before, isl_sched_after = sched_ab.create_isl_maps(knl) + isl_sched_before, isl_sched_after = sched_ab.build_maps(knl) # Create expected maps, align, compare @@ -172,7 +172,7 @@ def test_lexschedule_and_islmap_creation(): # Get two isl maps from the PairwiseScheduleBuilder - isl_sched_before, isl_sched_after = sched_ac.create_isl_maps(knl) + isl_sched_before, isl_sched_after = sched_ac.build_maps(knl) # Create expected maps, align, compare @@ -210,7 +210,7 @@ def test_lexschedule_and_islmap_creation(): # Get two isl maps from the PairwiseScheduleBuilder - isl_sched_before, isl_sched_after = sched_ad.create_isl_maps(knl) + isl_sched_before, isl_sched_after = sched_ad.build_maps(knl) # Create expected maps, align, compare @@ -255,7 +255,7 @@ def test_lexschedule_and_islmap_creation(): # Get two isl maps from the PairwiseScheduleBuilder - isl_sched_before, isl_sched_after = sched_bc.create_isl_maps(knl) + isl_sched_before, isl_sched_after = sched_bc.build_maps(knl) # Create expected maps, align, compare @@ -300,7 +300,7 @@ def test_lexschedule_and_islmap_creation(): # Get two isl maps from the PairwiseScheduleBuilder - isl_sched_before, isl_sched_after = sched_bd.create_isl_maps(knl) + isl_sched_before, isl_sched_after = sched_bd.build_maps(knl) # Create expected maps, align, compare @@ -345,7 +345,7 @@ def test_lexschedule_and_islmap_creation(): # Get two isl maps from the PairwiseScheduleBuilder - isl_sched_before, isl_sched_after = sched_cd.create_isl_maps(knl) + isl_sched_before, isl_sched_after = sched_cd.build_maps(knl) # Create expected maps, align, compare -- GitLab From 3e93b622192980ecd6c1a2b46391a25497e60127 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 7 Jun 2020 15:45:21 -0500 Subject: [PATCH 056/136] rename isl_map->map_obj --- loopy/schedule/checker/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index af9e4aaef..5c8ae05f2 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -23,8 +23,8 @@ THE SOFTWARE. import islpy as isl -def prettier_map_string(isl_map): - return str(isl_map +def prettier_map_string(map_obj): + return str(map_obj ).replace("{ ", "{\n").replace(" }", "\n}").replace("; ", ";\n") -- GitLab From ee4d98fbef071df03daaa6c99f36e3b10aae1881 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 8 Jun 2020 14:13:15 -0500 Subject: [PATCH 057/136] renamed create_symbolic_isl_map_from_tuples()->create_symbolic_map_from_tuples() --- loopy/schedule/checker/schedule.py | 4 ++-- loopy/schedule/checker/utils.py | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index c9cc5981e..d63bb9c41 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -340,7 +340,7 @@ class PairwiseScheduleBuilder(object): from loopy.schedule.checker.utils import ( list_var_names_in_isl_sets, get_isl_space, - create_symbolic_isl_map_from_tuples, + create_symbolic_map_from_tuples, add_dims_to_isl_set, ) @@ -380,7 +380,7 @@ class PairwiseScheduleBuilder(object): )] # create isl map - return create_symbolic_isl_map_from_tuples( + return create_symbolic_map_from_tuples( tuple_pairs_with_domains=zip(tuple_pair, dom_to_intersect), space=sched_space, ) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index 5c8ae05f2..8e65d9905 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -161,7 +161,7 @@ def list_var_names_in_isl_sets( return sorted(list(inames)) -def create_symbolic_isl_map_from_tuples( +def create_symbolic_map_from_tuples( tuple_pairs_with_domains, space, ): @@ -191,7 +191,6 @@ def create_symbolic_isl_map_from_tuples( dim_type = isl.dim_type - #param_names = space.get_var_names(isl.dim_type.param) space_out_names = space.get_var_names(dim_type.out) space_in_names = space.get_var_names(isl.dim_type.in_) -- GitLab From 6e2becf4da7f0567ab801bb012ee4dd9a48055bc Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 8 Jun 2020 14:29:40 -0500 Subject: [PATCH 058/136] remove 'isl' from more locally used var names --- loopy/schedule/checker/__init__.py | 2 +- loopy/schedule/checker/schedule.py | 6 +- test/test_linearization_checker.py | 122 ++++++++++++++--------------- 3 files changed, 65 insertions(+), 65 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 6fd280a45..716a0cb58 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -83,7 +83,7 @@ def get_schedule_for_statement_pair( "insn_b", ) - # Get two isl maps from the PairwiseScheduleBuilder ---------------------- + # Get two maps from the PairwiseScheduleBuilder -------------------------- sched_a, sched_b = sched_builder_ab.build_maps(knl) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index d63bb9c41..8c503b191 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -353,7 +353,7 @@ class PairwiseScheduleBuilder(object): dom = knl.get_inames_domain( knl.id_to_insn[stmt_inst.stmt_ref.insn_id].within_inames) - # create an isl space + # create space (an isl space in current implementation) # {('statement', used in statement domain>) -> # (lexicographic ordering dims)} if dom_inames_ordered is None: @@ -370,7 +370,7 @@ class PairwiseScheduleBuilder(object): add_dims_to_isl_set( dom, isl.dim_type.set, [self.statement_var_name], 0), ] - # Each isl map representing the schedule will map + # Each map representing the schedule will map # statement instances -> lex time. # Right now, statement instance tuples consist of single int. # Add all inames from domains to each map domain tuple. @@ -379,7 +379,7 @@ class PairwiseScheduleBuilder(object): stmt_inst.lex_points )] - # create isl map + # create map return create_symbolic_map_from_tuples( tuple_pairs_with_domains=zip(tuple_pair, dom_to_intersect), space=sched_space, diff --git a/test/test_linearization_checker.py b/test/test_linearization_checker.py index 16c56274d..559a5c24e 100644 --- a/test/test_linearization_checker.py +++ b/test/test_linearization_checker.py @@ -46,7 +46,7 @@ else: faulthandler.enable() -def test_lexschedule_and_islmap_creation(): +def test_lexschedule_and_map_creation(): import islpy as isl from loopy.schedule.checker import ( get_schedule_for_statement_pair, @@ -135,34 +135,34 @@ def test_lexschedule_and_islmap_creation(): assert sched_ab.stmt_instance_before.lex_points == [0, 'i', 0, 'k', 0] assert sched_ab.stmt_instance_after.lex_points == [0, 'i', 1, 'j', 0] - # Get two isl maps from the PairwiseScheduleBuilder + # Get two maps from the PairwiseScheduleBuilder - isl_sched_before, isl_sched_after = sched_ab.build_maps(knl) + sched_map_before, sched_map_after = sched_ab.build_maps(knl) # Create expected maps, align, compare - isl_sched_before_expected = isl.Map( + sched_map_before_expected = isl.Map( "[pi, pk] -> { " "[_lp_linchk_statement=0, i, k] -> " "[_lp_linchk_l0=0, _lp_linchk_l1=i, _lp_linchk_l2=0, _lp_linchk_l3=k, " "_lp_linchk_l4=0] : " "0 <= i < pi and 0 <= k < pk }" ) - isl_sched_before_expected = align_isl_maps_by_var_names( - isl_sched_before_expected, isl_sched_before) + sched_map_before_expected = align_isl_maps_by_var_names( + sched_map_before_expected, sched_map_before) - isl_sched_after_expected = isl.Map( + sched_map_after_expected = isl.Map( "[pi, pj] -> { " "[_lp_linchk_statement=1, i, j] -> " "[_lp_linchk_l0=0, _lp_linchk_l1=i, _lp_linchk_l2=1, _lp_linchk_l3=j, " "_lp_linchk_l4=0] : " "0 <= i < pi and 0 <= j < pj }" ) - isl_sched_after_expected = align_isl_maps_by_var_names( - isl_sched_after_expected, isl_sched_after) + sched_map_after_expected = align_isl_maps_by_var_names( + sched_map_after_expected, sched_map_after) - assert isl_sched_before == isl_sched_before_expected - assert isl_sched_after == isl_sched_after_expected + assert sched_map_before == sched_map_before_expected + assert sched_map_after == sched_map_after_expected # ------------------------------------------------------------------------------ # Relationship between insn_a and insn_c --------------------------------------- @@ -170,34 +170,34 @@ def test_lexschedule_and_islmap_creation(): assert sched_ac.stmt_instance_before.lex_points == [0, 'i', 0, 'k', 0] assert sched_ac.stmt_instance_after.lex_points == [0, 'i', 1, 'j', 0] - # Get two isl maps from the PairwiseScheduleBuilder + # Get two maps from the PairwiseScheduleBuilder - isl_sched_before, isl_sched_after = sched_ac.build_maps(knl) + sched_map_before, sched_map_after = sched_ac.build_maps(knl) # Create expected maps, align, compare - isl_sched_before_expected = isl.Map( + sched_map_before_expected = isl.Map( "[pi, pk] -> { " "[_lp_linchk_statement=0, i, k] -> " "[_lp_linchk_l0=0, _lp_linchk_l1=i, _lp_linchk_l2=0, _lp_linchk_l3=k, " "_lp_linchk_l4=0] : " "0 <= i < pi and 0 <= k < pk }" ) - isl_sched_before_expected = align_isl_maps_by_var_names( - isl_sched_before_expected, isl_sched_before) + sched_map_before_expected = align_isl_maps_by_var_names( + sched_map_before_expected, sched_map_before) - isl_sched_after_expected = isl.Map( + sched_map_after_expected = isl.Map( "[pi, pj] -> { " "[_lp_linchk_statement=1, i, j] -> " "[_lp_linchk_l0=0, _lp_linchk_l1=i, _lp_linchk_l2=1, _lp_linchk_l3=j, " "_lp_linchk_l4=0] : " "0 <= i < pi and 0 <= j < pj }" ) - isl_sched_after_expected = align_isl_maps_by_var_names( - isl_sched_after_expected, isl_sched_after) + sched_map_after_expected = align_isl_maps_by_var_names( + sched_map_after_expected, sched_map_after) - assert isl_sched_before == isl_sched_before_expected - assert isl_sched_after == isl_sched_after_expected + assert sched_map_before == sched_map_before_expected + assert sched_map_after == sched_map_after_expected # ------------------------------------------------------------------------------ # Relationship between insn_a and insn_d --------------------------------------- @@ -208,13 +208,13 @@ def test_lexschedule_and_islmap_creation(): assert sched_ad.stmt_instance_before.lex_points == [sid_a, 'i', 0, 'k', 0] assert sched_ad.stmt_instance_after.lex_points == [sid_d, 't', 0, 0, 0] - # Get two isl maps from the PairwiseScheduleBuilder + # Get two maps from the PairwiseScheduleBuilder - isl_sched_before, isl_sched_after = sched_ad.build_maps(knl) + sched_map_before, sched_map_after = sched_ad.build_maps(knl) # Create expected maps, align, compare - isl_sched_before_expected = isl.Map( + sched_map_before_expected = isl.Map( "[pi, pk] -> { " "[_lp_linchk_statement=%d, i, k] -> " "[_lp_linchk_l0=%d, _lp_linchk_l1=i, _lp_linchk_l2=0, _lp_linchk_l3=k, " @@ -222,10 +222,10 @@ def test_lexschedule_and_islmap_creation(): "0 <= i < pi and 0 <= k < pk }" % (sid_a, sid_a) ) - isl_sched_before_expected = align_isl_maps_by_var_names( - isl_sched_before_expected, isl_sched_before) + sched_map_before_expected = align_isl_maps_by_var_names( + sched_map_before_expected, sched_map_before) - isl_sched_after_expected = isl.Map( + sched_map_after_expected = isl.Map( "[pt] -> { " "[_lp_linchk_statement=%d, t] -> " "[_lp_linchk_l0=%d, _lp_linchk_l1=t, _lp_linchk_l2=0, _lp_linchk_l3=0, " @@ -233,11 +233,11 @@ def test_lexschedule_and_islmap_creation(): "0 <= t < pt }" % (sid_d, sid_d) ) - isl_sched_after_expected = align_isl_maps_by_var_names( - isl_sched_after_expected, isl_sched_after) + sched_map_after_expected = align_isl_maps_by_var_names( + sched_map_after_expected, sched_map_after) - assert isl_sched_before == isl_sched_before_expected - assert isl_sched_after == isl_sched_after_expected + assert sched_map_before == sched_map_before_expected + assert sched_map_after == sched_map_after_expected if sched_ad.stmt_instance_before.stmt_ref.int_id == 0: perform_insn_ad_checks_with(0, 1) @@ -253,13 +253,13 @@ def test_lexschedule_and_islmap_creation(): assert sched_bc.stmt_instance_before.lex_points == [0, 'i', 0, 'j', sid_b] assert sched_bc.stmt_instance_after.lex_points == [0, 'i', 0, 'j', sid_c] - # Get two isl maps from the PairwiseScheduleBuilder + # Get two maps from the PairwiseScheduleBuilder - isl_sched_before, isl_sched_after = sched_bc.build_maps(knl) + sched_map_before, sched_map_after = sched_bc.build_maps(knl) # Create expected maps, align, compare - isl_sched_before_expected = isl.Map( + sched_map_before_expected = isl.Map( "[pi, pj] -> { " "[_lp_linchk_statement=%d, i, j] -> " "[_lp_linchk_l0=0, _lp_linchk_l1=i, _lp_linchk_l2=0, _lp_linchk_l3=j, " @@ -267,10 +267,10 @@ def test_lexschedule_and_islmap_creation(): "0 <= i < pi and 0 <= j < pj }" % (sid_b, sid_b) ) - isl_sched_before_expected = align_isl_maps_by_var_names( - isl_sched_before_expected, isl_sched_before) + sched_map_before_expected = align_isl_maps_by_var_names( + sched_map_before_expected, sched_map_before) - isl_sched_after_expected = isl.Map( + sched_map_after_expected = isl.Map( "[pi, pj] -> { " "[_lp_linchk_statement=%d, i, j] -> " "[_lp_linchk_l0=0, _lp_linchk_l1=i, _lp_linchk_l2=0, _lp_linchk_l3=j, " @@ -278,11 +278,11 @@ def test_lexschedule_and_islmap_creation(): "0 <= i < pi and 0 <= j < pj }" % (sid_c, sid_c) ) - isl_sched_after_expected = align_isl_maps_by_var_names( - isl_sched_after_expected, isl_sched_after) + sched_map_after_expected = align_isl_maps_by_var_names( + sched_map_after_expected, sched_map_after) - assert isl_sched_before == isl_sched_before_expected - assert isl_sched_after == isl_sched_after_expected + assert sched_map_before == sched_map_before_expected + assert sched_map_after == sched_map_after_expected if sched_bc.stmt_instance_before.stmt_ref.int_id == 0: perform_insn_bc_checks_with(0, 1) @@ -298,13 +298,13 @@ def test_lexschedule_and_islmap_creation(): assert sched_bd.stmt_instance_before.lex_points == [sid_b, 'i', 0, 'j', 0] assert sched_bd.stmt_instance_after.lex_points == [sid_d, 't', 0, 0, 0] - # Get two isl maps from the PairwiseScheduleBuilder + # Get two maps from the PairwiseScheduleBuilder - isl_sched_before, isl_sched_after = sched_bd.build_maps(knl) + sched_map_before, sched_map_after = sched_bd.build_maps(knl) # Create expected maps, align, compare - isl_sched_before_expected = isl.Map( + sched_map_before_expected = isl.Map( "[pi, pj] -> { " "[_lp_linchk_statement=%d, i, j] -> " "[_lp_linchk_l0=%d, _lp_linchk_l1=i, _lp_linchk_l2=0, _lp_linchk_l3=j, " @@ -312,10 +312,10 @@ def test_lexschedule_and_islmap_creation(): "0 <= i < pi and 0 <= j < pj }" % (sid_b, sid_b) ) - isl_sched_before_expected = align_isl_maps_by_var_names( - isl_sched_before_expected, isl_sched_before) + sched_map_before_expected = align_isl_maps_by_var_names( + sched_map_before_expected, sched_map_before) - isl_sched_after_expected = isl.Map( + sched_map_after_expected = isl.Map( "[pt] -> { " "[_lp_linchk_statement=%d, t] -> " "[_lp_linchk_l0=%d, _lp_linchk_l1=t, _lp_linchk_l2=0, _lp_linchk_l3=0, " @@ -323,11 +323,11 @@ def test_lexschedule_and_islmap_creation(): "0 <= t < pt }" % (sid_d, sid_d) ) - isl_sched_after_expected = align_isl_maps_by_var_names( - isl_sched_after_expected, isl_sched_after) + sched_map_after_expected = align_isl_maps_by_var_names( + sched_map_after_expected, sched_map_after) - assert isl_sched_before == isl_sched_before_expected - assert isl_sched_after == isl_sched_after_expected + assert sched_map_before == sched_map_before_expected + assert sched_map_after == sched_map_after_expected if sched_bd.stmt_instance_before.stmt_ref.int_id == 0: perform_insn_bd_checks_with(0, 1) @@ -343,13 +343,13 @@ def test_lexschedule_and_islmap_creation(): assert sched_cd.stmt_instance_before.lex_points == [sid_c, 'i', 0, 'j', 0] assert sched_cd.stmt_instance_after.lex_points == [sid_d, 't', 0, 0, 0] - # Get two isl maps from the PairwiseScheduleBuilder + # Get two maps from the PairwiseScheduleBuilder - isl_sched_before, isl_sched_after = sched_cd.build_maps(knl) + sched_map_before, sched_map_after = sched_cd.build_maps(knl) # Create expected maps, align, compare - isl_sched_before_expected = isl.Map( + sched_map_before_expected = isl.Map( "[pi, pj] -> { " "[_lp_linchk_statement=%d, i, j] -> " "[_lp_linchk_l0=%d, _lp_linchk_l1=i, _lp_linchk_l2=0, _lp_linchk_l3=j, " @@ -357,10 +357,10 @@ def test_lexschedule_and_islmap_creation(): "0 <= i < pi and 0 <= j < pj }" % (sid_c, sid_c) ) - isl_sched_before_expected = align_isl_maps_by_var_names( - isl_sched_before_expected, isl_sched_before) + sched_map_before_expected = align_isl_maps_by_var_names( + sched_map_before_expected, sched_map_before) - isl_sched_after_expected = isl.Map( + sched_map_after_expected = isl.Map( "[pt] -> { " "[_lp_linchk_statement=%d, t] -> " "[_lp_linchk_l0=%d, _lp_linchk_l1=t, _lp_linchk_l2=0, _lp_linchk_l3=0, " @@ -368,11 +368,11 @@ def test_lexschedule_and_islmap_creation(): "0 <= t < pt }" % (sid_d, sid_d) ) - isl_sched_after_expected = align_isl_maps_by_var_names( - isl_sched_after_expected, isl_sched_after) + sched_map_after_expected = align_isl_maps_by_var_names( + sched_map_after_expected, sched_map_after) - assert isl_sched_before == isl_sched_before_expected - assert isl_sched_after == isl_sched_after_expected + assert sched_map_before == sched_map_before_expected + assert sched_map_after == sched_map_after_expected if sched_cd.stmt_instance_before.stmt_ref.int_id == 0: perform_insn_cd_checks_with(0, 1) -- GitLab From f528b58622953390e5930c4ba1543ae2c17abae9 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 8 Jun 2020 14:32:42 -0500 Subject: [PATCH 059/136] rename _union_of_isl_sets_or_maps()->_get_union() --- loopy/schedule/checker/utils.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index 8e65d9905..4b51a16d1 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -143,9 +143,9 @@ def align_isl_maps_by_var_names(input_map, target_map): return aligned_input_map -def _union_of_isl_sets_or_maps(set_list): - union = set_list[0] - for s in set_list[1:]: +def _get_union(list_items): + union = list_items[0] + for s in list_items[1:]: union = union.union(s) return union @@ -247,7 +247,7 @@ def create_symbolic_map_from_tuples( all_maps.append( map_from_set.intersect_domain(dom_with_all_inames)) - return _union_of_isl_sets_or_maps(all_maps) + return _get_union(all_maps) def set_all_isl_space_names( -- GitLab From 070ca3a534ea135607cbfd0717b2caef9b1d5a49 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 8 Jun 2020 16:31:06 -0500 Subject: [PATCH 060/136] create map_names_match_check() function for checking conditions on isl set/map name matching; use it to verify conditions before calling islpy.align_space() (which doesn't perform all necessary checks); TODO after making sure this works: remove now unused calls to reorder_dims_by_name() --- loopy/schedule/checker/utils.py | 54 +++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index 4b51a16d1..852b24735 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -44,6 +44,27 @@ def add_dims_to_isl_set(isl_set, dim_type, names, new_idx_start): return new_set +def map_names_match_check( + obj_map, + desired_names, + dim_type, + assert_subset=True, + assert_permutation=True, + ): + + obj_map_names = obj_map.space.get_var_names(dim_type) + if assert_permutation: + if not set(obj_map_names) == set(desired_names): + raise ValueError( + "Set of map names %s for dim %s does not match target set %s" + % (obj_map_names, dim_type, desired_names)) + elif assert_subset: + if not set(obj_map_names).issubset(desired_names): + raise ValueError( + "Map names %s for dim %s are not a subset of target names %s" + % (obj_map_names, dim_type, desired_names)) + + def reorder_dims_by_name( isl_set, dim_type, desired_dims_ordered, add_missing=False, new_names_are_permutation_only=False): @@ -75,7 +96,10 @@ def reorder_dims_by_name( """ - assert set(isl_set.get_var_names(dim_type)).issubset(desired_dims_ordered) + map_names_match_check( + isl_set, desired_dims_ordered, dim_type, + assert_subset=True, assert_permutation=False) + assert dim_type != isl.dim_type.param if new_names_are_permutation_only and ( @@ -117,13 +141,23 @@ def reorder_dims_by_name( def align_isl_maps_by_var_names(input_map, target_map): + # first make sure names match + for dt in [isl.dim_type.in_, isl.dim_type.out, isl.dim_type.param]: + map_names_match_check( + input_map, target_map.get_var_names(dt), dt, + assert_permutation=True) + + aligned_input_map = isl.align_spaces(input_map, target_map) + + # TODO remove once satisfied that above can replace below: + # align params - aligned_input_map = input_map.align_params(target_map.space) + _aligned_input_map = input_map.align_params(target_map.space) # align in_ dims target_map_in_names = target_map.space.get_var_names(isl.dim_type.in_) - aligned_input_map = reorder_dims_by_name( - aligned_input_map, + _aligned_input_map = reorder_dims_by_name( + _aligned_input_map, isl.dim_type.in_, target_map_in_names, add_missing=False, @@ -132,14 +166,22 @@ def align_isl_maps_by_var_names(input_map, target_map): # align out dims target_map_out_names = target_map.space.get_var_names(isl.dim_type.out) - aligned_input_map = reorder_dims_by_name( - aligned_input_map, + _aligned_input_map = reorder_dims_by_name( + _aligned_input_map, isl.dim_type.out, target_map_out_names, add_missing=False, new_names_are_permutation_only=True, ) + assert aligned_input_map == _aligned_input_map + assert aligned_input_map.get_var_names( + isl.dim_type.param) == _aligned_input_map.get_var_names(isl.dim_type.param) + assert aligned_input_map.get_var_names( + isl.dim_type.in_) == _aligned_input_map.get_var_names(isl.dim_type.in_) + assert aligned_input_map.get_var_names( + isl.dim_type.out) == _aligned_input_map.get_var_names(isl.dim_type.out) + return aligned_input_map -- GitLab From 2f980346c719722ef61fb36055ec31705f17c534 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 8 Jun 2020 16:48:33 -0500 Subject: [PATCH 061/136] rename align_isl_maps_by_var_names()->ensure_dim_names_match_and_align() --- loopy/schedule/checker/utils.py | 43 ++++-------------------------- test/test_linearization_checker.py | 26 +++++++++--------- 2 files changed, 18 insertions(+), 51 deletions(-) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index 852b24735..2a42a098f 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -139,50 +139,17 @@ def reorder_dims_by_name( return new_set -def align_isl_maps_by_var_names(input_map, target_map): +def ensure_dim_names_match_and_align(obj_map, tgt_map): # first make sure names match for dt in [isl.dim_type.in_, isl.dim_type.out, isl.dim_type.param]: map_names_match_check( - input_map, target_map.get_var_names(dt), dt, + obj_map, tgt_map.get_var_names(dt), dt, assert_permutation=True) - aligned_input_map = isl.align_spaces(input_map, target_map) - - # TODO remove once satisfied that above can replace below: - - # align params - _aligned_input_map = input_map.align_params(target_map.space) - - # align in_ dims - target_map_in_names = target_map.space.get_var_names(isl.dim_type.in_) - _aligned_input_map = reorder_dims_by_name( - _aligned_input_map, - isl.dim_type.in_, - target_map_in_names, - add_missing=False, - new_names_are_permutation_only=True, - ) - - # align out dims - target_map_out_names = target_map.space.get_var_names(isl.dim_type.out) - _aligned_input_map = reorder_dims_by_name( - _aligned_input_map, - isl.dim_type.out, - target_map_out_names, - add_missing=False, - new_names_are_permutation_only=True, - ) - - assert aligned_input_map == _aligned_input_map - assert aligned_input_map.get_var_names( - isl.dim_type.param) == _aligned_input_map.get_var_names(isl.dim_type.param) - assert aligned_input_map.get_var_names( - isl.dim_type.in_) == _aligned_input_map.get_var_names(isl.dim_type.in_) - assert aligned_input_map.get_var_names( - isl.dim_type.out) == _aligned_input_map.get_var_names(isl.dim_type.out) - - return aligned_input_map + aligned_obj_map = isl.align_spaces(obj_map, tgt_map) + + return aligned_obj_map def _get_union(list_items): diff --git a/test/test_linearization_checker.py b/test/test_linearization_checker.py index 559a5c24e..41ac16feb 100644 --- a/test/test_linearization_checker.py +++ b/test/test_linearization_checker.py @@ -52,7 +52,7 @@ def test_lexschedule_and_map_creation(): get_schedule_for_statement_pair, ) from loopy.schedule.checker.utils import ( - align_isl_maps_by_var_names, + ensure_dim_names_match_and_align, ) # example kernel @@ -148,7 +148,7 @@ def test_lexschedule_and_map_creation(): "_lp_linchk_l4=0] : " "0 <= i < pi and 0 <= k < pk }" ) - sched_map_before_expected = align_isl_maps_by_var_names( + sched_map_before_expected = ensure_dim_names_match_and_align( sched_map_before_expected, sched_map_before) sched_map_after_expected = isl.Map( @@ -158,7 +158,7 @@ def test_lexschedule_and_map_creation(): "_lp_linchk_l4=0] : " "0 <= i < pi and 0 <= j < pj }" ) - sched_map_after_expected = align_isl_maps_by_var_names( + sched_map_after_expected = ensure_dim_names_match_and_align( sched_map_after_expected, sched_map_after) assert sched_map_before == sched_map_before_expected @@ -183,7 +183,7 @@ def test_lexschedule_and_map_creation(): "_lp_linchk_l4=0] : " "0 <= i < pi and 0 <= k < pk }" ) - sched_map_before_expected = align_isl_maps_by_var_names( + sched_map_before_expected = ensure_dim_names_match_and_align( sched_map_before_expected, sched_map_before) sched_map_after_expected = isl.Map( @@ -193,7 +193,7 @@ def test_lexschedule_and_map_creation(): "_lp_linchk_l4=0] : " "0 <= i < pi and 0 <= j < pj }" ) - sched_map_after_expected = align_isl_maps_by_var_names( + sched_map_after_expected = ensure_dim_names_match_and_align( sched_map_after_expected, sched_map_after) assert sched_map_before == sched_map_before_expected @@ -222,7 +222,7 @@ def test_lexschedule_and_map_creation(): "0 <= i < pi and 0 <= k < pk }" % (sid_a, sid_a) ) - sched_map_before_expected = align_isl_maps_by_var_names( + sched_map_before_expected = ensure_dim_names_match_and_align( sched_map_before_expected, sched_map_before) sched_map_after_expected = isl.Map( @@ -233,7 +233,7 @@ def test_lexschedule_and_map_creation(): "0 <= t < pt }" % (sid_d, sid_d) ) - sched_map_after_expected = align_isl_maps_by_var_names( + sched_map_after_expected = ensure_dim_names_match_and_align( sched_map_after_expected, sched_map_after) assert sched_map_before == sched_map_before_expected @@ -267,7 +267,7 @@ def test_lexschedule_and_map_creation(): "0 <= i < pi and 0 <= j < pj }" % (sid_b, sid_b) ) - sched_map_before_expected = align_isl_maps_by_var_names( + sched_map_before_expected = ensure_dim_names_match_and_align( sched_map_before_expected, sched_map_before) sched_map_after_expected = isl.Map( @@ -278,7 +278,7 @@ def test_lexschedule_and_map_creation(): "0 <= i < pi and 0 <= j < pj }" % (sid_c, sid_c) ) - sched_map_after_expected = align_isl_maps_by_var_names( + sched_map_after_expected = ensure_dim_names_match_and_align( sched_map_after_expected, sched_map_after) assert sched_map_before == sched_map_before_expected @@ -312,7 +312,7 @@ def test_lexschedule_and_map_creation(): "0 <= i < pi and 0 <= j < pj }" % (sid_b, sid_b) ) - sched_map_before_expected = align_isl_maps_by_var_names( + sched_map_before_expected = ensure_dim_names_match_and_align( sched_map_before_expected, sched_map_before) sched_map_after_expected = isl.Map( @@ -323,7 +323,7 @@ def test_lexschedule_and_map_creation(): "0 <= t < pt }" % (sid_d, sid_d) ) - sched_map_after_expected = align_isl_maps_by_var_names( + sched_map_after_expected = ensure_dim_names_match_and_align( sched_map_after_expected, sched_map_after) assert sched_map_before == sched_map_before_expected @@ -357,7 +357,7 @@ def test_lexschedule_and_map_creation(): "0 <= i < pi and 0 <= j < pj }" % (sid_c, sid_c) ) - sched_map_before_expected = align_isl_maps_by_var_names( + sched_map_before_expected = ensure_dim_names_match_and_align( sched_map_before_expected, sched_map_before) sched_map_after_expected = isl.Map( @@ -368,7 +368,7 @@ def test_lexschedule_and_map_creation(): "0 <= t < pt }" % (sid_d, sid_d) ) - sched_map_after_expected = align_isl_maps_by_var_names( + sched_map_after_expected = ensure_dim_names_match_and_align( sched_map_after_expected, sched_map_after) assert sched_map_before == sched_map_before_expected -- GitLab From c7ce50da737d3a6df80a26184fd6d5d7c3762d45 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 8 Jun 2020 17:00:06 -0500 Subject: [PATCH 062/136] use map_names_match_check() to perform name set match check inside reorder_dims_by_name() --- loopy/schedule/checker/utils.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index 2a42a098f..b9de94921 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -98,18 +98,10 @@ def reorder_dims_by_name( map_names_match_check( isl_set, desired_dims_ordered, dim_type, - assert_subset=True, assert_permutation=False) + assert_subset=True, assert_permutation=new_names_are_permutation_only) assert dim_type != isl.dim_type.param - if new_names_are_permutation_only and ( - set(isl_set.get_var_names(dim_type)) - != set(desired_dims_ordered)): - raise ValueError( - "Var name sets must match with new_names_are_permutation_only=True. " - "isl vars: %s, desired dims: %s" - % (isl_set.get_var_names(dim_type), desired_dims_ordered)) - other_dim_type = isl.dim_type.param other_dim_len = len(isl_set.get_var_names(other_dim_type)) -- GitLab From d1a73971fd24902a0068f6c3cff3306c031b22e0 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 8 Jun 2020 17:21:48 -0500 Subject: [PATCH 063/136] rename reorder_dims_by_name()->insert_missing_dims_and_reorder_by_name(); remove params add_missing (now always true) and new_names_are_permutation_only (now always false) --- loopy/schedule/checker/utils.py | 38 +++++++++++---------------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index b9de94921..e862d166e 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -65,32 +65,21 @@ def map_names_match_check( % (obj_map_names, dim_type, desired_names)) -def reorder_dims_by_name( - isl_set, dim_type, desired_dims_ordered, - add_missing=False, new_names_are_permutation_only=False): +def insert_missing_dims_and_reorder_by_name( + isl_set, dim_type, desired_dims_ordered): """Return an isl_set with the dimensions in the specified order. :arg isl_set: A :class:`islpy.Set` whose dimensions are - to be reordered. + to be reordered and, if necessary, augmented with missing dimensions. :arg dim_type: A :class:`islpy.dim_type`, i.e., an :class:`int`, specifying the dimension to be reordered. :arg desired_dims_ordered: A :class:`list` of :class:`str` elements - representing the desired dimensions order by dimension name. - - :arg add_missing: A :class:`bool` specifying whether to insert - dimensions (by name) found in `desired_dims_ordered` that are not - present in `isl_set`. - - :arg new_names_are_permutation_only: A :class:`bool` indicating that - `desired_dims_ordered` contains the same names as the specified - dimensions in `isl_set`, and does not, e.g., contain additional - dimension names not found in `isl_set`. If set to True, and these - two sets of names do not match, an error is produced. + representing the desired dimensions in order by dimension name. :returns: An :class:`islpy.Set` matching `isl_set` with the - dimension order matching `desired_dims_ordered`, optionally + dimension order matching `desired_dims_ordered`, including additional dimensions present in `desred_dims_ordered` that are not present in `isl_set`. @@ -98,7 +87,7 @@ def reorder_dims_by_name( map_names_match_check( isl_set, desired_dims_ordered, dim_type, - assert_subset=True, assert_permutation=new_names_are_permutation_only) + assert_subset=True, assert_permutation=False) assert dim_type != isl.dim_type.param @@ -109,12 +98,11 @@ def reorder_dims_by_name( for desired_idx, name in enumerate(desired_dims_ordered): # if iname doesn't exist in set, add dim: if name not in new_set.get_var_names(dim_type): - if add_missing: - # insert missing dim in correct location - new_set = new_set.insert_dims( - dim_type, desired_idx, 1 - ).set_dim_name( - dim_type, desired_idx, name) + # insert missing dim in correct location + new_set = new_set.insert_dims( + dim_type, desired_idx, 1 + ).set_dim_name( + dim_type, desired_idx, name) else: # iname exists in set current_idx = new_set.find_dim_by_name(dim_type, name) if current_idx != desired_idx: @@ -237,11 +225,9 @@ def create_symbolic_map_from_tuples( # if there are any dimensions in dom that are missing from # map_from_set, we have a problem I think? # (assertion checks this in add_missing... - dom_with_all_inames = reorder_dims_by_name( + dom_with_all_inames = insert_missing_dims_and_reorder_by_name( dom, isl.dim_type.set, space_in_names, - add_missing=True, - new_names_are_permutation_only=False, ) # intersect domain with this map -- GitLab From 14105e5de024ebb657b25e2c29d95cd030291aab Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Thu, 11 Jun 2020 20:17:15 -0500 Subject: [PATCH 064/136] add class name to __str__ for StatementRef() --- loopy/schedule/checker/schedule.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 8c503b191..18337481c 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -69,7 +69,7 @@ class StatementRef(object): int_id = ":%d" % (self.int_id) else: int_id = "" - return "%s%s" % (self.insn_id, int_id) + return "%s(%s%s)" % (self.__class__.__name__, self.insn_id, int_id) class StatementInstanceSet(object): -- GitLab From 6058001645158d0ca04c59b8e40cc082b89319c8 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 30 Jun 2020 06:59:10 -0500 Subject: [PATCH 065/136] make the integer ids that are used to represent before/after statements in domain of PairwiseSchedule deterministic so that the 'before' statement is always 0 and 'after' statement is always 1 (unless they're the same statement) --- loopy/schedule/checker/schedule.py | 13 +++-- test/test_linearization_checker.py | 85 +++++++++++++++++++----------- 2 files changed, 62 insertions(+), 36 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 18337481c..e4a9a5864 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -167,6 +167,13 @@ class PairwiseScheduleBuilder(object): # PairwiseScheduleBuilder statements self.stmt_instance_before = None self.stmt_instance_after = None + + # Determine integer IDs that will represent each statement in mapping + # (dependency map creation assumes sid_before=0 and sid_after=1, unless + # before and after refer to same stmt, in which case sid_before=sid_after=0) + int_sid_before = 0 + int_sid_after = 0 if before_insn_id == after_insn_id else 1 + # TODO when/after dependencies are added, consider the possibility # of removing the two-statements-per-PairwiseScheduleBuilder limitation @@ -178,7 +185,6 @@ class PairwiseScheduleBuilder(object): # ordering, initially this as a 1-d point with value 0 next_insn_lex_tuple = [0] stmt_added_since_prev_block_at_tier = [False] - next_sid = 0 for linearization_item in linearization_items_ordered: if isinstance(linearization_item, EnterLoop): iname = linearization_item.iname @@ -241,7 +247,7 @@ class PairwiseScheduleBuilder(object): self.stmt_instance_before = StatementInstanceSet( StatementRef( insn_id=lp_insn_id, - int_id=next_sid, # int representing insn + int_id=int_sid_before, # int representing insn ), next_insn_lex_tuple[:]) stmt_added = True @@ -251,7 +257,7 @@ class PairwiseScheduleBuilder(object): self.stmt_instance_after = StatementInstanceSet( StatementRef( insn_id=lp_insn_id, - int_id=next_sid, # int representing insn + int_id=int_sid_after, # int representing insn ), next_insn_lex_tuple[:]) stmt_added = True @@ -262,7 +268,6 @@ class PairwiseScheduleBuilder(object): if stmt_added: # increment lex dim val enumerating items in current code block next_insn_lex_tuple[-1] = next_insn_lex_tuple[-1] + 1 - next_sid += 1 # all current (nested) blocks now contain a statement stmt_added_since_prev_block_at_tier = [True]*len( diff --git a/test/test_linearization_checker.py b/test/test_linearization_checker.py index 41ac16feb..520efba9b 100644 --- a/test/test_linearization_checker.py +++ b/test/test_linearization_checker.py @@ -130,6 +130,15 @@ def test_lexschedule_and_map_creation(): "insn_d", ) + # There are multiple potential linearization orders for this kernel, so when + # performing our comparisons for schedule correctness, we need to know which + # order loopy chose. + from loopy.schedule import RunInstruction + linearized_insn_ord = [] + for item in linearization_items: + if isinstance(item, RunInstruction): + linearized_insn_ord.append(item.insn_id) + # Relationship between insn_a and insn_b --------------------------------------- assert sched_ab.stmt_instance_before.lex_points == [0, 'i', 0, 'k', 0] @@ -204,9 +213,10 @@ def test_lexschedule_and_map_creation(): # insn_a and insn_d could have been linearized in either order # (i loop could be before or after t loop) - def perform_insn_ad_checks_with(sid_a, sid_d): - assert sched_ad.stmt_instance_before.lex_points == [sid_a, 'i', 0, 'k', 0] - assert sched_ad.stmt_instance_after.lex_points == [sid_d, 't', 0, 0, 0] + def perform_insn_ad_checks_with(a_lex_idx, d_lex_idx): + assert sched_ad.stmt_instance_before.lex_points == [ + a_lex_idx, 'i', 0, 'k', 0] + assert sched_ad.stmt_instance_after.lex_points == [d_lex_idx, 't', 0, 0, 0] # Get two maps from the PairwiseScheduleBuilder @@ -216,22 +226,22 @@ def test_lexschedule_and_map_creation(): sched_map_before_expected = isl.Map( "[pi, pk] -> { " - "[_lp_linchk_statement=%d, i, k] -> " + "[_lp_linchk_statement=0, i, k] -> " "[_lp_linchk_l0=%d, _lp_linchk_l1=i, _lp_linchk_l2=0, _lp_linchk_l3=k, " "_lp_linchk_l4=0] : " "0 <= i < pi and 0 <= k < pk }" - % (sid_a, sid_a) + % (a_lex_idx) ) sched_map_before_expected = ensure_dim_names_match_and_align( sched_map_before_expected, sched_map_before) sched_map_after_expected = isl.Map( "[pt] -> { " - "[_lp_linchk_statement=%d, t] -> " + "[_lp_linchk_statement=1, t] -> " "[_lp_linchk_l0=%d, _lp_linchk_l1=t, _lp_linchk_l2=0, _lp_linchk_l3=0, " "_lp_linchk_l4=0] : " "0 <= t < pt }" - % (sid_d, sid_d) + % (d_lex_idx) ) sched_map_after_expected = ensure_dim_names_match_and_align( sched_map_after_expected, sched_map_after) @@ -239,9 +249,11 @@ def test_lexschedule_and_map_creation(): assert sched_map_before == sched_map_before_expected assert sched_map_after == sched_map_after_expected - if sched_ad.stmt_instance_before.stmt_ref.int_id == 0: + if linearized_insn_ord.index("insn_a") < linearized_insn_ord.index("insn_d"): + # insn_a was linearized first, check schedule accordingly perform_insn_ad_checks_with(0, 1) else: + # insn_d was linearized first, check schedule accordingly perform_insn_ad_checks_with(1, 0) # ------------------------------------------------------------------------------ @@ -249,9 +261,10 @@ def test_lexschedule_and_map_creation(): # insn_b and insn_c could have been linearized in either order # (i loop could be before or after t loop) - def perform_insn_bc_checks_with(sid_b, sid_c): - assert sched_bc.stmt_instance_before.lex_points == [0, 'i', 0, 'j', sid_b] - assert sched_bc.stmt_instance_after.lex_points == [0, 'i', 0, 'j', sid_c] + def perform_insn_bc_checks_with(b_lex_idx, c_lex_idx): + assert sched_bc.stmt_instance_before.lex_points == [ + 0, 'i', 0, 'j', b_lex_idx] + assert sched_bc.stmt_instance_after.lex_points == [0, 'i', 0, 'j', c_lex_idx] # Get two maps from the PairwiseScheduleBuilder @@ -261,22 +274,22 @@ def test_lexschedule_and_map_creation(): sched_map_before_expected = isl.Map( "[pi, pj] -> { " - "[_lp_linchk_statement=%d, i, j] -> " + "[_lp_linchk_statement=0, i, j] -> " "[_lp_linchk_l0=0, _lp_linchk_l1=i, _lp_linchk_l2=0, _lp_linchk_l3=j, " "_lp_linchk_l4=%d] : " "0 <= i < pi and 0 <= j < pj }" - % (sid_b, sid_b) + % (b_lex_idx) ) sched_map_before_expected = ensure_dim_names_match_and_align( sched_map_before_expected, sched_map_before) sched_map_after_expected = isl.Map( "[pi, pj] -> { " - "[_lp_linchk_statement=%d, i, j] -> " + "[_lp_linchk_statement=1, i, j] -> " "[_lp_linchk_l0=0, _lp_linchk_l1=i, _lp_linchk_l2=0, _lp_linchk_l3=j, " "_lp_linchk_l4=%d] : " "0 <= i < pi and 0 <= j < pj }" - % (sid_c, sid_c) + % (c_lex_idx) ) sched_map_after_expected = ensure_dim_names_match_and_align( sched_map_after_expected, sched_map_after) @@ -284,9 +297,11 @@ def test_lexschedule_and_map_creation(): assert sched_map_before == sched_map_before_expected assert sched_map_after == sched_map_after_expected - if sched_bc.stmt_instance_before.stmt_ref.int_id == 0: + if linearized_insn_ord.index("insn_b") < linearized_insn_ord.index("insn_c"): + # insn_b was linearized first, check schedule accordingly perform_insn_bc_checks_with(0, 1) else: + # insn_c was linearized first, check schedule accordingly perform_insn_bc_checks_with(1, 0) # ------------------------------------------------------------------------------ @@ -294,9 +309,10 @@ def test_lexschedule_and_map_creation(): # insn_b and insn_d could have been linearized in either order # (i loop could be before or after t loop) - def perform_insn_bd_checks_with(sid_b, sid_d): - assert sched_bd.stmt_instance_before.lex_points == [sid_b, 'i', 0, 'j', 0] - assert sched_bd.stmt_instance_after.lex_points == [sid_d, 't', 0, 0, 0] + def perform_insn_bd_checks_with(b_lex_idx, d_lex_idx): + assert sched_bd.stmt_instance_before.lex_points == [ + b_lex_idx, 'i', 0, 'j', 0] + assert sched_bd.stmt_instance_after.lex_points == [d_lex_idx, 't', 0, 0, 0] # Get two maps from the PairwiseScheduleBuilder @@ -306,22 +322,22 @@ def test_lexschedule_and_map_creation(): sched_map_before_expected = isl.Map( "[pi, pj] -> { " - "[_lp_linchk_statement=%d, i, j] -> " + "[_lp_linchk_statement=0, i, j] -> " "[_lp_linchk_l0=%d, _lp_linchk_l1=i, _lp_linchk_l2=0, _lp_linchk_l3=j, " "_lp_linchk_l4=0] : " "0 <= i < pi and 0 <= j < pj }" - % (sid_b, sid_b) + % (b_lex_idx) ) sched_map_before_expected = ensure_dim_names_match_and_align( sched_map_before_expected, sched_map_before) sched_map_after_expected = isl.Map( "[pt] -> { " - "[_lp_linchk_statement=%d, t] -> " + "[_lp_linchk_statement=1, t] -> " "[_lp_linchk_l0=%d, _lp_linchk_l1=t, _lp_linchk_l2=0, _lp_linchk_l3=0, " "_lp_linchk_l4=0] : " "0 <= t < pt }" - % (sid_d, sid_d) + % (d_lex_idx) ) sched_map_after_expected = ensure_dim_names_match_and_align( sched_map_after_expected, sched_map_after) @@ -329,9 +345,11 @@ def test_lexschedule_and_map_creation(): assert sched_map_before == sched_map_before_expected assert sched_map_after == sched_map_after_expected - if sched_bd.stmt_instance_before.stmt_ref.int_id == 0: + if linearized_insn_ord.index("insn_b") < linearized_insn_ord.index("insn_d"): + # insn_b was linearized first, check schedule accordingly perform_insn_bd_checks_with(0, 1) else: + # insn_d was linearized first, check schedule accordingly perform_insn_bd_checks_with(1, 0) # ------------------------------------------------------------------------------ @@ -339,9 +357,10 @@ def test_lexschedule_and_map_creation(): # insn_c and insn_d could have been linearized in either order # (i loop could be before or after t loop) - def perform_insn_cd_checks_with(sid_c, sid_d): - assert sched_cd.stmt_instance_before.lex_points == [sid_c, 'i', 0, 'j', 0] - assert sched_cd.stmt_instance_after.lex_points == [sid_d, 't', 0, 0, 0] + def perform_insn_cd_checks_with(c_lex_idx, d_lex_idx): + assert sched_cd.stmt_instance_before.lex_points == [ + c_lex_idx, 'i', 0, 'j', 0] + assert sched_cd.stmt_instance_after.lex_points == [d_lex_idx, 't', 0, 0, 0] # Get two maps from the PairwiseScheduleBuilder @@ -351,22 +370,22 @@ def test_lexschedule_and_map_creation(): sched_map_before_expected = isl.Map( "[pi, pj] -> { " - "[_lp_linchk_statement=%d, i, j] -> " + "[_lp_linchk_statement=0, i, j] -> " "[_lp_linchk_l0=%d, _lp_linchk_l1=i, _lp_linchk_l2=0, _lp_linchk_l3=j, " "_lp_linchk_l4=0] : " "0 <= i < pi and 0 <= j < pj }" - % (sid_c, sid_c) + % (c_lex_idx) ) sched_map_before_expected = ensure_dim_names_match_and_align( sched_map_before_expected, sched_map_before) sched_map_after_expected = isl.Map( "[pt] -> { " - "[_lp_linchk_statement=%d, t] -> " + "[_lp_linchk_statement=1, t] -> " "[_lp_linchk_l0=%d, _lp_linchk_l1=t, _lp_linchk_l2=0, _lp_linchk_l3=0, " "_lp_linchk_l4=0] : " "0 <= t < pt }" - % (sid_d, sid_d) + % (d_lex_idx) ) sched_map_after_expected = ensure_dim_names_match_and_align( sched_map_after_expected, sched_map_after) @@ -374,9 +393,11 @@ def test_lexschedule_and_map_creation(): assert sched_map_before == sched_map_before_expected assert sched_map_after == sched_map_after_expected - if sched_cd.stmt_instance_before.stmt_ref.int_id == 0: + if linearized_insn_ord.index("insn_c") < linearized_insn_ord.index("insn_d"): + # insn_c was linearized first, check schedule accordingly perform_insn_cd_checks_with(0, 1) else: + # insn_d was linearized first, check schedule accordingly perform_insn_cd_checks_with(1, 0) -- GitLab From ffdca113b9c9fef44fdf3ff0fa70c77f399d0f2a Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 7 Jul 2020 00:08:06 -0500 Subject: [PATCH 066/136] eliminate 'dom_inames_ordered' args in build_maps() --- loopy/schedule/checker/schedule.py | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index e4a9a5864..bcdbb6346 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -311,8 +311,6 @@ class PairwiseScheduleBuilder(object): def build_maps( self, knl, - dom_inames_ordered_before=None, - dom_inames_ordered_after=None, ): r"""Create a pair of :class:`islpy.Map`\ s representing a pairwise schedule as two mappings from statement instances to lexicographic time, @@ -323,18 +321,6 @@ class PairwiseScheduleBuilder(object): kernel will be used to get the domains associated with the inames used in the statements. - :arg dom_inames_ordered_before: A list of :class:`str` - representing the union of inames used in - ``stmt_instance_before``. ``statement_var_name`` and - ``dom_inames_ordered_before`` are the names of the dims of - the space of the ISL map domain. - - :arg dom_inames_ordered_after: A list of :class:`str` - representing the union of inames used in - ``stmt_instance_after``. ``statement_var_name`` and - ``dom_inames_ordered_after`` are the names of the dims of - the space of the ISL map domain. - :returns: A two-tuple containing two :class:`islpy.Map`s representing the a pairwise schedule as two mappings from statement instances to lexicographic time, one for @@ -352,7 +338,7 @@ class PairwiseScheduleBuilder(object): params_sched = [] out_names_sched = self.get_lex_var_names() - def _get_map_for_stmt_inst(stmt_inst, dom_inames_ordered): + def _get_map_for_stmt_inst(stmt_inst): # Get inames domain for statement instance (a BasicSet) dom = knl.get_inames_domain( @@ -361,8 +347,7 @@ class PairwiseScheduleBuilder(object): # create space (an isl space in current implementation) # {('statement', used in statement domain>) -> # (lexicographic ordering dims)} - if dom_inames_ordered is None: - dom_inames_ordered = list_var_names_in_isl_sets([dom]) + dom_inames_ordered = list_var_names_in_isl_sets([dom]) in_names_sched = [ self.statement_var_name] + dom_inames_ordered[:] @@ -390,12 +375,8 @@ class PairwiseScheduleBuilder(object): space=sched_space, ) - map_before = _get_map_for_stmt_inst( - self.stmt_instance_before, - dom_inames_ordered_before) - map_after = _get_map_for_stmt_inst( - self.stmt_instance_after, - dom_inames_ordered_after) + map_before = _get_map_for_stmt_inst(self.stmt_instance_before) + map_after = _get_map_for_stmt_inst(self.stmt_instance_after) return (map_before, map_after) -- GitLab From 72a91ab7b3c8b3b482eb800b8a65518257ba75e7 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 7 Jul 2020 00:58:35 -0500 Subject: [PATCH 067/136] remove class variables statement_var_name and lex_var_prefix from schedule class; make them module-level variables that can be imported; (reducing state that is maintained in schedule objects) --- loopy/schedule/checker/schedule.py | 53 ++++++++++++++++++------------ 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index bcdbb6346..6e1faf0a4 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -23,6 +23,34 @@ THE SOFTWARE. import islpy as isl +STATEMENT_VAR_NAME = "_lp_linchk_statement" + + +def set_statement_var_name(name): + """Set the :class:`str` specifying the name of the variable used + to represent the unique :class:`int` statement id in a + pairwise schedule. + """ + global STATEMENT_VAR_NAME + STATEMENT_VAR_NAME = name + + +LEX_VAR_PREFIX = "_lp_linchk_l" + + +def set_lex_var_prefix(name): + """Set the :class:`str` specifying the prefix to be used for the variables + representing the dimensions in the lexicographic ordering used in a + pairwise schedule. + + E.g., a prefix of "_lp_linchk_lex" might yield lexicographic dimension + variables "_lp_linchk_lex0", "_lp_linchk_lex1", "_lp_linchk_lex2". Cf. + :ref:`reserved-identifiers`. + """ + global LEX_VAR_PREFIX + LEX_VAR_PREFIX = name + + class StatementRef(object): """A reference to a :mod:`loopy` statement. @@ -128,23 +156,8 @@ class PairwiseScheduleBuilder(object): in a single lexicographic ordering. Points in lexicographic ordering are represented as a list of :class:`int` or as :class:`str` :mod:`loopy` inames. - - .. attribute:: statement_var_name - - A :class:`str` specifying the name of the variable used - to represent the unique :class:`int` statement id. - - .. attribute:: lex_var_prefix - - A :class:`str` specifying the prefix to be used for the variables - representing the dimensions in the lexicographic ordering. E.g., - a prefix of "_lp_linchk_lex" might yield variables "_lp_linchk_lex0", - "_lp_linchk_lex1", "_lp_linchk_lex2". Cf. :ref:`reserved-identifiers`. """ - statement_var_name = "_lp_linchk_statement" - lex_var_prefix = "_lp_linchk_l" - def __init__( self, linearization_items_ordered, @@ -349,8 +362,7 @@ class PairwiseScheduleBuilder(object): # (lexicographic ordering dims)} dom_inames_ordered = list_var_names_in_isl_sets([dom]) - in_names_sched = [ - self.statement_var_name] + dom_inames_ordered[:] + in_names_sched = [STATEMENT_VAR_NAME] + dom_inames_ordered[:] sched_space = get_isl_space( params_sched, in_names_sched, out_names_sched) @@ -358,7 +370,7 @@ class PairwiseScheduleBuilder(object): # for intersection with sched map later dom_to_intersect = [ add_dims_to_isl_set( - dom, isl.dim_type.set, [self.statement_var_name], 0), ] + dom, isl.dim_type.set, [STATEMENT_VAR_NAME], 0), ] # Each map representing the schedule will map # statement instances -> lex time. @@ -381,14 +393,13 @@ class PairwiseScheduleBuilder(object): return (map_before, map_after) def get_lex_var_names(self): - return [self.lex_var_prefix+str(i) - for i in range(self.max_lex_dims())] + return [LEX_VAR_PREFIX+str(i) for i in range(self.max_lex_dims())] def __str__(self): def stringify_sched_stmt_instance(stmt_inst): return "{\n[%s=%s,] -> %s;\n}" % ( - self.statement_var_name, + STATEMENT_VAR_NAME, stmt_inst.stmt_ref.int_id, stmt_inst.lex_points) -- GitLab From 67bbe8b3ac14b7a05be3c14b1f0ab3000ae8987a Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Fri, 10 Jul 2020 06:40:29 -0500 Subject: [PATCH 068/136] remove setters for sched checking constants; make __doc__ string; add LIN_CHECK_IDENTIFIER_PREFIX --- loopy/schedule/checker/schedule.py | 32 +++++++++++++----------------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 6e1faf0a4..00a9ead51 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -22,33 +22,29 @@ THE SOFTWARE. import islpy as isl +__doc__ = """ -STATEMENT_VAR_NAME = "_lp_linchk_statement" +.. data:: LIN_CHECK_IDENTIFIER_PREFIX + The prefix for identifiers involved in linearization checking. -def set_statement_var_name(name): - """Set the :class:`str` specifying the name of the variable used - to represent the unique :class:`int` statement id in a - pairwise schedule. - """ - global STATEMENT_VAR_NAME - STATEMENT_VAR_NAME = name - +.. data:: LEX_VAR_PREFIX -LEX_VAR_PREFIX = "_lp_linchk_l" + E.g., a prefix of "_lp_linchk_lex" might yield lexicographic dimension + variables "_lp_linchk_lex0", "_lp_linchk_lex1", "_lp_linchk_lex2". Cf. + :ref:`reserved-identifiers`. +.. data:: STATEMENT_VAR_NAME -def set_lex_var_prefix(name): - """Set the :class:`str` specifying the prefix to be used for the variables + Set the :class:`str` specifying the prefix to be used for the variables representing the dimensions in the lexicographic ordering used in a pairwise schedule. - E.g., a prefix of "_lp_linchk_lex" might yield lexicographic dimension - variables "_lp_linchk_lex0", "_lp_linchk_lex1", "_lp_linchk_lex2". Cf. - :ref:`reserved-identifiers`. - """ - global LEX_VAR_PREFIX - LEX_VAR_PREFIX = name +""" + +LIN_CHECK_IDENTIFIER_PREFIX = "_lp_linchk_" +LEX_VAR_PREFIX = "%sl" % (LIN_CHECK_IDENTIFIER_PREFIX) +STATEMENT_VAR_NAME = "%sstatement" % (LIN_CHECK_IDENTIFIER_PREFIX) class StatementRef(object): -- GitLab From b54ed6f839c88618582085dc6d1393c5c3656a1a Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Fri, 10 Jul 2020 07:21:19 -0500 Subject: [PATCH 069/136] use STATEMENT_VAR_NAME and LEX_VAR_PREFIX constants when building test maps; use function to make test map creation easier --- test/test_linearization_checker.py | 139 +++++++++++++++-------------- 1 file changed, 71 insertions(+), 68 deletions(-) diff --git a/test/test_linearization_checker.py b/test/test_linearization_checker.py index 520efba9b..d3042b36c 100644 --- a/test/test_linearization_checker.py +++ b/test/test_linearization_checker.py @@ -35,6 +35,10 @@ from loopy import ( preprocess_kernel, get_one_linearized_kernel, ) +from loopy.schedule.checker.schedule import ( + LEX_VAR_PREFIX, + STATEMENT_VAR_NAME, +) logger = logging.getLogger(__name__) @@ -139,6 +143,13 @@ def test_lexschedule_and_map_creation(): if isinstance(item, RunInstruction): linearized_insn_ord.append(item.insn_id) + def _lex_space_string(dim_vals): + # Return a string describing lex space dimension assignments + # (used to create maps below) + return ", ".join( + ["%s%d=%s" % (LEX_VAR_PREFIX, idx, str(val)) + for idx, val in enumerate(dim_vals)]) + # Relationship between insn_a and insn_b --------------------------------------- assert sched_ab.stmt_instance_before.lex_points == [0, 'i', 0, 'k', 0] @@ -151,21 +162,21 @@ def test_lexschedule_and_map_creation(): # Create expected maps, align, compare sched_map_before_expected = isl.Map( - "[pi, pk] -> { " - "[_lp_linchk_statement=0, i, k] -> " - "[_lp_linchk_l0=0, _lp_linchk_l1=i, _lp_linchk_l2=0, _lp_linchk_l3=k, " - "_lp_linchk_l4=0] : " - "0 <= i < pi and 0 <= k < pk }" + "[pi, pk] -> { [%s=0, i, k] -> [%s] : 0 <= i < pi and 0 <= k < pk }" + % ( + STATEMENT_VAR_NAME, + _lex_space_string(["0", "i", "0", "k", "0"]), + ) ) sched_map_before_expected = ensure_dim_names_match_and_align( sched_map_before_expected, sched_map_before) sched_map_after_expected = isl.Map( - "[pi, pj] -> { " - "[_lp_linchk_statement=1, i, j] -> " - "[_lp_linchk_l0=0, _lp_linchk_l1=i, _lp_linchk_l2=1, _lp_linchk_l3=j, " - "_lp_linchk_l4=0] : " - "0 <= i < pi and 0 <= j < pj }" + "[pi, pj] -> { [%s=1, i, j] -> [%s] : 0 <= i < pi and 0 <= j < pj }" + % ( + STATEMENT_VAR_NAME, + _lex_space_string(["0", "i", "1", "j", "0"]), + ) ) sched_map_after_expected = ensure_dim_names_match_and_align( sched_map_after_expected, sched_map_after) @@ -186,21 +197,21 @@ def test_lexschedule_and_map_creation(): # Create expected maps, align, compare sched_map_before_expected = isl.Map( - "[pi, pk] -> { " - "[_lp_linchk_statement=0, i, k] -> " - "[_lp_linchk_l0=0, _lp_linchk_l1=i, _lp_linchk_l2=0, _lp_linchk_l3=k, " - "_lp_linchk_l4=0] : " - "0 <= i < pi and 0 <= k < pk }" + "[pi, pk] -> { [%s=0, i, k] -> [%s] : 0 <= i < pi and 0 <= k < pk }" + % ( + STATEMENT_VAR_NAME, + _lex_space_string(["0", "i", "0", "k", "0"]), + ) ) sched_map_before_expected = ensure_dim_names_match_and_align( sched_map_before_expected, sched_map_before) sched_map_after_expected = isl.Map( - "[pi, pj] -> { " - "[_lp_linchk_statement=1, i, j] -> " - "[_lp_linchk_l0=0, _lp_linchk_l1=i, _lp_linchk_l2=1, _lp_linchk_l3=j, " - "_lp_linchk_l4=0] : " - "0 <= i < pi and 0 <= j < pj }" + "[pi, pj] -> { [%s=1, i, j] -> [%s] : 0 <= i < pi and 0 <= j < pj }" + % ( + STATEMENT_VAR_NAME, + _lex_space_string(["0", "i", "1", "j", "0"]), + ) ) sched_map_after_expected = ensure_dim_names_match_and_align( sched_map_after_expected, sched_map_after) @@ -225,23 +236,21 @@ def test_lexschedule_and_map_creation(): # Create expected maps, align, compare sched_map_before_expected = isl.Map( - "[pi, pk] -> { " - "[_lp_linchk_statement=0, i, k] -> " - "[_lp_linchk_l0=%d, _lp_linchk_l1=i, _lp_linchk_l2=0, _lp_linchk_l3=k, " - "_lp_linchk_l4=0] : " - "0 <= i < pi and 0 <= k < pk }" - % (a_lex_idx) + "[pi, pk] -> { [%s=0, i, k] -> [%s] : 0 <= i < pi and 0 <= k < pk }" + % ( + STATEMENT_VAR_NAME, + _lex_space_string([a_lex_idx, "i", "0", "k", "0"]), + ) ) sched_map_before_expected = ensure_dim_names_match_and_align( sched_map_before_expected, sched_map_before) sched_map_after_expected = isl.Map( - "[pt] -> { " - "[_lp_linchk_statement=1, t] -> " - "[_lp_linchk_l0=%d, _lp_linchk_l1=t, _lp_linchk_l2=0, _lp_linchk_l3=0, " - "_lp_linchk_l4=0] : " - "0 <= t < pt }" - % (d_lex_idx) + "[pt] -> { [%s=1, t] -> [%s] : 0 <= t < pt }" + % ( + STATEMENT_VAR_NAME, + _lex_space_string([d_lex_idx, "t", "0", "0", "0"]), + ) ) sched_map_after_expected = ensure_dim_names_match_and_align( sched_map_after_expected, sched_map_after) @@ -273,23 +282,21 @@ def test_lexschedule_and_map_creation(): # Create expected maps, align, compare sched_map_before_expected = isl.Map( - "[pi, pj] -> { " - "[_lp_linchk_statement=0, i, j] -> " - "[_lp_linchk_l0=0, _lp_linchk_l1=i, _lp_linchk_l2=0, _lp_linchk_l3=j, " - "_lp_linchk_l4=%d] : " - "0 <= i < pi and 0 <= j < pj }" - % (b_lex_idx) + "[pi, pj] -> { [%s=0, i, j] -> [%s] : 0 <= i < pi and 0 <= j < pj }" + % ( + STATEMENT_VAR_NAME, + _lex_space_string(["0", "i", "0", "j", b_lex_idx]), + ) ) sched_map_before_expected = ensure_dim_names_match_and_align( sched_map_before_expected, sched_map_before) sched_map_after_expected = isl.Map( - "[pi, pj] -> { " - "[_lp_linchk_statement=1, i, j] -> " - "[_lp_linchk_l0=0, _lp_linchk_l1=i, _lp_linchk_l2=0, _lp_linchk_l3=j, " - "_lp_linchk_l4=%d] : " - "0 <= i < pi and 0 <= j < pj }" - % (c_lex_idx) + "[pi, pj] -> { [%s=1, i, j] -> [%s] : 0 <= i < pi and 0 <= j < pj }" + % ( + STATEMENT_VAR_NAME, + _lex_space_string(["0", "i", "0", "j", c_lex_idx]), + ) ) sched_map_after_expected = ensure_dim_names_match_and_align( sched_map_after_expected, sched_map_after) @@ -321,23 +328,21 @@ def test_lexschedule_and_map_creation(): # Create expected maps, align, compare sched_map_before_expected = isl.Map( - "[pi, pj] -> { " - "[_lp_linchk_statement=0, i, j] -> " - "[_lp_linchk_l0=%d, _lp_linchk_l1=i, _lp_linchk_l2=0, _lp_linchk_l3=j, " - "_lp_linchk_l4=0] : " - "0 <= i < pi and 0 <= j < pj }" - % (b_lex_idx) + "[pi, pj] -> { [%s=0, i, j] -> [%s] : 0 <= i < pi and 0 <= j < pj }" + % ( + STATEMENT_VAR_NAME, + _lex_space_string([b_lex_idx, "i", "0", "j", "0"]), + ) ) sched_map_before_expected = ensure_dim_names_match_and_align( sched_map_before_expected, sched_map_before) sched_map_after_expected = isl.Map( - "[pt] -> { " - "[_lp_linchk_statement=1, t] -> " - "[_lp_linchk_l0=%d, _lp_linchk_l1=t, _lp_linchk_l2=0, _lp_linchk_l3=0, " - "_lp_linchk_l4=0] : " - "0 <= t < pt }" - % (d_lex_idx) + "[pt] -> { [%s=1, t] -> [%s] : 0 <= t < pt }" + % ( + STATEMENT_VAR_NAME, + _lex_space_string([d_lex_idx, "t", "0", "0", "0"]), + ) ) sched_map_after_expected = ensure_dim_names_match_and_align( sched_map_after_expected, sched_map_after) @@ -369,23 +374,21 @@ def test_lexschedule_and_map_creation(): # Create expected maps, align, compare sched_map_before_expected = isl.Map( - "[pi, pj] -> { " - "[_lp_linchk_statement=0, i, j] -> " - "[_lp_linchk_l0=%d, _lp_linchk_l1=i, _lp_linchk_l2=0, _lp_linchk_l3=j, " - "_lp_linchk_l4=0] : " - "0 <= i < pi and 0 <= j < pj }" - % (c_lex_idx) + "[pi, pj] -> { [%s=0, i, j] -> [%s] : 0 <= i < pi and 0 <= j < pj }" + % ( + STATEMENT_VAR_NAME, + _lex_space_string([c_lex_idx, "i", "0", "j", "0"]), + ) ) sched_map_before_expected = ensure_dim_names_match_and_align( sched_map_before_expected, sched_map_before) sched_map_after_expected = isl.Map( - "[pt] -> { " - "[_lp_linchk_statement=1, t] -> " - "[_lp_linchk_l0=%d, _lp_linchk_l1=t, _lp_linchk_l2=0, _lp_linchk_l3=0, " - "_lp_linchk_l4=0] : " - "0 <= t < pt }" - % (d_lex_idx) + "[pt] -> { [%s=1, t] -> [%s] : 0 <= t < pt }" + % ( + STATEMENT_VAR_NAME, + _lex_space_string([d_lex_idx, "t", "0", "0", "0"]), + ) ) sched_map_after_expected = ensure_dim_names_match_and_align( sched_map_after_expected, sched_map_after) -- GitLab From b2c589713f7cc152650b5b3dec50bdfa9fb59b9d Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Fri, 10 Jul 2020 08:28:25 -0500 Subject: [PATCH 070/136] remove StatementRef and change StatementInstanceSet.stmt_ref to just StatementInstanceSet.insn_id --- loopy/schedule/checker/schedule.py | 116 +++++++++-------------------- 1 file changed, 37 insertions(+), 79 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 00a9ead51..db35ec124 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -47,55 +47,6 @@ LEX_VAR_PREFIX = "%sl" % (LIN_CHECK_IDENTIFIER_PREFIX) STATEMENT_VAR_NAME = "%sstatement" % (LIN_CHECK_IDENTIFIER_PREFIX) -class StatementRef(object): - """A reference to a :mod:`loopy` statement. - - .. attribute:: insn_id - - A :class:`str` specifying the :mod:`loopy` instruction id - for this statement. - - .. attribute:: int_id - - A :class:`int` uniquely identifying the statement within a - :class:`PairwiseScheduleBuilder`. A :class:`PairwiseScheduleBuilder` - builds a mapping from points in a space of statement instances to - points in a lexicographic ordering. The `statement` dimension of a - point in the statement instance space representing an instance of - this statement is assigned this value. - - """ - - def __init__( - self, - insn_id, - int_id=None, - ): - self.insn_id = insn_id - self.int_id = int_id - - def __eq__(self, other): - return ( - self.insn_id == other.insn_id - and self.int_id == other.int_id - ) - - def update_persistent_hash(self, key_hash, key_builder): - """Custom hash computation function for use with - :class:`pytools.persistent_dict.PersistentDict`. - """ - - key_builder.rec(key_hash, self.insn_id) - key_builder.rec(key_hash, self.int_id) - - def __str__(self): - if self.int_id is not None: - int_id = ":%d" % (self.int_id) - else: - int_id = "" - return "%s(%s%s)" % (self.__class__.__name__, self.insn_id, int_id) - - class StatementInstanceSet(object): """A representation of a set of (non-concurrent) instances of a statement being executed. The ordering of the instances is described @@ -103,9 +54,10 @@ class StatementInstanceSet(object): lexicographic ordering of statements. Each field in the list corresponds to a dimension in the lexicographic ordering. - .. attribute:: stmt_ref + .. attribute:: insn_id - A :class:`StatementRef`. + A :class:`str` instruction identifier that is unique within + a :class:`loopy.kernel.LoopKernel`. .. attribute:: lex_points @@ -116,15 +68,15 @@ class StatementInstanceSet(object): def __init__( self, - stmt_ref, + insn_id, lex_points, ): - self.stmt_ref = stmt_ref + self.insn_id = insn_id self.lex_points = lex_points def __repr__(self): return "%s(%s, %s)" % ( - self.__class__.__name__, self.stmt_ref, self.lex_points) + self.__class__.__name__, self.insn_id, self.lex_points) class PairwiseScheduleBuilder(object): @@ -177,12 +129,6 @@ class PairwiseScheduleBuilder(object): self.stmt_instance_before = None self.stmt_instance_after = None - # Determine integer IDs that will represent each statement in mapping - # (dependency map creation assumes sid_before=0 and sid_after=1, unless - # before and after refer to same stmt, in which case sid_before=sid_after=0) - int_sid_before = 0 - int_sid_after = 0 if before_insn_id == after_insn_id else 1 - # TODO when/after dependencies are added, consider the possibility # of removing the two-statements-per-PairwiseScheduleBuilder limitation @@ -254,20 +200,14 @@ class PairwiseScheduleBuilder(object): if lp_insn_id == before_insn_id: # add before sched item self.stmt_instance_before = StatementInstanceSet( - StatementRef( - insn_id=lp_insn_id, - int_id=int_sid_before, # int representing insn - ), + lp_insn_id, next_insn_lex_tuple[:]) stmt_added = True if lp_insn_id == after_insn_id: # add after sched item self.stmt_instance_after = StatementInstanceSet( - StatementRef( - insn_id=lp_insn_id, - int_id=int_sid_after, # int representing insn - ), + lp_insn_id, next_insn_lex_tuple[:]) stmt_added = True @@ -300,13 +240,13 @@ class PairwiseScheduleBuilder(object): def pad_lex_tuples_with_zeros(self): """Find the maximum number of lexicographic dimensions represented in the lexicographic ordering, and if any - :class:`StatementRef` maps to a lex point tuple with + :class:`StatementInstanceSet` maps to a lex point tuple with fewer dimensions, add a zero for each of the missing dimensions. """ def _pad_lex_tuple_with_zeros(stmt_inst, length): return StatementInstanceSet( - stmt_inst.stmt_ref, + stmt_inst.insn_id, stmt_inst.lex_points[:] + [0]*(length-len(stmt_inst.lex_points)), ) @@ -347,11 +287,11 @@ class PairwiseScheduleBuilder(object): params_sched = [] out_names_sched = self.get_lex_var_names() - def _get_map_for_stmt_inst(stmt_inst): + def _get_map_for_stmt_inst(stmt_inst, int_sid): # Get inames domain for statement instance (a BasicSet) dom = knl.get_inames_domain( - knl.id_to_insn[stmt_inst.stmt_ref.insn_id].within_inames) + knl.id_to_insn[stmt_inst.insn_id].within_inames) # create space (an isl space in current implementation) # {('statement', used in statement domain>) -> @@ -373,7 +313,7 @@ class PairwiseScheduleBuilder(object): # Right now, statement instance tuples consist of single int. # Add all inames from domains to each map domain tuple. tuple_pair = [( - (stmt_inst.stmt_ref.int_id, ) + tuple(dom_inames_ordered), + (int_sid, ) + tuple(dom_inames_ordered), stmt_inst.lex_points )] @@ -383,8 +323,18 @@ class PairwiseScheduleBuilder(object): space=sched_space, ) - map_before = _get_map_for_stmt_inst(self.stmt_instance_before) - map_after = _get_map_for_stmt_inst(self.stmt_instance_after) + # Determine integer IDs that will represent each statement in mapping + # (dependency map creation assumes sid_before=0 and sid_after=1, unless + # before and after refer to same stmt, in which case sid_before=sid_after=0) + int_sid_before = 0 + int_sid_after = 0 if ( + self.stmt_instance_before.insn_id == self.stmt_instance_after.insn_id + ) else 1 + + map_before = _get_map_for_stmt_inst( + self.stmt_instance_before, int_sid_before) + map_after = _get_map_for_stmt_inst( + self.stmt_instance_after, int_sid_after) return (map_before, map_after) @@ -393,13 +343,21 @@ class PairwiseScheduleBuilder(object): def __str__(self): - def stringify_sched_stmt_instance(stmt_inst): + def stringify_sched_stmt_instance(stmt_inst, int_sid): return "{\n[%s=%s,] -> %s;\n}" % ( STATEMENT_VAR_NAME, - stmt_inst.stmt_ref.int_id, + int_sid, stmt_inst.lex_points) + # TODO once we change class -> funcs, this repetition of logic will disappear + int_sid_before = 0 + int_sid_after = 0 if ( + self.stmt_instance_before.insn_id == self.stmt_instance_after.insn_id + ) else 1 + return "%s(\nBefore: %s\nAfter: %s\n)" % ( self.__class__.__name__, - stringify_sched_stmt_instance(self.stmt_instance_before), - stringify_sched_stmt_instance(self.stmt_instance_after)) + stringify_sched_stmt_instance( + self.stmt_instance_before, int_sid_before), + stringify_sched_stmt_instance( + self.stmt_instance_after, int_sid_after)) -- GitLab From b4e25dde21b214f5d5fa22c54fe8be1b0ad1664f Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Fri, 10 Jul 2020 08:30:22 -0500 Subject: [PATCH 071/136] rename PairwiseScheduleBuilder.statement_instance_before/after to PairwiseScheduleBuilder.statement_instance_set_before/after (since they're not just a single instance) --- loopy/schedule/checker/schedule.py | 49 ++++++++++++++++-------------- test/test_linearization_checker.py | 28 +++++++++-------- 2 files changed, 42 insertions(+), 35 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index db35ec124..04d1315e1 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -87,19 +87,19 @@ class PairwiseScheduleBuilder(object): :func:`loopy.schedule.checker.get_schedule_for_statement_pair` is the preferred method of creating a PairwiseScheduleBuilder. - .. attribute:: stmt_instance_before + .. attribute:: stmt_instance_set_before A :class:`StatementInstanceSet` whose ordering relative - to `stmt_instance_after is described by PairwiseScheduleBuilder. This + to `stmt_instance_set_after is described by PairwiseScheduleBuilder. This is achieved by mapping the statement instances in both sets to points in a single lexicographic ordering. Points in lexicographic ordering are represented as a list of :class:`int` or as :class:`str` :mod:`loopy` inames. - .. attribute:: stmt_instance_after + .. attribute:: stmt_instance_set_after A :class:`StatementInstanceSet` whose ordering relative - to `stmt_instance_before is described by PairwiseScheduleBuilder. This + to `stmt_instance_set_before is described by PairwiseScheduleBuilder. This is achieved by mapping the statement instances in both sets to points in a single lexicographic ordering. Points in lexicographic ordering are represented as a list of :class:`int` or as :class:`str` @@ -118,7 +118,7 @@ class PairwiseScheduleBuilder(object): order will be described by this :class:`PairwiseScheduleBuilder`. :arg before_insn_id: A :class:`str` instruction id specifying - stmt_instance_before in this pair of instructions. + stmt_instance_set_before in this pair of instructions. :arg after_insn_id: A :class:`str` instruction id specifying stmt_instancce_after in this pair of instructions. @@ -126,8 +126,8 @@ class PairwiseScheduleBuilder(object): """ # PairwiseScheduleBuilder statements - self.stmt_instance_before = None - self.stmt_instance_after = None + self.stmt_instance_set_before = None + self.stmt_instance_set_after = None # TODO when/after dependencies are added, consider the possibility # of removing the two-statements-per-PairwiseScheduleBuilder limitation @@ -199,14 +199,14 @@ class PairwiseScheduleBuilder(object): if lp_insn_id == before_insn_id: # add before sched item - self.stmt_instance_before = StatementInstanceSet( + self.stmt_instance_set_before = StatementInstanceSet( lp_insn_id, next_insn_lex_tuple[:]) stmt_added = True if lp_insn_id == after_insn_id: # add after sched item - self.stmt_instance_after = StatementInstanceSet( + self.stmt_instance_set_after = StatementInstanceSet( lp_insn_id, next_insn_lex_tuple[:]) stmt_added = True @@ -224,7 +224,7 @@ class PairwiseScheduleBuilder(object): else: pass # to save time, stop when we've created both statements - if self.stmt_instance_before and self.stmt_instance_after: + if self.stmt_instance_set_before and self.stmt_instance_set_after: break # At this point, pairwise sub-schedule may contain lex point tuples @@ -234,8 +234,8 @@ class PairwiseScheduleBuilder(object): def max_lex_dims(self): return max([ - len(self.stmt_instance_before.lex_points), - len(self.stmt_instance_after.lex_points)]) + len(self.stmt_instance_set_before.lex_points), + len(self.stmt_instance_set_after.lex_points)]) def pad_lex_tuples_with_zeros(self): """Find the maximum number of lexicographic dimensions represented @@ -252,10 +252,10 @@ class PairwiseScheduleBuilder(object): max_lex_dim = self.max_lex_dims() - self.stmt_instance_before = _pad_lex_tuple_with_zeros( - self.stmt_instance_before, max_lex_dim) - self.stmt_instance_after = _pad_lex_tuple_with_zeros( - self.stmt_instance_after, max_lex_dim) + self.stmt_instance_set_before = _pad_lex_tuple_with_zeros( + self.stmt_instance_set_before, max_lex_dim) + self.stmt_instance_set_after = _pad_lex_tuple_with_zeros( + self.stmt_instance_set_after, max_lex_dim) def build_maps( self, @@ -263,7 +263,8 @@ class PairwiseScheduleBuilder(object): ): r"""Create a pair of :class:`islpy.Map`\ s representing a pairwise schedule as two mappings from statement instances to lexicographic time, - one for ``stmt_instance_before`` and one for ``stmt_instance_after``. + one for ``stmt_instance_set_before`` and one for + ``stmt_instance_set_after``. :arg knl: A :class:`loopy.kernel.LoopKernel` containing the linearization items that are described by the schedule. This @@ -328,13 +329,14 @@ class PairwiseScheduleBuilder(object): # before and after refer to same stmt, in which case sid_before=sid_after=0) int_sid_before = 0 int_sid_after = 0 if ( - self.stmt_instance_before.insn_id == self.stmt_instance_after.insn_id + self.stmt_instance_set_before.insn_id == + self.stmt_instance_set_after.insn_id ) else 1 map_before = _get_map_for_stmt_inst( - self.stmt_instance_before, int_sid_before) + self.stmt_instance_set_before, int_sid_before) map_after = _get_map_for_stmt_inst( - self.stmt_instance_after, int_sid_after) + self.stmt_instance_set_after, int_sid_after) return (map_before, map_after) @@ -352,12 +354,13 @@ class PairwiseScheduleBuilder(object): # TODO once we change class -> funcs, this repetition of logic will disappear int_sid_before = 0 int_sid_after = 0 if ( - self.stmt_instance_before.insn_id == self.stmt_instance_after.insn_id + self.stmt_instance_set_before.insn_id == + self.stmt_instance_set_after.insn_id ) else 1 return "%s(\nBefore: %s\nAfter: %s\n)" % ( self.__class__.__name__, stringify_sched_stmt_instance( - self.stmt_instance_before, int_sid_before), + self.stmt_instance_set_before, int_sid_before), stringify_sched_stmt_instance( - self.stmt_instance_after, int_sid_after)) + self.stmt_instance_set_after, int_sid_after)) diff --git a/test/test_linearization_checker.py b/test/test_linearization_checker.py index d3042b36c..c87bb149b 100644 --- a/test/test_linearization_checker.py +++ b/test/test_linearization_checker.py @@ -152,8 +152,8 @@ def test_lexschedule_and_map_creation(): # Relationship between insn_a and insn_b --------------------------------------- - assert sched_ab.stmt_instance_before.lex_points == [0, 'i', 0, 'k', 0] - assert sched_ab.stmt_instance_after.lex_points == [0, 'i', 1, 'j', 0] + assert sched_ab.stmt_instance_set_before.lex_points == [0, 'i', 0, 'k', 0] + assert sched_ab.stmt_instance_set_after.lex_points == [0, 'i', 1, 'j', 0] # Get two maps from the PairwiseScheduleBuilder @@ -187,8 +187,8 @@ def test_lexschedule_and_map_creation(): # ------------------------------------------------------------------------------ # Relationship between insn_a and insn_c --------------------------------------- - assert sched_ac.stmt_instance_before.lex_points == [0, 'i', 0, 'k', 0] - assert sched_ac.stmt_instance_after.lex_points == [0, 'i', 1, 'j', 0] + assert sched_ac.stmt_instance_set_before.lex_points == [0, 'i', 0, 'k', 0] + assert sched_ac.stmt_instance_set_after.lex_points == [0, 'i', 1, 'j', 0] # Get two maps from the PairwiseScheduleBuilder @@ -225,9 +225,10 @@ def test_lexschedule_and_map_creation(): # insn_a and insn_d could have been linearized in either order # (i loop could be before or after t loop) def perform_insn_ad_checks_with(a_lex_idx, d_lex_idx): - assert sched_ad.stmt_instance_before.lex_points == [ + assert sched_ad.stmt_instance_set_before.lex_points == [ a_lex_idx, 'i', 0, 'k', 0] - assert sched_ad.stmt_instance_after.lex_points == [d_lex_idx, 't', 0, 0, 0] + assert sched_ad.stmt_instance_set_after.lex_points == [ + d_lex_idx, 't', 0, 0, 0] # Get two maps from the PairwiseScheduleBuilder @@ -271,9 +272,10 @@ def test_lexschedule_and_map_creation(): # insn_b and insn_c could have been linearized in either order # (i loop could be before or after t loop) def perform_insn_bc_checks_with(b_lex_idx, c_lex_idx): - assert sched_bc.stmt_instance_before.lex_points == [ + assert sched_bc.stmt_instance_set_before.lex_points == [ 0, 'i', 0, 'j', b_lex_idx] - assert sched_bc.stmt_instance_after.lex_points == [0, 'i', 0, 'j', c_lex_idx] + assert sched_bc.stmt_instance_set_after.lex_points == [ + 0, 'i', 0, 'j', c_lex_idx] # Get two maps from the PairwiseScheduleBuilder @@ -317,9 +319,10 @@ def test_lexschedule_and_map_creation(): # insn_b and insn_d could have been linearized in either order # (i loop could be before or after t loop) def perform_insn_bd_checks_with(b_lex_idx, d_lex_idx): - assert sched_bd.stmt_instance_before.lex_points == [ + assert sched_bd.stmt_instance_set_before.lex_points == [ b_lex_idx, 'i', 0, 'j', 0] - assert sched_bd.stmt_instance_after.lex_points == [d_lex_idx, 't', 0, 0, 0] + assert sched_bd.stmt_instance_set_after.lex_points == [ + d_lex_idx, 't', 0, 0, 0] # Get two maps from the PairwiseScheduleBuilder @@ -363,9 +366,10 @@ def test_lexschedule_and_map_creation(): # insn_c and insn_d could have been linearized in either order # (i loop could be before or after t loop) def perform_insn_cd_checks_with(c_lex_idx, d_lex_idx): - assert sched_cd.stmt_instance_before.lex_points == [ + assert sched_cd.stmt_instance_set_before.lex_points == [ c_lex_idx, 'i', 0, 'j', 0] - assert sched_cd.stmt_instance_after.lex_points == [d_lex_idx, 't', 0, 0, 0] + assert sched_cd.stmt_instance_set_after.lex_points == [ + d_lex_idx, 't', 0, 0, 0] # Get two maps from the PairwiseScheduleBuilder -- GitLab From bb18e5823f422ce1b034389c52119fd3a4efd5f7 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 13 Jul 2020 02:47:33 -0500 Subject: [PATCH 072/136] remove pad_lex_tuples_with_zeros() method since it's only ever called once (in-line its functionality) --- loopy/schedule/checker/schedule.py | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 04d1315e1..818d8355c 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -230,19 +230,6 @@ class PairwiseScheduleBuilder(object): # At this point, pairwise sub-schedule may contain lex point tuples # missing dimensions; the values in these missing dims should # be zero, so add them. - self.pad_lex_tuples_with_zeros() - - def max_lex_dims(self): - return max([ - len(self.stmt_instance_set_before.lex_points), - len(self.stmt_instance_set_after.lex_points)]) - - def pad_lex_tuples_with_zeros(self): - """Find the maximum number of lexicographic dimensions represented - in the lexicographic ordering, and if any - :class:`StatementInstanceSet` maps to a lex point tuple with - fewer dimensions, add a zero for each of the missing dimensions. - """ def _pad_lex_tuple_with_zeros(stmt_inst, length): return StatementInstanceSet( @@ -257,6 +244,11 @@ class PairwiseScheduleBuilder(object): self.stmt_instance_set_after = _pad_lex_tuple_with_zeros( self.stmt_instance_set_after, max_lex_dim) + def max_lex_dims(self): + return max([ + len(self.stmt_instance_set_before.lex_points), + len(self.stmt_instance_set_after.lex_points)]) + def build_maps( self, knl, -- GitLab From 2f0c95cec3659c3e154e5fee60b664a21ef7f77e Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 13 Jul 2020 03:25:15 -0500 Subject: [PATCH 073/136] remove get_isl_space() and set_all_isl_space_names(), instead use isl.Space.create_from_names() --- loopy/schedule/checker/schedule.py | 6 ++--- loopy/schedule/checker/utils.py | 42 ------------------------------ 2 files changed, 3 insertions(+), 45 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 818d8355c..f085547c6 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -272,7 +272,6 @@ class PairwiseScheduleBuilder(object): from loopy.schedule.checker.utils import ( list_var_names_in_isl_sets, - get_isl_space, create_symbolic_map_from_tuples, add_dims_to_isl_set, ) @@ -292,8 +291,9 @@ class PairwiseScheduleBuilder(object): dom_inames_ordered = list_var_names_in_isl_sets([dom]) in_names_sched = [STATEMENT_VAR_NAME] + dom_inames_ordered[:] - sched_space = get_isl_space( - params_sched, in_names_sched, out_names_sched) + sched_space = isl.Space.create_from_names( + isl.DEFAULT_CONTEXT, + in_=in_names_sched, out=out_names_sched, params=params_sched) # Insert 'statement' dim into domain so that its space allows # for intersection with sched map later diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index e862d166e..f336d21f7 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -237,48 +237,6 @@ def create_symbolic_map_from_tuples( return _get_union(all_maps) -def set_all_isl_space_names( - isl_space, param_names=None, in_names=None, out_names=None): - """Return a copy of `isl_space` with the specified dimension names. - If no names are provided, use `p0, p1, ...` for parameters, - `i0, i1, ...`, for in_ dimensions, and `o0, o1, ...` for out - dimensions. - - """ - - new_space = isl_space.copy() - dim_type = isl.dim_type - if param_names: - for i, p in enumerate(param_names): - new_space = new_space.set_dim_name(dim_type.param, i, p) - else: - for i in range(len(isl_space.get_var_names(dim_type.param))): - new_space = new_space.set_dim_name(dim_type.param, i, "p%d" % (i)) - if in_names: - for i, p in enumerate(in_names): - new_space = new_space.set_dim_name(dim_type.in_, i, p) - else: - for i in range(len(isl_space.get_var_names(dim_type.in_))): - new_space = new_space.set_dim_name(dim_type.in_, i, "i%d" % (i)) - if out_names: - for i, p in enumerate(out_names): - new_space = new_space.set_dim_name(dim_type.out, i, p) - else: - for i in range(len(isl_space.get_var_names(dim_type.out))): - new_space = new_space.set_dim_name(dim_type.out, i, "o%d" % (i)) - return new_space - - -def get_isl_space(param_names, in_names, out_names): - """Return an :class:`islpy.Space` with the specified dimension names. - """ - - space = isl.Space.alloc( - isl.DEFAULT_CONTEXT, len(param_names), len(in_names), len(out_names)) - return set_all_isl_space_names( - space, param_names=param_names, in_names=in_names, out_names=out_names) - - def get_concurrent_inames(knl): from loopy.kernel.data import ConcurrentTag conc_inames = set() -- GitLab From d8587b0f824e45b1640c2747a332100dd9ab469b Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 13 Jul 2020 04:12:49 -0500 Subject: [PATCH 074/136] perform union of maps upon creation in create_symbolic_map_from_tuples() rather than afterward; temporarily leave old version in place to test for equality --- loopy/schedule/checker/utils.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index f336d21f7..3a7688e4d 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -187,7 +187,14 @@ def create_symbolic_map_from_tuples( # loop through pairs and create a set that will later be converted to a map + # TODO remove after testing: all_maps = [] + + # initialize union to empty + union_of_maps = isl.Map.from_domain( + islvars[0].eq_set(islvars[0]+1) # 0 == 1 (false) + ).move_dims( + dim_type.out, 0, dim_type.in_, len(space_in_names), len(space_out_names)) for (tup_in, tup_out), dom in tuple_pairs_with_domains: # initialize constraint with true @@ -231,10 +238,17 @@ def create_symbolic_map_from_tuples( ) # intersect domain with this map + union_of_maps = union_of_maps.union( + map_from_set.intersect_domain(dom_with_all_inames)) + + # TODO remove after testing: all_maps.append( map_from_set.intersect_domain(dom_with_all_inames)) - return _get_union(all_maps) + # TODO remove after testing: + assert union_of_maps == _get_union(all_maps) + + return union_of_maps def get_concurrent_inames(knl): -- GitLab From c465bdb4cecfe1f700bede85680b06d51734b634 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 13 Jul 2020 04:15:58 -0500 Subject: [PATCH 075/136] remove utils._get_union() --- loopy/schedule/checker/utils.py | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index 3a7688e4d..cef985ee6 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -132,13 +132,6 @@ def ensure_dim_names_match_and_align(obj_map, tgt_map): return aligned_obj_map -def _get_union(list_items): - union = list_items[0] - for s in list_items[1:]: - union = union.union(s) - return union - - def list_var_names_in_isl_sets( isl_sets, set_dim=isl.dim_type.set): @@ -187,9 +180,6 @@ def create_symbolic_map_from_tuples( # loop through pairs and create a set that will later be converted to a map - # TODO remove after testing: - all_maps = [] - # initialize union to empty union_of_maps = isl.Map.from_domain( islvars[0].eq_set(islvars[0]+1) # 0 == 1 (false) @@ -241,13 +231,6 @@ def create_symbolic_map_from_tuples( union_of_maps = union_of_maps.union( map_from_set.intersect_domain(dom_with_all_inames)) - # TODO remove after testing: - all_maps.append( - map_from_set.intersect_domain(dom_with_all_inames)) - - # TODO remove after testing: - assert union_of_maps == _get_union(all_maps) - return union_of_maps -- GitLab From 138702bda0750e4693b946ccf31b6e0fa06b23fa Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 13 Jul 2020 11:45:25 -0500 Subject: [PATCH 076/136] (commented out code that compares result from isl.affs_from_space() to result from isl.make_zero_and_vars()) --- loopy/schedule/checker/utils.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index cef985ee6..0bfdf0a54 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -29,10 +29,15 @@ def prettier_map_string(map_obj): def get_islvars_from_space(space): + #pu.db param_names = space.get_var_names(isl.dim_type.param) in_names = space.get_var_names(isl.dim_type.in_) out_names = space.get_var_names(isl.dim_type.out) return isl.make_zero_and_vars(in_names+out_names, param_names) + #old = isl.make_zero_and_vars(in_names+out_names, param_names) + #new = isl.affs_from_space(space) + #assert old == new + #return new def add_dims_to_isl_set(isl_set, dim_type, names, new_idx_start): -- GitLab From 6f7e2a3168f05d6def4925fa1bac13c9032d51bf Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 14 Jul 2020 08:28:42 -0500 Subject: [PATCH 077/136] removed PairwiseScheduleBuilder class; removed PSB methods max_lex_dims() and build_maps() (and __str__() but no one cares); combined removed functions/class into single generate_pairwise_schedule() func that returns a pair of maps (one for each statement) so that intermediate state (what used to be PSB) is no longer kept around --- loopy/schedule/checker/__init__.py | 43 +-- loopy/schedule/checker/schedule.py | 508 +++++++++++++---------------- test/test_linearization_checker.py | 124 +++---- 3 files changed, 299 insertions(+), 376 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 716a0cb58..a2963f689 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -21,7 +21,7 @@ THE SOFTWARE. """ -# {{{ create PairwiseScheduleBuilder for statement pair +# {{{ create a pairwise schedule for statement pair def get_schedule_for_statement_pair( knl, @@ -29,9 +29,11 @@ def get_schedule_for_statement_pair( insn_id_before, insn_id_after, ): - """Create a :class:`loopy.schedule.checker.schedule.PairwiseScheduleBuilder` - representing the order of two statements as a mapping from - :class:`loopy.schedule.checker.StatementInstanceSet` + r"""Given a pair of statements in a linearized kernel, determine + the (relative) order in which the instances are executed, + by creating a mapping from statement instances to points in a single + lexicographic ordering. Create a pair of :class:`islpy.Map`\ s + representing a pairwise schedule as two mappings from statement instances to lexicographic time. :arg knl: A :class:`loopy.kernel.LoopKernel` containing the @@ -50,10 +52,10 @@ def get_schedule_for_statement_pair( :arg insn_id_after: An instruction identifier that is unique within a :class:`loopy.kernel.LoopKernel`. - :returns: A :class:`loopy.schedule.checker.schedule.PairwiseScheduleBuilder` - representing the order of two statements as a mapping from - :class:`loopy.schedule.checker.StatementInstanceSet` - to lexicographic time. + :returns: A two-tuple containing two :class:`islpy.Map`s + representing the a pairwise schedule as two mappings + from statement instances to lexicographic time, one for + each of the two statements. Example usage:: @@ -76,17 +78,16 @@ def get_schedule_for_statement_pair( from loopy.schedule.checker import ( get_schedule_for_statement_pair, ) - sched_builder_ab = get_schedule_for_statement_pair( + + # Get two maps ----------------------------------------------------------- + + sched_a, sched_b = get_schedule_for_statement_pair( knl, knl.linearization, "insn_a", "insn_b", ) - # Get two maps from the PairwiseScheduleBuilder -------------------------- - - sched_a, sched_b = sched_builder_ab.build_maps(knl) - print(sched_a) print(sched_b) @@ -112,12 +113,11 @@ def get_schedule_for_statement_pair( # }}} - # {{{ find any EnterLoop inames that are tagged as concurrent - - # so that PairwiseScheduleBuilder knows to ignore them + # {{{ Find any EnterLoop inames that are tagged as concurrent + # so that generate_pairwise_schedule() knows to ignore them # (In the future, this shouldn't be necessary because there - # won't be any inames with ConcurrentTags in EnterLoop linearization items. - # Test which exercises this: test_linearization_checker_with_stroud_bernstein()) + # won't be any inames with ConcurrentTags in EnterLoop linearization items. + # Test which exercises this: test_linearization_checker_with_stroud_bernstein()) from loopy.schedule.checker.utils import ( get_concurrent_inames, get_EnterLoop_inames, @@ -134,11 +134,12 @@ def get_schedule_for_statement_pair( # }}} - # {{{ Create PairwiseScheduleBuilder: mapping of {statement instance: lex point} + # {{{ Create two mappings from {statement instance: lex point} # include only instructions involved in this dependency - from loopy.schedule.checker.schedule import PairwiseScheduleBuilder - return PairwiseScheduleBuilder( + from loopy.schedule.checker.schedule import generate_pairwise_schedule + return generate_pairwise_schedule( + preproc_knl, linearization_items, insn_id_before, insn_id_after, diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index f085547c6..9e693a9a1 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -79,280 +79,242 @@ class StatementInstanceSet(object): self.__class__.__name__, self.insn_id, self.lex_points) -class PairwiseScheduleBuilder(object): - """Given a pair of statements in a linearized kernel, PairwiseScheduleBuilder - determines the (relative) order in which the instances are executed, +def generate_pairwise_schedule( + knl, + linearization_items_ordered, + before_insn_id, + after_insn_id, + loops_to_ignore=set(), + ): + r"""Given a pair of statements in a linearized kernel, determine + the (relative) order in which the instances are executed, by creating a mapping from statement instances to points in a single - lexicographic ordering. The function - :func:`loopy.schedule.checker.get_schedule_for_statement_pair` is the - preferred method of creating a PairwiseScheduleBuilder. - - .. attribute:: stmt_instance_set_before - - A :class:`StatementInstanceSet` whose ordering relative - to `stmt_instance_set_after is described by PairwiseScheduleBuilder. This - is achieved by mapping the statement instances in both sets to points - in a single lexicographic ordering. Points in lexicographic ordering - are represented as a list of :class:`int` or as :class:`str` - :mod:`loopy` inames. - - .. attribute:: stmt_instance_set_after - - A :class:`StatementInstanceSet` whose ordering relative - to `stmt_instance_set_before is described by PairwiseScheduleBuilder. This - is achieved by mapping the statement instances in both sets to points - in a single lexicographic ordering. Points in lexicographic ordering - are represented as a list of :class:`int` or as :class:`str` - :mod:`loopy` inames. + lexicographic ordering. Create a pair of :class:`islpy.Map`\ s + representing a pairwise schedule as two mappings from statement instances + to lexicographic time. + + :arg knl: A :class:`loopy.kernel.LoopKernel` containing the + linearization items that will be described by the schedule. This + kernel will be used to get the domains associated with the inames + used in the statements. + + :arg linearization_items_ordered: A list of :class:`loopy.schedule.ScheduleItem` + (to be renamed to `loopy.schedule.LinearizationItem`) containing the + two linearization items whose relative order will be described by the + schedule. This list may be a *partial* linearization for a kernel since + this function may be used during the linearization process. + + :arg before_insn_id: A :class:`str` instruction id specifying + stmt_instance_set_before in this pair of instructions. + + :arg after_insn_id: A :class:`str` instruction id specifying + stmt_instance_set_after in this pair of instructions. + + :returns: A two-tuple containing two :class:`islpy.Map`s + representing the a pairwise schedule as two mappings + from statement instances to lexicographic time, one for + each of the two statements. """ - def __init__( - self, - linearization_items_ordered, - before_insn_id, - after_insn_id, - loops_to_ignore=set(), - ): - """ - :arg linearization_items_ordered: A list of :class:`ScheduleItem` whose - order will be described by this :class:`PairwiseScheduleBuilder`. - - :arg before_insn_id: A :class:`str` instruction id specifying - stmt_instance_set_before in this pair of instructions. - - :arg after_insn_id: A :class:`str` instruction id specifying - stmt_instancce_after in this pair of instructions. - - """ - - # PairwiseScheduleBuilder statements - self.stmt_instance_set_before = None - self.stmt_instance_set_after = None - - # TODO when/after dependencies are added, consider the possibility - # of removing the two-statements-per-PairwiseScheduleBuilder limitation - - from loopy.schedule import (EnterLoop, LeaveLoop, Barrier, RunInstruction) - - # go through linearization_items_ordered and generate pairwise sub-schedule - - # keep track of the next tuple of points in our lexicographic - # ordering, initially this as a 1-d point with value 0 - next_insn_lex_tuple = [0] - stmt_added_since_prev_block_at_tier = [False] - for linearization_item in linearization_items_ordered: - if isinstance(linearization_item, EnterLoop): - iname = linearization_item.iname - if iname in loops_to_ignore: - continue - - # We could always increment next_insn_lex_tuple[-1] here since - # this new section of code comes after the previous section - # (statements since last opened/closed loop), but if we have - # not added any statements within the previous section yet, we - # don't have to (effectively ignoring that section of code). - if stmt_added_since_prev_block_at_tier[-1]: - next_insn_lex_tuple[-1] = next_insn_lex_tuple[-1]+1 - stmt_added_since_prev_block_at_tier[-1] = False - - # upon entering a loop, we enter a new (deeper) tier, - # add one lex dimension for the loop variable, - # add second lex dim to enumerate code blocks within new loop, and - # append a dim to stmt_added_since_prev_block_at_tier to represent - # new tier - next_insn_lex_tuple.append(iname) - next_insn_lex_tuple.append(0) - stmt_added_since_prev_block_at_tier.append(False) - elif isinstance(linearization_item, LeaveLoop): - if linearization_item.iname in loops_to_ignore: - continue - # upon leaving a loop, - # pop lex dimension for enumerating code blocks within this loop, and - # pop lex dimension for the loop variable, and + # Two StatementInstanceSets, one for each statement: + + """ + stmt_instance_set_before + + A :class:`StatementInstanceSet` whose ordering relative + to `stmt_instance_set_after is described by the schedule blueprint. This + is achieved by mapping the statement instances in both sets to points + in a single lexicographic ordering. Points in lexicographic ordering + are represented as a list of :class:`int` or as :class:`str` + :mod:`loopy` inames. + """ + stmt_instance_set_before = None + + """ + stmt_instance_set_after + + A :class:`StatementInstanceSet` whose ordering relative + to `stmt_instance_set_before is described by the schedule blueprint. This + is achieved by mapping the statement instances in both sets to points + in a single lexicographic ordering. Points in lexicographic ordering + are represented as a list of :class:`int` or as :class:`str` + :mod:`loopy` inames. + """ + stmt_instance_set_after = None + + from loopy.schedule import (EnterLoop, LeaveLoop, Barrier, RunInstruction) + + # go through linearization_items_ordered and generate pairwise sub-schedule + + # keep track of the next tuple of points in our lexicographic + # ordering, initially this as a 1-d point with value 0 + next_insn_lex_tuple = [0] + stmt_added_since_prev_block_at_tier = [False] + max_lex_dim = 0 + for linearization_item in linearization_items_ordered: + if isinstance(linearization_item, EnterLoop): + iname = linearization_item.iname + if iname in loops_to_ignore: + continue + + # We could always increment next_insn_lex_tuple[-1] here since + # this new section of code comes after the previous section + # (statements since last opened/closed loop), but if we have + # not added any statements within the previous section yet, we + # don't have to (effectively ignoring that section of code). + if stmt_added_since_prev_block_at_tier[-1]: + next_insn_lex_tuple[-1] = next_insn_lex_tuple[-1]+1 + stmt_added_since_prev_block_at_tier[-1] = False + + # upon entering a loop, we enter a new (deeper) tier, + # add one lex dimension for the loop variable, + # add second lex dim to enumerate code blocks within new loop, and + # append a dim to stmt_added_since_prev_block_at_tier to represent + # new tier + next_insn_lex_tuple.append(iname) + next_insn_lex_tuple.append(0) + stmt_added_since_prev_block_at_tier.append(False) + elif isinstance(linearization_item, LeaveLoop): + if linearization_item.iname in loops_to_ignore: + continue + # upon leaving a loop, + # pop lex dimension for enumerating code blocks within this loop, and + # pop lex dimension for the loop variable, and + # increment lex dim val enumerating items in current code block + next_insn_lex_tuple.pop() + next_insn_lex_tuple.pop() + + # We could always increment next_insn_lex_tuple[-1] here since + # this new block of code comes after the previous block (all + # statements since last opened/closed loop), but if we have not + # added any statements within the previous section yet, we + # don't have to (effectively ignoring that section of code). + stmt_added_since_prev_block_at_tier.pop() + if stmt_added_since_prev_block_at_tier[-1]: + next_insn_lex_tuple[-1] = next_insn_lex_tuple[-1]+1 + stmt_added_since_prev_block_at_tier[-1] = False + elif isinstance(linearization_item, (RunInstruction, Barrier)): + from loopy.schedule.checker.utils import ( + get_insn_id_from_linearization_item, + ) + lp_insn_id = get_insn_id_from_linearization_item(linearization_item) + if lp_insn_id is None: + # TODO make sure it's okay to ignore barriers without id + # (because they'll never be part of a dependency?) + # matmul example has barrier that fails this assertion... + # assert linearization_item.originating_insn_id is not None + continue + + # only process before/after insns, otherwise ignore + stmt_added = False + + if lp_insn_id == before_insn_id: + # add before sched item + stmt_instance_set_before = StatementInstanceSet( + lp_insn_id, + next_insn_lex_tuple[:]) + stmt_added = True + + if lp_insn_id == after_insn_id: + # add after sched item + stmt_instance_set_after = StatementInstanceSet( + lp_insn_id, + next_insn_lex_tuple[:]) + stmt_added = True + + # Note: before/after may refer to same stmt, in which case + # both of the above conditionals execute + + if stmt_added: + + # track the max number of lex dims used + if len(next_insn_lex_tuple) > max_lex_dim: + max_lex_dim = len(next_insn_lex_tuple) + # increment lex dim val enumerating items in current code block - next_insn_lex_tuple.pop() - next_insn_lex_tuple.pop() - - # We could always increment next_insn_lex_tuple[-1] here since - # this new block of code comes after the previous block (all - # statements since last opened/closed loop), but if we have not - # added any statements within the previous section yet, we - # don't have to (effectively ignoring that section of code). - stmt_added_since_prev_block_at_tier.pop() - if stmt_added_since_prev_block_at_tier[-1]: - next_insn_lex_tuple[-1] = next_insn_lex_tuple[-1]+1 - stmt_added_since_prev_block_at_tier[-1] = False - elif isinstance(linearization_item, (RunInstruction, Barrier)): - from loopy.schedule.checker.utils import ( - get_insn_id_from_linearization_item, - ) - lp_insn_id = get_insn_id_from_linearization_item(linearization_item) - if lp_insn_id is None: - # TODO make sure it's okay to ignore barriers without id - # (because they'll never be part of a dependency?) - # matmul example has barrier that fails this assertion... - # assert linearization_item.originating_insn_id is not None - continue - - # only process before/after insns, otherwise ignore - stmt_added = False - - if lp_insn_id == before_insn_id: - # add before sched item - self.stmt_instance_set_before = StatementInstanceSet( - lp_insn_id, - next_insn_lex_tuple[:]) - stmt_added = True - - if lp_insn_id == after_insn_id: - # add after sched item - self.stmt_instance_set_after = StatementInstanceSet( - lp_insn_id, - next_insn_lex_tuple[:]) - stmt_added = True - - # Note: before/after may refer to same stmt, in which case - # both of the above conditionals execute - - if stmt_added: - # increment lex dim val enumerating items in current code block - next_insn_lex_tuple[-1] = next_insn_lex_tuple[-1] + 1 - - # all current (nested) blocks now contain a statement - stmt_added_since_prev_block_at_tier = [True]*len( - stmt_added_since_prev_block_at_tier) - else: - pass - # to save time, stop when we've created both statements - if self.stmt_instance_set_before and self.stmt_instance_set_after: - break - - # At this point, pairwise sub-schedule may contain lex point tuples - # missing dimensions; the values in these missing dims should - # be zero, so add them. - - def _pad_lex_tuple_with_zeros(stmt_inst, length): - return StatementInstanceSet( - stmt_inst.insn_id, - stmt_inst.lex_points[:] + [0]*(length-len(stmt_inst.lex_points)), - ) - - max_lex_dim = self.max_lex_dims() - - self.stmt_instance_set_before = _pad_lex_tuple_with_zeros( - self.stmt_instance_set_before, max_lex_dim) - self.stmt_instance_set_after = _pad_lex_tuple_with_zeros( - self.stmt_instance_set_after, max_lex_dim) - - def max_lex_dims(self): - return max([ - len(self.stmt_instance_set_before.lex_points), - len(self.stmt_instance_set_after.lex_points)]) - - def build_maps( - self, - knl, - ): - r"""Create a pair of :class:`islpy.Map`\ s representing a pairwise schedule - as two mappings from statement instances to lexicographic time, - one for ``stmt_instance_set_before`` and one for - ``stmt_instance_set_after``. - - :arg knl: A :class:`loopy.kernel.LoopKernel` containing the - linearization items that are described by the schedule. This - kernel will be used to get the domains associated with the inames - used in the statements. - - :returns: A two-tuple containing two :class:`islpy.Map`s - representing the a pairwise schedule as two mappings - from statement instances to lexicographic time, one for - each of the two :class:`StatementInstanceSet`s. - - """ - - from loopy.schedule.checker.utils import ( - list_var_names_in_isl_sets, - create_symbolic_map_from_tuples, - add_dims_to_isl_set, - ) - - params_sched = [] - out_names_sched = self.get_lex_var_names() - - def _get_map_for_stmt_inst(stmt_inst, int_sid): - - # Get inames domain for statement instance (a BasicSet) - dom = knl.get_inames_domain( - knl.id_to_insn[stmt_inst.insn_id].within_inames) - - # create space (an isl space in current implementation) - # {('statement', used in statement domain>) -> - # (lexicographic ordering dims)} - dom_inames_ordered = list_var_names_in_isl_sets([dom]) - - in_names_sched = [STATEMENT_VAR_NAME] + dom_inames_ordered[:] - sched_space = isl.Space.create_from_names( - isl.DEFAULT_CONTEXT, - in_=in_names_sched, out=out_names_sched, params=params_sched) - - # Insert 'statement' dim into domain so that its space allows - # for intersection with sched map later - dom_to_intersect = [ - add_dims_to_isl_set( - dom, isl.dim_type.set, [STATEMENT_VAR_NAME], 0), ] - - # Each map representing the schedule will map - # statement instances -> lex time. - # Right now, statement instance tuples consist of single int. - # Add all inames from domains to each map domain tuple. - tuple_pair = [( - (int_sid, ) + tuple(dom_inames_ordered), - stmt_inst.lex_points - )] - - # create map - return create_symbolic_map_from_tuples( - tuple_pairs_with_domains=zip(tuple_pair, dom_to_intersect), - space=sched_space, - ) - - # Determine integer IDs that will represent each statement in mapping - # (dependency map creation assumes sid_before=0 and sid_after=1, unless - # before and after refer to same stmt, in which case sid_before=sid_after=0) - int_sid_before = 0 - int_sid_after = 0 if ( - self.stmt_instance_set_before.insn_id == - self.stmt_instance_set_after.insn_id - ) else 1 - - map_before = _get_map_for_stmt_inst( - self.stmt_instance_set_before, int_sid_before) - map_after = _get_map_for_stmt_inst( - self.stmt_instance_set_after, int_sid_after) - - return (map_before, map_after) - - def get_lex_var_names(self): - return [LEX_VAR_PREFIX+str(i) for i in range(self.max_lex_dims())] - - def __str__(self): - - def stringify_sched_stmt_instance(stmt_inst, int_sid): - return "{\n[%s=%s,] -> %s;\n}" % ( - STATEMENT_VAR_NAME, - int_sid, - stmt_inst.lex_points) - - # TODO once we change class -> funcs, this repetition of logic will disappear - int_sid_before = 0 - int_sid_after = 0 if ( - self.stmt_instance_set_before.insn_id == - self.stmt_instance_set_after.insn_id - ) else 1 - - return "%s(\nBefore: %s\nAfter: %s\n)" % ( - self.__class__.__name__, - stringify_sched_stmt_instance( - self.stmt_instance_set_before, int_sid_before), - stringify_sched_stmt_instance( - self.stmt_instance_set_after, int_sid_after)) + next_insn_lex_tuple[-1] = next_insn_lex_tuple[-1] + 1 + + # all current (nested) blocks now contain a statement + stmt_added_since_prev_block_at_tier = [True]*len( + stmt_added_since_prev_block_at_tier) + else: + pass + # to save time, stop when we've created both statements + if stmt_instance_set_before and stmt_instance_set_after: + break + + # At this point, pairwise sub-schedule may contain lex point tuples + # missing dimensions; the values in these missing dims should + # be zero, so add them. + + def _pad_lex_tuple_with_zeros(stmt_inst, length): + return StatementInstanceSet( + stmt_inst.insn_id, + stmt_inst.lex_points[:] + [0]*(length-len(stmt_inst.lex_points)), + ) + + stmt_instance_set_before = _pad_lex_tuple_with_zeros( + stmt_instance_set_before, max_lex_dim) + stmt_instance_set_after = _pad_lex_tuple_with_zeros( + stmt_instance_set_after, max_lex_dim) + + # Now generate maps from the blueprint --------------------------------------- + + from loopy.schedule.checker.utils import ( + list_var_names_in_isl_sets, + create_symbolic_map_from_tuples, + add_dims_to_isl_set, + ) + + params_sched = [] + out_names_sched = [LEX_VAR_PREFIX+str(i) for i in range(max_lex_dim)] + + def _get_map_for_stmt_inst(stmt_inst, int_sid): + + # Get inames domain for statement instance (a BasicSet) + dom = knl.get_inames_domain( + knl.id_to_insn[stmt_inst.insn_id].within_inames) + + # create space (an isl space in current implementation) + # {('statement', used in statement domain>) -> + # (lexicographic ordering dims)} + dom_inames_ordered = list_var_names_in_isl_sets([dom]) + + in_names_sched = [STATEMENT_VAR_NAME] + dom_inames_ordered[:] + sched_space = isl.Space.create_from_names( + isl.DEFAULT_CONTEXT, + in_=in_names_sched, out=out_names_sched, params=params_sched) + + # Insert 'statement' dim into domain so that its space allows + # for intersection with sched map later + dom_to_intersect = [ + add_dims_to_isl_set( + dom, isl.dim_type.set, [STATEMENT_VAR_NAME], 0), ] + + # Each map representing the schedule will map + # statement instances -> lex time. + # Right now, statement instance tuples consist of single int. + # Add all inames from domains to each map domain tuple. + tuple_pair = [( + (int_sid, ) + tuple(dom_inames_ordered), + stmt_inst.lex_points + )] + + # create map + return create_symbolic_map_from_tuples( + tuple_pairs_with_domains=zip(tuple_pair, dom_to_intersect), + space=sched_space, + ) + + # Determine integer IDs that will represent each statement in mapping + # (dependency map creation assumes sid_before=0 and sid_after=1, unless + # before and after refer to same stmt, in which case sid_before=sid_after=0) + int_sid_before = 0 + int_sid_after = 0 if ( + stmt_instance_set_before.insn_id == stmt_instance_set_after.insn_id + ) else 1 + + map_before = _get_map_for_stmt_inst(stmt_instance_set_before, int_sid_before) + map_after = _get_map_for_stmt_inst(stmt_instance_set_after, int_sid_after) + + return (map_before, map_after) diff --git a/test/test_linearization_checker.py b/test/test_linearization_checker.py index c87bb149b..3834f280a 100644 --- a/test/test_linearization_checker.py +++ b/test/test_linearization_checker.py @@ -96,44 +96,6 @@ def test_lexschedule_and_map_creation(): knl = get_one_linearized_kernel(knl) linearization_items = knl.linearization - # Create PairwiseScheduleBuilder: mapping of {statement instance: lex point} - sched_ab = get_schedule_for_statement_pair( - knl, - linearization_items, - "insn_a", - "insn_b", - ) - sched_ac = get_schedule_for_statement_pair( - knl, - linearization_items, - "insn_a", - "insn_c", - ) - sched_ad = get_schedule_for_statement_pair( - knl, - linearization_items, - "insn_a", - "insn_d", - ) - sched_bc = get_schedule_for_statement_pair( - knl, - linearization_items, - "insn_b", - "insn_c", - ) - sched_bd = get_schedule_for_statement_pair( - knl, - linearization_items, - "insn_b", - "insn_d", - ) - sched_cd = get_schedule_for_statement_pair( - knl, - linearization_items, - "insn_c", - "insn_d", - ) - # There are multiple potential linearization orders for this kernel, so when # performing our comparisons for schedule correctness, we need to know which # order loopy chose. @@ -152,12 +114,13 @@ def test_lexschedule_and_map_creation(): # Relationship between insn_a and insn_b --------------------------------------- - assert sched_ab.stmt_instance_set_before.lex_points == [0, 'i', 0, 'k', 0] - assert sched_ab.stmt_instance_set_after.lex_points == [0, 'i', 1, 'j', 0] - - # Get two maps from the PairwiseScheduleBuilder - - sched_map_before, sched_map_after = sched_ab.build_maps(knl) + # Get two maps + sched_map_before, sched_map_after = get_schedule_for_statement_pair( + knl, + linearization_items, + "insn_a", + "insn_b", + ) # Create expected maps, align, compare @@ -187,12 +150,13 @@ def test_lexschedule_and_map_creation(): # ------------------------------------------------------------------------------ # Relationship between insn_a and insn_c --------------------------------------- - assert sched_ac.stmt_instance_set_before.lex_points == [0, 'i', 0, 'k', 0] - assert sched_ac.stmt_instance_set_after.lex_points == [0, 'i', 1, 'j', 0] - - # Get two maps from the PairwiseScheduleBuilder - - sched_map_before, sched_map_after = sched_ac.build_maps(knl) + # Get two maps + sched_map_before, sched_map_after = get_schedule_for_statement_pair( + knl, + linearization_items, + "insn_a", + "insn_c", + ) # Create expected maps, align, compare @@ -225,14 +189,13 @@ def test_lexschedule_and_map_creation(): # insn_a and insn_d could have been linearized in either order # (i loop could be before or after t loop) def perform_insn_ad_checks_with(a_lex_idx, d_lex_idx): - assert sched_ad.stmt_instance_set_before.lex_points == [ - a_lex_idx, 'i', 0, 'k', 0] - assert sched_ad.stmt_instance_set_after.lex_points == [ - d_lex_idx, 't', 0, 0, 0] - - # Get two maps from the PairwiseScheduleBuilder - - sched_map_before, sched_map_after = sched_ad.build_maps(knl) + # Get two maps + sched_map_before, sched_map_after = get_schedule_for_statement_pair( + knl, + linearization_items, + "insn_a", + "insn_d", + ) # Create expected maps, align, compare @@ -272,14 +235,13 @@ def test_lexschedule_and_map_creation(): # insn_b and insn_c could have been linearized in either order # (i loop could be before or after t loop) def perform_insn_bc_checks_with(b_lex_idx, c_lex_idx): - assert sched_bc.stmt_instance_set_before.lex_points == [ - 0, 'i', 0, 'j', b_lex_idx] - assert sched_bc.stmt_instance_set_after.lex_points == [ - 0, 'i', 0, 'j', c_lex_idx] - - # Get two maps from the PairwiseScheduleBuilder - - sched_map_before, sched_map_after = sched_bc.build_maps(knl) + # Get two maps + sched_map_before, sched_map_after = get_schedule_for_statement_pair( + knl, + linearization_items, + "insn_b", + "insn_c", + ) # Create expected maps, align, compare @@ -319,14 +281,13 @@ def test_lexschedule_and_map_creation(): # insn_b and insn_d could have been linearized in either order # (i loop could be before or after t loop) def perform_insn_bd_checks_with(b_lex_idx, d_lex_idx): - assert sched_bd.stmt_instance_set_before.lex_points == [ - b_lex_idx, 'i', 0, 'j', 0] - assert sched_bd.stmt_instance_set_after.lex_points == [ - d_lex_idx, 't', 0, 0, 0] - - # Get two maps from the PairwiseScheduleBuilder - - sched_map_before, sched_map_after = sched_bd.build_maps(knl) + # Get two maps + sched_map_before, sched_map_after = get_schedule_for_statement_pair( + knl, + linearization_items, + "insn_b", + "insn_d", + ) # Create expected maps, align, compare @@ -366,14 +327,13 @@ def test_lexschedule_and_map_creation(): # insn_c and insn_d could have been linearized in either order # (i loop could be before or after t loop) def perform_insn_cd_checks_with(c_lex_idx, d_lex_idx): - assert sched_cd.stmt_instance_set_before.lex_points == [ - c_lex_idx, 'i', 0, 'j', 0] - assert sched_cd.stmt_instance_set_after.lex_points == [ - d_lex_idx, 't', 0, 0, 0] - - # Get two maps from the PairwiseScheduleBuilder - - sched_map_before, sched_map_after = sched_cd.build_maps(knl) + # Get two maps + sched_map_before, sched_map_after = get_schedule_for_statement_pair( + knl, + linearization_items, + "insn_c", + "insn_d", + ) # Create expected maps, align, compare -- GitLab From 87ac1b9e8c99f52e4a64f3db701159e907bc3764 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 14 Jul 2020 09:13:00 -0500 Subject: [PATCH 078/136] rename test_lexschedule_and_map_creation()->test_lexschedule_creation() --- test/test_linearization_checker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_linearization_checker.py b/test/test_linearization_checker.py index 3834f280a..60abfade0 100644 --- a/test/test_linearization_checker.py +++ b/test/test_linearization_checker.py @@ -50,7 +50,7 @@ else: faulthandler.enable() -def test_lexschedule_and_map_creation(): +def test_lexschedule_creation(): import islpy as isl from loopy.schedule.checker import ( get_schedule_for_statement_pair, -- GitLab From 2251fa20eefb7f978c1a16131cefdeeb36c2586a Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 14 Jul 2020 10:30:02 -0500 Subject: [PATCH 079/136] remove StatementInstanceSet class, use an ImmutableRecord instead --- loopy/schedule/checker/schedule.py | 78 ++++++------------------------ 1 file changed, 14 insertions(+), 64 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 9e693a9a1..fc4938c98 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -47,38 +47,6 @@ LEX_VAR_PREFIX = "%sl" % (LIN_CHECK_IDENTIFIER_PREFIX) STATEMENT_VAR_NAME = "%sstatement" % (LIN_CHECK_IDENTIFIER_PREFIX) -class StatementInstanceSet(object): - """A representation of a set of (non-concurrent) instances of a - statement being executed. The ordering of the instances is described - by the `lex_points` attribute, a list representing points in a - lexicographic ordering of statements. Each field in the list - corresponds to a dimension in the lexicographic ordering. - - .. attribute:: insn_id - - A :class:`str` instruction identifier that is unique within - a :class:`loopy.kernel.LoopKernel`. - - .. attribute:: lex_points - - A list containing one value for each dimension in a lexicographic - ordering. These values describe the ordering of the statements, - and may be :class:`str` :mod:`loopy` inames or :class:`int`. - """ - - def __init__( - self, - insn_id, - lex_points, - ): - self.insn_id = insn_id - self.lex_points = lex_points - - def __repr__(self): - return "%s(%s, %s)" % ( - self.__class__.__name__, self.insn_id, self.lex_points) - - def generate_pairwise_schedule( knl, linearization_items_ordered, @@ -116,33 +84,15 @@ def generate_pairwise_schedule( each of the two statements. """ - # Two StatementInstanceSets, one for each statement: - - """ - stmt_instance_set_before - - A :class:`StatementInstanceSet` whose ordering relative - to `stmt_instance_set_after is described by the schedule blueprint. This - is achieved by mapping the statement instances in both sets to points - in a single lexicographic ordering. Points in lexicographic ordering - are represented as a list of :class:`int` or as :class:`str` - :mod:`loopy` inames. - """ + # For each statement, create a :class:`ImmutableRecord` describing the set of + # statement instances. Contains the insn_id and a list representing points + # in the lexicographic ordering containing items of :class:`int` or + # :class:`str` :mod:`loopy` inames. stmt_instance_set_before = None - - """ - stmt_instance_set_after - - A :class:`StatementInstanceSet` whose ordering relative - to `stmt_instance_set_before is described by the schedule blueprint. This - is achieved by mapping the statement instances in both sets to points - in a single lexicographic ordering. Points in lexicographic ordering - are represented as a list of :class:`int` or as :class:`str` - :mod:`loopy` inames. - """ stmt_instance_set_after = None from loopy.schedule import (EnterLoop, LeaveLoop, Barrier, RunInstruction) + from pytools import ImmutableRecord # go through linearization_items_ordered and generate pairwise sub-schedule @@ -210,16 +160,16 @@ def generate_pairwise_schedule( if lp_insn_id == before_insn_id: # add before sched item - stmt_instance_set_before = StatementInstanceSet( - lp_insn_id, - next_insn_lex_tuple[:]) + stmt_instance_set_before = ImmutableRecord( + insn_id=lp_insn_id, + lex_points=next_insn_lex_tuple[:]) stmt_added = True if lp_insn_id == after_insn_id: # add after sched item - stmt_instance_set_after = StatementInstanceSet( - lp_insn_id, - next_insn_lex_tuple[:]) + stmt_instance_set_after = ImmutableRecord( + insn_id=lp_insn_id, + lex_points=next_insn_lex_tuple[:]) stmt_added = True # Note: before/after may refer to same stmt, in which case @@ -248,9 +198,9 @@ def generate_pairwise_schedule( # be zero, so add them. def _pad_lex_tuple_with_zeros(stmt_inst, length): - return StatementInstanceSet( - stmt_inst.insn_id, - stmt_inst.lex_points[:] + [0]*(length-len(stmt_inst.lex_points)), + return ImmutableRecord( + insn_id=stmt_inst.insn_id, + lex_points=stmt_inst.lex_points[:] + [0]*(length-len(stmt_inst.lex_points)) ) stmt_instance_set_before = _pad_lex_tuple_with_zeros( -- GitLab From 87933ce1f4a8b90c578b250a8d7c666af9479505 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 14 Jul 2020 11:09:43 -0500 Subject: [PATCH 080/136] fix flake8 error --- loopy/schedule/checker/schedule.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index fc4938c98..6b047ed26 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -200,7 +200,8 @@ def generate_pairwise_schedule( def _pad_lex_tuple_with_zeros(stmt_inst, length): return ImmutableRecord( insn_id=stmt_inst.insn_id, - lex_points=stmt_inst.lex_points[:] + [0]*(length-len(stmt_inst.lex_points)) + lex_points=stmt_inst.lex_points[:] + [0]*( + length-len(stmt_inst.lex_points)) ) stmt_instance_set_before = _pad_lex_tuple_with_zeros( -- GitLab From e07b1476c6e04e094901412cc4ecce09562bc23f Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 19 Jul 2020 14:26:38 -0500 Subject: [PATCH 081/136] assert knl is preprocessed (rather than performing the preprocessing) in get_schedule_for_statement_pair() --- loopy/schedule/checker/__init__.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index a2963f689..ca1684ec4 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -36,7 +36,7 @@ def get_schedule_for_statement_pair( representing a pairwise schedule as two mappings from statement instances to lexicographic time. - :arg knl: A :class:`loopy.kernel.LoopKernel` containing the + :arg knl: A preprocessed :class:`loopy.kernel.LoopKernel` containing the linearization items that will be used to create a schedule. :arg linearization_items: A list of :class:`loopy.schedule.ScheduleItem` @@ -106,10 +106,12 @@ def get_schedule_for_statement_pair( """ - # {{{ preprocess if not already preprocessed + # {{{ make sure kernel has been preprocessed - from loopy import preprocess_kernel - preproc_knl = preprocess_kernel(knl) + from loopy.kernel import KernelState + assert knl.state in [ + KernelState.PREPROCESSED, + KernelState.LINEARIZED] # }}} @@ -122,15 +124,15 @@ def get_schedule_for_statement_pair( get_concurrent_inames, get_EnterLoop_inames, ) - conc_inames, _ = get_concurrent_inames(preproc_knl) - enterloop_inames = get_EnterLoop_inames(linearization_items, preproc_knl) + conc_inames, _ = get_concurrent_inames(knl) + enterloop_inames = get_EnterLoop_inames(linearization_items, knl) conc_loop_inames = conc_inames & enterloop_inames if conc_loop_inames: from warnings import warn warn( "get_schedule_for_statement_pair encountered EnterLoop for inames %s " "with ConcurrentTag(s) in linearization for kernel %s. " - "Ignoring these loops." % (conc_loop_inames, preproc_knl.name)) + "Ignoring these loops." % (conc_loop_inames, knl.name)) # }}} @@ -139,7 +141,7 @@ def get_schedule_for_statement_pair( # include only instructions involved in this dependency from loopy.schedule.checker.schedule import generate_pairwise_schedule return generate_pairwise_schedule( - preproc_knl, + knl, linearization_items, insn_id_before, insn_id_after, -- GitLab From 17ed282c9955e399b3363993abd675ca571742d5 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 19 Jul 2020 14:34:34 -0500 Subject: [PATCH 082/136] make lex_points a tuple instead of a list --- loopy/schedule/checker/schedule.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 6b047ed26..8ee2e5106 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -162,14 +162,14 @@ def generate_pairwise_schedule( # add before sched item stmt_instance_set_before = ImmutableRecord( insn_id=lp_insn_id, - lex_points=next_insn_lex_tuple[:]) + lex_points=tuple(next_insn_lex_tuple[:])) stmt_added = True if lp_insn_id == after_insn_id: # add after sched item stmt_instance_set_after = ImmutableRecord( insn_id=lp_insn_id, - lex_points=next_insn_lex_tuple[:]) + lex_points=tuple(next_insn_lex_tuple[:])) stmt_added = True # Note: before/after may refer to same stmt, in which case @@ -200,8 +200,8 @@ def generate_pairwise_schedule( def _pad_lex_tuple_with_zeros(stmt_inst, length): return ImmutableRecord( insn_id=stmt_inst.insn_id, - lex_points=stmt_inst.lex_points[:] + [0]*( - length-len(stmt_inst.lex_points)) + lex_points=stmt_inst.lex_points[:] + tuple( + [0]*(length-len(stmt_inst.lex_points))) ) stmt_instance_set_before = _pad_lex_tuple_with_zeros( -- GitLab From 41e8acbbcbf265e3b28d18fdd6a5228d71f569e5 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 19 Jul 2020 14:37:52 -0500 Subject: [PATCH 083/136] renamed linearization_items_ordered->linearization_items in generate_pairwise_schedule() --- loopy/schedule/checker/schedule.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 8ee2e5106..838c5f74b 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -49,7 +49,7 @@ STATEMENT_VAR_NAME = "%sstatement" % (LIN_CHECK_IDENTIFIER_PREFIX) def generate_pairwise_schedule( knl, - linearization_items_ordered, + linearization_items, before_insn_id, after_insn_id, loops_to_ignore=set(), @@ -66,8 +66,8 @@ def generate_pairwise_schedule( kernel will be used to get the domains associated with the inames used in the statements. - :arg linearization_items_ordered: A list of :class:`loopy.schedule.ScheduleItem` - (to be renamed to `loopy.schedule.LinearizationItem`) containing the + :arg linearization_items: A list of :class:`loopy.schedule.ScheduleItem` + (to be renamed to `loopy.schedule.LinearizationItem`) including the two linearization items whose relative order will be described by the schedule. This list may be a *partial* linearization for a kernel since this function may be used during the linearization process. @@ -94,14 +94,14 @@ def generate_pairwise_schedule( from loopy.schedule import (EnterLoop, LeaveLoop, Barrier, RunInstruction) from pytools import ImmutableRecord - # go through linearization_items_ordered and generate pairwise sub-schedule + # go through linearization_items and generate pairwise sub-schedule # keep track of the next tuple of points in our lexicographic # ordering, initially this as a 1-d point with value 0 next_insn_lex_tuple = [0] stmt_added_since_prev_block_at_tier = [False] max_lex_dim = 0 - for linearization_item in linearization_items_ordered: + for linearization_item in linearization_items: if isinstance(linearization_item, EnterLoop): iname = linearization_item.iname if iname in loops_to_ignore: -- GitLab From bb5128d61f15cfa8fdee667e5f93c02d6bf88c00 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 19 Jul 2020 14:49:39 -0500 Subject: [PATCH 084/136] when creating schedule, if lp_insn_id is None, assert that the linearization item is a barrier; update comment explaining this scenario; add fixme about potential future work --- loopy/schedule/checker/schedule.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 838c5f74b..c71381761 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -148,11 +148,17 @@ def generate_pairwise_schedule( get_insn_id_from_linearization_item, ) lp_insn_id = get_insn_id_from_linearization_item(linearization_item) + if lp_insn_id is None: - # TODO make sure it's okay to ignore barriers without id - # (because they'll never be part of a dependency?) - # matmul example has barrier that fails this assertion... - # assert linearization_item.originating_insn_id is not None + assert isinstance(linearization_item, Barrier) + + # Barriers without insn ids were inserted as a result of a + # dependency. They don't themselves have dependencies. Ignore them. + + # FIXME: It's possible that we could record metadata about them + # (e.g. what dependency produced them) and verify that they're + # adequately protecting all statement instance pairs. + continue # only process before/after insns, otherwise ignore -- GitLab From 3550e6d35dcfe5baf9c759024170fcf887b73e60 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 19 Jul 2020 16:49:00 -0500 Subject: [PATCH 085/136] fix indentation on function docstring --- loopy/schedule/checker/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index 0bfdf0a54..abd06685a 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -153,8 +153,8 @@ def create_symbolic_map_from_tuples( space, ): """Return an :class:`islpy.Map` constructed using the provided space, - mapping input->output tuples provided in `tuple_pairs_with_domains`, - with each set of tuple variables constrained by the domains provided. + mapping input->output tuples provided in `tuple_pairs_with_domains`, + with each set of tuple variables constrained by the domains provided. :arg tuple_pairs_with_domains: A :class:`list` with each element being a tuple of the form `((tup_in, tup_out), domain)`. -- GitLab From 38d584a9409cbb3486f0e05cf94258a2455c7ad2 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 19 Jul 2020 16:55:45 -0500 Subject: [PATCH 086/136] fix pluralizing class in docstring --- loopy/schedule/checker/schedule.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index c71381761..5cbe4c463 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -78,7 +78,7 @@ def generate_pairwise_schedule( :arg after_insn_id: A :class:`str` instruction id specifying stmt_instance_set_after in this pair of instructions. - :returns: A two-tuple containing two :class:`islpy.Map`s + :returns: A two-tuple containing two :class:`islpy.Map`\ s representing the a pairwise schedule as two mappings from statement instances to lexicographic time, one for each of the two statements. -- GitLab From 18e468134f3b6e8fc36838d178207933deb53115 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 20 Jul 2020 14:21:59 -0500 Subject: [PATCH 087/136] assert that ignored linearization items are of specific type --- loopy/schedule/checker/schedule.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 5cbe4c463..6d4382c11 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -194,6 +194,10 @@ def generate_pairwise_schedule( stmt_added_since_prev_block_at_tier = [True]*len( stmt_added_since_prev_block_at_tier) else: + from loopy.schedule import (CallKernel, ReturnFromKernel) + # no action needed for these types of linearization item + assert isinstance( + linearization_item, (CallKernel, ReturnFromKernel)) pass # to save time, stop when we've created both statements if stmt_instance_set_before and stmt_instance_set_after: -- GitLab From 1f4edf2e678e257f30ec32d8ffc65b9b1a7e0fed Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 20 Jul 2020 14:46:16 -0500 Subject: [PATCH 088/136] use set().union(*[list comprehension]) instead of loop in list_var_names_in_isl_sets() --- loopy/schedule/checker/utils.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index abd06685a..6c6cf160d 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -140,12 +140,11 @@ def ensure_dim_names_match_and_align(obj_map, tgt_map): def list_var_names_in_isl_sets( isl_sets, set_dim=isl.dim_type.set): - inames = set() - for isl_set in isl_sets: - inames.update(isl_set.get_var_names(set_dim)) + + inames = set().union(*[isl_set.get_var_names(set_dim) for isl_set in isl_sets]) # sorting is not necessary, but keeps results consistent between runs - return sorted(list(inames)) + return sorted(inames) def create_symbolic_map_from_tuples( -- GitLab From 7635f47bfafadcd9936a7be8b728b71ed31e75d0 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 20 Jul 2020 14:55:19 -0500 Subject: [PATCH 089/136] renamed list_var_names_in_isl_sets()->sorted_union_of_names_in_isl_sets() --- loopy/schedule/checker/schedule.py | 4 ++-- loopy/schedule/checker/utils.py | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 6d4382c11..b56040adf 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -222,7 +222,7 @@ def generate_pairwise_schedule( # Now generate maps from the blueprint --------------------------------------- from loopy.schedule.checker.utils import ( - list_var_names_in_isl_sets, + sorted_union_of_names_in_isl_sets, create_symbolic_map_from_tuples, add_dims_to_isl_set, ) @@ -239,7 +239,7 @@ def generate_pairwise_schedule( # create space (an isl space in current implementation) # {('statement', used in statement domain>) -> # (lexicographic ordering dims)} - dom_inames_ordered = list_var_names_in_isl_sets([dom]) + dom_inames_ordered = sorted_union_of_names_in_isl_sets([dom]) in_names_sched = [STATEMENT_VAR_NAME] + dom_inames_ordered[:] sched_space = isl.Space.create_from_names( diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index 6c6cf160d..b845edacc 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -137,9 +137,12 @@ def ensure_dim_names_match_and_align(obj_map, tgt_map): return aligned_obj_map -def list_var_names_in_isl_sets( +def sorted_union_of_names_in_isl_sets( isl_sets, set_dim=isl.dim_type.set): + """Return a sorted list of the union of all variable names found in + the provided :class:`islpy.Set`\ s. + """ inames = set().union(*[isl_set.get_var_names(set_dim) for isl_set in isl_sets]) -- GitLab From 227762f5a6e345843584495310c138fac3c684a4 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 20 Jul 2020 15:04:54 -0500 Subject: [PATCH 090/136] rename constraint->condition in create_symbolic_map_from_tuples() --- loopy/schedule/checker/utils.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index b845edacc..92219b875 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -172,7 +172,7 @@ def create_symbolic_map_from_tuples( `tuple_pairs_with_domains`, map `(tup_in)->(tup_out) : domain`, where `tup_in` and `tup_out` are numeric or symbolic values assigned to the input and output - dimension variables in `space`, and `domain` specifies constraints + dimension variables in `space`, and `domain` specifies conditions on these values. """ @@ -194,31 +194,31 @@ def create_symbolic_map_from_tuples( dim_type.out, 0, dim_type.in_, len(space_in_names), len(space_out_names)) for (tup_in, tup_out), dom in tuple_pairs_with_domains: - # initialize constraint with true - constraint = islvars[0].eq_set(islvars[0]) + # initialize condition with true + condition = islvars[0].eq_set(islvars[0]) # set values for 'in' dimension using tuple vals assert len(tup_in) == len(space_in_names) for dim_name, val_in in zip(space_in_names, tup_in): if isinstance(val_in, int): - constraint = constraint \ + condition = condition \ & islvars[dim_name].eq_set(islvars[0]+val_in) else: - constraint = constraint \ + condition = condition \ & islvars[dim_name].eq_set(islvars[val_in]) # set values for 'out' dimension using tuple vals assert len(tup_out) == len(space_out_names) for dim_name, val_out in zip(space_out_names, tup_out): if isinstance(val_out, int): - constraint = constraint \ + condition = condition \ & islvars[dim_name].eq_set(islvars[0]+val_out) else: - constraint = constraint \ + condition = condition \ & islvars[dim_name].eq_set(islvars[val_out]) # convert set to map by moving dimensions around - map_from_set = isl.Map.from_domain(constraint) + map_from_set = isl.Map.from_domain(condition) map_from_set = map_from_set.move_dims( dim_type.out, 0, dim_type.in_, len(space_in_names), len(space_out_names)) -- GitLab From 6d336bae34cc43ed628d9fa67f56161a4d7dbb20 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 20 Jul 2020 15:48:56 -0500 Subject: [PATCH 091/136] make function for duplicated code: _conjunction_of_dim_eq_conditions() --- loopy/schedule/checker/utils.py | 34 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index 92219b875..2cf8e90fb 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -187,6 +187,17 @@ def create_symbolic_map_from_tuples( # loop through pairs and create a set that will later be converted to a map + def _conjunction_of_dim_eq_conditions(dim_names, values, islvars): + condition = islvars[0].eq_set(islvars[0]) + for dim_name, val in zip(dim_names, values): + if isinstance(val, int): + condition = condition \ + & islvars[dim_name].eq_set(islvars[0]+val) + else: + condition = condition \ + & islvars[dim_name].eq_set(islvars[val]) + return condition + # initialize union to empty union_of_maps = isl.Map.from_domain( islvars[0].eq_set(islvars[0]+1) # 0 == 1 (false) @@ -194,28 +205,13 @@ def create_symbolic_map_from_tuples( dim_type.out, 0, dim_type.in_, len(space_in_names), len(space_out_names)) for (tup_in, tup_out), dom in tuple_pairs_with_domains: - # initialize condition with true - condition = islvars[0].eq_set(islvars[0]) - # set values for 'in' dimension using tuple vals - assert len(tup_in) == len(space_in_names) - for dim_name, val_in in zip(space_in_names, tup_in): - if isinstance(val_in, int): - condition = condition \ - & islvars[dim_name].eq_set(islvars[0]+val_in) - else: - condition = condition \ - & islvars[dim_name].eq_set(islvars[val_in]) + condition = _conjunction_of_dim_eq_conditions( + space_in_names, tup_in, islvars) # set values for 'out' dimension using tuple vals - assert len(tup_out) == len(space_out_names) - for dim_name, val_out in zip(space_out_names, tup_out): - if isinstance(val_out, int): - condition = condition \ - & islvars[dim_name].eq_set(islvars[0]+val_out) - else: - condition = condition \ - & islvars[dim_name].eq_set(islvars[val_out]) + condition = condition & _conjunction_of_dim_eq_conditions( + space_out_names, tup_out, islvars) # convert set to map by moving dimensions around map_from_set = isl.Map.from_domain(condition) -- GitLab From a81bd480459cbddb9b9c025e60407ca5cbaf3192 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 20 Jul 2020 15:56:36 -0500 Subject: [PATCH 092/136] rename get_concurrent_inames(knl)->partition_inames_by_concurrency(knl) --- loopy/schedule/checker/__init__.py | 4 ++-- loopy/schedule/checker/utils.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index ca1684ec4..466837534 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -121,10 +121,10 @@ def get_schedule_for_statement_pair( # won't be any inames with ConcurrentTags in EnterLoop linearization items. # Test which exercises this: test_linearization_checker_with_stroud_bernstein()) from loopy.schedule.checker.utils import ( - get_concurrent_inames, + partition_inames_by_concurrency, get_EnterLoop_inames, ) - conc_inames, _ = get_concurrent_inames(knl) + conc_inames, _ = partition_inames_by_concurrency(knl) enterloop_inames = get_EnterLoop_inames(linearization_items, knl) conc_loop_inames = conc_inames & enterloop_inames if conc_loop_inames: diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index 2cf8e90fb..bad083558 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -237,7 +237,7 @@ def create_symbolic_map_from_tuples( return union_of_maps -def get_concurrent_inames(knl): +def partition_inames_by_concurrency(knl): from loopy.kernel.data import ConcurrentTag conc_inames = set() non_conc_inames = set() -- GitLab From be1cf81556b359c5c63fe21d6f2909198b83732d Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 21 Jul 2020 11:14:32 -0500 Subject: [PATCH 093/136] to prevent quadratic complexity in schedule creation, create lex points for all relevant insn_ids simultaneously; then afterward process pairs individually; (also eliminate more unnecessary lex dims) --- loopy/schedule/checker/__init__.py | 14 ++- loopy/schedule/checker/schedule.py | 138 +++++++++++++++-------------- test/test_linearization_checker.py | 68 +++++++------- 3 files changed, 107 insertions(+), 113 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 466837534..fa9700b47 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -21,13 +21,12 @@ THE SOFTWARE. """ -# {{{ create a pairwise schedule for statement pair +# {{{ create a pairwise schedules for statement pairs -def get_schedule_for_statement_pair( +def get_schedules_for_statement_pairs( knl, linearization_items, - insn_id_before, - insn_id_after, + insn_id_pairs, ): r"""Given a pair of statements in a linearized kernel, determine the (relative) order in which the instances are executed, @@ -139,12 +138,11 @@ def get_schedule_for_statement_pair( # {{{ Create two mappings from {statement instance: lex point} # include only instructions involved in this dependency - from loopy.schedule.checker.schedule import generate_pairwise_schedule - return generate_pairwise_schedule( + from loopy.schedule.checker.schedule import generate_pairwise_schedules + return generate_pairwise_schedules( knl, linearization_items, - insn_id_before, - insn_id_after, + insn_id_pairs, loops_to_ignore=conc_loop_inames, ) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index b56040adf..6b9905613 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -47,11 +47,10 @@ LEX_VAR_PREFIX = "%sl" % (LIN_CHECK_IDENTIFIER_PREFIX) STATEMENT_VAR_NAME = "%sstatement" % (LIN_CHECK_IDENTIFIER_PREFIX) -def generate_pairwise_schedule( +def generate_pairwise_schedules( knl, linearization_items, - before_insn_id, - after_insn_id, + insn_id_pairs, loops_to_ignore=set(), ): r"""Given a pair of statements in a linearized kernel, determine @@ -79,17 +78,21 @@ def generate_pairwise_schedule( stmt_instance_set_after in this pair of instructions. :returns: A two-tuple containing two :class:`islpy.Map`\ s - representing the a pairwise schedule as two mappings + representing a pairwise schedule as two mappings from statement instances to lexicographic time, one for each of the two statements. """ + # TODO + # update documentation + + all_insn_ids = set().union(*insn_id_pairs) + # For each statement, create a :class:`ImmutableRecord` describing the set of # statement instances. Contains the insn_id and a list representing points # in the lexicographic ordering containing items of :class:`int` or # :class:`str` :mod:`loopy` inames. - stmt_instance_set_before = None - stmt_instance_set_after = None + stmt_instances = {} from loopy.schedule import (EnterLoop, LeaveLoop, Barrier, RunInstruction) from pytools import ImmutableRecord @@ -161,31 +164,10 @@ def generate_pairwise_schedule( continue - # only process before/after insns, otherwise ignore - stmt_added = False - - if lp_insn_id == before_insn_id: - # add before sched item - stmt_instance_set_before = ImmutableRecord( - insn_id=lp_insn_id, - lex_points=tuple(next_insn_lex_tuple[:])) - stmt_added = True - - if lp_insn_id == after_insn_id: - # add after sched item - stmt_instance_set_after = ImmutableRecord( - insn_id=lp_insn_id, - lex_points=tuple(next_insn_lex_tuple[:])) - stmt_added = True - - # Note: before/after may refer to same stmt, in which case - # both of the above conditionals execute - - if stmt_added: - - # track the max number of lex dims used - if len(next_insn_lex_tuple) > max_lex_dim: - max_lex_dim = len(next_insn_lex_tuple) + # only process listed insns, otherwise ignore + if lp_insn_id in all_insn_ids: + # add item + stmt_instances[lp_insn_id] = tuple(next_insn_lex_tuple[:]) # increment lex dim val enumerating items in current code block next_insn_lex_tuple[-1] = next_insn_lex_tuple[-1] + 1 @@ -199,27 +181,10 @@ def generate_pairwise_schedule( assert isinstance( linearization_item, (CallKernel, ReturnFromKernel)) pass - # to save time, stop when we've created both statements - if stmt_instance_set_before and stmt_instance_set_after: - break - - # At this point, pairwise sub-schedule may contain lex point tuples - # missing dimensions; the values in these missing dims should - # be zero, so add them. - - def _pad_lex_tuple_with_zeros(stmt_inst, length): - return ImmutableRecord( - insn_id=stmt_inst.insn_id, - lex_points=stmt_inst.lex_points[:] + tuple( - [0]*(length-len(stmt_inst.lex_points))) - ) - stmt_instance_set_before = _pad_lex_tuple_with_zeros( - stmt_instance_set_before, max_lex_dim) - stmt_instance_set_after = _pad_lex_tuple_with_zeros( - stmt_instance_set_after, max_lex_dim) - - # Now generate maps from the blueprint --------------------------------------- + # to save time, stop when we've created all statements + if len(stmt_instances.keys()) == all_insn_ids: + break from loopy.schedule.checker.utils import ( sorted_union_of_names_in_isl_sets, @@ -227,14 +192,28 @@ def generate_pairwise_schedule( add_dims_to_isl_set, ) - params_sched = [] - out_names_sched = [LEX_VAR_PREFIX+str(i) for i in range(max_lex_dim)] - - def _get_map_for_stmt_inst(stmt_inst, int_sid): + def _pad_tuple_with_zeros(tup, length): + return tup[:] + tuple([0]*(length-len(tup))) + + def _remove_matching_integer_dims(tup0, tup1): + new_tup0 = [] + new_tup1 = [] + for d0, d1 in zip(tup0, tup1): + if not ( + isinstance(d0, int) and + isinstance(d1, int) and + d0 == d1): + # keep this dim + new_tup0.append(d0) + new_tup1.append(d1) + # TODO? also change all ints to 0 or 1 + return tuple(new_tup0), tuple(new_tup1) + + def _get_map_for_stmt_inst(insn_id, lex_points, int_sid, out_names_sched): # Get inames domain for statement instance (a BasicSet) dom = knl.get_inames_domain( - knl.id_to_insn[stmt_inst.insn_id].within_inames) + knl.id_to_insn[insn_id].within_inames) # create space (an isl space in current implementation) # {('statement', used in statement domain>) -> @@ -244,7 +223,7 @@ def generate_pairwise_schedule( in_names_sched = [STATEMENT_VAR_NAME] + dom_inames_ordered[:] sched_space = isl.Space.create_from_names( isl.DEFAULT_CONTEXT, - in_=in_names_sched, out=out_names_sched, params=params_sched) + in_=in_names_sched, out=out_names_sched, params=[]) # Insert 'statement' dim into domain so that its space allows # for intersection with sched map later @@ -258,7 +237,7 @@ def generate_pairwise_schedule( # Add all inames from domains to each map domain tuple. tuple_pair = [( (int_sid, ) + tuple(dom_inames_ordered), - stmt_inst.lex_points + lex_points )] # create map @@ -267,15 +246,38 @@ def generate_pairwise_schedule( space=sched_space, ) - # Determine integer IDs that will represent each statement in mapping - # (dependency map creation assumes sid_before=0 and sid_after=1, unless - # before and after refer to same stmt, in which case sid_before=sid_after=0) - int_sid_before = 0 - int_sid_after = 0 if ( - stmt_instance_set_before.insn_id == stmt_instance_set_after.insn_id - ) else 1 + pairwise_schedules = [] + for insn_id_before, insn_id_after in insn_id_pairs: + lex_tup_before = stmt_instances[insn_id_before] + lex_tup_after = stmt_instances[insn_id_after] + + # simplify tuples to the extent possible ------------------------------------- + + # At this point, pairwise sub-schedule may contain lex point tuples + # missing dimensions; the values in these missing dims should + # be zero, so add them. + max_lex_dims = max(len(lex_tup_before), len(lex_tup_after)) + lex_tup_before = _pad_tuple_with_zeros(lex_tup_before, max_lex_dims) + lex_tup_after = _pad_tuple_with_zeros(lex_tup_after, max_lex_dims) + + lex_tup_before, lex_tup_after = _remove_matching_integer_dims( + lex_tup_before, lex_tup_after) + + # Now generate maps from the blueprint --------------------------------------- + + out_names_sched = [LEX_VAR_PREFIX+str(i) for i in range(len(lex_tup_before))] + + # Determine integer IDs that will represent each statement in mapping + # (dependency map creation assumes sid_before=0 and sid_after=1, unless + # before and after refer to same stmt, in which case sid_before=sid_after=0) + int_sid_before = 0 + int_sid_after = 0 if insn_id_before == insn_id_after else 1 + + map_before = _get_map_for_stmt_inst( + insn_id_before, lex_tup_before, int_sid_before, out_names_sched) + map_after = _get_map_for_stmt_inst( + insn_id_after, lex_tup_after, int_sid_after, out_names_sched) - map_before = _get_map_for_stmt_inst(stmt_instance_set_before, int_sid_before) - map_after = _get_map_for_stmt_inst(stmt_instance_set_after, int_sid_after) + pairwise_schedules.append((map_before, map_after)) - return (map_before, map_after) + return pairwise_schedules diff --git a/test/test_linearization_checker.py b/test/test_linearization_checker.py index 60abfade0..716737bdd 100644 --- a/test/test_linearization_checker.py +++ b/test/test_linearization_checker.py @@ -53,7 +53,7 @@ else: def test_lexschedule_creation(): import islpy as isl from loopy.schedule.checker import ( - get_schedule_for_statement_pair, + get_schedules_for_statement_pairs, ) from loopy.schedule.checker.utils import ( ensure_dim_names_match_and_align, @@ -115,12 +115,11 @@ def test_lexschedule_creation(): # Relationship between insn_a and insn_b --------------------------------------- # Get two maps - sched_map_before, sched_map_after = get_schedule_for_statement_pair( + sched_map_before, sched_map_after = get_schedules_for_statement_pairs( knl, linearization_items, - "insn_a", - "insn_b", - ) + [("insn_a", "insn_b")], + )[0] # Create expected maps, align, compare @@ -128,7 +127,7 @@ def test_lexschedule_creation(): "[pi, pk] -> { [%s=0, i, k] -> [%s] : 0 <= i < pi and 0 <= k < pk }" % ( STATEMENT_VAR_NAME, - _lex_space_string(["0", "i", "0", "k", "0"]), + _lex_space_string(["i", "0", "k"]), ) ) sched_map_before_expected = ensure_dim_names_match_and_align( @@ -138,7 +137,7 @@ def test_lexschedule_creation(): "[pi, pj] -> { [%s=1, i, j] -> [%s] : 0 <= i < pi and 0 <= j < pj }" % ( STATEMENT_VAR_NAME, - _lex_space_string(["0", "i", "1", "j", "0"]), + _lex_space_string(["i", "1", "j"]), ) ) sched_map_after_expected = ensure_dim_names_match_and_align( @@ -151,12 +150,11 @@ def test_lexschedule_creation(): # Relationship between insn_a and insn_c --------------------------------------- # Get two maps - sched_map_before, sched_map_after = get_schedule_for_statement_pair( + sched_map_before, sched_map_after = get_schedules_for_statement_pairs( knl, linearization_items, - "insn_a", - "insn_c", - ) + [("insn_a", "insn_c")], + )[0] # Create expected maps, align, compare @@ -164,7 +162,7 @@ def test_lexschedule_creation(): "[pi, pk] -> { [%s=0, i, k] -> [%s] : 0 <= i < pi and 0 <= k < pk }" % ( STATEMENT_VAR_NAME, - _lex_space_string(["0", "i", "0", "k", "0"]), + _lex_space_string(["i", "0", "k"]), ) ) sched_map_before_expected = ensure_dim_names_match_and_align( @@ -174,7 +172,7 @@ def test_lexschedule_creation(): "[pi, pj] -> { [%s=1, i, j] -> [%s] : 0 <= i < pi and 0 <= j < pj }" % ( STATEMENT_VAR_NAME, - _lex_space_string(["0", "i", "1", "j", "0"]), + _lex_space_string(["i", "1", "j"]), ) ) sched_map_after_expected = ensure_dim_names_match_and_align( @@ -190,12 +188,11 @@ def test_lexschedule_creation(): # (i loop could be before or after t loop) def perform_insn_ad_checks_with(a_lex_idx, d_lex_idx): # Get two maps - sched_map_before, sched_map_after = get_schedule_for_statement_pair( + sched_map_before, sched_map_after = get_schedules_for_statement_pairs( knl, linearization_items, - "insn_a", - "insn_d", - ) + [("insn_a", "insn_d")], + )[0] # Create expected maps, align, compare @@ -203,7 +200,7 @@ def test_lexschedule_creation(): "[pi, pk] -> { [%s=0, i, k] -> [%s] : 0 <= i < pi and 0 <= k < pk }" % ( STATEMENT_VAR_NAME, - _lex_space_string([a_lex_idx, "i", "0", "k", "0"]), + _lex_space_string([a_lex_idx, "i", "k"]), ) ) sched_map_before_expected = ensure_dim_names_match_and_align( @@ -213,7 +210,7 @@ def test_lexschedule_creation(): "[pt] -> { [%s=1, t] -> [%s] : 0 <= t < pt }" % ( STATEMENT_VAR_NAME, - _lex_space_string([d_lex_idx, "t", "0", "0", "0"]), + _lex_space_string([d_lex_idx, "t", "0"]), ) ) sched_map_after_expected = ensure_dim_names_match_and_align( @@ -236,12 +233,11 @@ def test_lexschedule_creation(): # (i loop could be before or after t loop) def perform_insn_bc_checks_with(b_lex_idx, c_lex_idx): # Get two maps - sched_map_before, sched_map_after = get_schedule_for_statement_pair( + sched_map_before, sched_map_after = get_schedules_for_statement_pairs( knl, linearization_items, - "insn_b", - "insn_c", - ) + [("insn_b", "insn_c")], + )[0] # Create expected maps, align, compare @@ -249,7 +245,7 @@ def test_lexschedule_creation(): "[pi, pj] -> { [%s=0, i, j] -> [%s] : 0 <= i < pi and 0 <= j < pj }" % ( STATEMENT_VAR_NAME, - _lex_space_string(["0", "i", "0", "j", b_lex_idx]), + _lex_space_string(["i", "j", b_lex_idx]), ) ) sched_map_before_expected = ensure_dim_names_match_and_align( @@ -259,7 +255,7 @@ def test_lexschedule_creation(): "[pi, pj] -> { [%s=1, i, j] -> [%s] : 0 <= i < pi and 0 <= j < pj }" % ( STATEMENT_VAR_NAME, - _lex_space_string(["0", "i", "0", "j", c_lex_idx]), + _lex_space_string(["i", "j", c_lex_idx]), ) ) sched_map_after_expected = ensure_dim_names_match_and_align( @@ -282,12 +278,11 @@ def test_lexschedule_creation(): # (i loop could be before or after t loop) def perform_insn_bd_checks_with(b_lex_idx, d_lex_idx): # Get two maps - sched_map_before, sched_map_after = get_schedule_for_statement_pair( + sched_map_before, sched_map_after = get_schedules_for_statement_pairs( knl, linearization_items, - "insn_b", - "insn_d", - ) + [("insn_b", "insn_d")], + )[0] # Create expected maps, align, compare @@ -295,7 +290,7 @@ def test_lexschedule_creation(): "[pi, pj] -> { [%s=0, i, j] -> [%s] : 0 <= i < pi and 0 <= j < pj }" % ( STATEMENT_VAR_NAME, - _lex_space_string([b_lex_idx, "i", "0", "j", "0"]), + _lex_space_string([b_lex_idx, "i", "j"]), ) ) sched_map_before_expected = ensure_dim_names_match_and_align( @@ -305,7 +300,7 @@ def test_lexschedule_creation(): "[pt] -> { [%s=1, t] -> [%s] : 0 <= t < pt }" % ( STATEMENT_VAR_NAME, - _lex_space_string([d_lex_idx, "t", "0", "0", "0"]), + _lex_space_string([d_lex_idx, "t", "0"]), ) ) sched_map_after_expected = ensure_dim_names_match_and_align( @@ -328,12 +323,11 @@ def test_lexschedule_creation(): # (i loop could be before or after t loop) def perform_insn_cd_checks_with(c_lex_idx, d_lex_idx): # Get two maps - sched_map_before, sched_map_after = get_schedule_for_statement_pair( + sched_map_before, sched_map_after = get_schedules_for_statement_pairs( knl, linearization_items, - "insn_c", - "insn_d", - ) + [("insn_c", "insn_d")], + )[0] # Create expected maps, align, compare @@ -341,7 +335,7 @@ def test_lexschedule_creation(): "[pi, pj] -> { [%s=0, i, j] -> [%s] : 0 <= i < pi and 0 <= j < pj }" % ( STATEMENT_VAR_NAME, - _lex_space_string([c_lex_idx, "i", "0", "j", "0"]), + _lex_space_string([c_lex_idx, "i", "j"]), ) ) sched_map_before_expected = ensure_dim_names_match_and_align( @@ -351,7 +345,7 @@ def test_lexschedule_creation(): "[pt] -> { [%s=1, t] -> [%s] : 0 <= t < pt }" % ( STATEMENT_VAR_NAME, - _lex_space_string([d_lex_idx, "t", "0", "0", "0"]), + _lex_space_string([d_lex_idx, "t", "0"]), ) ) sched_map_after_expected = ensure_dim_names_match_and_align( -- GitLab From 4211f6e3c519072970830c796d46cef7a975ea17 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Fri, 24 Jul 2020 13:14:32 -0500 Subject: [PATCH 094/136] add todo --- loopy/schedule/checker/schedule.py | 1 + 1 file changed, 1 insertion(+) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 6b9905613..6ebf7848d 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -142,6 +142,7 @@ def generate_pairwise_schedules( # statements since last opened/closed loop), but if we have not # added any statements within the previous section yet, we # don't have to (effectively ignoring that section of code). + # TODO since we're getting rid of unnecessary dims later, maybe don't need this? stmt_added_since_prev_block_at_tier.pop() if stmt_added_since_prev_block_at_tier[-1]: next_insn_lex_tuple[-1] = next_insn_lex_tuple[-1]+1 -- GitLab From a4e790f28563f62479a6f66b93d5c41a38045f17 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 26 Jul 2020 18:33:30 -0500 Subject: [PATCH 095/136] while removing unnecessary dims in maps, also replace int-valued dims that are not in {0,1} with {0,1} (we're only describing relative order, so higher int values are unnecessary and confusing) --- loopy/schedule/checker/schedule.py | 47 +++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 6ebf7848d..dff0162d6 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -88,14 +88,12 @@ def generate_pairwise_schedules( all_insn_ids = set().union(*insn_id_pairs) - # For each statement, create a :class:`ImmutableRecord` describing the set of - # statement instances. Contains the insn_id and a list representing points + # For each statement, map the insn_id to a tuple representing points # in the lexicographic ordering containing items of :class:`int` or # :class:`str` :mod:`loopy` inames. stmt_instances = {} from loopy.schedule import (EnterLoop, LeaveLoop, Barrier, RunInstruction) - from pytools import ImmutableRecord # go through linearization_items and generate pairwise sub-schedule @@ -103,7 +101,6 @@ def generate_pairwise_schedules( # ordering, initially this as a 1-d point with value 0 next_insn_lex_tuple = [0] stmt_added_since_prev_block_at_tier = [False] - max_lex_dim = 0 for linearization_item in linearization_items: if isinstance(linearization_item, EnterLoop): iname = linearization_item.iname @@ -196,18 +193,41 @@ def generate_pairwise_schedules( def _pad_tuple_with_zeros(tup, length): return tup[:] + tuple([0]*(length-len(tup))) - def _remove_matching_integer_dims(tup0, tup1): + def _simplify_dims(tup0, tup1): new_tup0 = [] new_tup1 = [] + # loop over dims for d0, d1 in zip(tup0, tup1): - if not ( - isinstance(d0, int) and - isinstance(d1, int) and - d0 == d1): + if isinstance(d0, int) and isinstance(d1, int): + # Both vals are ints for this dim + + # If the ints match, this dim doesn't provide info about the + # relative ordering of these two statements, + # so skip (remove) this dim. + + # Otherwise, the ints inform us about the relative ordering of + # two statements. While their values may be larger than 1 in + # the lexicographic ordering describing a larger set of + # statements, in a pairwise schedule, only ints 0 and 1 are + # necessary to specify relative order. To keep the pairwise + # schedules as simple and comprehensible as possible, use only + # integers 0 and 1 to specify relative orderings in integer lex + # dims. + # (doesn't take much extra time since we are already going + # through these to remove unnecessary map dims) + + if d0 == d1: + continue + elif d0 > d1: + new_tup0.append(1) + new_tup1.append(0) + else: # d1 > d0 + new_tup0.append(0) + new_tup1.append(1) + else: # keep this dim new_tup0.append(d0) new_tup1.append(d1) - # TODO? also change all ints to 0 or 1 return tuple(new_tup0), tuple(new_tup1) def _get_map_for_stmt_inst(insn_id, lex_points, int_sid, out_names_sched): @@ -252,7 +272,7 @@ def generate_pairwise_schedules( lex_tup_before = stmt_instances[insn_id_before] lex_tup_after = stmt_instances[insn_id_after] - # simplify tuples to the extent possible ------------------------------------- + # simplify tuples to the extent possible ------------------------------------ # At this point, pairwise sub-schedule may contain lex point tuples # missing dimensions; the values in these missing dims should @@ -261,10 +281,9 @@ def generate_pairwise_schedules( lex_tup_before = _pad_tuple_with_zeros(lex_tup_before, max_lex_dims) lex_tup_after = _pad_tuple_with_zeros(lex_tup_after, max_lex_dims) - lex_tup_before, lex_tup_after = _remove_matching_integer_dims( - lex_tup_before, lex_tup_after) + lex_tup_before, lex_tup_after = _simplify_dims(lex_tup_before, lex_tup_after) - # Now generate maps from the blueprint --------------------------------------- + # Now generate maps from the blueprint -------------------------------------- out_names_sched = [LEX_VAR_PREFIX+str(i) for i in range(len(lex_tup_before))] -- GitLab From 80a89ea3a1e06ffe5c91158d6789f154cd93076b Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 26 Jul 2020 20:19:28 -0500 Subject: [PATCH 096/136] Remove logic avoiding gratuitous incrementing of integer lex dim values in schedule outline creation since these are replaced with {0, 1} in the map simplification step. Further reduce number of lex dims in pairwise maps with the following strategy: once a lex tuple dimension is found where both tuples have non-matching integer values, remove any faster-updating lex dimensions where both tuples have integer values, even if the integers don't match. --- loopy/schedule/checker/schedule.py | 86 +++++++++++++++--------------- 1 file changed, 42 insertions(+), 44 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index dff0162d6..cd9443e67 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -100,33 +100,29 @@ def generate_pairwise_schedules( # keep track of the next tuple of points in our lexicographic # ordering, initially this as a 1-d point with value 0 next_insn_lex_tuple = [0] - stmt_added_since_prev_block_at_tier = [False] for linearization_item in linearization_items: if isinstance(linearization_item, EnterLoop): iname = linearization_item.iname if iname in loops_to_ignore: continue - # We could always increment next_insn_lex_tuple[-1] here since - # this new section of code comes after the previous section - # (statements since last opened/closed loop), but if we have - # not added any statements within the previous section yet, we - # don't have to (effectively ignoring that section of code). - if stmt_added_since_prev_block_at_tier[-1]: - next_insn_lex_tuple[-1] = next_insn_lex_tuple[-1]+1 - stmt_added_since_prev_block_at_tier[-1] = False + # Increment next_insn_lex_tuple[-1] for statements in the section + # of code after this EnterLoop. + # (not technically necessary if no statement was added in the + # previous section; gratuitious incrementing is counteracted + # in the simplification step below) + next_insn_lex_tuple[-1] = next_insn_lex_tuple[-1]+1 # upon entering a loop, we enter a new (deeper) tier, # add one lex dimension for the loop variable, - # add second lex dim to enumerate code blocks within new loop, and - # append a dim to stmt_added_since_prev_block_at_tier to represent - # new tier + # add second lex dim to enumerate code blocks within new loop next_insn_lex_tuple.append(iname) next_insn_lex_tuple.append(0) - stmt_added_since_prev_block_at_tier.append(False) + elif isinstance(linearization_item, LeaveLoop): if linearization_item.iname in loops_to_ignore: continue + # upon leaving a loop, # pop lex dimension for enumerating code blocks within this loop, and # pop lex dimension for the loop variable, and @@ -134,16 +130,13 @@ def generate_pairwise_schedules( next_insn_lex_tuple.pop() next_insn_lex_tuple.pop() - # We could always increment next_insn_lex_tuple[-1] here since - # this new block of code comes after the previous block (all - # statements since last opened/closed loop), but if we have not - # added any statements within the previous section yet, we - # don't have to (effectively ignoring that section of code). - # TODO since we're getting rid of unnecessary dims later, maybe don't need this? - stmt_added_since_prev_block_at_tier.pop() - if stmt_added_since_prev_block_at_tier[-1]: - next_insn_lex_tuple[-1] = next_insn_lex_tuple[-1]+1 - stmt_added_since_prev_block_at_tier[-1] = False + # Increment next_insn_lex_tuple[-1] for statements in the section + # of code after this LeaveLoop. + # (not technically necessary if no statement was added in the + # previous section; gratuitious incrementing is counteracted + # in the simplification step below) + next_insn_lex_tuple[-1] = next_insn_lex_tuple[-1]+1 + elif isinstance(linearization_item, (RunInstruction, Barrier)): from loopy.schedule.checker.utils import ( get_insn_id_from_linearization_item, @@ -170,9 +163,6 @@ def generate_pairwise_schedules( # increment lex dim val enumerating items in current code block next_insn_lex_tuple[-1] = next_insn_lex_tuple[-1] + 1 - # all current (nested) blocks now contain a statement - stmt_added_since_prev_block_at_tier = [True]*len( - stmt_added_since_prev_block_at_tier) else: from loopy.schedule import (CallKernel, ReturnFromKernel) # no action needed for these types of linearization item @@ -193,37 +183,44 @@ def generate_pairwise_schedules( def _pad_tuple_with_zeros(tup, length): return tup[:] + tuple([0]*(length-len(tup))) - def _simplify_dims(tup0, tup1): + def _simplify_lex_dims(tup0, tup1): + """Simplify pair of lex tuples in order to reduce the complexity of + resulting maps. Remove lex tuple dimensions with matching integer values + since these do not provide information on relative ordering. For the same + reason, once a dimension is found where both tuples have non-matching integer + values, remove any faster-updating lex dimensions where both tuples have + integer values, even if the integers don't match. + """ + # TODO actually, once we find non-matching integer dims, we don't + # need *any* more lex dims to specify relative ordering. + new_tup0 = [] new_tup1 = [] + non_matching_int_dims_found = False # loop over dims for d0, d1 in zip(tup0, tup1): if isinstance(d0, int) and isinstance(d1, int): # Both vals are ints for this dim - # If the ints match, this dim doesn't provide info about the - # relative ordering of these two statements, - # so skip (remove) this dim. - - # Otherwise, the ints inform us about the relative ordering of - # two statements. While their values may be larger than 1 in - # the lexicographic ordering describing a larger set of - # statements, in a pairwise schedule, only ints 0 and 1 are - # necessary to specify relative order. To keep the pairwise - # schedules as simple and comprehensible as possible, use only - # integers 0 and 1 to specify relative orderings in integer lex - # dims. - # (doesn't take much extra time since we are already going - # through these to remove unnecessary map dims) - - if d0 == d1: + if non_matching_int_dims_found or d0 == d1: continue elif d0 > d1: + # These ints inform us about the relative ordering of + # two statements. While their values may be larger than 1 in + # the lexicographic ordering describing a larger set of + # statements, in a pairwise schedule, only ints 0 and 1 are + # necessary to specify relative order. To keep the pairwise + # schedules as simple and comprehensible as possible, use only + # integers 0 and 1 to specify this relative ordering. + # (doesn't take much extra time since we are already going + # through these to remove unnecessary lex tuple dims) new_tup0.append(1) new_tup1.append(0) + non_matching_int_dims_found = True else: # d1 > d0 new_tup0.append(0) new_tup1.append(1) + non_matching_int_dims_found = True else: # keep this dim new_tup0.append(d0) @@ -281,7 +278,8 @@ def generate_pairwise_schedules( lex_tup_before = _pad_tuple_with_zeros(lex_tup_before, max_lex_dims) lex_tup_after = _pad_tuple_with_zeros(lex_tup_after, max_lex_dims) - lex_tup_before, lex_tup_after = _simplify_dims(lex_tup_before, lex_tup_after) + lex_tup_before, lex_tup_after = _simplify_lex_dims( + lex_tup_before, lex_tup_after) # Now generate maps from the blueprint -------------------------------------- -- GitLab From 3dd9327d0ad604ba8e6ace69d9ddda0478695ed7 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 26 Jul 2020 20:33:19 -0500 Subject: [PATCH 097/136] make generate_pairwise_schedules() return a dictionary mapping (insn_id_before, insn_id_after) tuples to (schedule_before, schedule_after) tuples --- loopy/schedule/checker/__init__.py | 2 ++ loopy/schedule/checker/schedule.py | 4 +-- test/test_linearization_checker.py | 51 ++++++++++++------------------ 3 files changed, 24 insertions(+), 33 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index fa9700b47..000265486 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -105,6 +105,8 @@ def get_schedules_for_statement_pairs( """ + # TODO update documentation + # {{{ make sure kernel has been preprocessed from loopy.kernel import KernelState diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index cd9443e67..7b98c621a 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -264,7 +264,7 @@ def generate_pairwise_schedules( space=sched_space, ) - pairwise_schedules = [] + pairwise_schedules = {} for insn_id_before, insn_id_after in insn_id_pairs: lex_tup_before = stmt_instances[insn_id_before] lex_tup_after = stmt_instances[insn_id_after] @@ -296,6 +296,6 @@ def generate_pairwise_schedules( map_after = _get_map_for_stmt_inst( insn_id_after, lex_tup_after, int_sid_after, out_names_sched) - pairwise_schedules.append((map_before, map_after)) + pairwise_schedules[(insn_id_before, insn_id_after)] = (map_before, map_after) return pairwise_schedules diff --git a/test/test_linearization_checker.py b/test/test_linearization_checker.py index 716737bdd..a4657ba1f 100644 --- a/test/test_linearization_checker.py +++ b/test/test_linearization_checker.py @@ -112,14 +112,24 @@ def test_lexschedule_creation(): ["%s%d=%s" % (LEX_VAR_PREFIX, idx, str(val)) for idx, val in enumerate(dim_vals)]) + insn_id_pairs = [ + ("insn_a", "insn_b"), + ("insn_a", "insn_c"), + ("insn_a", "insn_d"), + ("insn_b", "insn_c"), + ("insn_b", "insn_d"), + ("insn_c", "insn_d"), + ] + sched_maps = get_schedules_for_statement_pairs( + knl, + linearization_items, + insn_id_pairs, + ) + # Relationship between insn_a and insn_b --------------------------------------- # Get two maps - sched_map_before, sched_map_after = get_schedules_for_statement_pairs( - knl, - linearization_items, - [("insn_a", "insn_b")], - )[0] + sched_map_before, sched_map_after = sched_maps[("insn_a", "insn_b")] # Create expected maps, align, compare @@ -150,11 +160,7 @@ def test_lexschedule_creation(): # Relationship between insn_a and insn_c --------------------------------------- # Get two maps - sched_map_before, sched_map_after = get_schedules_for_statement_pairs( - knl, - linearization_items, - [("insn_a", "insn_c")], - )[0] + sched_map_before, sched_map_after = sched_maps[("insn_a", "insn_c")] # Create expected maps, align, compare @@ -188,11 +194,7 @@ def test_lexschedule_creation(): # (i loop could be before or after t loop) def perform_insn_ad_checks_with(a_lex_idx, d_lex_idx): # Get two maps - sched_map_before, sched_map_after = get_schedules_for_statement_pairs( - knl, - linearization_items, - [("insn_a", "insn_d")], - )[0] + sched_map_before, sched_map_after = sched_maps[("insn_a", "insn_d")] # Create expected maps, align, compare @@ -230,14 +232,9 @@ def test_lexschedule_creation(): # Relationship between insn_b and insn_c --------------------------------------- # insn_b and insn_c could have been linearized in either order - # (i loop could be before or after t loop) def perform_insn_bc_checks_with(b_lex_idx, c_lex_idx): # Get two maps - sched_map_before, sched_map_after = get_schedules_for_statement_pairs( - knl, - linearization_items, - [("insn_b", "insn_c")], - )[0] + sched_map_before, sched_map_after = sched_maps[("insn_b", "insn_c")] # Create expected maps, align, compare @@ -278,11 +275,7 @@ def test_lexschedule_creation(): # (i loop could be before or after t loop) def perform_insn_bd_checks_with(b_lex_idx, d_lex_idx): # Get two maps - sched_map_before, sched_map_after = get_schedules_for_statement_pairs( - knl, - linearization_items, - [("insn_b", "insn_d")], - )[0] + sched_map_before, sched_map_after = sched_maps[("insn_b", "insn_d")] # Create expected maps, align, compare @@ -323,11 +316,7 @@ def test_lexschedule_creation(): # (i loop could be before or after t loop) def perform_insn_cd_checks_with(c_lex_idx, d_lex_idx): # Get two maps - sched_map_before, sched_map_after = get_schedules_for_statement_pairs( - knl, - linearization_items, - [("insn_c", "insn_d")], - )[0] + sched_map_before, sched_map_after = sched_maps[("insn_c", "insn_d")] # Create expected maps, align, compare -- GitLab From a4ff29d4f828f0b00983b57bd0ec90206f4478f5 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 27 Jul 2020 18:06:02 -0500 Subject: [PATCH 098/136] minor comment change --- loopy/schedule/checker/schedule.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 7b98c621a..65905862e 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -113,8 +113,7 @@ def generate_pairwise_schedules( # in the simplification step below) next_insn_lex_tuple[-1] = next_insn_lex_tuple[-1]+1 - # upon entering a loop, we enter a new (deeper) tier, - # add one lex dimension for the loop variable, + # Upon entering a loop, add one lex dimension for the loop variable, # add second lex dim to enumerate code blocks within new loop next_insn_lex_tuple.append(iname) next_insn_lex_tuple.append(0) -- GitLab From 86c3ff938be14495e4567d62dd9d86761e650009 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 2 Aug 2020 20:58:50 -0500 Subject: [PATCH 099/136] When simplifying pairs of lex tuples before map creation, once a dimension is found where both tuples have non-matching integer values, remove all faster-updating lex dimensions. --- loopy/schedule/checker/schedule.py | 30 +++++++++++++++++------------- test/test_linearization_checker.py | 20 ++++++++++---------- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 65905862e..6044f7c7d 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -183,25 +183,24 @@ def generate_pairwise_schedules( return tup[:] + tuple([0]*(length-len(tup))) def _simplify_lex_dims(tup0, tup1): - """Simplify pair of lex tuples in order to reduce the complexity of + """Simplify a pair of lex tuples in order to reduce the complexity of resulting maps. Remove lex tuple dimensions with matching integer values - since these do not provide information on relative ordering. For the same - reason, once a dimension is found where both tuples have non-matching integer - values, remove any faster-updating lex dimensions where both tuples have - integer values, even if the integers don't match. + since these do not provide information on relative ordering. Once a + dimension is found where both tuples have non-matching integer values, + remove any faster-updating lex dimensions since they are not necessary + to speficy relative ordering. """ - # TODO actually, once we find non-matching integer dims, we don't - # need *any* more lex dims to specify relative ordering. new_tup0 = [] new_tup1 = [] - non_matching_int_dims_found = False + # loop over dims for d0, d1 in zip(tup0, tup1): if isinstance(d0, int) and isinstance(d1, int): - # Both vals are ints for this dim - if non_matching_int_dims_found or d0 == d1: + # Both vals are ints for this dim + if d0 == d1: + # Do not keep this dim continue elif d0 > d1: # These ints inform us about the relative ordering of @@ -215,15 +214,20 @@ def generate_pairwise_schedules( # through these to remove unnecessary lex tuple dims) new_tup0.append(1) new_tup1.append(0) - non_matching_int_dims_found = True + + # No further dims needed to fully specify ordering + break else: # d1 > d0 new_tup0.append(0) new_tup1.append(1) - non_matching_int_dims_found = True + + # No further dims needed to fully specify ordering + break else: - # keep this dim + # Keep this dim without modifying new_tup0.append(d0) new_tup1.append(d1) + return tuple(new_tup0), tuple(new_tup1) def _get_map_for_stmt_inst(insn_id, lex_points, int_sid, out_names_sched): diff --git a/test/test_linearization_checker.py b/test/test_linearization_checker.py index a4657ba1f..6d0fd3abf 100644 --- a/test/test_linearization_checker.py +++ b/test/test_linearization_checker.py @@ -137,7 +137,7 @@ def test_lexschedule_creation(): "[pi, pk] -> { [%s=0, i, k] -> [%s] : 0 <= i < pi and 0 <= k < pk }" % ( STATEMENT_VAR_NAME, - _lex_space_string(["i", "0", "k"]), + _lex_space_string(["i", "0"]), ) ) sched_map_before_expected = ensure_dim_names_match_and_align( @@ -147,7 +147,7 @@ def test_lexschedule_creation(): "[pi, pj] -> { [%s=1, i, j] -> [%s] : 0 <= i < pi and 0 <= j < pj }" % ( STATEMENT_VAR_NAME, - _lex_space_string(["i", "1", "j"]), + _lex_space_string(["i", "1"]), ) ) sched_map_after_expected = ensure_dim_names_match_and_align( @@ -168,7 +168,7 @@ def test_lexschedule_creation(): "[pi, pk] -> { [%s=0, i, k] -> [%s] : 0 <= i < pi and 0 <= k < pk }" % ( STATEMENT_VAR_NAME, - _lex_space_string(["i", "0", "k"]), + _lex_space_string(["i", "0"]), ) ) sched_map_before_expected = ensure_dim_names_match_and_align( @@ -178,7 +178,7 @@ def test_lexschedule_creation(): "[pi, pj] -> { [%s=1, i, j] -> [%s] : 0 <= i < pi and 0 <= j < pj }" % ( STATEMENT_VAR_NAME, - _lex_space_string(["i", "1", "j"]), + _lex_space_string(["i", "1"]), ) ) sched_map_after_expected = ensure_dim_names_match_and_align( @@ -202,7 +202,7 @@ def test_lexschedule_creation(): "[pi, pk] -> { [%s=0, i, k] -> [%s] : 0 <= i < pi and 0 <= k < pk }" % ( STATEMENT_VAR_NAME, - _lex_space_string([a_lex_idx, "i", "k"]), + _lex_space_string([a_lex_idx, ]), ) ) sched_map_before_expected = ensure_dim_names_match_and_align( @@ -212,7 +212,7 @@ def test_lexschedule_creation(): "[pt] -> { [%s=1, t] -> [%s] : 0 <= t < pt }" % ( STATEMENT_VAR_NAME, - _lex_space_string([d_lex_idx, "t", "0"]), + _lex_space_string([d_lex_idx, ]), ) ) sched_map_after_expected = ensure_dim_names_match_and_align( @@ -283,7 +283,7 @@ def test_lexschedule_creation(): "[pi, pj] -> { [%s=0, i, j] -> [%s] : 0 <= i < pi and 0 <= j < pj }" % ( STATEMENT_VAR_NAME, - _lex_space_string([b_lex_idx, "i", "j"]), + _lex_space_string([b_lex_idx, ]), ) ) sched_map_before_expected = ensure_dim_names_match_and_align( @@ -293,7 +293,7 @@ def test_lexschedule_creation(): "[pt] -> { [%s=1, t] -> [%s] : 0 <= t < pt }" % ( STATEMENT_VAR_NAME, - _lex_space_string([d_lex_idx, "t", "0"]), + _lex_space_string([d_lex_idx, ]), ) ) sched_map_after_expected = ensure_dim_names_match_and_align( @@ -324,7 +324,7 @@ def test_lexschedule_creation(): "[pi, pj] -> { [%s=0, i, j] -> [%s] : 0 <= i < pi and 0 <= j < pj }" % ( STATEMENT_VAR_NAME, - _lex_space_string([c_lex_idx, "i", "j"]), + _lex_space_string([c_lex_idx, ]), ) ) sched_map_before_expected = ensure_dim_names_match_and_align( @@ -334,7 +334,7 @@ def test_lexschedule_creation(): "[pt] -> { [%s=1, t] -> [%s] : 0 <= t < pt }" % ( STATEMENT_VAR_NAME, - _lex_space_string([d_lex_idx, "t", "0"]), + _lex_space_string([d_lex_idx, ]), ) ) sched_map_after_expected = ensure_dim_names_match_and_align( -- GitLab From 39ec3c4ebfca2b02e36a8c94d2953d5a62aa2ea7 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 2 Aug 2020 21:26:25 -0500 Subject: [PATCH 100/136] instead of operating on Xbefore and Xafter pairs in pairs of statements, keep all pairs in lists (of length 2) and operate on the lists with loops --- loopy/schedule/checker/schedule.py | 32 +++++++++++++++--------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 6044f7c7d..769a690f2 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -268,37 +268,37 @@ def generate_pairwise_schedules( ) pairwise_schedules = {} - for insn_id_before, insn_id_after in insn_id_pairs: - lex_tup_before = stmt_instances[insn_id_before] - lex_tup_after = stmt_instances[insn_id_after] + for insn_ids in insn_id_pairs: + lex_tuples = [stmt_instances[insn_id] for insn_id in insn_ids] # simplify tuples to the extent possible ------------------------------------ # At this point, pairwise sub-schedule may contain lex point tuples # missing dimensions; the values in these missing dims should # be zero, so add them. - max_lex_dims = max(len(lex_tup_before), len(lex_tup_after)) - lex_tup_before = _pad_tuple_with_zeros(lex_tup_before, max_lex_dims) - lex_tup_after = _pad_tuple_with_zeros(lex_tup_after, max_lex_dims) + max_lex_dims = max([len(lex_tuple) for lex_tuple in lex_tuples]) + lex_tuples_padded = [ + _pad_tuple_with_zeros(lex_tuple, max_lex_dims) + for lex_tuple in lex_tuples] - lex_tup_before, lex_tup_after = _simplify_lex_dims( - lex_tup_before, lex_tup_after) + lex_tuples_simplified = _simplify_lex_dims(*lex_tuples_padded) # Now generate maps from the blueprint -------------------------------------- - out_names_sched = [LEX_VAR_PREFIX+str(i) for i in range(len(lex_tup_before))] + out_names_sched = [ + LEX_VAR_PREFIX+str(i) for i in range(len(lex_tuples_simplified[0]))] # Determine integer IDs that will represent each statement in mapping # (dependency map creation assumes sid_before=0 and sid_after=1, unless # before and after refer to same stmt, in which case sid_before=sid_after=0) - int_sid_before = 0 - int_sid_after = 0 if insn_id_before == insn_id_after else 1 + int_sids = [0, 0] if insn_ids[0] == insn_ids[1] else [0, 1] - map_before = _get_map_for_stmt_inst( - insn_id_before, lex_tup_before, int_sid_before, out_names_sched) - map_after = _get_map_for_stmt_inst( - insn_id_after, lex_tup_after, int_sid_after, out_names_sched) + sched_maps = [ + _get_map_for_stmt_inst(insn_id, lex_tuple, int_sid, out_names_sched) + for insn_id, lex_tuple, int_sid + in zip(insn_ids, lex_tuples_simplified, int_sids) + ] - pairwise_schedules[(insn_id_before, insn_id_after)] = (map_before, map_after) + pairwise_schedules[tuple(insn_ids)] = tuple(sched_maps) return pairwise_schedules -- GitLab From 6bb69899730e940ce5e462500cc40827ec23261f Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 2 Aug 2020 21:34:24 -0500 Subject: [PATCH 101/136] fix flake8 issue --- loopy/schedule/checker/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index bad083558..3bde5247b 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -140,7 +140,7 @@ def ensure_dim_names_match_and_align(obj_map, tgt_map): def sorted_union_of_names_in_isl_sets( isl_sets, set_dim=isl.dim_type.set): - """Return a sorted list of the union of all variable names found in + r"""Return a sorted list of the union of all variable names found in the provided :class:`islpy.Set`\ s. """ -- GitLab From 41654850aac4b18394883c6f3607076b74b10021 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 2 Aug 2020 22:25:56 -0500 Subject: [PATCH 102/136] remove get_islvars_from_space(); instead use isl.affs_from_space() --- loopy/schedule/checker/utils.py | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index 3bde5247b..019117231 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -28,18 +28,6 @@ def prettier_map_string(map_obj): ).replace("{ ", "{\n").replace(" }", "\n}").replace("; ", ";\n") -def get_islvars_from_space(space): - #pu.db - param_names = space.get_var_names(isl.dim_type.param) - in_names = space.get_var_names(isl.dim_type.in_) - out_names = space.get_var_names(isl.dim_type.out) - return isl.make_zero_and_vars(in_names+out_names, param_names) - #old = isl.make_zero_and_vars(in_names+out_names, param_names) - #new = isl.affs_from_space(space) - #assert old == new - #return new - - def add_dims_to_isl_set(isl_set, dim_type, names, new_idx_start): new_set = isl_set.insert_dims( dim_type, new_idx_start, len(names) @@ -183,7 +171,14 @@ def create_symbolic_map_from_tuples( space_out_names = space.get_var_names(dim_type.out) space_in_names = space.get_var_names(isl.dim_type.in_) - islvars = get_islvars_from_space(space) + # get islvars from space + islvars = isl.affs_from_space( + space.move_dims( + isl.dim_type.out, 0, + isl.dim_type.in_, 0, + len(space_in_names), + ).range() + ) # loop through pairs and create a set that will later be converted to a map -- GitLab From 3f4b3b8fbf0d057e317d48eb4164eaedc86f3c94 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 4 Aug 2020 01:41:09 -0500 Subject: [PATCH 103/136] make example usage of get_schedules_for_statement_pairs() into a doctest; probably the wrong way to do this... (but it's not time to add this to tutorial yet) --- loopy/schedule/checker/__init__.py | 73 +++++++++++------------------- 1 file changed, 27 insertions(+), 46 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 000265486..d28c2f676 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -56,52 +56,33 @@ def get_schedules_for_statement_pairs( from statement instances to lexicographic time, one for each of the two statements. - Example usage:: - - # Make kernel ------------------------------------------------------------ - knl = lp.make_kernel( - "{[i,j,k]: 0<=i { - [_lp_linchk_statement = 0, i, j, k] -> - [_lp_linchk_l0 = 0, _lp_linchk_l1 = i, _lp_linchk_l2 = 0, - _lp_linchk_l3 = j, _lp_linchk_l4 = 0] : - 0 <= i < pi and 0 <= j < pj and 0 <= k < pk } - [pi, pj, pk] -> { - [_lp_linchk_statement = 1, i, j, k] -> - [_lp_linchk_l0 = 0, _lp_linchk_l1 = i, _lp_linchk_l2 = 1, - _lp_linchk_l3 = k, _lp_linchk_l4 = 0] : - 0 <= i < pi and 0 <= j < pj and 0 <= k < pk } + .. doctest: + + >>> import loopy as lp + >>> import numpy as np + >>> # Make kernel ----------------------------------------------------------- + >>> knl = lp.make_kernel( + ... "{[i,j,k]: 0<=i>> knl = lp.add_and_infer_dtypes(knl, {"a": np.float32, "b": np.float32}) + >>> knl = lp.prioritize_loops(knl, "i,j") + >>> knl = lp.prioritize_loops(knl, "i,k") + >>> # Get a linearization + >>> knl = lp.get_one_linearized_kernel(lp.preprocess_kernel(knl)) + >>> # Get a pairwise schedule ----------------------------------------------- + >>> from loopy.schedule.checker import get_schedules_for_statement_pairs + >>> # Get two maps ---------------------------------------------------------- + >>> schedules = get_schedules_for_statement_pairs( + ... knl, + ... knl.linearization, + ... [("insn_a", "insn_b")], + ... ) + >>> print(*schedules[("insn_a", "insn_b")], sep="\n") + [pi, pj, pk] -> { [_lp_linchk_statement = 0, i, j, k] -> [_lp_linchk_l0 = i, _lp_linchk_l1 = 0] : 0 <= i < pi and 0 <= j < pj and 0 <= k < pk } + [pi, pj, pk] -> { [_lp_linchk_statement = 1, i, j, k] -> [_lp_linchk_l0 = i, _lp_linchk_l1 = 1] : 0 <= i < pi and 0 <= j < pj and 0 <= k < pk } """ -- GitLab From de5ab4480058c797d09830102e70a9a402053f9b Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 4 Aug 2020 02:37:14 -0500 Subject: [PATCH 104/136] update all docstrings/comments after recent changes --- loopy/schedule/checker/__init__.py | 31 ++++---- loopy/schedule/checker/schedule.py | 115 +++++++++++++++-------------- loopy/schedule/checker/utils.py | 41 +++++----- 3 files changed, 94 insertions(+), 93 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index d28c2f676..269e7ba05 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -28,32 +28,31 @@ def get_schedules_for_statement_pairs( linearization_items, insn_id_pairs, ): - r"""Given a pair of statements in a linearized kernel, determine - the (relative) order in which the instances are executed, - by creating a mapping from statement instances to points in a single - lexicographic ordering. Create a pair of :class:`islpy.Map`\ s - representing a pairwise schedule as two mappings from statement instances - to lexicographic time. + r"""For each statement pair in a subset of all statement pairs found in a + linearized kernel, determine the (relative) order in which the statement + instances are executed. For each pair, describe this relative ordering with + a pair of mappings from statement instances to points in a single + lexicographic ordering (a ``pairwise schedule''). When determining the + relative ordering, ignore concurrent inames. :arg knl: A preprocessed :class:`loopy.kernel.LoopKernel` containing the linearization items that will be used to create a schedule. :arg linearization_items: A list of :class:`loopy.schedule.ScheduleItem` (to be renamed to `loopy.schedule.LinearizationItem`) containing - the two linearization items for which a schedule will be + all linearization items for which pairwise schedules will be created. This list may be a *partial* linearization for a kernel since this function may be used during the linearization process. - :arg insn_id_before: An instruction identifier that is unique within - a :class:`loopy.kernel.LoopKernel`. + :arg insn_id_pairs: A list of two-tuples containing pairs of instruction + identifiers, each of which is unique within a + :class:`loopy.kernel.LoopKernel`. - :arg insn_id_after: An instruction identifier that is unique within - a :class:`loopy.kernel.LoopKernel`. - - :returns: A two-tuple containing two :class:`islpy.Map`s - representing the a pairwise schedule as two mappings - from statement instances to lexicographic time, one for + :returns: A dictionary mapping each two-tuple of instruction identifiers + provided in `insn_id_pairs` to a corresponding two-tuple containing two + :class:`islpy.Map`\ s representing a pairwise schedule as two + mappings from statement instances to lexicographic time, one for each of the two statements. .. doctest: @@ -86,8 +85,6 @@ def get_schedules_for_statement_pairs( """ - # TODO update documentation - # {{{ make sure kernel has been preprocessed from loopy.kernel import KernelState diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 769a690f2..724053e59 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -53,53 +53,56 @@ def generate_pairwise_schedules( insn_id_pairs, loops_to_ignore=set(), ): - r"""Given a pair of statements in a linearized kernel, determine - the (relative) order in which the instances are executed, - by creating a mapping from statement instances to points in a single - lexicographic ordering. Create a pair of :class:`islpy.Map`\ s - representing a pairwise schedule as two mappings from statement instances - to lexicographic time. - - :arg knl: A :class:`loopy.kernel.LoopKernel` containing the - linearization items that will be described by the schedule. This + r"""For each statement pair in a subset of all statement pairs found in a + linearized kernel, determine the (relative) order in which the statement + instances are executed. For each pair, describe this relative ordering with + a pair of mappings from statement instances to points in a single + lexicographic ordering (a ``pairwise schedule''). + + :arg knl: A preprocessed :class:`loopy.kernel.LoopKernel` containing the + linearization items that will be used to create a schedule. This kernel will be used to get the domains associated with the inames used in the statements. :arg linearization_items: A list of :class:`loopy.schedule.ScheduleItem` - (to be renamed to `loopy.schedule.LinearizationItem`) including the - two linearization items whose relative order will be described by the - schedule. This list may be a *partial* linearization for a kernel since - this function may be used during the linearization process. - - :arg before_insn_id: A :class:`str` instruction id specifying - stmt_instance_set_before in this pair of instructions. - - :arg after_insn_id: A :class:`str` instruction id specifying - stmt_instance_set_after in this pair of instructions. - - :returns: A two-tuple containing two :class:`islpy.Map`\ s - representing a pairwise schedule as two mappings - from statement instances to lexicographic time, one for + (to be renamed to `loopy.schedule.LinearizationItem`) containing + all linearization items for which pairwise schedules will be + created. This list may be a *partial* linearization for a + kernel since this function may be used during the linearization + process. + + :arg insn_id_pairs: A list of two-tuples containing pairs of instruction + identifiers, each of which is unique within a + :class:`loopy.kernel.LoopKernel`. + + :arg loops_to_ignore: A set of inames that will be ignored when + determining the relative ordering of statements. This will typically + contain concurrent inames. + + :returns: A dictionary mapping each two-tuple of instruction identifiers + provided in `insn_id_pairs` to a corresponding two-tuple containing two + :class:`islpy.Map`\ s representing a pairwise schedule as two + mappings from statement instances to lexicographic time, one for each of the two statements. """ - # TODO - # update documentation + from loopy.schedule import (EnterLoop, LeaveLoop, Barrier, RunInstruction) all_insn_ids = set().union(*insn_id_pairs) + # First, use one pass through linearization_items to generate a lexicographic + # ordering describing the relative order of *all* statements represented by + # all_insn_ids + # For each statement, map the insn_id to a tuple representing points # in the lexicographic ordering containing items of :class:`int` or # :class:`str` :mod:`loopy` inames. stmt_instances = {} - from loopy.schedule import (EnterLoop, LeaveLoop, Barrier, RunInstruction) - - # go through linearization_items and generate pairwise sub-schedule - - # keep track of the next tuple of points in our lexicographic + # Keep track of the next tuple of points in our lexicographic # ordering, initially this as a 1-d point with value 0 next_insn_lex_tuple = [0] + for linearization_item in linearization_items: if isinstance(linearization_item, EnterLoop): iname = linearization_item.iname @@ -109,12 +112,12 @@ def generate_pairwise_schedules( # Increment next_insn_lex_tuple[-1] for statements in the section # of code after this EnterLoop. # (not technically necessary if no statement was added in the - # previous section; gratuitious incrementing is counteracted + # previous section; gratuitous incrementing is counteracted # in the simplification step below) next_insn_lex_tuple[-1] = next_insn_lex_tuple[-1]+1 # Upon entering a loop, add one lex dimension for the loop variable, - # add second lex dim to enumerate code blocks within new loop + # add second lex dim to enumerate sections of code within new loop next_insn_lex_tuple.append(iname) next_insn_lex_tuple.append(0) @@ -122,17 +125,17 @@ def generate_pairwise_schedules( if linearization_item.iname in loops_to_ignore: continue - # upon leaving a loop, - # pop lex dimension for enumerating code blocks within this loop, and + # Upon leaving a loop, + # pop lex dimension for enumerating code sections within this loop, and # pop lex dimension for the loop variable, and - # increment lex dim val enumerating items in current code block + # increment lex dim val enumerating items in current section of code next_insn_lex_tuple.pop() next_insn_lex_tuple.pop() # Increment next_insn_lex_tuple[-1] for statements in the section # of code after this LeaveLoop. # (not technically necessary if no statement was added in the - # previous section; gratuitious incrementing is counteracted + # previous section; gratuitous incrementing is counteracted # in the simplification step below) next_insn_lex_tuple[-1] = next_insn_lex_tuple[-1]+1 @@ -154,23 +157,23 @@ def generate_pairwise_schedules( continue - # only process listed insns, otherwise ignore + # Only process listed insns, otherwise ignore if lp_insn_id in all_insn_ids: - # add item + # Add item to stmt_instances stmt_instances[lp_insn_id] = tuple(next_insn_lex_tuple[:]) - # increment lex dim val enumerating items in current code block + # Increment lex dim val enumerating items in current section of code next_insn_lex_tuple[-1] = next_insn_lex_tuple[-1] + 1 else: from loopy.schedule import (CallKernel, ReturnFromKernel) - # no action needed for these types of linearization item + # No action needed for these types of linearization item assert isinstance( linearization_item, (CallKernel, ReturnFromKernel)) pass - # to save time, stop when we've created all statements - if len(stmt_instances.keys()) == all_insn_ids: + # To save time, stop when we've found all statements + if len(stmt_instances.keys()) == len(all_insn_ids): break from loopy.schedule.checker.utils import ( @@ -179,8 +182,8 @@ def generate_pairwise_schedules( add_dims_to_isl_set, ) - def _pad_tuple_with_zeros(tup, length): - return tup[:] + tuple([0]*(length-len(tup))) + def _pad_tuple_with_zeros(tup, desired_length): + return tup[:] + tuple([0]*(desired_length-len(tup))) def _simplify_lex_dims(tup0, tup1): """Simplify a pair of lex tuples in order to reduce the complexity of @@ -188,13 +191,13 @@ def generate_pairwise_schedules( since these do not provide information on relative ordering. Once a dimension is found where both tuples have non-matching integer values, remove any faster-updating lex dimensions since they are not necessary - to speficy relative ordering. + to specify a relative ordering. """ new_tup0 = [] new_tup1 = [] - # loop over dims + # Loop over dims from slowest updating to fastest for d0, d1 in zip(tup0, tup1): if isinstance(d0, int) and isinstance(d1, int): @@ -236,8 +239,8 @@ def generate_pairwise_schedules( dom = knl.get_inames_domain( knl.id_to_insn[insn_id].within_inames) - # create space (an isl space in current implementation) - # {('statement', used in statement domain>) -> + # Create map space (an isl space in current implementation) + # {('statement', ) -> # (lexicographic ordering dims)} dom_inames_ordered = sorted_union_of_names_in_isl_sets([dom]) @@ -252,8 +255,7 @@ def generate_pairwise_schedules( add_dims_to_isl_set( dom, isl.dim_type.set, [STATEMENT_VAR_NAME], 0), ] - # Each map representing the schedule will map - # statement instances -> lex time. + # Each map will map statement instances -> lex time. # Right now, statement instance tuples consist of single int. # Add all inames from domains to each map domain tuple. tuple_pair = [( @@ -261,21 +263,23 @@ def generate_pairwise_schedules( lex_points )] - # create map + # Create map return create_symbolic_map_from_tuples( tuple_pairs_with_domains=zip(tuple_pair, dom_to_intersect), space=sched_space, ) + # Second, create pairwise schedules for each individual pair of insns + pairwise_schedules = {} for insn_ids in insn_id_pairs: lex_tuples = [stmt_instances[insn_id] for insn_id in insn_ids] - # simplify tuples to the extent possible ------------------------------------ + # Simplify tuples to the extent possible ------------------------------------ - # At this point, pairwise sub-schedule may contain lex point tuples - # missing dimensions; the values in these missing dims should - # be zero, so add them. + # At this point, one of the lex tuples may have more dimensions than another; + # the missing dims are the fastest-updating dims, and their values should + # be zero. Add them. max_lex_dims = max([len(lex_tuple) for lex_tuple in lex_tuples]) lex_tuples_padded = [ _pad_tuple_with_zeros(lex_tuple, max_lex_dims) @@ -285,6 +289,7 @@ def generate_pairwise_schedules( # Now generate maps from the blueprint -------------------------------------- + # Create names for the output dimensions out_names_sched = [ LEX_VAR_PREFIX+str(i) for i in range(len(lex_tuples_simplified[0]))] diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index 019117231..10ccc7191 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -44,6 +44,9 @@ def map_names_match_check( assert_subset=True, assert_permutation=True, ): + """Raise an error if names of the specified map dimension do not match + the desired names + """ obj_map_names = obj_map.space.get_var_names(dim_type) if assert_permutation: @@ -89,23 +92,19 @@ def insert_missing_dims_and_reorder_by_name( new_set = isl_set.copy() for desired_idx, name in enumerate(desired_dims_ordered): - # if iname doesn't exist in set, add dim: + # If iname doesn't exist in set, add dim if name not in new_set.get_var_names(dim_type): - # insert missing dim in correct location + # Insert missing dim in correct location new_set = new_set.insert_dims( dim_type, desired_idx, 1 - ).set_dim_name( - dim_type, desired_idx, name) - else: # iname exists in set + ).set_dim_name(dim_type, desired_idx, name) + else: # Iname exists in set current_idx = new_set.find_dim_by_name(dim_type, name) if current_idx != desired_idx: - # move_dims(dst_type, dst_idx, src_type, src_idx, n) - - # first move to other dim because isl is stupid + # First move to other dim because isl is stupid new_set = new_set.move_dims( other_dim_type, other_dim_len, dim_type, current_idx, 1) - - # now move it where we actually want it + # Now move it where we actually want it new_set = new_set.move_dims( dim_type, desired_idx, other_dim_type, other_dim_len, 1) @@ -134,7 +133,7 @@ def sorted_union_of_names_in_isl_sets( inames = set().union(*[isl_set.get_var_names(set_dim) for isl_set in isl_sets]) - # sorting is not necessary, but keeps results consistent between runs + # Sorting is not necessary, but keeps results consistent between runs return sorted(inames) @@ -171,7 +170,7 @@ def create_symbolic_map_from_tuples( space_out_names = space.get_var_names(dim_type.out) space_in_names = space.get_var_names(isl.dim_type.in_) - # get islvars from space + # Get islvars from space islvars = isl.affs_from_space( space.move_dims( isl.dim_type.out, 0, @@ -180,8 +179,6 @@ def create_symbolic_map_from_tuples( ).range() ) - # loop through pairs and create a set that will later be converted to a map - def _conjunction_of_dim_eq_conditions(dim_names, values, islvars): condition = islvars[0].eq_set(islvars[0]) for dim_name, val in zip(dim_names, values): @@ -193,22 +190,24 @@ def create_symbolic_map_from_tuples( & islvars[dim_name].eq_set(islvars[val]) return condition - # initialize union to empty + # Initialize union of maps to empty union_of_maps = isl.Map.from_domain( islvars[0].eq_set(islvars[0]+1) # 0 == 1 (false) ).move_dims( dim_type.out, 0, dim_type.in_, len(space_in_names), len(space_out_names)) + + # Loop through tuple pairs for (tup_in, tup_out), dom in tuple_pairs_with_domains: - # set values for 'in' dimension using tuple vals + # Set values for 'in' dimension using tuple vals condition = _conjunction_of_dim_eq_conditions( space_in_names, tup_in, islvars) - # set values for 'out' dimension using tuple vals + # Set values for 'out' dimension using tuple vals condition = condition & _conjunction_of_dim_eq_conditions( space_out_names, tup_out, islvars) - # convert set to map by moving dimensions around + # Convert set to map by moving dimensions around map_from_set = isl.Map.from_domain(condition) map_from_set = map_from_set.move_dims( dim_type.out, 0, dim_type.in_, @@ -217,15 +216,15 @@ def create_symbolic_map_from_tuples( assert space_in_names == map_from_set.get_var_names( isl.dim_type.in_) - # if there are any dimensions in dom that are missing from + # If there are any dimensions in dom that are missing from # map_from_set, we have a problem I think? - # (assertion checks this in add_missing... + # (assertion checks this in add_missing...) dom_with_all_inames = insert_missing_dims_and_reorder_by_name( dom, isl.dim_type.set, space_in_names, ) - # intersect domain with this map + # Intersect domain with this map union_of_maps = union_of_maps.union( map_from_set.intersect_domain(dom_with_all_inames)) -- GitLab From 5551fd9ba664e99042205bf6564d540c8b6781c6 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 4 Aug 2020 02:38:41 -0500 Subject: [PATCH 105/136] remove unused arg (knl) from get_EnterLoop_inames() --- loopy/schedule/checker/__init__.py | 2 +- loopy/schedule/checker/utils.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 269e7ba05..09ffd6bde 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -104,7 +104,7 @@ def get_schedules_for_statement_pairs( get_EnterLoop_inames, ) conc_inames, _ = partition_inames_by_concurrency(knl) - enterloop_inames = get_EnterLoop_inames(linearization_items, knl) + enterloop_inames = get_EnterLoop_inames(linearization_items) conc_loop_inames = conc_inames & enterloop_inames if conc_loop_inames: from warnings import warn diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index 10ccc7191..23880bbfa 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -254,7 +254,7 @@ def get_insn_id_from_linearization_item(linearization_item): return linearization_item.insn_id -def get_EnterLoop_inames(linearization_items, knl): +def get_EnterLoop_inames(linearization_items): from loopy.schedule import EnterLoop loop_inames = set() for linearization_item in linearization_items: -- GitLab From 222b0c729b07936d13b72763859d41b23857f8b7 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 4 Aug 2020 02:56:05 -0500 Subject: [PATCH 106/136] use list comprehension instead of loop in get_EnterLoop_inames() --- loopy/schedule/checker/utils.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index 23880bbfa..b09c9fb16 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -256,8 +256,9 @@ def get_insn_id_from_linearization_item(linearization_item): def get_EnterLoop_inames(linearization_items): from loopy.schedule import EnterLoop - loop_inames = set() - for linearization_item in linearization_items: - if isinstance(linearization_item, EnterLoop): - loop_inames.add(linearization_item.iname) - return loop_inames + + # Note: each iname must live in len-1 list to avoid char separation + return set().union(*[ + [item.iname, ] for item in linearization_items + if isinstance(item, EnterLoop) + ]) -- GitLab From f1e31d52ffe97d10583469fd4fe870f5a6ae2429 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 4 Aug 2020 03:11:10 -0500 Subject: [PATCH 107/136] temporarily add an assert-false to check for unnecessary functionality --- loopy/schedule/checker/utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index b09c9fb16..babb2b24a 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -94,6 +94,7 @@ def insert_missing_dims_and_reorder_by_name( for desired_idx, name in enumerate(desired_dims_ordered): # If iname doesn't exist in set, add dim if name not in new_set.get_var_names(dim_type): + assert False # Insert missing dim in correct location new_set = new_set.insert_dims( dim_type, desired_idx, 1 -- GitLab From 8001bd61ad9c3a77c5c9a781bb856c5cf331e66c Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 4 Aug 2020 03:35:12 -0500 Subject: [PATCH 108/136] handle special case where simplified lex tuples are empty (means statements map to the exact same point(s) in the lex ordering, which is okay, but to represent this, our lex tuple cannot be empty, so map to (0)) --- loopy/schedule/checker/schedule.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 724053e59..1e6e30fb7 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -231,7 +231,12 @@ def generate_pairwise_schedules( new_tup0.append(d0) new_tup1.append(d1) - return tuple(new_tup0), tuple(new_tup1) + if len(new_tup0) == 0: + # Statements map to the exact same point(s) in the lex ordering, + # which is okay, but to represent this, our lex tuple cannot be empty. + return (0, ), (0, ) + else: + return tuple(new_tup0), tuple(new_tup1) def _get_map_for_stmt_inst(insn_id, lex_points, int_sid, out_names_sched): -- GitLab From 567c40545d5c77731d8cc3a097ee72cc3d8e12f9 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 4 Aug 2020 04:53:05 -0500 Subject: [PATCH 109/136] don't add missing dims when aligning domain for intersection in create_symbolic_map_from_tuples(), all dims will always be present by construction; rename insert_missing_dims_and_reorder_by_name()->reorder_dims_by_name() --- loopy/schedule/checker/utils.py | 46 ++++++++++++--------------------- 1 file changed, 17 insertions(+), 29 deletions(-) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index babb2b24a..3a2c7c682 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -61,12 +61,12 @@ def map_names_match_check( % (obj_map_names, dim_type, desired_names)) -def insert_missing_dims_and_reorder_by_name( +def reorder_dims_by_name( isl_set, dim_type, desired_dims_ordered): """Return an isl_set with the dimensions in the specified order. :arg isl_set: A :class:`islpy.Set` whose dimensions are - to be reordered and, if necessary, augmented with missing dimensions. + to be reordered. :arg dim_type: A :class:`islpy.dim_type`, i.e., an :class:`int`, specifying the dimension to be reordered. @@ -75,9 +75,7 @@ def insert_missing_dims_and_reorder_by_name( representing the desired dimensions in order by dimension name. :returns: An :class:`islpy.Set` matching `isl_set` with the - dimension order matching `desired_dims_ordered`, - including additional dimensions present in `desred_dims_ordered` - that are not present in `isl_set`. + dimension order matching `desired_dims_ordered`. """ @@ -92,22 +90,16 @@ def insert_missing_dims_and_reorder_by_name( new_set = isl_set.copy() for desired_idx, name in enumerate(desired_dims_ordered): - # If iname doesn't exist in set, add dim - if name not in new_set.get_var_names(dim_type): - assert False - # Insert missing dim in correct location - new_set = new_set.insert_dims( - dim_type, desired_idx, 1 - ).set_dim_name(dim_type, desired_idx, name) - else: # Iname exists in set - current_idx = new_set.find_dim_by_name(dim_type, name) - if current_idx != desired_idx: - # First move to other dim because isl is stupid - new_set = new_set.move_dims( - other_dim_type, other_dim_len, dim_type, current_idx, 1) - # Now move it where we actually want it - new_set = new_set.move_dims( - dim_type, desired_idx, other_dim_type, other_dim_len, 1) + assert name in new_set.get_var_names(dim_type) + + current_idx = new_set.find_dim_by_name(dim_type, name) + if current_idx != desired_idx: + # First move to other dim because isl is stupid + new_set = new_set.move_dims( + other_dim_type, other_dim_len, dim_type, current_idx, 1) + # Now move it where we actually want it + new_set = new_set.move_dims( + dim_type, desired_idx, other_dim_type, other_dim_len, 1) return new_set @@ -214,20 +206,16 @@ def create_symbolic_map_from_tuples( dim_type.out, 0, dim_type.in_, len(space_in_names), len(space_out_names)) - assert space_in_names == map_from_set.get_var_names( - isl.dim_type.in_) - - # If there are any dimensions in dom that are missing from - # map_from_set, we have a problem I think? - # (assertion checks this in add_missing...) - dom_with_all_inames = insert_missing_dims_and_reorder_by_name( + # Align the *out* dims of dom with the space *in_* dims + # in preparation for intersection + dom_with_set_dim_aligned = reorder_dims_by_name( dom, isl.dim_type.set, space_in_names, ) # Intersect domain with this map union_of_maps = union_of_maps.union( - map_from_set.intersect_domain(dom_with_all_inames)) + map_from_set.intersect_domain(dom_with_set_dim_aligned)) return union_of_maps -- GitLab From 3d321ae5d83592162fb5012b743ab32ac5506b18 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 4 Aug 2020 05:04:02 -0500 Subject: [PATCH 110/136] more precise docstring for reorder_dims_by_name() --- loopy/schedule/checker/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index 3a2c7c682..b3143a2ff 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -63,7 +63,8 @@ def map_names_match_check( def reorder_dims_by_name( isl_set, dim_type, desired_dims_ordered): - """Return an isl_set with the dimensions in the specified order. + """Return an isl_set with the dimensions of the specified dim_type + in the specified order. :arg isl_set: A :class:`islpy.Set` whose dimensions are to be reordered. -- GitLab From 0f1857921263d0e568ee59496a5f2480ed37e975 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 4 Aug 2020 12:35:26 -0500 Subject: [PATCH 111/136] make doctest output invalid to see if it fails ci test --- loopy/schedule/checker/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 09ffd6bde..446aeb377 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -80,7 +80,7 @@ def get_schedules_for_statement_pairs( ... [("insn_a", "insn_b")], ... ) >>> print(*schedules[("insn_a", "insn_b")], sep="\n") - [pi, pj, pk] -> { [_lp_linchk_statement = 0, i, j, k] -> [_lp_linchk_l0 = i, _lp_linchk_l1 = 0] : 0 <= i < pi and 0 <= j < pj and 0 <= k < pk } + [pi, pj, pk] -> { [_lp_linchk_statement = 777, i, j, k] -> [_lp_linchk_l0 = i, _lp_linchk_l1 = 0] : 0 <= i < pi and 0 <= j < pj and 0 <= k < pk } [pi, pj, pk] -> { [_lp_linchk_statement = 1, i, j, k] -> [_lp_linchk_l0 = i, _lp_linchk_l1 = 1] : 0 <= i < pi and 0 <= j < pj and 0 <= k < pk } """ -- GitLab From 503247dde928408b87244e150dfb13629d088268 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 4 Aug 2020 13:39:37 -0500 Subject: [PATCH 112/136] undo intentionally incorrect doctest output, also add line break to placate flake8 --- loopy/schedule/checker/__init__.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 446aeb377..55d2876da 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -80,8 +80,12 @@ def get_schedules_for_statement_pairs( ... [("insn_a", "insn_b")], ... ) >>> print(*schedules[("insn_a", "insn_b")], sep="\n") - [pi, pj, pk] -> { [_lp_linchk_statement = 777, i, j, k] -> [_lp_linchk_l0 = i, _lp_linchk_l1 = 0] : 0 <= i < pi and 0 <= j < pj and 0 <= k < pk } - [pi, pj, pk] -> { [_lp_linchk_statement = 1, i, j, k] -> [_lp_linchk_l0 = i, _lp_linchk_l1 = 1] : 0 <= i < pi and 0 <= j < pj and 0 <= k < pk } + [pi, pj, pk] -> { [_lp_linchk_statement = 0, i, j, k] -> \ + [_lp_linchk_l0 = i, _lp_linchk_l1 = 0] : \ + 0 <= i < pi and 0 <= j < pj and 0 <= k < pk } + [pi, pj, pk] -> { [_lp_linchk_statement = 1, i, j, k] -> \ + [_lp_linchk_l0 = i, _lp_linchk_l1 = 1] : \ + 0 <= i < pi and 0 <= j < pj and 0 <= k < pk } """ -- GitLab From 2504e3a5c0bd25b060448a6afde20202bc52e3b4 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 4 Aug 2020 13:58:54 -0500 Subject: [PATCH 113/136] try another approach to handling broken lines in expected doctest results --- loopy/schedule/checker/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 55d2876da..89395b198 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -81,11 +81,11 @@ def get_schedules_for_statement_pairs( ... ) >>> print(*schedules[("insn_a", "insn_b")], sep="\n") [pi, pj, pk] -> { [_lp_linchk_statement = 0, i, j, k] -> \ - [_lp_linchk_l0 = i, _lp_linchk_l1 = 0] : \ - 0 <= i < pi and 0 <= j < pj and 0 <= k < pk } +[_lp_linchk_l0 = i, _lp_linchk_l1 = 0] : \ +0 <= i < pi and 0 <= j < pj and 0 <= k < pk } [pi, pj, pk] -> { [_lp_linchk_statement = 1, i, j, k] -> \ - [_lp_linchk_l0 = i, _lp_linchk_l1 = 1] : \ - 0 <= i < pi and 0 <= j < pj and 0 <= k < pk } +[_lp_linchk_l0 = i, _lp_linchk_l1 = 1] : \ +0 <= i < pi and 0 <= j < pj and 0 <= k < pk } """ -- GitLab From 0d7742396f83c25946852a3b8c25990bd9c0e66a Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Tue, 4 Aug 2020 14:19:01 -0500 Subject: [PATCH 114/136] workaround for dumb doctest that can't handle expected output split up across lines: add line breaks to print statement --- loopy/schedule/checker/__init__.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 89395b198..bb96ebbaa 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -79,13 +79,17 @@ def get_schedules_for_statement_pairs( ... knl.linearization, ... [("insn_a", "insn_b")], ... ) - >>> print(*schedules[("insn_a", "insn_b")], sep="\n") - [pi, pj, pk] -> { [_lp_linchk_statement = 0, i, j, k] -> \ -[_lp_linchk_l0 = i, _lp_linchk_l1 = 0] : \ -0 <= i < pi and 0 <= j < pj and 0 <= k < pk } - [pi, pj, pk] -> { [_lp_linchk_statement = 1, i, j, k] -> \ -[_lp_linchk_l0 = i, _lp_linchk_l1 = 1] : \ -0 <= i < pi and 0 <= j < pj and 0 <= k < pk } + >>> # Print maps + >>> print("\n".join( + ... str(m).replace("{ ", "{\n").replace(" :", "\n:") + ... for m in schedules[("insn_a", "insn_b")] + ... )) + [pi, pj, pk] -> { + [_lp_linchk_statement = 0, i, j, k] -> [_lp_linchk_l0 = i, _lp_linchk_l1 = 0] + : 0 <= i < pi and 0 <= j < pj and 0 <= k < pk } + [pi, pj, pk] -> { + [_lp_linchk_statement = 1, i, j, k] -> [_lp_linchk_l0 = i, _lp_linchk_l1 = 1] + : 0 <= i < pi and 0 <= j < pj and 0 <= k < pk } """ -- GitLab From 049d17b4ecc7c1aa39011aaeaa55956d9ccc1e4c Mon Sep 17 00:00:00 2001 From: James Stevens Date: Fri, 28 Aug 2020 04:19:45 +0200 Subject: [PATCH 115/136] Apply 1 suggestion(s) to 1 file(s) --- loopy/schedule/checker/schedule.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 1e6e30fb7..b088c40f1 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -114,7 +114,7 @@ def generate_pairwise_schedules( # (not technically necessary if no statement was added in the # previous section; gratuitous incrementing is counteracted # in the simplification step below) - next_insn_lex_tuple[-1] = next_insn_lex_tuple[-1]+1 + next_insn_lex_tuple[-1] += 1 # Upon entering a loop, add one lex dimension for the loop variable, # add second lex dim to enumerate sections of code within new loop -- GitLab From 15f085598653d904e62d4758818b21aff010299d Mon Sep 17 00:00:00 2001 From: James Stevens Date: Fri, 28 Aug 2020 04:20:20 +0200 Subject: [PATCH 116/136] Apply 1 suggestion(s) to 1 file(s) --- loopy/schedule/checker/schedule.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index b088c40f1..bc249952a 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -44,7 +44,7 @@ __doc__ = """ LIN_CHECK_IDENTIFIER_PREFIX = "_lp_linchk_" LEX_VAR_PREFIX = "%sl" % (LIN_CHECK_IDENTIFIER_PREFIX) -STATEMENT_VAR_NAME = "%sstatement" % (LIN_CHECK_IDENTIFIER_PREFIX) +STATEMENT_VAR_NAME = "%sstmt" % (LIN_CHECK_IDENTIFIER_PREFIX) def generate_pairwise_schedules( -- GitLab From 2f583e5468b99d6b643cb7aa9d84fe09a187e03a Mon Sep 17 00:00:00 2001 From: James Stevens Date: Fri, 28 Aug 2020 04:21:01 +0200 Subject: [PATCH 117/136] Apply 1 suggestion(s) to 1 file(s) --- loopy/schedule/checker/schedule.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index bc249952a..0380bd4f0 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -30,8 +30,8 @@ __doc__ = """ .. data:: LEX_VAR_PREFIX - E.g., a prefix of "_lp_linchk_lex" might yield lexicographic dimension - variables "_lp_linchk_lex0", "_lp_linchk_lex1", "_lp_linchk_lex2". Cf. + E.g., a prefix of ``_lp_linchk_lex`` might yield lexicographic dimension + variables ``_lp_linchk_lex0``, ``_lp_linchk_lex1``, ``_lp_linchk_lex2``. Cf. :ref:`reserved-identifiers`. .. data:: STATEMENT_VAR_NAME -- GitLab From 05d57062a681bb6f0c85a91d4f88120567953005 Mon Sep 17 00:00:00 2001 From: James Stevens Date: Fri, 28 Aug 2020 04:21:22 +0200 Subject: [PATCH 118/136] Apply 1 suggestion(s) to 1 file(s) --- loopy/schedule/checker/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index bb96ebbaa..99525a983 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -46,8 +46,7 @@ def get_schedules_for_statement_pairs( process. :arg insn_id_pairs: A list of two-tuples containing pairs of instruction - identifiers, each of which is unique within a - :class:`loopy.kernel.LoopKernel`. + identifiers. :returns: A dictionary mapping each two-tuple of instruction identifiers provided in `insn_id_pairs` to a corresponding two-tuple containing two -- GitLab From 8a882e008a68bd89779053458c2b543d5fb21fb2 Mon Sep 17 00:00:00 2001 From: James Stevens Date: Fri, 28 Aug 2020 04:21:37 +0200 Subject: [PATCH 119/136] Apply 1 suggestion(s) to 1 file(s) --- loopy/schedule/checker/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 99525a983..e41215897 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -45,7 +45,7 @@ def get_schedules_for_statement_pairs( kernel since this function may be used during the linearization process. - :arg insn_id_pairs: A list of two-tuples containing pairs of instruction + :arg insn_id_pairs: A list containing pairs of instruction identifiers. :returns: A dictionary mapping each two-tuple of instruction identifiers -- GitLab From 0985a6b2bbfb569ee4f1f2e4c5a3f9d403114efe Mon Sep 17 00:00:00 2001 From: James Stevens Date: Fri, 28 Aug 2020 04:21:59 +0200 Subject: [PATCH 120/136] Apply 1 suggestion(s) to 1 file(s) --- loopy/schedule/checker/schedule.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 0380bd4f0..a438ca1b6 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -137,7 +137,7 @@ def generate_pairwise_schedules( # (not technically necessary if no statement was added in the # previous section; gratuitous incrementing is counteracted # in the simplification step below) - next_insn_lex_tuple[-1] = next_insn_lex_tuple[-1]+1 + next_insn_lex_tuple[-1] += 1 elif isinstance(linearization_item, (RunInstruction, Barrier)): from loopy.schedule.checker.utils import ( -- GitLab From 88557eedf4e17331b7d7726eb1154479920b357e Mon Sep 17 00:00:00 2001 From: James Stevens Date: Fri, 28 Aug 2020 04:22:11 +0200 Subject: [PATCH 121/136] Apply 1 suggestion(s) to 1 file(s) --- loopy/schedule/checker/schedule.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index a438ca1b6..6d32f36b9 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -160,7 +160,7 @@ def generate_pairwise_schedules( # Only process listed insns, otherwise ignore if lp_insn_id in all_insn_ids: # Add item to stmt_instances - stmt_instances[lp_insn_id] = tuple(next_insn_lex_tuple[:]) + stmt_instances[lp_insn_id] = tuple(next_insn_lex_tuple) # Increment lex dim val enumerating items in current section of code next_insn_lex_tuple[-1] = next_insn_lex_tuple[-1] + 1 -- GitLab From 5f9d4295a91e51507726b357001598c1a53f2f0c Mon Sep 17 00:00:00 2001 From: James Stevens Date: Fri, 28 Aug 2020 04:22:17 +0200 Subject: [PATCH 122/136] Apply 1 suggestion(s) to 1 file(s) --- loopy/schedule/checker/schedule.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 6d32f36b9..dec9cf24a 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -163,7 +163,7 @@ def generate_pairwise_schedules( stmt_instances[lp_insn_id] = tuple(next_insn_lex_tuple) # Increment lex dim val enumerating items in current section of code - next_insn_lex_tuple[-1] = next_insn_lex_tuple[-1] + 1 + next_insn_lex_tuple[-1] += 1 else: from loopy.schedule import (CallKernel, ReturnFromKernel) -- GitLab From 0b1994113c394efcd2fc59f7f8b0ee6c9bc91962 Mon Sep 17 00:00:00 2001 From: James Stevens Date: Fri, 28 Aug 2020 04:23:00 +0200 Subject: [PATCH 123/136] Apply 1 suggestion(s) to 1 file(s) --- loopy/schedule/checker/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index b3143a2ff..92b471f6d 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -37,7 +37,7 @@ def add_dims_to_isl_set(isl_set, dim_type, names, new_idx_start): return new_set -def map_names_match_check( +def check_that_map_names_match( obj_map, desired_names, dim_type, -- GitLab From a6ab09d4c2faa7aea81f15b16a54ed8153e93001 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Thu, 27 Aug 2020 21:32:42 -0500 Subject: [PATCH 124/136] change _lp_linchk_statement->_lp_linchk_stmt in doctest after renaming of module prefix --- loopy/schedule/checker/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index e41215897..0935e22f0 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -84,10 +84,10 @@ def get_schedules_for_statement_pairs( ... for m in schedules[("insn_a", "insn_b")] ... )) [pi, pj, pk] -> { - [_lp_linchk_statement = 0, i, j, k] -> [_lp_linchk_l0 = i, _lp_linchk_l1 = 0] + [_lp_linchk_stmt = 0, i, j, k] -> [_lp_linchk_l0 = i, _lp_linchk_l1 = 0] : 0 <= i < pi and 0 <= j < pj and 0 <= k < pk } [pi, pj, pk] -> { - [_lp_linchk_statement = 1, i, j, k] -> [_lp_linchk_l0 = i, _lp_linchk_l1 = 1] + [_lp_linchk_stmt = 1, i, j, k] -> [_lp_linchk_l0 = i, _lp_linchk_l1 = 1] : 0 <= i < pi and 0 <= j < pj and 0 <= k < pk } """ -- GitLab From 852ba31431b87859fdf0c58e7077417a0608a0f5 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Thu, 27 Aug 2020 21:34:56 -0500 Subject: [PATCH 125/136] change map_names_match_check->check_that_map_names_match after renaming of function --- loopy/schedule/checker/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index 92b471f6d..548ef2db2 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -80,7 +80,7 @@ def reorder_dims_by_name( """ - map_names_match_check( + check_that_map_names_match( isl_set, desired_dims_ordered, dim_type, assert_subset=True, assert_permutation=False) @@ -109,7 +109,7 @@ def ensure_dim_names_match_and_align(obj_map, tgt_map): # first make sure names match for dt in [isl.dim_type.in_, isl.dim_type.out, isl.dim_type.param]: - map_names_match_check( + check_that_map_names_match( obj_map, tgt_map.get_var_names(dt), dt, assert_permutation=True) -- GitLab From 88f23ead8694360d35c6b877bbc3823d18fd763d Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Thu, 27 Aug 2020 21:42:42 -0500 Subject: [PATCH 126/136] rephrase docstring for linearization_items argument (the part about a partial list of linearization items) --- loopy/schedule/checker/__init__.py | 6 +++--- loopy/schedule/checker/schedule.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 0935e22f0..5572b03e8 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -41,9 +41,9 @@ def get_schedules_for_statement_pairs( :arg linearization_items: A list of :class:`loopy.schedule.ScheduleItem` (to be renamed to `loopy.schedule.LinearizationItem`) containing all linearization items for which pairwise schedules will be - created. This list may be a *partial* linearization for a - kernel since this function may be used during the linearization - process. + created. To allow usage of this routine during linearization, a + truncated (i.e. partial) linearization may be passed through this + argument. :arg insn_id_pairs: A list containing pairs of instruction identifiers. diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index dec9cf24a..4b1b4e07c 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -67,9 +67,9 @@ def generate_pairwise_schedules( :arg linearization_items: A list of :class:`loopy.schedule.ScheduleItem` (to be renamed to `loopy.schedule.LinearizationItem`) containing all linearization items for which pairwise schedules will be - created. This list may be a *partial* linearization for a - kernel since this function may be used during the linearization - process. + created. To allow usage of this routine during linearization, a + truncated (i.e. partial) linearization may be passed through this + argument. :arg insn_id_pairs: A list of two-tuples containing pairs of instruction identifiers, each of which is unique within a -- GitLab From d72e65375cae25e1a99252feabbcaf8096af8abc Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Thu, 27 Aug 2020 22:18:16 -0500 Subject: [PATCH 127/136] assert that all concurrent EnterLoop inames are tagged Vec or ILP, and don't warn if any such inames are found --- loopy/schedule/checker/__init__.py | 13 +++++++------ loopy/schedule/checker/schedule.py | 3 ++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 5572b03e8..3bfb3822a 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -113,12 +113,13 @@ def get_schedules_for_statement_pairs( conc_inames, _ = partition_inames_by_concurrency(knl) enterloop_inames = get_EnterLoop_inames(linearization_items) conc_loop_inames = conc_inames & enterloop_inames - if conc_loop_inames: - from warnings import warn - warn( - "get_schedule_for_statement_pair encountered EnterLoop for inames %s " - "with ConcurrentTag(s) in linearization for kernel %s. " - "Ignoring these loops." % (conc_loop_inames, knl.name)) + + # The only concurrent EnterLoop inames should be Vec and ILP + from loopy.kernel.data import (VectorizeTag, IlpBaseTag) + for conc_iname in conc_loop_inames: + assert any( + isinstance(tag, (VectorizeTag, IlpBaseTag)) + for tag in knl.iname_to_tags[conc_iname]) # }}} diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 4b1b4e07c..15440c520 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -77,7 +77,8 @@ def generate_pairwise_schedules( :arg loops_to_ignore: A set of inames that will be ignored when determining the relative ordering of statements. This will typically - contain concurrent inames. + contain concurrent inames tagged with the ``vec`` or ``ilp`` array + access tags. :returns: A dictionary mapping each two-tuple of instruction identifiers provided in `insn_id_pairs` to a corresponding two-tuple containing two -- GitLab From 559f7781ef63128e26301ac8f138b9497d337daf Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Thu, 27 Aug 2020 22:28:10 -0500 Subject: [PATCH 128/136] simplify phrasing of insn_id_pairs arg description (to match phrasing in generate_pairwise_schedules()) --- loopy/schedule/checker/schedule.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index 15440c520..aeac8bdfc 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -71,9 +71,7 @@ def generate_pairwise_schedules( truncated (i.e. partial) linearization may be passed through this argument. - :arg insn_id_pairs: A list of two-tuples containing pairs of instruction - identifiers, each of which is unique within a - :class:`loopy.kernel.LoopKernel`. + :arg insn_id_pairs: A list containing pairs of instruction identifiers. :arg loops_to_ignore: A set of inames that will be ignored when determining the relative ordering of statements. This will typically -- GitLab From b992340916ee2a46a4f16316c84959ea2a758cc5 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Thu, 27 Aug 2020 22:36:23 -0500 Subject: [PATCH 129/136] move function defs for _pad_tuple_with_zeros() and _simplify_lex_dims() outside of generate_pairwise_schedules() --- loopy/schedule/checker/schedule.py | 114 +++++++++++++++-------------- 1 file changed, 58 insertions(+), 56 deletions(-) diff --git a/loopy/schedule/checker/schedule.py b/loopy/schedule/checker/schedule.py index aeac8bdfc..bc71df5d8 100644 --- a/loopy/schedule/checker/schedule.py +++ b/loopy/schedule/checker/schedule.py @@ -47,6 +47,64 @@ LEX_VAR_PREFIX = "%sl" % (LIN_CHECK_IDENTIFIER_PREFIX) STATEMENT_VAR_NAME = "%sstmt" % (LIN_CHECK_IDENTIFIER_PREFIX) +def _pad_tuple_with_zeros(tup, desired_length): + return tup[:] + tuple([0]*(desired_length-len(tup))) + + +def _simplify_lex_dims(tup0, tup1): + """Simplify a pair of lex tuples in order to reduce the complexity of + resulting maps. Remove lex tuple dimensions with matching integer values + since these do not provide information on relative ordering. Once a + dimension is found where both tuples have non-matching integer values, + remove any faster-updating lex dimensions since they are not necessary + to specify a relative ordering. + """ + + new_tup0 = [] + new_tup1 = [] + + # Loop over dims from slowest updating to fastest + for d0, d1 in zip(tup0, tup1): + if isinstance(d0, int) and isinstance(d1, int): + + # Both vals are ints for this dim + if d0 == d1: + # Do not keep this dim + continue + elif d0 > d1: + # These ints inform us about the relative ordering of + # two statements. While their values may be larger than 1 in + # the lexicographic ordering describing a larger set of + # statements, in a pairwise schedule, only ints 0 and 1 are + # necessary to specify relative order. To keep the pairwise + # schedules as simple and comprehensible as possible, use only + # integers 0 and 1 to specify this relative ordering. + # (doesn't take much extra time since we are already going + # through these to remove unnecessary lex tuple dims) + new_tup0.append(1) + new_tup1.append(0) + + # No further dims needed to fully specify ordering + break + else: # d1 > d0 + new_tup0.append(0) + new_tup1.append(1) + + # No further dims needed to fully specify ordering + break + else: + # Keep this dim without modifying + new_tup0.append(d0) + new_tup1.append(d1) + + if len(new_tup0) == 0: + # Statements map to the exact same point(s) in the lex ordering, + # which is okay, but to represent this, our lex tuple cannot be empty. + return (0, ), (0, ) + else: + return tuple(new_tup0), tuple(new_tup1) + + def generate_pairwise_schedules( knl, linearization_items, @@ -181,62 +239,6 @@ def generate_pairwise_schedules( add_dims_to_isl_set, ) - def _pad_tuple_with_zeros(tup, desired_length): - return tup[:] + tuple([0]*(desired_length-len(tup))) - - def _simplify_lex_dims(tup0, tup1): - """Simplify a pair of lex tuples in order to reduce the complexity of - resulting maps. Remove lex tuple dimensions with matching integer values - since these do not provide information on relative ordering. Once a - dimension is found where both tuples have non-matching integer values, - remove any faster-updating lex dimensions since they are not necessary - to specify a relative ordering. - """ - - new_tup0 = [] - new_tup1 = [] - - # Loop over dims from slowest updating to fastest - for d0, d1 in zip(tup0, tup1): - if isinstance(d0, int) and isinstance(d1, int): - - # Both vals are ints for this dim - if d0 == d1: - # Do not keep this dim - continue - elif d0 > d1: - # These ints inform us about the relative ordering of - # two statements. While their values may be larger than 1 in - # the lexicographic ordering describing a larger set of - # statements, in a pairwise schedule, only ints 0 and 1 are - # necessary to specify relative order. To keep the pairwise - # schedules as simple and comprehensible as possible, use only - # integers 0 and 1 to specify this relative ordering. - # (doesn't take much extra time since we are already going - # through these to remove unnecessary lex tuple dims) - new_tup0.append(1) - new_tup1.append(0) - - # No further dims needed to fully specify ordering - break - else: # d1 > d0 - new_tup0.append(0) - new_tup1.append(1) - - # No further dims needed to fully specify ordering - break - else: - # Keep this dim without modifying - new_tup0.append(d0) - new_tup1.append(d1) - - if len(new_tup0) == 0: - # Statements map to the exact same point(s) in the lex ordering, - # which is okay, but to represent this, our lex tuple cannot be empty. - return (0, ), (0, ) - else: - return tuple(new_tup0), tuple(new_tup1) - def _get_map_for_stmt_inst(insn_id, lex_points, int_sid, out_names_sched): # Get inames domain for statement instance (a BasicSet) -- GitLab From 0921a33b5ec57fe2779407b5b02ea2904f1eca54 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Thu, 27 Aug 2020 22:46:11 -0500 Subject: [PATCH 130/136] remove faulthandler stuff --- test/test_linearization_checker.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/test/test_linearization_checker.py b/test/test_linearization_checker.py index 6d0fd3abf..ade47f0c6 100644 --- a/test/test_linearization_checker.py +++ b/test/test_linearization_checker.py @@ -42,13 +42,6 @@ from loopy.schedule.checker.schedule import ( logger = logging.getLogger(__name__) -try: - import faulthandler -except ImportError: - pass -else: - faulthandler.enable() - def test_lexschedule_creation(): import islpy as isl -- GitLab From 237e7d69e000f70ab3321480d244bcd20d164930 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Thu, 27 Aug 2020 22:46:55 -0500 Subject: [PATCH 131/136] remove redundant lang_version --- test/test_linearization_checker.py | 1 - 1 file changed, 1 deletion(-) diff --git a/test/test_linearization_checker.py b/test/test_linearization_checker.py index ade47f0c6..56e1c0722 100644 --- a/test/test_linearization_checker.py +++ b/test/test_linearization_checker.py @@ -76,7 +76,6 @@ def test_lexschedule_creation(): """, name="example", assumptions="pi,pj,pk,pt >= 1", - lang_version=(2018, 2) ) knl = lp.add_and_infer_dtypes( knl, -- GitLab From 74f9ee40732f0bed15d53e13cb1c471c589843bd Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Thu, 27 Aug 2020 22:59:11 -0500 Subject: [PATCH 132/136] test_lexschedule_creation(), make kernel instruction/loop order deterministic and remove machinery for handling multiple potential orderings --- test/test_linearization_checker.py | 230 ++++++++++++----------------- 1 file changed, 92 insertions(+), 138 deletions(-) diff --git a/test/test_linearization_checker.py b/test/test_linearization_checker.py index 56e1c0722..3c927a9ce 100644 --- a/test/test_linearization_checker.py +++ b/test/test_linearization_checker.py @@ -53,6 +53,8 @@ def test_lexschedule_creation(): ) # example kernel + # insn_c depends on insn_b only to create deterministic order + # insn_d depends on insn_c only to create deterministic order knl = lp.make_kernel( [ "{[i]: 0<=i { [%s=0, i, k] -> [%s] : 0 <= i < pi and 0 <= k < pk }" - % ( - STATEMENT_VAR_NAME, - _lex_space_string([a_lex_idx, ]), - ) - ) - sched_map_before_expected = ensure_dim_names_match_and_align( - sched_map_before_expected, sched_map_before) - - sched_map_after_expected = isl.Map( - "[pt] -> { [%s=1, t] -> [%s] : 0 <= t < pt }" - % ( - STATEMENT_VAR_NAME, - _lex_space_string([d_lex_idx, ]), - ) + sched_map_before_expected = isl.Map( + "[pi, pk] -> { [%s=0, i, k] -> [%s] : 0 <= i < pi and 0 <= k < pk }" + % ( + STATEMENT_VAR_NAME, + _lex_space_string([0, ]), ) - sched_map_after_expected = ensure_dim_names_match_and_align( - sched_map_after_expected, sched_map_after) + ) + sched_map_before_expected = ensure_dim_names_match_and_align( + sched_map_before_expected, sched_map_before) - assert sched_map_before == sched_map_before_expected - assert sched_map_after == sched_map_after_expected + sched_map_after_expected = isl.Map( + "[pt] -> { [%s=1, t] -> [%s] : 0 <= t < pt }" + % ( + STATEMENT_VAR_NAME, + _lex_space_string([1, ]), + ) + ) + sched_map_after_expected = ensure_dim_names_match_and_align( + sched_map_after_expected, sched_map_after) - if linearized_insn_ord.index("insn_a") < linearized_insn_ord.index("insn_d"): - # insn_a was linearized first, check schedule accordingly - perform_insn_ad_checks_with(0, 1) - else: - # insn_d was linearized first, check schedule accordingly - perform_insn_ad_checks_with(1, 0) + assert sched_map_before == sched_map_before_expected + assert sched_map_after == sched_map_after_expected # ------------------------------------------------------------------------------ # Relationship between insn_b and insn_c --------------------------------------- - # insn_b and insn_c could have been linearized in either order - def perform_insn_bc_checks_with(b_lex_idx, c_lex_idx): - # Get two maps - sched_map_before, sched_map_after = sched_maps[("insn_b", "insn_c")] + # Get two maps + sched_map_before, sched_map_after = sched_maps[("insn_b", "insn_c")] - # Create expected maps, align, compare + # Create expected maps, align, compare - sched_map_before_expected = isl.Map( - "[pi, pj] -> { [%s=0, i, j] -> [%s] : 0 <= i < pi and 0 <= j < pj }" - % ( - STATEMENT_VAR_NAME, - _lex_space_string(["i", "j", b_lex_idx]), - ) - ) - sched_map_before_expected = ensure_dim_names_match_and_align( - sched_map_before_expected, sched_map_before) - - sched_map_after_expected = isl.Map( - "[pi, pj] -> { [%s=1, i, j] -> [%s] : 0 <= i < pi and 0 <= j < pj }" - % ( - STATEMENT_VAR_NAME, - _lex_space_string(["i", "j", c_lex_idx]), - ) + sched_map_before_expected = isl.Map( + "[pi, pj] -> { [%s=0, i, j] -> [%s] : 0 <= i < pi and 0 <= j < pj }" + % ( + STATEMENT_VAR_NAME, + _lex_space_string(["i", "j", 0]), ) - sched_map_after_expected = ensure_dim_names_match_and_align( - sched_map_after_expected, sched_map_after) + ) + sched_map_before_expected = ensure_dim_names_match_and_align( + sched_map_before_expected, sched_map_before) - assert sched_map_before == sched_map_before_expected - assert sched_map_after == sched_map_after_expected + sched_map_after_expected = isl.Map( + "[pi, pj] -> { [%s=1, i, j] -> [%s] : 0 <= i < pi and 0 <= j < pj }" + % ( + STATEMENT_VAR_NAME, + _lex_space_string(["i", "j", 1]), + ) + ) + sched_map_after_expected = ensure_dim_names_match_and_align( + sched_map_after_expected, sched_map_after) - if linearized_insn_ord.index("insn_b") < linearized_insn_ord.index("insn_c"): - # insn_b was linearized first, check schedule accordingly - perform_insn_bc_checks_with(0, 1) - else: - # insn_c was linearized first, check schedule accordingly - perform_insn_bc_checks_with(1, 0) + assert sched_map_before == sched_map_before_expected + assert sched_map_after == sched_map_after_expected # ------------------------------------------------------------------------------ # Relationship between insn_b and insn_d --------------------------------------- - # insn_b and insn_d could have been linearized in either order - # (i loop could be before or after t loop) - def perform_insn_bd_checks_with(b_lex_idx, d_lex_idx): - # Get two maps - sched_map_before, sched_map_after = sched_maps[("insn_b", "insn_d")] + # Get two maps + sched_map_before, sched_map_after = sched_maps[("insn_b", "insn_d")] - # Create expected maps, align, compare + # Create expected maps, align, compare - sched_map_before_expected = isl.Map( - "[pi, pj] -> { [%s=0, i, j] -> [%s] : 0 <= i < pi and 0 <= j < pj }" - % ( - STATEMENT_VAR_NAME, - _lex_space_string([b_lex_idx, ]), - ) - ) - sched_map_before_expected = ensure_dim_names_match_and_align( - sched_map_before_expected, sched_map_before) - - sched_map_after_expected = isl.Map( - "[pt] -> { [%s=1, t] -> [%s] : 0 <= t < pt }" - % ( - STATEMENT_VAR_NAME, - _lex_space_string([d_lex_idx, ]), - ) + sched_map_before_expected = isl.Map( + "[pi, pj] -> { [%s=0, i, j] -> [%s] : 0 <= i < pi and 0 <= j < pj }" + % ( + STATEMENT_VAR_NAME, + _lex_space_string([0, ]), ) - sched_map_after_expected = ensure_dim_names_match_and_align( - sched_map_after_expected, sched_map_after) + ) + sched_map_before_expected = ensure_dim_names_match_and_align( + sched_map_before_expected, sched_map_before) - assert sched_map_before == sched_map_before_expected - assert sched_map_after == sched_map_after_expected + sched_map_after_expected = isl.Map( + "[pt] -> { [%s=1, t] -> [%s] : 0 <= t < pt }" + % ( + STATEMENT_VAR_NAME, + _lex_space_string([1, ]), + ) + ) + sched_map_after_expected = ensure_dim_names_match_and_align( + sched_map_after_expected, sched_map_after) - if linearized_insn_ord.index("insn_b") < linearized_insn_ord.index("insn_d"): - # insn_b was linearized first, check schedule accordingly - perform_insn_bd_checks_with(0, 1) - else: - # insn_d was linearized first, check schedule accordingly - perform_insn_bd_checks_with(1, 0) + assert sched_map_before == sched_map_before_expected + assert sched_map_after == sched_map_after_expected # ------------------------------------------------------------------------------ # Relationship between insn_c and insn_d --------------------------------------- - # insn_c and insn_d could have been linearized in either order - # (i loop could be before or after t loop) - def perform_insn_cd_checks_with(c_lex_idx, d_lex_idx): - # Get two maps - sched_map_before, sched_map_after = sched_maps[("insn_c", "insn_d")] + # Get two maps + sched_map_before, sched_map_after = sched_maps[("insn_c", "insn_d")] - # Create expected maps, align, compare + # Create expected maps, align, compare - sched_map_before_expected = isl.Map( - "[pi, pj] -> { [%s=0, i, j] -> [%s] : 0 <= i < pi and 0 <= j < pj }" - % ( - STATEMENT_VAR_NAME, - _lex_space_string([c_lex_idx, ]), - ) - ) - sched_map_before_expected = ensure_dim_names_match_and_align( - sched_map_before_expected, sched_map_before) - - sched_map_after_expected = isl.Map( - "[pt] -> { [%s=1, t] -> [%s] : 0 <= t < pt }" - % ( - STATEMENT_VAR_NAME, - _lex_space_string([d_lex_idx, ]), - ) + sched_map_before_expected = isl.Map( + "[pi, pj] -> { [%s=0, i, j] -> [%s] : 0 <= i < pi and 0 <= j < pj }" + % ( + STATEMENT_VAR_NAME, + _lex_space_string([0, ]), ) - sched_map_after_expected = ensure_dim_names_match_and_align( - sched_map_after_expected, sched_map_after) + ) + sched_map_before_expected = ensure_dim_names_match_and_align( + sched_map_before_expected, sched_map_before) - assert sched_map_before == sched_map_before_expected - assert sched_map_after == sched_map_after_expected + sched_map_after_expected = isl.Map( + "[pt] -> { [%s=1, t] -> [%s] : 0 <= t < pt }" + % ( + STATEMENT_VAR_NAME, + _lex_space_string([1, ]), + ) + ) + sched_map_after_expected = ensure_dim_names_match_and_align( + sched_map_after_expected, sched_map_after) - if linearized_insn_ord.index("insn_c") < linearized_insn_ord.index("insn_d"): - # insn_c was linearized first, check schedule accordingly - perform_insn_cd_checks_with(0, 1) - else: - # insn_d was linearized first, check schedule accordingly - perform_insn_cd_checks_with(1, 0) + assert sched_map_before == sched_map_before_expected + assert sched_map_after == sched_map_after_expected if __name__ == "__main__": -- GitLab From 7d34e958233ffc742a147e5e47069b17f0a6e758 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Wed, 2 Sep 2020 08:42:16 -0500 Subject: [PATCH 133/136] replace call to check_that_map_names_match() with equivalent assertion in reorder_dims_by_name() --- loopy/schedule/checker/utils.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index 548ef2db2..36851de44 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -80,10 +80,7 @@ def reorder_dims_by_name( """ - check_that_map_names_match( - isl_set, desired_dims_ordered, dim_type, - assert_subset=True, assert_permutation=False) - + assert set(isl_set.get_var_names(dim_type)).issubset(desired_dims_ordered) assert dim_type != isl.dim_type.param other_dim_type = isl.dim_type.param -- GitLab From 6f6d708fb291d12a69cc5fb9362a5d2a70ceeb46 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Wed, 2 Sep 2020 08:59:49 -0500 Subject: [PATCH 134/136] make stronger assertion in reorder_dims_by_name (just assert that sets match) --- loopy/schedule/checker/utils.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index 36851de44..0953454aa 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -80,15 +80,14 @@ def reorder_dims_by_name( """ - assert set(isl_set.get_var_names(dim_type)).issubset(desired_dims_ordered) assert dim_type != isl.dim_type.param + assert set(isl_set.get_var_names(dim_type)) == set(desired_dims_ordered) other_dim_type = isl.dim_type.param other_dim_len = len(isl_set.get_var_names(other_dim_type)) new_set = isl_set.copy() for desired_idx, name in enumerate(desired_dims_ordered): - assert name in new_set.get_var_names(dim_type) current_idx = new_set.find_dim_by_name(dim_type, name) if current_idx != desired_idx: -- GitLab From ee4faf0f82a867f7b76586b5baefe5f234845bd0 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Wed, 2 Sep 2020 09:12:00 -0500 Subject: [PATCH 135/136] remove check_that_map_names_match(), replace function call with assertion --- loopy/schedule/checker/utils.py | 35 ++++----------------------------- 1 file changed, 4 insertions(+), 31 deletions(-) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index 0953454aa..8e2a82a01 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -37,30 +37,6 @@ def add_dims_to_isl_set(isl_set, dim_type, names, new_idx_start): return new_set -def check_that_map_names_match( - obj_map, - desired_names, - dim_type, - assert_subset=True, - assert_permutation=True, - ): - """Raise an error if names of the specified map dimension do not match - the desired names - """ - - obj_map_names = obj_map.space.get_var_names(dim_type) - if assert_permutation: - if not set(obj_map_names) == set(desired_names): - raise ValueError( - "Set of map names %s for dim %s does not match target set %s" - % (obj_map_names, dim_type, desired_names)) - elif assert_subset: - if not set(obj_map_names).issubset(desired_names): - raise ValueError( - "Map names %s for dim %s are not a subset of target names %s" - % (obj_map_names, dim_type, desired_names)) - - def reorder_dims_by_name( isl_set, dim_type, desired_dims_ordered): """Return an isl_set with the dimensions of the specified dim_type @@ -104,14 +80,11 @@ def reorder_dims_by_name( def ensure_dim_names_match_and_align(obj_map, tgt_map): # first make sure names match - for dt in [isl.dim_type.in_, isl.dim_type.out, isl.dim_type.param]: - check_that_map_names_match( - obj_map, tgt_map.get_var_names(dt), dt, - assert_permutation=True) - - aligned_obj_map = isl.align_spaces(obj_map, tgt_map) + assert all( + set(obj_map.get_var_names(dt)) == set(tgt_map.get_var_names(dt)) + for dt in [isl.dim_type.in_, isl.dim_type.out, isl.dim_type.param]) - return aligned_obj_map + return isl.align_spaces(obj_map, tgt_map) def sorted_union_of_names_in_isl_sets( -- GitLab From b8edba90e6ec31df28dc62db1cc79aedd60237c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Kl=C3=B6ckner?= Date: Fri, 4 Sep 2020 06:41:00 +0200 Subject: [PATCH 136/136] Apply 1 suggestion(s) to 1 file(s) --- loopy/schedule/checker/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/loopy/schedule/checker/__init__.py b/loopy/schedule/checker/__init__.py index 3bfb3822a..f9e9933c6 100644 --- a/loopy/schedule/checker/__init__.py +++ b/loopy/schedule/checker/__init__.py @@ -117,6 +117,8 @@ def get_schedules_for_statement_pairs( # The only concurrent EnterLoop inames should be Vec and ILP from loopy.kernel.data import (VectorizeTag, IlpBaseTag) for conc_iname in conc_loop_inames: + # Assert that there exists an ilp or vectorize tag (out of the + # potentially multiple other tags on this concurrent iname). assert any( isinstance(tag, (VectorizeTag, IlpBaseTag)) for tag in knl.iname_to_tags[conc_iname]) -- GitLab