From 8b9d59d39473a6780d2e2beedecd410089f83198 Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Tue, 12 Sep 2017 15:57:07 -0500 Subject: [PATCH 1/3] * Remove automatic uniquification of instruction ids in the kernel constructor. * Check that all instruction ids are unique on kernel creation. * Add a uniquify_instruction_ids() transform. This closes #89. --- loopy/kernel/__init__.py | 39 +--------------------------------- loopy/kernel/creation.py | 13 ++++++++++++ loopy/transform/instruction.py | 35 ++++++++++++++++++++++++++++++ test/test_transform.py | 17 +++++++++++++++ 4 files changed, 66 insertions(+), 38 deletions(-) diff --git a/loopy/kernel/__init__.py b/loopy/kernel/__init__.py index ad8643668..084c37b45 100644 --- a/loopy/kernel/__init__.py +++ b/loopy/kernel/__init__.py @@ -212,54 +212,17 @@ class LoopKernel(ImmutableRecordWithoutPickling): state=kernel_state.INITIAL, target=None, - overridden_get_grid_sizes_for_insn_ids=None, - uniquify_instruction_ids=True): + overridden_get_grid_sizes_for_insn_ids=None): """ :arg overridden_get_grid_sizes_for_insn_ids: A callable. When kernels get intersected in slab decomposition, their grid sizes shouldn't change. This provides a way to forward sub-kernel grid size requests. - - :arg uniquify_instruction_ids: Ensure all instruction IDs are unique and - convert any IDs that are :class:`loopy.kernel.creation.UniqueName` or - *None* into appropriate strings. If *False*, does not look at - `instructions`. """ if cache_manager is None: from loopy.kernel.tools import SetOperationCacheManager cache_manager = SetOperationCacheManager() - # {{{ make instruction ids unique - - if uniquify_instruction_ids: - from loopy.kernel.creation import UniqueName - - insn_ids = set() - for insn in instructions: - if insn.id is not None and not isinstance(insn.id, UniqueName): - if insn.id in insn_ids: - raise RuntimeError("duplicate instruction id: %s" % insn.id) - insn_ids.add(insn.id) - - insn_id_gen = UniqueNameGenerator(insn_ids) - - new_instructions = [] - - for insn in instructions: - if insn.id is None: - new_instructions.append( - insn.copy(id=insn_id_gen("insn"))) - elif isinstance(insn.id, UniqueName): - new_instructions.append( - insn.copy(id=insn_id_gen(insn.id.name))) - else: - new_instructions.append(insn) - - instructions = new_instructions - del new_instructions - - # }}} - # {{{ process assumptions if assumptions is None: diff --git a/loopy/kernel/creation.py b/loopy/kernel/creation.py index aacd76c09..d9fff6631 100644 --- a/loopy/kernel/creation.py +++ b/loopy/kernel/creation.py @@ -1205,6 +1205,15 @@ def check_for_duplicate_names(knl): add_name(name, "substitution") +def check_for_duplicate_instruction_ids(knl): + insn_ids = set() + + for insn in knl.instructions: + if insn.id in insn_ids: + raise RuntimeError("duplicate instruction id: '%s'" % insn.id) + insn_ids.add(insn.id) + + def check_for_nonexistent_iname_deps(knl): for insn in knl.instructions: if not set(insn.within_inames) <= knl.all_inames(): @@ -1984,6 +1993,10 @@ def make_kernel(domains, instructions, kernel_data=["..."], **kwargs): target=target, **kwargs) + from loopy.transform.instruction import uniquify_instruction_ids + knl = uniquify_instruction_ids(knl) + check_for_duplicate_instruction_ids(knl) + if seq_dependencies: knl = add_sequential_dependencies(knl) diff --git a/loopy/transform/instruction.py b/loopy/transform/instruction.py index 2be78f8e5..37c5d85a1 100644 --- a/loopy/transform/instruction.py +++ b/loopy/transform/instruction.py @@ -301,4 +301,39 @@ def add_nosync(kernel, scope, source, sink, bidirectional=False, force=False): # }}} +# {{{ uniquify_instruction_ids + +def uniquify_instruction_ids(kernel): + """Converts any ids that are :class:`loopy.UniqueName` or *None* into unique + strings. + + This function does *not* deduplicate existing instruction ids. + """ + + from loopy.kernel.creation import UniqueName + + insn_ids = set( + insn.id for insn in kernel.instructions + if insn.id is not None and not isinstance(insn.id, UniqueName)) + + from pytools import UniqueNameGenerator + insn_id_gen = UniqueNameGenerator(insn_ids) + + new_instructions = [] + + for insn in kernel.instructions: + if insn.id is None: + new_instructions.append( + insn.copy(id=insn_id_gen("insn"))) + elif isinstance(insn.id, UniqueName): + new_instructions.append( + insn.copy(id=insn_id_gen(insn.id.name))) + else: + new_instructions.append(insn) + + return kernel.copy(instructions=new_instructions) + +# }}} + + # vim: foldmethod=marker diff --git a/test/test_transform.py b/test/test_transform.py index b5fcdf04c..d17f6c707 100644 --- a/test/test_transform.py +++ b/test/test_transform.py @@ -438,6 +438,23 @@ def test_add_nosync(): assert frozenset([("insn5", "local")]) == knl.id_to_insn["insn6"].no_sync_with +def test_uniquify_instruction_ids(): + i1 = lp.Assignment("b", 1, id=None) + i2 = lp.Assignment("b", 1, id=None) + i3 = lp.Assignment("b", 1, id=lp.UniqueName("b")) + i4 = lp.Assignment("b", 1, id=lp.UniqueName("b")) + + knl = lp.make_kernel("{[i]: i = 1}", []).copy(instructions=[i1, i2, i3, i4]) + + from loopy.transform.instruction import uniquify_instruction_ids + knl = uniquify_instruction_ids(knl) + + insn_ids = set(insn.id for insn in knl.instructions) + + assert len(insn_ids) == 4 + assert all(isinstance(id, str) for id in insn_ids) + + if __name__ == "__main__": if len(sys.argv) > 1: exec(sys.argv[1]) -- GitLab From bb6013e973ad7e9dcd57334c055e46c3df7dd0c4 Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Tue, 12 Sep 2017 16:04:13 -0500 Subject: [PATCH 2/3] Make the duplicate instruction id check also run at preprocess. --- loopy/check.py | 10 ++++++++++ loopy/kernel/creation.py | 12 ++---------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/loopy/check.py b/loopy/check.py index 9115d740e..2ce9ffe0f 100644 --- a/loopy/check.py +++ b/loopy/check.py @@ -96,6 +96,15 @@ def check_insn_attributes(kernel): ", ".join(no_sync_with_scopes - VALID_NOSYNC_SCOPES))) +def check_for_duplicate_insn_ids(knl): + insn_ids = set() + + for insn in knl.instructions: + if insn.id in insn_ids: + raise LoopyError("duplicate instruction id: '%s'" % insn.id) + insn_ids.add(insn.id) + + def check_loop_priority_inames_known(kernel): for prio in kernel.loop_priority: for iname in prio: @@ -375,6 +384,7 @@ def pre_schedule_checks(kernel): try: logger.debug("%s: pre-schedule check: start" % kernel.name) + check_for_duplicate_insn_ids(kernel) check_for_orphaned_user_hardware_axes(kernel) check_for_double_use_of_hw_axes(kernel) check_insn_attributes(kernel) diff --git a/loopy/kernel/creation.py b/loopy/kernel/creation.py index d9fff6631..c6618d62f 100644 --- a/loopy/kernel/creation.py +++ b/loopy/kernel/creation.py @@ -1205,15 +1205,6 @@ def check_for_duplicate_names(knl): add_name(name, "substitution") -def check_for_duplicate_instruction_ids(knl): - insn_ids = set() - - for insn in knl.instructions: - if insn.id in insn_ids: - raise RuntimeError("duplicate instruction id: '%s'" % insn.id) - insn_ids.add(insn.id) - - def check_for_nonexistent_iname_deps(knl): for insn in knl.instructions: if not set(insn.within_inames) <= knl.all_inames(): @@ -1995,7 +1986,8 @@ def make_kernel(domains, instructions, kernel_data=["..."], **kwargs): from loopy.transform.instruction import uniquify_instruction_ids knl = uniquify_instruction_ids(knl) - check_for_duplicate_instruction_ids(knl) + from loopy.check import check_for_duplicate_insn_ids + check_for_duplicate_insn_ids(knl) if seq_dependencies: knl = add_sequential_dependencies(knl) -- GitLab From 7e261c67bfeab5931d0c396c89d6bc91c02ef2b4 Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Tue, 12 Sep 2017 21:28:19 -0500 Subject: [PATCH 3/3] Check that instruction ids are strings. --- loopy/check.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/loopy/check.py b/loopy/check.py index 2ce9ffe0f..a8ec1ad35 100644 --- a/loopy/check.py +++ b/loopy/check.py @@ -100,6 +100,8 @@ def check_for_duplicate_insn_ids(knl): insn_ids = set() for insn in knl.instructions: + if not isinstance(insn.id, str): + raise LoopyError("instruction id %r is not a string" % insn.id) if insn.id in insn_ids: raise LoopyError("duplicate instruction id: '%s'" % insn.id) insn_ids.add(insn.id) -- GitLab