diff --git a/loopy/check.py b/loopy/check.py index 0d2bbff7cf8d6f9e63a33dc2c8814f29afae70f0..da49c1d116df1a9fbf92e8ef41822b6741405604 100644 --- a/loopy/check.py +++ b/loopy/check.py @@ -184,6 +184,19 @@ def check_for_inactive_iname_access(kernel): ", ".join(expression_inames - kernel.insn_inames(insn)))) +def check_for_unused_inames(kernel): + # Warn if kernel has unused inames + from loopy.transform.iname import get_used_inames + unused_inames = kernel.all_inames() - get_used_inames(kernel) + if unused_inames: + warn_with_kernel( + kernel, "unused_inames", + "Found unused inames in kernel: %s " + "Unused inames during linearization will be prohibited in " + "Loopy version 2021.X." + % unused_inames) + + def _is_racing_iname_tag(tv, tag): from loopy.kernel.data import (AddressSpace, LocalIndexTagBase, GroupIndexTag, ConcurrentTag, auto) @@ -658,6 +671,7 @@ def pre_schedule_checks(kernel): check_loop_priority_inames_known(kernel) check_multiple_tags_allowed(kernel) check_for_inactive_iname_access(kernel) + check_for_unused_inames(kernel) check_for_write_races(kernel) check_for_data_dependent_parallel_bounds(kernel) check_bounds(kernel) diff --git a/loopy/preprocess.py b/loopy/preprocess.py index 23c4b7fbd9e55006dd17ed9b127e598a14ee17a2..221233ed010e4cd3c574cf047f73263063152d93 100644 --- a/loopy/preprocess.py +++ b/loopy/preprocess.py @@ -37,6 +37,7 @@ from loopy.version import DATA_MODEL_VERSION from loopy.kernel.data import make_assignment, filter_iname_tags_by_type # for the benefit of loopy.statistics, for now from loopy.type_inference import infer_unknown_types +from loopy.transform.iname import remove_any_newly_unused_inames import logging logger = logging.getLogger(__name__) @@ -882,6 +883,7 @@ def _insert_subdomain_into_domain_tree(kernel, domains, subdomain): # }}} +@remove_any_newly_unused_inames def realize_reduction(kernel, insn_id_filter=None, unknown_types_ok=True, automagic_scans_ok=False, force_scan=False, force_outer_iname_for_scan=None): @@ -1924,8 +1926,6 @@ def realize_reduction(kernel, insn_id_filter=None, unknown_types_ok=True, kernel = lp.tag_inames(kernel, new_iname_tags) - # TODO: remove unused inames... - kernel = ( _hackily_ensure_multi_assignment_return_values_are_scoped_private( kernel)) diff --git a/loopy/transform/iname.py b/loopy/transform/iname.py index 96c8252ef7e6622250e9006b2275ef7816700b5c..ae717e1c7550b697c23b9d032fd795c362e387f0 100644 --- a/loopy/transform/iname.py +++ b/loopy/transform/iname.py @@ -1184,6 +1184,19 @@ def rename_iname(knl, old_iname, new_iname, existing_ok=False, within=None): # {{{ remove unused inames +def get_used_inames(knl): + import loopy as lp + exp_knl = lp.expand_subst(knl) + + used_inames = set() + for insn in exp_knl.instructions: + used_inames.update( + exp_knl.insn_inames(insn.id) + | insn.reduction_inames()) + + return used_inames + + def remove_unused_inames(knl, inames=None): """Delete those among *inames* that are unused, i.e. project them out of the domain. If these inames pose implicit restrictions on @@ -1204,17 +1217,7 @@ def remove_unused_inames(knl, inames=None): # {{{ check which inames are unused - import loopy as lp - exp_knl = lp.expand_subst(knl) - - inames = set(inames) - used_inames = set() - for insn in exp_knl.instructions: - used_inames.update( - exp_knl.insn_inames(insn.id) - | insn.reduction_inames()) - - unused_inames = inames - used_inames + unused_inames = set(inames) - get_used_inames(knl) # }}} @@ -1235,6 +1238,33 @@ def remove_unused_inames(knl, inames=None): return knl + +def remove_any_newly_unused_inames(transformation_func): + from functools import wraps + + @wraps(transformation_func) + def wrapper(knl, *args, **kwargs): + + # check for remove_unused_inames argument, default: True + remove_newly_unused_inames = kwargs.pop("remove_newly_unused_inames", True) + + if remove_newly_unused_inames: + # determine which inames were already unused + inames_already_unused = knl.all_inames() - get_used_inames(knl) + + # call transform + transformed_knl = transformation_func(knl, *args, **kwargs) + + # Remove inames that are unused due to transform + return remove_unused_inames( + transformed_knl, + transformed_knl.all_inames()-inames_already_unused) + else: + # call transform + return transformation_func(knl, *args, **kwargs) + + return wrapper + # }}} diff --git a/loopy/transform/subst.py b/loopy/transform/subst.py index fa145fbbf3e51670f7ac42307e4ffde75df07618..717a051930e938457dae0ee4441325b3e631d2d9 100644 --- a/loopy/transform/subst.py +++ b/loopy/transform/subst.py @@ -27,6 +27,7 @@ import six from loopy.symbolic import ( RuleAwareIdentityMapper, SubstitutionRuleMappingContext) from loopy.diagnostic import LoopyError +from loopy.transform.iname import remove_any_newly_unused_inames from pytools import ImmutableRecord from pymbolic import var @@ -278,6 +279,7 @@ class AssignmentToSubstChanger(RuleAwareIdentityMapper): return var(subst_name)(*index) +@remove_any_newly_unused_inames def assignment_to_subst(kernel, lhs_name, extra_arguments=(), within=None, force_retain_argument=False): """Extract an assignment (to a temporary variable or an argument) diff --git a/test/test_apps.py b/test/test_apps.py index e07262dbdda8ad3c24522f7d0eb4dba8422bf0ce..71029cc9ce408f8e7fa95eaf3b766864c4beee5b 100644 --- a/test/test_apps.py +++ b/test/test_apps.py @@ -566,7 +566,7 @@ def test_poisson_fem(ctx_factory): sdim = 3 knl = lp.make_kernel( - "{ [c,i,j,k,ell,ell2,ell3]: \ + "{ [c,i,j,k,ell,ell2]: \ 0 <= c < nels and \ 0 <= i < nbf and \ 0 <= j < nbf and \ diff --git a/test/test_domain.py b/test/test_domain.py index ebfde850907d68bebf06076fbf1c87d8bb093f71..5daf84eaa5b7ffd1647daf4b35acd7a5de91c5d1 100644 --- a/test/test_domain.py +++ b/test/test_domain.py @@ -111,7 +111,7 @@ def test_eq_constraint(ctx_factory): ctx = ctx_factory() knl = lp.make_kernel( - "{[i,j]: 0<= i,j < 32}", + "{[i]: 0<= i < 32}", [ "a[i] = b[i]" ], diff --git a/test/test_loopy.py b/test/test_loopy.py index 6b78ac26b78d8c85dab3cd41af0ce1d99d52ec07..61a3f167be66f1c99adc3a52473d8edc747479e1 100644 --- a/test/test_loopy.py +++ b/test/test_loopy.py @@ -177,7 +177,7 @@ def test_simple_side_effect(ctx_factory): ctx = ctx_factory() knl = lp.make_kernel( - "{[i,j]: 0<=i,j<100}", + "{[i]: 0<=i<100}", """ a[i] = a[i] + 1 """, @@ -456,7 +456,7 @@ def test_nonlinear_index(ctx_factory): ctx = ctx_factory() knl = lp.make_kernel( - "{[i,j]: 0<=i,j src_ibox = source_boxes[isrc_box] @@ -769,7 +769,7 @@ def test_multiple_writes_to_local_temporary(): # writes are OK. knl = lp.make_kernel( - "{[i,e]: 0<=i<5 and 0<=e temp[i, 0] = 17 temp[i, 1] = 15 @@ -952,7 +952,7 @@ def test_atomic_init(dtype): vec_width = 4 knl = lp.make_kernel( - "{ [i,j]: 0<=i<100 }", + "{ [i]: 0<=i<100 }", """ out[i%4] = 0 {id=init, atomic=init} """, @@ -1555,7 +1555,7 @@ def test_finite_difference_expr_subst(ctx_factory): gpu_knl, "f_subst", "inew_inner", fetch_bounding_box=True, default_tag="l.auto") - precomp_knl = lp.tag_inames(precomp_knl, {"j_0_outer": "unr"}) + precomp_knl = lp.tag_inames(precomp_knl, {"j_outer": "unr"}) precomp_knl = lp.set_options(precomp_knl, return_dict=True) evt, _ = precomp_knl(queue, u=u, h=h) @@ -1926,8 +1926,9 @@ def test_scalars_with_base_storage(ctx_factory): ctx = ctx_factory() queue = cl.CommandQueue(ctx) + import islpy as isl knl = lp.make_kernel( - "{ [i]: 0<=i<1}", + [isl.BasicSet("[] -> {[]: }")], # empty (domain w/unused inames errors) "a = 1", [lp.TemporaryVariable("a", dtype=np.float64, shape=(), base_storage="base")]) diff --git a/test/test_sem_reagan.py b/test/test_sem_reagan.py index e022e92f3712d984c1ad68061d0052240ff9d20c..54c64e0a4d4a23b429eb83be6c0a19f482a1b922 100644 --- a/test/test_sem_reagan.py +++ b/test/test_sem_reagan.py @@ -48,7 +48,7 @@ def test_tim2d(ctx_factory): # K - run-time symbolic knl = lp.make_kernel( - "{[i,j,e,m,o,o2,gi]: 0<=i,j,m,o,o2 {[]: }")], """ a, b = make_tuple(1, 2.) """) diff --git a/test/test_transform.py b/test/test_transform.py index d21d2c9da7ac28f119d3c5b475116dcc4b19e871..ffef893b05fbca5a0d244ff17f379e1bb5cf27a1 100644 --- a/test/test_transform.py +++ b/test/test_transform.py @@ -74,7 +74,7 @@ def test_collect_common_factors(ctx_factory): ctx = ctx_factory() knl = lp.make_kernel( - "{[i,j,k]: 0<=i,j out_tmp = 0 {id=out_init,inames=i} out_tmp = out_tmp + alpha[i]*a[i,j]*b1[j] {id=out_up1,dep=out_init} @@ -385,7 +385,7 @@ def test_precompute_nested_subst(ctx_factory): ctx = ctx_factory() knl = lp.make_kernel( - "{[i,j]: 0<=i