From 7fbc7af440e37205dad8d7400134acc730f53912 Mon Sep 17 00:00:00 2001 From: "[6~" Date: Tue, 12 Nov 2019 22:05:06 -0600 Subject: [PATCH 01/24] Add wave equation solver on the way to diamond tiling demo --- test/test_transform.py | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/test/test_transform.py b/test/test_transform.py index cdc0c14b8..0906c9b34 100644 --- a/test/test_transform.py +++ b/test/test_transform.py @@ -552,7 +552,6 @@ def test_split_iname_only_if_in_within(): def test_nested_substs_in_insns(ctx_factory): ctx = ctx_factory() - import loopy as lp ref_knl = lp.make_kernel( "{[i]: 0<=i<10}", @@ -570,6 +569,37 @@ def test_nested_substs_in_insns(ctx_factory): lp.auto_test_vs_ref(ref_knl, ctx, knl) +def test_diamond_tiling(ctx_factory): + ctx = ctx_factory() + queue = cl.CommandQueue(ctx) + + ref_knl = lp.make_kernel( + "[nx,nt] -> {[ix, it]: 1<=ix 1: exec(sys.argv[1]) From af822259a1be28cf30f710fe0bbd4bf731ef54b5 Mon Sep 17 00:00:00 2001 From: "[6~" Date: Wed, 13 Nov 2019 00:56:16 -0600 Subject: [PATCH 02/24] Add initial prototype of map_domain and (currently broken) test of diamond tiling --- loopy/__init__.py | 4 +- loopy/transform/iname.py | 234 +++++++++++++++++++++++++++++++++++++++ test/test_transform.py | 30 ++++- 3 files changed, 263 insertions(+), 5 deletions(-) diff --git a/loopy/__init__.py b/loopy/__init__.py index b60de6e2d..f8a43df6d 100644 --- a/loopy/__init__.py +++ b/loopy/__init__.py @@ -78,7 +78,7 @@ affine_map_inames, find_unused_axis_tag, make_reduction_inames_unique, has_schedulable_iname_nesting, get_iname_duplication_options, - add_inames_to_insn) + add_inames_to_insn, map_domain) from loopy.transform.instruction import ( find_instructions, map_instructions, @@ -195,7 +195,7 @@ "affine_map_inames", "find_unused_axis_tag", "make_reduction_inames_unique", "has_schedulable_iname_nesting", "get_iname_duplication_options", - "add_inames_to_insn", + "add_inames_to_insn", "map_domain", "add_prefetch", "change_arg_to_image", "tag_array_axes", "tag_data_axes", diff --git a/loopy/transform/iname.py b/loopy/transform/iname.py index 96c8252ef..e627604c1 100644 --- a/loopy/transform/iname.py +++ b/loopy/transform/iname.py @@ -1759,4 +1759,238 @@ def add_inames_to_insn(knl, inames, insn_match): # }}} +# {{{ map_domain + +class _MapDomainMapper(RuleAwareIdentityMapper): + def __init__(self, rule_mapping_context, within, new_inames, substitutions): + super(_MapDomainMapper, self).__init__(rule_mapping_context) + + self.within = within + + self.old_inames = frozenset(substitutions) + self.new_inames = new_inames + + self.substitutions = substitutions + + def map_reduction(self, expr, expn_state): + overlap = frozenset(expr.inames) & self.old_inames + if (overlap + and self.split_iname not in expn_state.arg_context + and self.within( + expn_state.kernel, + expn_state.instruction)): + # FIXME + if len(overlap) != len(self.old_inames): + raise LoopyError(...) + + raise NotImplementedError("reductions") + new_inames = list(expr.inames) + new_inames.remove(self.split_iname) + new_inames.extend([self.outer_iname, self.inner_iname]) + + from loopy.symbolic import Reduction + return Reduction(expr.operation, tuple(new_inames), + self.rec(expr.expr, expn_state), + expr.allow_simultaneous) + else: + return super(_MapDomainMapper, self).map_reduction(expr, expn_state) + + def map_variable(self, expr, expn_state): + if (expr.name in self.old_inames + and expr.name not in expn_state.arg_context + and self.within( + expn_state.kernel, + expn_state.instruction)): + return self.substitutions[expr.name] + else: + return super(_MapDomainMapper, self).map_variable(expr, expn_state) + + +def _find_aff_subst_from_map(iname, isl_map): + if not isinstance(isl_map, isl.BasicMap): + raise RuntimeError("isl_map must be a BasicMap") + + dt, dim_idx = isl_map.get_var_dict()[iname] + + assert dt == dim_type.in_ + + # Force isl to solve for only this iname on its side of the map, by + # projecting out all other "in" variables. + isl_map = isl_map.project_out(dt, dim_idx+1, isl_map.dim(dt)-(dim_idx+1)) + isl_map = isl_map.project_out(dt, 0, dim_idx) + dim_idx = 0 + + # Convert map to set to avoid "domain of affine expression should be a set". + # The old "in" variable will be the last of the out_dims. + new_dim_idx = isl_map.dim(dim_type.out) + isl_map = isl_map.move_dims( + dim_type.out, isl_map.dim(dim_type.out), + dt, dim_idx, 1) + isl_map = isl_map.range() # now a set + dt = dim_type.set + dim_idx = new_dim_idx + del new_dim_idx + + for cns in isl_map.get_constraints(): + if cns.is_equality() and cns.involves_dims(dt, dim_idx, 1): + coeff = cns.get_coefficient_val(dt, dim_idx) + cns_zeroed = cns.set_coefficient_val(dt, dim_idx, 0) + if cns_zeroed.involves_dims(dt, dim_idx, 1): + # not suitable, constraint still involves dim, perhaps in a div + continue + + if coeff.is_one(): + return -cns_zeroed.get_aff() + elif coeff.is_negone(): + return cns_zeroed.get_aff() + else: + # not suitable, coefficient does not have unit coefficient + continue + + raise LoopyError("no suitable equation for '%s' found" % iname) + + +def map_domain(kernel, isl_map, within=None): + # FIXME: Express _split_iname_backend in terms of this + # Missing/deleted for now: + # - slab processing + # - priorities processing + # FIXME: Process priorities + # FIXME: Express affine_map_inames in terms of this, deprecate + # FIXME: Document + + # FIXME: Support within + + # {{{ within processing (disabled for now) + if within is not None: + raise NotImplementedError("within") + + from loopy.match import parse_match + within = parse_match(within) + + # {{{ return the same kernel if no kernel matches + + def _do_not_transform_if_no_within_matches(): + for insn in kernel.instructions: + if within(kernel, insn): + return + + return kernel + + _do_not_transform_if_no_within_matches() + + # }}} + + # }}} + + if not isl_map.is_bijective(): + raise LoopyError("isl_map must be bijective") + + new_inames = frozenset(isl_map.get_var_dict(dim_type.out)) + old_inames = frozenset(isl_map.get_var_dict(dim_type.in_)) + + # {{{ solve for representation of old inames in terms of new + + substitutions = {} + var_substitutions = {} + applied_iname_rewrites = kernel.applied_iname_rewrites[:] + + from loopy.symbolic import aff_to_expr + from pymbolic import var + for iname in old_inames: + substitutions[iname] = aff_to_expr( + _find_aff_subst_from_map(iname, isl_map)) + var_substitutions[var(iname)] = aff_to_expr( + _find_aff_subst_from_map(iname, isl_map)) + + applied_iname_rewrites.append(var_substitutions) + del var_substitutions + + # }}} + + def process_set(s): + var_dict = s.get_var_dict() + + overlap = old_inames & frozenset(var_dict) + if overlap and len(overlap) != len(old_inames): + raise LoopyError("loop domain '%s' involves a part " + "of the map domain inames. Domains must " + "either involve all or none of the map domain " + "inames." % s) + + # {{{ align dims of isl_map and s + + # FIXME: Make this less gross + # FIXME: Make an exported/documented interface of this in islpy + from islpy import _align_dim_type + + map_with_s_domain = isl.Map.from_domain(s) + + dim_types = [dim_type.param, dim_type.in_, dim_type.out] + s_names = [ + map_with_s_domain.get_dim_name(dt, i) + for dt in dim_types + for i in range(map_with_s_domain.dim(dt)) + ] + map_names = [ + isl_map.get_dim_name(dt, i) + for dt in dim_types + for i in range(isl_map.dim(dt)) + ] + aligned_map = _align_dim_type( + dim_type.param, + isl_map, map_with_s_domain, obj_bigger_ok=False, + obj_names=map_names, tgt_names=s_names) + aligned_map = _align_dim_type( + dim_type.in_, + isl_map, map_with_s_domain, obj_bigger_ok=False, + obj_names=map_names, tgt_names=s_names) + + # }}} + + return aligned_map.intersect_domain(s).range() + + # FIXME: Revive _project_out_only_if_all_instructions_in_within + + new_domains = [process_set(dom) for dom in kernel.domains] + + # {{{ update within_inames + + new_insns = [] + for insn in kernel.instructions: + overlap = old_inames & insn.within_inames + if overlap and within(kernel, insn): + if len(overlap) != len(old_inames): + raise LoopyError("instruction '%s' is within only a part " + "of the map domain inames. Instructions must " + "either be within all or none of the map domain " + "inames." % insn.id) + + insn = insn.copy( + within_inames=(insn.within_inames - old_inames) | new_inames) + else: + # leave insn unmodified + pass + + new_insns.append(insn) + + # }}} + + kernel = kernel.copy( + domains=new_domains, + instructions=new_insns, + applied_iname_rewrites=applied_iname_rewrites) + + rule_mapping_context = SubstitutionRuleMappingContext( + kernel.substitutions, kernel.get_var_name_generator()) + ins = _MapDomainMapper(rule_mapping_context, within, + new_inames, substitutions) + + kernel = ins.map_kernel(kernel) + kernel = rule_mapping_context.finish_kernel(kernel) + + return kernel + +# }}} + # vim: foldmethod=marker diff --git a/test/test_transform.py b/test/test_transform.py index 0906c9b34..9b184f4b0 100644 --- a/test/test_transform.py +++ b/test/test_transform.py @@ -578,21 +578,45 @@ def test_diamond_tiling(ctx_factory): """ u[ix, it+2] = ( 2*u[ix, it+1] - + dt**2/dx**2 * (u[ix+1, it+1] - 2*u[ix, it+1] + u[ix-1, it+1]) + + dt**2/dx**2 * (u[ix+1, it+1] - 2*u[ix, it+1] + u[ix-1, it+1]) - u[ix, it]) """) + ref_knl = lp.set_options(ref_knl, write_cl=True) + + # FIXME: Handle priorities in map_domain + knl_for_transform = ref_knl ref_knl = lp.prioritize_loops(ref_knl, "it, ix") - ref_knl = lp.set_options(ref_knl, write_cl=True) nx = 43 u = np.zeros((nx, 200)) x = np.linspace(-1, 1, nx) dx = x[1] - x[0] u[:, 0] = u[:, 1] = np.exp(-100*x**2) + import islpy as isl + if 1: + m = isl.BasicMap( + "[nx,nt] -> {[ix, it] -> [tx, tt, tparity, itt, itx]: " + "16*(tx - tt + tparity) + itx - itt = ix - it and " + "16*(tx + tt) + itt + itx = ix + it and " + "0<=tparity<2 and 0 <= itx - itt < 16 and 0 <= itt+itx < 16}") + knl = lp.map_domain(knl_for_transform, m) + knl = lp.prioritize_loops(knl, "tt,tparity,tx,itt,itx") + else: + # This is more like what split_iname does, but it is *not* + # a correct tiling for the stencil operator. + m = isl.BasicMap( + "[nx,nt] -> {[ix, it] -> [tx, tt, itt, itx]: " + "16*tx + itx = ix and " + "16*tt + itt = it and " + "0 <= itx < 16 and 0 <= itt< 16}") + + knl = lp.map_domain(knl_for_transform, m) + knl = lp.prioritize_loops(knl, "tt,tx,itt,itx") + u_dev = cl.array.to_device(queue, u) - ref_knl(queue, u=u_dev, dx=dx, dt=dx) + knl(queue, u=u_dev, dx=dx, dt=dx) u = u_dev.get() import matplotlib.pyplot as plt From 70ee84dfda8139f8826aada1d49f4a6c9a0d7f24 Mon Sep 17 00:00:00 2001 From: "[6~" Date: Wed, 13 Nov 2019 18:07:41 -0600 Subject: [PATCH 03/24] Make placeholder error message Py2-compatible --- loopy/transform/iname.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loopy/transform/iname.py b/loopy/transform/iname.py index e627604c1..6236ace72 100644 --- a/loopy/transform/iname.py +++ b/loopy/transform/iname.py @@ -1781,7 +1781,7 @@ def map_reduction(self, expr, expn_state): expn_state.instruction)): # FIXME if len(overlap) != len(self.old_inames): - raise LoopyError(...) + raise LoopyError("...") raise NotImplementedError("reductions") new_inames = list(expr.inames) From 3c4c1ff2e46a8feecf7ac1053cb2a90fc7aebb25 Mon Sep 17 00:00:00 2001 From: "[6~" Date: Wed, 13 Nov 2019 18:07:59 -0600 Subject: [PATCH 04/24] test_diamond_tiling: Remove split_iname analog --- test/test_transform.py | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/test/test_transform.py b/test/test_transform.py index 9b184f4b0..6c15b91ec 100644 --- a/test/test_transform.py +++ b/test/test_transform.py @@ -595,25 +595,13 @@ def test_diamond_tiling(ctx_factory): u[:, 0] = u[:, 1] = np.exp(-100*x**2) import islpy as isl - if 1: - m = isl.BasicMap( - "[nx,nt] -> {[ix, it] -> [tx, tt, tparity, itt, itx]: " - "16*(tx - tt + tparity) + itx - itt = ix - it and " - "16*(tx + tt) + itt + itx = ix + it and " - "0<=tparity<2 and 0 <= itx - itt < 16 and 0 <= itt+itx < 16}") - knl = lp.map_domain(knl_for_transform, m) - knl = lp.prioritize_loops(knl, "tt,tparity,tx,itt,itx") - else: - # This is more like what split_iname does, but it is *not* - # a correct tiling for the stencil operator. - m = isl.BasicMap( - "[nx,nt] -> {[ix, it] -> [tx, tt, itt, itx]: " - "16*tx + itx = ix and " - "16*tt + itt = it and " - "0 <= itx < 16 and 0 <= itt< 16}") - - knl = lp.map_domain(knl_for_transform, m) - knl = lp.prioritize_loops(knl, "tt,tx,itt,itx") + m = isl.BasicMap( + "[nx,nt] -> {[ix, it] -> [tx, tt, tparity, itt, itx]: " + "16*(tx - tt + tparity) + itx - itt = ix - it and " + "16*(tx + tt) + itt + itx = ix + it and " + "0<=tparity<2 and 0 <= itx - itt < 16 and 0 <= itt+itx < 16}") + knl = lp.map_domain(knl_for_transform, m) + knl = lp.prioritize_loops(knl, "tt,tparity,tx,itt,itx") u_dev = cl.array.to_device(queue, u) knl(queue, u=u_dev, dx=dx, dt=dx) From b61dbcf7aeb705e7071d2129fc20bb40facbf076 Mon Sep 17 00:00:00 2001 From: "[6~" Date: Wed, 13 Nov 2019 18:08:47 -0600 Subject: [PATCH 05/24] Fix diamond tile mapping --- test/test_transform.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_transform.py b/test/test_transform.py index 6c15b91ec..9cb1af4ab 100644 --- a/test/test_transform.py +++ b/test/test_transform.py @@ -597,8 +597,8 @@ def test_diamond_tiling(ctx_factory): import islpy as isl m = isl.BasicMap( "[nx,nt] -> {[ix, it] -> [tx, tt, tparity, itt, itx]: " - "16*(tx - tt + tparity) + itx - itt = ix - it and " - "16*(tx + tt) + itt + itx = ix + it and " + "16*(tx - tt) + itx - itt = ix - it and " + "16*(tx + tt + tparity) + itt + itx = ix + it and " "0<=tparity<2 and 0 <= itx - itt < 16 and 0 <= itt+itx < 16}") knl = lp.map_domain(knl_for_transform, m) knl = lp.prioritize_loops(knl, "tt,tparity,tx,itt,itx") From c6610312666c6f8bb38acbb439bf7fc1199aa529 Mon Sep 17 00:00:00 2001 From: "[6~" Date: Thu, 14 Nov 2019 16:37:20 -0600 Subject: [PATCH 06/24] Make test_diamond_tiling an actual test --- test/test_transform.py | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/test/test_transform.py b/test/test_transform.py index 9cb1af4ab..d8030358b 100644 --- a/test/test_transform.py +++ b/test/test_transform.py @@ -569,7 +569,7 @@ def test_nested_substs_in_insns(ctx_factory): lp.auto_test_vs_ref(ref_knl, ctx, knl) -def test_diamond_tiling(ctx_factory): +def test_diamond_tiling(ctx_factory, interactive=False): ctx = ctx_factory() queue = cl.CommandQueue(ctx) @@ -581,19 +581,12 @@ def test_diamond_tiling(ctx_factory): + dt**2/dx**2 * (u[ix+1, it+1] - 2*u[ix, it+1] + u[ix-1, it+1]) - u[ix, it]) """) - ref_knl = lp.set_options(ref_knl, write_cl=True) # FIXME: Handle priorities in map_domain knl_for_transform = ref_knl ref_knl = lp.prioritize_loops(ref_knl, "it, ix") - nx = 43 - u = np.zeros((nx, 200)) - x = np.linspace(-1, 1, nx) - dx = x[1] - x[0] - u[:, 0] = u[:, 1] = np.exp(-100*x**2) - import islpy as isl m = isl.BasicMap( "[nx,nt] -> {[ix, it] -> [tx, tt, tparity, itt, itx]: " @@ -603,13 +596,30 @@ def test_diamond_tiling(ctx_factory): knl = lp.map_domain(knl_for_transform, m) knl = lp.prioritize_loops(knl, "tt,tparity,tx,itt,itx") - u_dev = cl.array.to_device(queue, u) - knl(queue, u=u_dev, dx=dx, dt=dx) + if interactive: + nx = 43 + u = np.zeros((nx, 200)) + x = np.linspace(-1, 1, nx) + dx = x[1] - x[0] + u[:, 0] = u[:, 1] = np.exp(-100*x**2) + + u_dev = cl.array.to_device(queue, u) + knl(queue, u=u_dev, dx=dx, dt=dx) - u = u_dev.get() - import matplotlib.pyplot as plt - plt.imshow(u.T) - plt.show() + u = u_dev.get() + import matplotlib.pyplot as plt + plt.imshow(u.T) + plt.show() + else: + types = {"dt,dx,u": np.float64} + knl = lp.add_and_infer_dtypes(knl, types) + ref_knl = lp.add_and_infer_dtypes(ref_knl, types) + + lp.auto_test_vs_ref(ref_knl, ctx, knl, + parameters={ + "nx": 200, "nt": 300, + "dx": 1, "dt": 1 + }) if __name__ == "__main__": From e1ae8cf8080f93f8cb1252a194414c2cf60f1f78 Mon Sep 17 00:00:00 2001 From: "[6~" Date: Thu, 14 Nov 2019 16:37:43 -0600 Subject: [PATCH 07/24] Fix handling of reductions in map_domain --- loopy/transform/iname.py | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/loopy/transform/iname.py b/loopy/transform/iname.py index 6236ace72..c49f26137 100644 --- a/loopy/transform/iname.py +++ b/loopy/transform/iname.py @@ -1773,20 +1773,34 @@ def __init__(self, rule_mapping_context, within, new_inames, substitutions): self.substitutions = substitutions def map_reduction(self, expr, expn_state): - overlap = frozenset(expr.inames) & self.old_inames - if (overlap - and self.split_iname not in expn_state.arg_context + red_overlap = frozenset(expr.inames) & self.old_inames + arg_ctx_overlap = frozenset(expn_state.arg_context) & self.old_inames + if (red_overlap and self.within( expn_state.kernel, expn_state.instruction)): - # FIXME - if len(overlap) != len(self.old_inames): - raise LoopyError("...") + if len(red_overlap) != len(self.old_inames): + raise LoopyError("reduction '%s' involves a part " + "of the map domain inames. Reductions must " + "either involve all or none of the map domain " + "inames." % str(expr)) + + if arg_ctx_overlap: + if arg_ctx_overlap == red_overlap: + # All variables are shadowed by context, that's OK. + return super(_MapDomainMapper, self).map_reduction( + expr, expn_state) + else: + raise LoopyError("reduction '%s' has" + "some of the reduction variables affected " + "by the map_domain shadowed by context. " + "Either all or none must be shadowed." + % str(expr)) - raise NotImplementedError("reductions") new_inames = list(expr.inames) - new_inames.remove(self.split_iname) - new_inames.extend([self.outer_iname, self.inner_iname]) + for old_iname in self.old_inames: + new_inames.remove(old_iname) + new_inames.extend(self.new_inames) from loopy.symbolic import Reduction return Reduction(expr.operation, tuple(new_inames), From da35b59d0188c0e838178235bf3d742df2b4c6a4 Mon Sep 17 00:00:00 2001 From: Nicholas Christensen Date: Mon, 1 Feb 2021 11:51:08 -0600 Subject: [PATCH 08/24] Update to use new islpy _laign_dim_type parameters --- loopy/transform/iname.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/loopy/transform/iname.py b/loopy/transform/iname.py index fbd0d57bc..d832adbd7 100644 --- a/loopy/transform/iname.py +++ b/loopy/transform/iname.py @@ -1975,6 +1975,16 @@ def process_set(s): for dt in dim_types for i in range(isl_map.dim(dt)) ] + aligned_map = _align_dim_type( + dim_type.param, + isl_map, map_with_s_domain, False, + map_names, s_names) + aligned_map = _align_dim_type( + dim_type.in_, + isl_map, map_with_s_domain, False, + map_names, s_names) + # Old code + """ aligned_map = _align_dim_type( dim_type.param, isl_map, map_with_s_domain, obj_bigger_ok=False, @@ -1983,7 +1993,7 @@ def process_set(s): dim_type.in_, isl_map, map_with_s_domain, obj_bigger_ok=False, obj_names=map_names, tgt_names=s_names) - + """ # }}} return aligned_map.intersect_domain(s).range() From 34fab989cb019289431bbd532fd24bf0db67b3e7 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 18 Apr 2021 15:10:43 -0500 Subject: [PATCH 09/24] fix bug in map_domain (when aligning second dim type, make sure to use result from first align) --- loopy/transform/iname.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/loopy/transform/iname.py b/loopy/transform/iname.py index eed310f29..962566433 100644 --- a/loopy/transform/iname.py +++ b/loopy/transform/iname.py @@ -1977,13 +1977,17 @@ def process_set(s): for dt in dim_types for i in range(isl_map.dim(dt)) ] + # (order doesn't matter in s_names/map_names, + # _align_dim_type just converts these to sets + # to determine which names are in both the obj and template, + # not sure why this isn't just handled inside _align_dim_type) aligned_map = _align_dim_type( dim_type.param, isl_map, map_with_s_domain, False, map_names, s_names) aligned_map = _align_dim_type( dim_type.in_, - isl_map, map_with_s_domain, False, + aligned_map, map_with_s_domain, False, map_names, s_names) # Old code """ From 137e7c7e4a4a15d5a46f2ae7adfe4f7432e0fc75 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 19 Apr 2021 17:31:28 -0500 Subject: [PATCH 10/24] fix bug in map_domain to actually allow instructions with domains independent from the transformation map, as advertised --- loopy/transform/iname.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/loopy/transform/iname.py b/loopy/transform/iname.py index 962566433..490c1622b 100644 --- a/loopy/transform/iname.py +++ b/loopy/transform/iname.py @@ -1952,7 +1952,12 @@ def process_set(s): var_dict = s.get_var_dict() overlap = old_inames & frozenset(var_dict) - if overlap and len(overlap) != len(old_inames): + + if not overlap: + # inames in s are not present in transform map, don't change s + return s + + if len(overlap) != len(old_inames): raise LoopyError("loop domain '%s' involves a part " "of the map domain inames. Domains must " "either involve all or none of the map domain " From 399ec46a8049d51b0776ece395ce327e7ace92bc Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 19 Apr 2021 17:34:05 -0500 Subject: [PATCH 11/24] allow post-transform iname renaming in map_domain to handle case where desired transformation map would keep an old iname around (with same name) after the map is applied (maybe handle differently later) --- loopy/transform/iname.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/loopy/transform/iname.py b/loopy/transform/iname.py index 490c1622b..534d553ab 100644 --- a/loopy/transform/iname.py +++ b/loopy/transform/iname.py @@ -1890,7 +1890,7 @@ def _find_aff_subst_from_map(iname, isl_map): raise LoopyError("no suitable equation for '%s' found" % iname) -def map_domain(kernel, isl_map, within=None): +def map_domain(kernel, isl_map, within=None, rename_after={}): # FIXME: Express _split_iname_backend in terms of this # Missing/deleted for now: # - slab processing @@ -2048,6 +2048,24 @@ def process_set(s): kernel = ins.map_kernel(kernel) kernel = rule_mapping_context.finish_kernel(kernel) + # {{{ Rename inames according to rename_after dict + + # This is currently an option because various isl operations fail when map dim + # names are not unique, so even if someone wants their transformation map to keep + # one of the inames unchanged, they must give it a new name + # in their map, e.g., "[x, t] -> [x_, t_outer, t_inner] : x_ = x ..." (see + # test_map_domain_vs_split_iname()). Currently, they can't + # simply exclude that iname from the transformation map because, as stated in + # the error above, all domains must either involve all or none of the + # transform map domain inames. This renaming option lets them, e.g. switch + # an iname back to its original name. + + # TODO come up with better solution for this + for old_iname, new_iname in rename_after.items(): + kernel = rename_iname(kernel, old_iname, new_iname, within=within) + + # }}} + return kernel # }}} From 632aafd84d2a3568a5b98c1d931765dac6ea4337 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 19 Apr 2021 17:34:28 -0500 Subject: [PATCH 12/24] create test to compare map_domain result to split_iname result --- test/test_transform.py | 78 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/test/test_transform.py b/test/test_transform.py index fdba857c9..6954513c8 100644 --- a/test/test_transform.py +++ b/test/test_transform.py @@ -567,6 +567,84 @@ def test_nested_substs_in_insns(ctx_factory): lp.auto_test_vs_ref(ref_knl, ctx, knl) +# {{{ test_map_domain_vs_split_iname + +def test_map_domain_vs_split_iname(): + + # {{{ Make kernel + + knl = lp.make_kernel( + [ + "[nx,nt] -> {[x, t]: 0 <= x < nx and 0 <= t < nt}", + "[ni] -> {[i]: 0 <= i < ni}", + ], + """ + a[x,t] = b[x,t] {id=stmta} + c[x,t] = d[x,t] {id=stmtc} + e[i] = f[i] + """, + name="wave_equation", + lang_version=(2018, 2), + ) + knl = lp.add_and_infer_dtypes(knl, {"b,d,f": np.float32}) + ref_knl = knl + + # }}} + + # {{{ Apply domain change mapping + + knl_map_dom = ref_knl # loop priority goes away, deps stay + + # Create map_domain mapping: + import islpy as isl + transform_map = isl.BasicMap( + "[nx,nt] -> {[x, t] -> [x_, t_outer, t_inner]: " + "x = x_ and " + "0 <= t_inner < 32 and " + "32*t_outer + t_inner = t and " + "0 <= 32*t_outer + t_inner < nt}") + + # Call map_domain to transform kernel + knl_map_dom = lp.map_domain(knl_map_dom, transform_map, rename_after={"x_": "x"}) + + # Prioritize loops (prio should eventually be updated in map_domain?) + knl_map_dom = lp.prioritize_loops(knl_map_dom, "x, t_outer, t_inner") + + # Get a linearization + proc_knl_map_dom = lp.preprocess_kernel(knl_map_dom) + lin_knl_map_dom = lp.get_one_linearized_kernel(proc_knl_map_dom) + + # }}} + + # {{{ Split iname and see if we get the same result + + knl_split_iname = ref_knl + knl_split_iname = lp.split_iname(knl_split_iname, "t", 32) + knl_split_iname = lp.prioritize_loops(knl_split_iname, "x, t_outer, t_inner") + proc_knl_split_iname = lp.preprocess_kernel(knl_split_iname) + lin_knl_split_iname = lp.get_one_linearized_kernel(proc_knl_split_iname) + + from loopy.schedule.checker.utils import ( + ensure_dim_names_match_and_align, + ) + for d_map_domain, d_split_iname in zip( + knl_map_dom.domains, knl_split_iname.domains): + d_map_domain_aligned = ensure_dim_names_match_and_align( + d_map_domain, d_split_iname) + assert d_map_domain_aligned == d_split_iname + + for litem_map_domain, litem_split_iname in zip( + lin_knl_map_dom.linearization, lin_knl_split_iname.linearization): + assert litem_map_domain == litem_split_iname + + # Can't easily compare instructions because equivalent subscript + # expressions may have different orders + + # }}} + +# }}} + + def test_diamond_tiling(ctx_factory, interactive=False): ctx = ctx_factory() queue = cl.CommandQueue(ctx) From 0166f8d1b5df9a48e722f19259cc4f2b0c32ca1d Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Mon, 19 Apr 2021 22:37:09 -0500 Subject: [PATCH 13/24] slight clarification of comment --- loopy/transform/iname.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loopy/transform/iname.py b/loopy/transform/iname.py index 534d553ab..c594b0e6a 100644 --- a/loopy/transform/iname.py +++ b/loopy/transform/iname.py @@ -2050,7 +2050,7 @@ def process_set(s): # {{{ Rename inames according to rename_after dict - # This is currently an option because various isl operations fail when map dim + # This renaming option exists because various isl operations fail when map dim # names are not unique, so even if someone wants their transformation map to keep # one of the inames unchanged, they must give it a new name # in their map, e.g., "[x, t] -> [x_, t_outer, t_inner] : x_ = x ..." (see From 9c0c2dfe48aea7356af718251d5b1bf109b6378b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Kl=C3=B6ckner?= Date: Tue, 20 Apr 2021 12:16:59 -0500 Subject: [PATCH 14/24] Add map_domain FIXME --- loopy/transform/iname.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/loopy/transform/iname.py b/loopy/transform/iname.py index c594b0e6a..0c768759c 100644 --- a/loopy/transform/iname.py +++ b/loopy/transform/iname.py @@ -1900,6 +1900,8 @@ def map_domain(kernel, isl_map, within=None, rename_after={}): # FIXME: Document # FIXME: Support within + # FIXME: Right now, this requires all inames in a domain (or none) to + # be mapped. That makes this awkward to use. # {{{ within processing (disabled for now) if within is not None: From ab983950e8c8b8e4ae6e7f3d531471de1e2897d4 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Fri, 23 Apr 2021 17:38:41 -0500 Subject: [PATCH 15/24] fix flake8 issues --- loopy/transform/iname.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/loopy/transform/iname.py b/loopy/transform/iname.py index e9b92d62e..29a27f074 100644 --- a/loopy/transform/iname.py +++ b/loopy/transform/iname.py @@ -2049,13 +2049,13 @@ def process_set(s): # {{{ Rename inames according to rename_after dict - # This renaming option exists because various isl operations fail when map dim - # names are not unique, so even if someone wants their transformation map to keep - # one of the inames unchanged, they must give it a new name + # This renaming option exists because various isl operations fail when map + # dim names are not unique, so even if someone wants their transformation + # map to keep one of the inames unchanged, they must give it a new name # in their map, e.g., "[x, t] -> [x_, t_outer, t_inner] : x_ = x ..." (see # test_map_domain_vs_split_iname()). Currently, they can't - # simply exclude that iname from the transformation map because, as stated in - # the error above, all domains must either involve all or none of the + # simply exclude that iname from the transformation map because, as stated + # in the error above, all domains must either involve all or none of the # transform map domain inames. This renaming option lets them, e.g. switch # an iname back to its original name. From ff482538e17cc2dd89d6da7b82d19d8efcd3014c Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Wed, 5 May 2021 20:18:36 -0500 Subject: [PATCH 16/24] fix bug in map_domain where we attempt to return the same kernel if no kernel matches within --- loopy/transform/iname.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/loopy/transform/iname.py b/loopy/transform/iname.py index 29a27f074..1e216509f 100644 --- a/loopy/transform/iname.py +++ b/loopy/transform/iname.py @@ -1909,15 +1909,9 @@ def map_domain(kernel, isl_map, within=None, rename_after={}): # {{{ return the same kernel if no kernel matches - def _do_not_transform_if_no_within_matches(): - for insn in kernel.instructions: - if within(kernel, insn): - return - + if not any(within(kernel, insn) for insn in kernel.instructions): return kernel - _do_not_transform_if_no_within_matches() - # }}} # }}} From 502e155206fed7f4c9adff8aae7ac29e7f98d0ce Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 16 May 2021 19:52:03 -0500 Subject: [PATCH 17/24] add find_and_rename_dim() --- loopy/schedule/checker/utils.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index 401fd477a..c02149790 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -107,6 +107,14 @@ def add_eq_isl_constraint_from_names(isl_map, var1, var2): {1: 0, var1: 1, var2: -1})) +def find_and_rename_dim(old_map, dim_types, old_name, new_name): + new_map = old_map.copy() + for dim_type in dim_types: + new_map = new_map.set_dim_name( + dim_type, new_map.find_dim_by_name(dim_type, old_name), new_name) + return new_map + + def append_mark_to_isl_map_var_names(old_isl_map, dim_type, mark): """Return an :class:`islpy.Map` with a mark appended to the specified dimension names. From 003eed17e4dab494ef5630eea83348fabe144dcc Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 16 May 2021 19:53:22 -0500 Subject: [PATCH 18/24] in map_domain, deal with situation where transform map doesn't include all the inames in the domain (in which case the missing inames should be unaffected --- loopy/transform/iname.py | 77 ++++++++++++++++++++++++++++++++-------- 1 file changed, 62 insertions(+), 15 deletions(-) diff --git a/loopy/transform/iname.py b/loopy/transform/iname.py index 29a27f074..3c851a0aa 100644 --- a/loopy/transform/iname.py +++ b/loopy/transform/iname.py @@ -67,6 +67,8 @@ .. autofunction:: add_inames_to_insn +.. autofunction:: map_domain + .. autofunction:: add_inames_for_unused_hw_axes """ @@ -1887,6 +1889,8 @@ def _find_aff_subst_from_map(iname, isl_map): raise LoopyError("no suitable equation for '%s' found" % iname) +# TODO swap dt and dim_type + def map_domain(kernel, isl_map, within=None, rename_after={}): # FIXME: Express _split_iname_backend in terms of this # Missing/deleted for now: @@ -1947,6 +1951,10 @@ def _do_not_transform_if_no_within_matches(): # }}} + from loopy.schedule.checker.utils import ( + add_and_name_isl_dims, + ) + def process_set(s): var_dict = s.get_var_dict() @@ -1962,6 +1970,11 @@ def process_set(s): "either involve all or none of the map domain " "inames." % s) + from loopy.schedule.checker.utils import ( + find_and_rename_dim, + add_eq_isl_constraint_from_names, + ) + # {{{ align dims of isl_map and s # FIXME: Make this less gross @@ -1970,6 +1983,40 @@ def process_set(s): map_with_s_domain = isl.Map.from_domain(s) + # {{{ deal with dims missing from transform map (isl_map) + + # If dims in s are missing from transform map, they need to be added + # so that intersect_domain doesn't remove them. + # Order doesn't matter here because dims will be aligned in the next step. + dims_missing_from_transform_map = list( + set(s.get_var_names(dim_type.set)) - + set(isl_map.get_var_names(dim_type.in_))) + augmented_isl_map = add_and_name_isl_dims( + isl_map, dim_type.in_, dims_missing_from_transform_map) + + # We want these missing inames to map to themselves so that the transform + # has no effect on them. Unfortunatley isl will break if the + # names of the out dims aren't unique, so we will temporariliy rename them + # and then change the names back afterward. + + # FIXME: need better way to make sure proxy dim names are unique + dims_missing_from_transform_map_proxies = [ + d+"__prox" for d in dims_missing_from_transform_map] + assert not set(dims_missing_from_transform_map_proxies) & set( + augmented_isl_map.get_var_dict().keys()) + + augmented_isl_map = add_and_name_isl_dims( + augmented_isl_map, dim_type.out, dims_missing_from_transform_map_proxies) + + # Set proxy iname equal to real iname + for proxy_iname, real_iname in zip( + dims_missing_from_transform_map_proxies, + dims_missing_from_transform_map): + augmented_isl_map = add_eq_isl_constraint_from_names( + augmented_isl_map, proxy_iname, real_iname) + + # }}} + dim_types = [dim_type.param, dim_type.in_, dim_type.out] s_names = [ map_with_s_domain.get_dim_name(dt, i) @@ -1977,36 +2024,36 @@ def process_set(s): for i in range(map_with_s_domain.dim(dt)) ] map_names = [ - isl_map.get_dim_name(dt, i) + augmented_isl_map.get_dim_name(dt, i) for dt in dim_types - for i in range(isl_map.dim(dt)) + for i in range(augmented_isl_map.dim(dt)) ] + # (order doesn't matter in s_names/map_names, # _align_dim_type just converts these to sets # to determine which names are in both the obj and template, # not sure why this isn't just handled inside _align_dim_type) aligned_map = _align_dim_type( dim_type.param, - isl_map, map_with_s_domain, False, + augmented_isl_map, map_with_s_domain, False, map_names, s_names) aligned_map = _align_dim_type( dim_type.in_, aligned_map, map_with_s_domain, False, map_names, s_names) - # Old code - """ - aligned_map = _align_dim_type( - dim_type.param, - isl_map, map_with_s_domain, obj_bigger_ok=False, - obj_names=map_names, tgt_names=s_names) - aligned_map = _align_dim_type( - dim_type.in_, - isl_map, map_with_s_domain, obj_bigger_ok=False, - obj_names=map_names, tgt_names=s_names) - """ + # }}} - return aligned_map.intersect_domain(s).range() + new_s = aligned_map.intersect_domain(s).range() + + # Now rename the proxy dims back to their original names + for proxy_iname, real_iname in zip( + dims_missing_from_transform_map_proxies, + dims_missing_from_transform_map): + new_s = find_and_rename_dim( + new_s, [dim_type.set], proxy_iname, real_iname) + + return new_s # FIXME: Revive _project_out_only_if_all_instructions_in_within From 5138b16137d57fb29e80ac4cb31c1c964ccd2cb4 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Sun, 16 May 2021 19:53:55 -0500 Subject: [PATCH 19/24] test map_domain with situation where transform map doesn't include all the inames in the domain (in which case the missing inames should be unaffected) --- test/test_transform.py | 91 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/test/test_transform.py b/test/test_transform.py index 6954513c8..00e1896a4 100644 --- a/test/test_transform.py +++ b/test/test_transform.py @@ -645,6 +645,97 @@ def test_map_domain_vs_split_iname(): # }}} +# {{{ test_map_domain_with_transform_map_missing_dims + +def test_map_domain_with_transform_map_missing_dims(): + # Make sure map_domain works correctly when the mapping doesn't include + # all the dims in the domain. + + # {{{ Make kernel + + knl = lp.make_kernel( + [ + "[nx,nt] -> {[x, y, z, t]: 0 <= x,y,z < nx and 0 <= t < nt}", + ], + """ + a[y,x,t,z] = b[y,x,t,z] {id=stmta} + """, + lang_version=(2018, 2), + ) + knl = lp.add_and_infer_dtypes(knl, {"b": np.float32}) + ref_knl = knl + + # }}} + + # {{{ Apply domain change mapping + + knl_map_dom = ref_knl # loop priority goes away, deps stay + + # Create map_domain mapping that only includes t and y + # (x and z should be unaffected) + import islpy as isl + transform_map = isl.BasicMap( + "[nx,nt] -> {[t, y] -> [t_outer, t_inner, y_new]: " + "0 <= t_inner < 32 and " + "32*t_outer + t_inner = t and " + "0 <= 32*t_outer + t_inner < nt and " + "y = y_new" + "}") + + # Call map_domain to transform kernel + knl_map_dom = lp.map_domain(knl_map_dom, transform_map) + + # Prioritize loops (prio should eventually be updated in map_domain?) + try: + # Use constrain_loop_nesting if it's available + desired_prio = "x, t_outer, t_inner, z, y_new" + knl_map_dom = lp.constrain_loop_nesting(knl_map_dom, desired_prio) + except AttributeError: + # For some reason, prioritize_loops can't handle the ordering above + # when linearizing knl_split_iname below + desired_prio = "z, y_new, x, t_outer, t_inner" + knl_map_dom = lp.prioritize_loops(knl_map_dom, desired_prio) + + # Get a linearization + proc_knl_map_dom = lp.preprocess_kernel(knl_map_dom) + lin_knl_map_dom = lp.get_one_linearized_kernel(proc_knl_map_dom) + + # }}} + + # {{{ Split iname and see if we get the same result + + knl_split_iname = ref_knl + knl_split_iname = lp.split_iname(knl_split_iname, "t", 32) + knl_split_iname = lp.rename_iname(knl_split_iname, "y", "y_new") + try: + # Use constrain_loop_nesting if it's available + knl_split_iname = lp.constrain_loop_nesting(knl_split_iname, desired_prio) + except AttributeError: + knl_split_iname = lp.prioritize_loops(knl_split_iname, desired_prio) + proc_knl_split_iname = lp.preprocess_kernel(knl_split_iname) + lin_knl_split_iname = lp.get_one_linearized_kernel(proc_knl_split_iname) + + from loopy.schedule.checker.utils import ( + ensure_dim_names_match_and_align, + ) + for d_map_domain, d_split_iname in zip( + knl_map_dom.domains, knl_split_iname.domains): + d_map_domain_aligned = ensure_dim_names_match_and_align( + d_map_domain, d_split_iname) + assert d_map_domain_aligned == d_split_iname + + for litem_map_domain, litem_split_iname in zip( + lin_knl_map_dom.linearization, lin_knl_split_iname.linearization): + assert litem_map_domain == litem_split_iname + + # Can't easily compare instructions because equivalent subscript + # expressions may have different orders + + # }}} + +# }}} + + def test_diamond_tiling(ctx_factory, interactive=False): ctx = ctx_factory() queue = cl.CommandQueue(ctx) From 7faa802c92809bddf351fbbe2d549683eb932d5b Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Wed, 21 Jul 2021 13:42:35 -0500 Subject: [PATCH 20/24] add for_each_kernel decorator to map_domain --- loopy/transform/iname.py | 1 + 1 file changed, 1 insertion(+) diff --git a/loopy/transform/iname.py b/loopy/transform/iname.py index be7a57d3f..81b253feb 100644 --- a/loopy/transform/iname.py +++ b/loopy/transform/iname.py @@ -1941,6 +1941,7 @@ def _find_aff_subst_from_map(iname, isl_map): # TODO swap dt and dim_type +@for_each_kernel def map_domain(kernel, isl_map, within=None, rename_after={}): # FIXME: Express _split_iname_backend in terms of this # Missing/deleted for now: From a5bdc98f63a271d769d97ebeda1c785faf32db5a Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Wed, 21 Jul 2021 13:42:54 -0500 Subject: [PATCH 21/24] after callables update, use knl[loopy_kernel] where needed --- test/test_transform.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/test/test_transform.py b/test/test_transform.py index cda729da8..6d6ad6e02 100644 --- a/test/test_transform.py +++ b/test/test_transform.py @@ -609,7 +609,6 @@ def test_map_domain_vs_split_iname(): c[x,t] = d[x,t] {id=stmtc} e[i] = f[i] """, - name="wave_equation", lang_version=(2018, 2), ) knl = lp.add_and_infer_dtypes(knl, {"b,d,f": np.float32}) @@ -638,7 +637,8 @@ def test_map_domain_vs_split_iname(): # Get a linearization proc_knl_map_dom = lp.preprocess_kernel(knl_map_dom) - lin_knl_map_dom = lp.get_one_linearized_kernel(proc_knl_map_dom) + lin_knl_map_dom = lp.get_one_linearized_kernel( + proc_knl_map_dom["loopy_kernel"], proc_knl_map_dom.callables_table) # }}} @@ -648,13 +648,15 @@ def test_map_domain_vs_split_iname(): knl_split_iname = lp.split_iname(knl_split_iname, "t", 32) knl_split_iname = lp.prioritize_loops(knl_split_iname, "x, t_outer, t_inner") proc_knl_split_iname = lp.preprocess_kernel(knl_split_iname) - lin_knl_split_iname = lp.get_one_linearized_kernel(proc_knl_split_iname) + lin_knl_split_iname = lp.get_one_linearized_kernel( + proc_knl_split_iname["loopy_kernel"], proc_knl_split_iname.callables_table) from loopy.schedule.checker.utils import ( ensure_dim_names_match_and_align, ) for d_map_domain, d_split_iname in zip( - knl_map_dom.domains, knl_split_iname.domains): + knl_map_dom["loopy_kernel"].domains, + knl_split_iname["loopy_kernel"].domains): d_map_domain_aligned = ensure_dim_names_match_and_align( d_map_domain, d_split_iname) assert d_map_domain_aligned == d_split_iname @@ -724,7 +726,8 @@ def test_map_domain_with_transform_map_missing_dims(): # Get a linearization proc_knl_map_dom = lp.preprocess_kernel(knl_map_dom) - lin_knl_map_dom = lp.get_one_linearized_kernel(proc_knl_map_dom) + lin_knl_map_dom = lp.get_one_linearized_kernel( + proc_knl_map_dom["loopy_kernel"], proc_knl_map_dom.callables_table) # }}} @@ -739,13 +742,15 @@ def test_map_domain_with_transform_map_missing_dims(): except AttributeError: knl_split_iname = lp.prioritize_loops(knl_split_iname, desired_prio) proc_knl_split_iname = lp.preprocess_kernel(knl_split_iname) - lin_knl_split_iname = lp.get_one_linearized_kernel(proc_knl_split_iname) + lin_knl_split_iname = lp.get_one_linearized_kernel( + proc_knl_split_iname["loopy_kernel"], proc_knl_split_iname.callables_table) from loopy.schedule.checker.utils import ( ensure_dim_names_match_and_align, ) for d_map_domain, d_split_iname in zip( - knl_map_dom.domains, knl_split_iname.domains): + knl_map_dom["loopy_kernel"].domains, + knl_split_iname["loopy_kernel"].domains): d_map_domain_aligned = ensure_dim_names_match_and_align( d_map_domain, d_split_iname) assert d_map_domain_aligned == d_split_iname From dd7cbea5e7dfa0095cfd9c7f4f22bc3d1ad3cce6 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Wed, 21 Jul 2021 13:57:28 -0500 Subject: [PATCH 22/24] remove rename_after arg in map_domain, which is no longer necessary due to previous map machinery update --- loopy/transform/iname.py | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/loopy/transform/iname.py b/loopy/transform/iname.py index 81b253feb..fc01f75ab 100644 --- a/loopy/transform/iname.py +++ b/loopy/transform/iname.py @@ -1942,7 +1942,7 @@ def _find_aff_subst_from_map(iname, isl_map): # TODO swap dt and dim_type @for_each_kernel -def map_domain(kernel, isl_map, within=None, rename_after={}): +def map_domain(kernel, isl_map, within=None): # FIXME: Express _split_iname_backend in terms of this # Missing/deleted for now: # - slab processing @@ -2139,24 +2139,6 @@ def process_set(s): kernel = ins.map_kernel(kernel) kernel = rule_mapping_context.finish_kernel(kernel) - # {{{ Rename inames according to rename_after dict - - # This renaming option exists because various isl operations fail when map - # dim names are not unique, so even if someone wants their transformation - # map to keep one of the inames unchanged, they must give it a new name - # in their map, e.g., "[x, t] -> [x_, t_outer, t_inner] : x_ = x ..." (see - # test_map_domain_vs_split_iname()). Currently, they can't - # simply exclude that iname from the transformation map because, as stated - # in the error above, all domains must either involve all or none of the - # transform map domain inames. This renaming option lets them, e.g. switch - # an iname back to its original name. - - # TODO come up with better solution for this - for old_iname, new_iname in rename_after.items(): - kernel = rename_iname(kernel, old_iname, new_iname, within=within) - - # }}} - return kernel # }}} From 4052fb94ff273b0e9927e63500e2e61185b462d8 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Wed, 21 Jul 2021 13:58:14 -0500 Subject: [PATCH 23/24] remove rename_after arg in map_domain, which is no longer necessary due to previous map machinery update --- test/test_transform.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/test_transform.py b/test/test_transform.py index 6d6ad6e02..feda064e3 100644 --- a/test/test_transform.py +++ b/test/test_transform.py @@ -623,14 +623,13 @@ def test_map_domain_vs_split_iname(): # Create map_domain mapping: import islpy as isl transform_map = isl.BasicMap( - "[nx,nt] -> {[x, t] -> [x_, t_outer, t_inner]: " - "x = x_ and " + "[nt] -> {[t] -> [t_outer, t_inner]: " "0 <= t_inner < 32 and " "32*t_outer + t_inner = t and " "0 <= 32*t_outer + t_inner < nt}") # Call map_domain to transform kernel - knl_map_dom = lp.map_domain(knl_map_dom, transform_map, rename_after={"x_": "x"}) + knl_map_dom = lp.map_domain(knl_map_dom, transform_map) # Prioritize loops (prio should eventually be updated in map_domain?) knl_map_dom = lp.prioritize_loops(knl_map_dom, "x, t_outer, t_inner") From 8a40d4ed42eb391323e622d8abff3ca0c29cb503 Mon Sep 17 00:00:00 2001 From: jdsteve2 Date: Thu, 5 Aug 2021 16:31:41 -0500 Subject: [PATCH 24/24] move find_and_rename_dim into iname.py since that's the only place it is/will be used; rename to _find_and_rename_dim --- loopy/schedule/checker/utils.py | 8 -------- loopy/transform/iname.py | 17 ++++++++++++++--- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/loopy/schedule/checker/utils.py b/loopy/schedule/checker/utils.py index 8e131168e..a47e12f30 100644 --- a/loopy/schedule/checker/utils.py +++ b/loopy/schedule/checker/utils.py @@ -107,14 +107,6 @@ def add_eq_isl_constraint_from_names(isl_map, var1, var2): {1: 0, var1: 1, var2: -1})) -def find_and_rename_dim(old_map, dim_types, old_name, new_name): - new_map = old_map.copy() - for dim_type in dim_types: - new_map = new_map.set_dim_name( - dim_type, new_map.find_dim_by_name(dim_type, old_name), new_name) - return new_map - - def append_mark_to_isl_map_var_names(old_isl_map, dim_type, mark): """Return an :class:`islpy.Map` with a mark appended to the specified dimension names. diff --git a/loopy/transform/iname.py b/loopy/transform/iname.py index fc01f75ab..33b52b913 100644 --- a/loopy/transform/iname.py +++ b/loopy/transform/iname.py @@ -1939,7 +1939,19 @@ def _find_aff_subst_from_map(iname, isl_map): raise LoopyError("no suitable equation for '%s' found" % iname) -# TODO swap dt and dim_type +# TODO to match convention elsewhere, swap 'dt' and 'dim_type' identifiers +# (use dt to abbreviate islpy.dim_type, and use dim_type for variables +# containing a specific dim_type) + +def _find_and_rename_dim(old_map, dim_types, old_name, new_name): + # (This function is only used once here, but do not inline it; it is used many + # times in child branch update-dependencies-during-transformations.) + new_map = old_map.copy() + for dt in dim_types: + new_map = new_map.set_dim_name( + dt, new_map.find_dim_by_name(dt, old_name), new_name) + return new_map + @for_each_kernel def map_domain(kernel, isl_map, within=None): @@ -2016,7 +2028,6 @@ def process_set(s): "inames." % s) from loopy.schedule.checker.utils import ( - find_and_rename_dim, add_eq_isl_constraint_from_names, ) @@ -2095,7 +2106,7 @@ def process_set(s): for proxy_iname, real_iname in zip( dims_missing_from_transform_map_proxies, dims_missing_from_transform_map): - new_s = find_and_rename_dim( + new_s = _find_and_rename_dim( new_s, [dim_type.set], proxy_iname, real_iname) return new_s