Skip to content

Dependency finding#704

Draft
a-alveyblanc wants to merge 55 commits intoinducer:mainfrom
a-alveyblanc:dependencies-wip
Draft

Dependency finding#704
a-alveyblanc wants to merge 55 commits intoinducer:mainfrom
a-alveyblanc:dependencies-wip

Conversation

@a-alveyblanc
Copy link
Copy Markdown
Contributor

New draft PR based on PR 683. Major change is that the HappensAfter data structure used to represent statement-level dependency relations has been implemented into the InstructionBase data structure.

@inducer inducer changed the title New branch for dependency finding Dependency finding Nov 14, 2022
@inducer inducer mentioned this pull request Nov 14, 2022
Comment thread loopy/kernel/dependency.py Outdated
variable_name: Optional[str]
instances_rel: Optional[Map]

class AccessMapMapper(WalkMapper):
Copy link
Copy Markdown
Owner

@inducer inducer Jan 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider making this a CombineMapper? (In that case, you'd need to define combine)

Comment thread loopy/kernel/dependency.py Outdated
self._var_names = var_names

from collections import defaultdict
self.access_maps = defaultdict(lambda:
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Document what the keys/values of these mappings are.

Comment thread loopy/kernel/dependency.py Outdated

super.__init__()

def map_subscript(self, expr, inames, insn_id):
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think about type annotation

Comment thread loopy/kernel/dependency.py Outdated
try:
access_map = get_access_map(domain, subscript)
except UnableToDetermineAccessRangeError:
return
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the conservative approach?

Comment thread loopy/kernel/dependency.py Outdated
except UnableToDetermineAccessRangeError:
return

if self.access_maps[insn_id][arg_name][inames] is None:
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about the else case?

Comment thread loopy/kernel/dependency.py Outdated
}

new_insns = []
for insn in knl.instructions:
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think about transitive dependencies

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

git grep -i transitive

Comment thread loopy/kernel/dependency.py Outdated
# return the kernel with the new instructions
return knl.copy(instructions=new_insns)

def add_lexicographic_happens_after(knl: LoopKernel) -> None:
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lexicographic happens before is the "coarsest" ordering, and the above would be the refinement of that based on data dependencies.

Comment on lines +197 to +198
assert shared_inames_order_after == shared_inames_order_before
shared_inames_order = shared_inames_order_after
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a big unresolved question here, in terms of what nesting order we should use for the shared inames. Right now, this uses the axis order in the domains, however we also already do have LoopKernel.loop_priority to indicate nesting order during code generation). If nothing else, this should make sure that the order produced is consistent with that. But there's also the option of using/introducing a different mechanism entirely for this.

@kaushikcfd, got an opinion?

Comment thread loopy/kernel/dependency.py Outdated
Comment on lines +78 to +79
def map_linear_subscript(self, expr, insn):
self.rec(expr.index, insn)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably error.

Comment thread loopy/kernel/dependency.py Outdated

amf = AccessMapFinder(knl)
for insn in knl.instructions:
amf(insn.assignee, insn)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Some instructions (specifically CallInstructions) have more than one assignee.

Comment thread loopy/kernel/dependency.py Outdated
def get_map(self, insn_id: str, variable_name: str) -> isl.Map:
try:
return self.access_maps[insn_id][variable_name]
except KeyError:
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this KeyError ever happen?

Comment thread loopy/kernel/dependency.py Outdated

def __init__(self, knl: LoopKernel) -> None:
self.kernel = knl
self.access_maps = defaultdict(lambda: defaultdict(lambda: None))
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe avoid defaultdicts?

Comment thread loopy/kernel/dependency.py Outdated
domain, subscript, self.kernel.assumptions
)

if self.access_maps[insn.id][arg_name]:
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if self.access_maps[insn.id][arg_name]:
if self.access_maps[insn.id][arg_name] is not None:

Comment thread loopy/kernel/dependency.py Outdated
def map_reduction(self, expr, insn):
return WalkMapper.map_reduction(self, expr, insn)

def map_type_cast(self, expr, inames):
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def map_type_cast(self, expr, inames):
def map_type_cast(self, expr, insn):

Comment thread loopy/kernel/dependency.py Outdated
Comment on lines +139 to +140
accessed_by = reader_map.get(variable, set()) | \
writer_map.get(variable, set())
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you still avoiding read-after-read?

…ndency finding in narrow_dependencies [skip ci]
Comment on lines +1192 to 1194
happens_after=(
red_realize_ctx.surrounding_depends_on
| frozenset([init_id, init_neutral_id])),
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new code suggests that happens_after is still a set?

Comment thread loopy/kernel/dependency.py Outdated

@for_each_kernel
def narrow_dependencies(knl: LoopKernel) -> LoopKernel:
"""Attempt to relax a strict (lexical) ordering between statements in a
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lexicographic or lexical?

Comment thread loopy/kernel/dependency.py Outdated

@for_each_kernel
def narrow_dependencies(knl: LoopKernel) -> LoopKernel:
"""Attempt to relax a strict (lexical) ordering between statements in a
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably not safe to assume that the input ordering is lexicographic.

Comment thread loopy/kernel/dependency.py Outdated
statements.
"""

assert isinstance(insn.id, str) # stop complaints
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Turns this into an actual type annotation in InstructionBase.

Comment thread loopy/transform/dependency.py Outdated
t_sort = compute_topological_order(deps_dag)

for insn_id in t_sort:
transitive_deps[insn_id] = reduce(
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

transitive_deps can't help but be quadratic in the size of the program.

Comment thread loopy/transform/dependency.py Outdated
Comment on lines +216 to +218
lex_map = insn.happens_after[dependency].instances_rel
else:
lex_map = dep_map.lex_lt_map(dep_map)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use the fine-grain/instance-level dependency info that's already in the kernel at this point.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants