Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dependency finding #704

Draft
wants to merge 55 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
9f097a3
Sketch out where precise dependencies might go in the IR
inducer Nov 7, 2022
779c2f0
New branch
a-alveyblanc Nov 8, 2022
365781d
Merge branch 'inducer:main' into dependencies-wip
a-alveyblanc Nov 14, 2022
6a58e1d
Added draft of new version of dependency finding
a-alveyblanc Jan 13, 2023
ba3fbf5
Added some documentation
a-alveyblanc Jan 13, 2023
990624b
Started implementation of add_lexicographic_...
a-alveyblanc Jan 20, 2023
93b4126
Update gitignore to ignore DS_STORE
a-alveyblanc Jan 20, 2023
01d3688
Sketch out add_lexicographic_happens_after
inducer Jan 20, 2023
51c460d
Add relation to HappensAfter data structure
a-alveyblanc Jan 21, 2023
f6b75dd
New version of data dependency finding, still WIP
a-alveyblanc Jan 29, 2023
8327c70
added read-after-write, write-after-read, write-after-write dep findi…
a-alveyblanc Feb 4, 2023
999446f
update documentation
a-alveyblanc Feb 6, 2023
f110b30
Added first implementation of dependency finding for non-successive i…
a-alveyblanc Feb 12, 2023
a671762
Minor fixes for some failing tests
a-alveyblanc Feb 14, 2023
34f5b90
Slight refactor to improve readability and remove repeated code
a-alveyblanc Feb 16, 2023
adb924c
Merge branch 'main' into dependencies-wip
a-alveyblanc Feb 16, 2023
a7eb364
More changes to fix failing CI
a-alveyblanc Feb 16, 2023
c23eff4
Some slight changes to fix failing CI and improve readability
a-alveyblanc Feb 16, 2023
1647d5a
More fixes for CI
a-alveyblanc Feb 16, 2023
055d7e3
Add knl.id_to_insn to find instructions from ids instead of looping t…
a-alveyblanc Feb 25, 2023
888291f
Change the way the new happens_after is updated when finding dependen…
a-alveyblanc Feb 28, 2023
b785738
Temporary changes for how to handle cases in which happens_after and …
a-alveyblanc Mar 6, 2023
457cb6f
Revert a change to a test that was not supposed to be changed
a-alveyblanc Mar 6, 2023
096e68b
pushing
a-alveyblanc Mar 20, 2023
1b9f186
Revert "pushing"
a-alveyblanc Mar 21, 2023
5f3a249
Refactor dependency finding code to eliminate bugs.
a-alveyblanc Mar 23, 2023
169e808
Attempt at fixing CI failures due to replacing happens_after with dep…
a-alveyblanc Mar 24, 2023
faa5f23
Remove HappensAfter import from where it never should have been
a-alveyblanc Mar 24, 2023
d3224d1
Minor tweaks. Add a function to print dependency info of a knl
a-alveyblanc Apr 6, 2023
a215511
Refactored code. Much shorter with better access map finding.
a-alveyblanc Apr 10, 2023
72ab7e7
Remove giant todo list from top of file, change printing code
a-alveyblanc Apr 10, 2023
590a8cf
Minor grammatical fix
a-alveyblanc Apr 10, 2023
5208fb6
Minor print function change
a-alveyblanc Apr 10, 2023
cf4b9bd
Implement map_sub_array_ref in AccessMapFinder
a-alveyblanc Apr 11, 2023
faff25c
Read-after-read dependency finding avoided
a-alveyblanc Apr 11, 2023
d967949
Change back to long version of dependency finding. Switch to using pmap
a-alveyblanc Apr 12, 2023
307aa83
Nested array access finding
a-alveyblanc Apr 12, 2023
808cef6
Allow depends_on to be passed as an argument for legacy purposes
a-alveyblanc Apr 17, 2023
8a28e7f
Fix issues found by mypy and pylint
a-alveyblanc Apr 17, 2023
5731025
Fix documentation issues, handle cases where depends_on and happens_a…
a-alveyblanc Apr 18, 2023
e745336
Fix dependency cylce introduced by interaction between add_lexicograp…
a-alveyblanc Apr 21, 2023
b9cc691
Add a possible solution for supporting scalars in dependency finding …
a-alveyblanc Apr 25, 2023
d361167
Pushing [skip ci]
a-alveyblanc Apr 25, 2023
16be472
Precompute coarse-grained dependencies, add traces of transitive depe…
a-alveyblanc May 1, 2023
8e0e384
Use fine-grain dependency information that exists in the kernel when …
a-alveyblanc May 8, 2023
69265b2
Fix failing pylint
a-alveyblanc May 8, 2023
8c42f69
Remove file that was accidentally created
a-alveyblanc May 8, 2023
970feb0
Some unimportant changes
a-alveyblanc Jun 8, 2023
5b98c84
Remove unnecessary tests
a-alveyblanc Jun 9, 2023
2043233
Fix failing doctests
a-alveyblanc Jun 13, 2023
1cea1b3
Remove some (currently) unnecessary changes
a-alveyblanc Jun 13, 2023
9131461
Remove accidentally added files
a-alveyblanc Jun 13, 2023
290c91e
Remove more (temporarily) unnecessary code to prep for compatibility …
a-alveyblanc Jun 13, 2023
7cd7ea0
Fix failing doctest
a-alveyblanc Jun 13, 2023
c1a553a
Merge branch 'inducer:main' into dependencies-wip
a-alveyblanc Sep 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ htmlcov
lextab.py
yacctab.py
.pytest_cache/*
.DS_STORE

loopy/_git_rev.py

Expand Down
5 changes: 5 additions & 0 deletions doc/ref_kernel.rst
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ Instructions

.. {{{

.. autoclass:: HappensAfter
.. autoclass:: InstructionBase

.. _assignments:
Expand Down Expand Up @@ -457,6 +458,10 @@ Loopy's expressions are a slight superset of the expressions supported by
TODO: Functions
TODO: Reductions

Dependencies
^^^^^^^^^^^^
.. automodule:: loopy.kernel.dependency

Function Call Instructions
^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down
2 changes: 2 additions & 0 deletions loopy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
# {{{ imported user interface

from loopy.kernel.instruction import (
HappensAfter,
LegacyStringInstructionTag, UseStreamingStoreTag,
MemoryOrdering,
MemoryScope,
Expand Down Expand Up @@ -172,6 +173,7 @@
"LoopKernel",
"KernelState",

"HappensAfter",
"LegacyStringInstructionTag", "UseStreamingStoreTag",
"MemoryOrdering",
"MemoryScope",
Expand Down
3 changes: 1 addition & 2 deletions loopy/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -1057,8 +1057,7 @@ def _check_variable_access_ordered_inner(kernel):
# depends_on: mapping from insn_ids to their dependencies
depends_on = {insn.id: set() for insn in kernel.instructions}
# rev_depends: mapping from insn_ids to their reverse deps.
rev_depends = {insn.id: set() for insn in kernel.instructions}

rev_depends = {insn.id: set() for insn in kernel.instructions}
for insn in kernel.instructions:
depends_on[insn.id].update(insn.depends_on)
for dep in insn.depends_on:
Expand Down
85 changes: 37 additions & 48 deletions loopy/kernel/creation.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ def subst_func(var):

def get_default_insn_options_dict():
return {
"depends_on": frozenset(),
"happens_after": frozenset(),
"depends_on_is_final": False,
"no_sync_with": frozenset(),
"groups": frozenset(),
Expand Down Expand Up @@ -289,14 +289,15 @@ def parse_nosync_option(opt_value):
result["depends_on_is_final"] = True
opt_value = (opt_value[1:]).strip()

result["depends_on"] = result["depends_on"].union(frozenset(
result["happens_after"] = result["happens_after"].union(frozenset(
intern(dep.strip()) for dep in opt_value.split(":")
if dep.strip()))

elif opt_key == "dep_query" and opt_value is not None:
from loopy.match import parse_match
match = parse_match(opt_value)
result["depends_on"] = result["depends_on"].union(frozenset([match]))
result["happens_after"] = result["happens_after"].union(
frozenset([match]))

elif opt_key == "nosync" and opt_value is not None:
if is_with_block:
Expand Down Expand Up @@ -684,6 +685,7 @@ def _count_open_paren_symbols(s):


def parse_instructions(instructions, defines):

if isinstance(instructions, str):
instructions = [instructions]

Expand Down Expand Up @@ -716,8 +718,8 @@ def intern_if_str(s):

copy_args = {
"id": intern_if_str(insn.id),
"depends_on": frozenset(intern_if_str(dep)
for dep in insn.depends_on),
"happens_after": frozenset(intern_if_str(dep)
for dep in insn.happens_after),
"groups": frozenset(checked_intern(grp) for grp in insn.groups),
"conflicts_with_groups": frozenset(
checked_intern(grp) for grp in insn.conflicts_with_groups),
Expand Down Expand Up @@ -834,11 +836,11 @@ def intern_if_str(s):
# If it's inside a for/with block, then it's
# final now.
bool(local_w_inames)),
depends_on=(
happens_after=(
(insn.depends_on
| insn_options_stack[-1]["depends_on"])
if insn_options_stack[-1]["depends_on"] is not None
else insn.depends_on),
| insn_options_stack[-1]["happens_after"])
if insn_options_stack[-1]["happens_after"] is not None
else insn.happens_after),
tags=(
insn.tags
| insn_options_stack[-1]["tags"]),
Expand Down Expand Up @@ -1441,32 +1443,6 @@ def add_assignment(base_name, expr, dtype, additional_inames):
# }}}


# {{{ add_sequential_dependencies

def add_sequential_dependencies(knl):
new_insns = []
prev_insn = None
for insn in knl.instructions:
depon = insn.depends_on
if depon is None:
depon = frozenset()

if prev_insn is not None:
depon = depon | frozenset((prev_insn.id,))

insn = insn.copy(
depends_on=depon,
depends_on_is_final=True)

new_insns.append(insn)

prev_insn = insn

return knl.copy(instructions=new_insns)

# }}}


# {{{ temporary variable creation

def create_temporaries(knl, default_order):
Expand Down Expand Up @@ -1794,18 +1770,20 @@ def resolve_dependencies(knl):
new_insns = []

for insn in knl.instructions:
depends_on = _resolve_dependencies(
"a dependency", knl, insn, insn.depends_on)
happens_after = _resolve_dependencies(
"a dependency", knl, insn, insn.happens_after)
no_sync_with = frozenset(
(resolved_insn_id, nosync_scope)
for nosync_dep, nosync_scope in insn.no_sync_with
for resolved_insn_id in
_resolve_dependencies("nosync", knl, insn, (nosync_dep,)))

if depends_on == insn.depends_on and no_sync_with == insn.no_sync_with:
if happens_after == insn.happens_after and \
no_sync_with == insn.no_sync_with:
new_insn = insn
else:
new_insn = insn.copy(depends_on=depends_on, no_sync_with=no_sync_with)
new_insn = insn.copy(happens_after=happens_after,
no_sync_with=no_sync_with)
new_insns.append(new_insn)

return knl.copy(instructions=new_insns)
Expand Down Expand Up @@ -1899,13 +1877,17 @@ def apply_single_writer_depencency_heuristic(kernel, warn_if_used=True,

# }}}

depends_on = insn.depends_on
if depends_on is None:
depends_on = frozenset()
happens_after = insn.happens_after

new_deps = frozenset(auto_deps) | depends_on
if not isinstance(happens_after, frozenset):
happens_after = frozenset(happens_after)

if new_deps != depends_on:
if happens_after is None:
happens_after = frozenset()

new_deps = frozenset(auto_deps) | frozenset(happens_after)

if new_deps != happens_after:
msg = (
"The single-writer dependency heuristic added dependencies "
"on instruction ID(s) '%s' to instruction ID '%s' after "
Expand All @@ -1914,13 +1896,13 @@ def apply_single_writer_depencency_heuristic(kernel, warn_if_used=True,
"To fix this, ensure that instruction dependencies "
"are added/resolved as soon as possible, ideally at kernel "
"creation time."
% (", ".join(new_deps - depends_on), insn.id))
% (", ".join(new_deps - happens_after), insn.id))
if warn_if_used:
warn_with_kernel(kernel, "single_writer_after_creation", msg)
if error_if_used:
raise LoopyError(msg)

insn = insn.copy(depends_on=new_deps)
insn = insn.copy(happens_after=new_deps)
changed = True

new_insns.append(insn)
Expand Down Expand Up @@ -2497,7 +2479,8 @@ def make_function(domains, instructions, kernel_data=None, **kwargs):
check_for_duplicate_insn_ids(knl)

if seq_dependencies:
knl = add_sequential_dependencies(knl)
from loopy.kernel.dependency import add_lexicographic_happens_after
knl = add_lexicographic_happens_after(knl)

assert len(knl.instructions) == len(inames_to_dup)

Expand Down Expand Up @@ -2539,7 +2522,13 @@ def make_function(domains, instructions, kernel_data=None, **kwargs):
knl = guess_arg_shape_if_requested(knl, default_order)
knl = apply_default_order_to_args(knl, default_order)
knl = resolve_dependencies(knl)
knl = apply_single_writer_depencency_heuristic(knl, warn_if_used=False)

from loopy.kernel.dependency import narrow_dependencies
knl = narrow_dependencies(knl)

# precise dependency semantics should not rely on this
if not seq_dependencies:
knl = apply_single_writer_depencency_heuristic(knl, warn_if_used=False)

# -------------------------------------------------------------------------
# Ordering dependency:
Expand Down
Loading