-
Notifications
You must be signed in to change notification settings - Fork 72
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
base: main
Are you sure you want to change the base?
Dependency finding #704
Conversation
loopy/kernel/dependency.py
Outdated
variable_name: Optional[str] | ||
instances_rel: Optional[Map] | ||
|
||
class AccessMapMapper(WalkMapper): |
There was a problem hiding this comment.
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
)
loopy/kernel/dependency.py
Outdated
self._var_names = var_names | ||
|
||
from collections import defaultdict | ||
self.access_maps = defaultdict(lambda: |
There was a problem hiding this comment.
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.
loopy/kernel/dependency.py
Outdated
|
||
super.__init__() | ||
|
||
def map_subscript(self, expr, inames, insn_id): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Think about type annotation
loopy/kernel/dependency.py
Outdated
try: | ||
access_map = get_access_map(domain, subscript) | ||
except UnableToDetermineAccessRangeError: | ||
return |
There was a problem hiding this comment.
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?
loopy/kernel/dependency.py
Outdated
except UnableToDetermineAccessRangeError: | ||
return | ||
|
||
if self.access_maps[insn_id][arg_name][inames] is None: |
There was a problem hiding this comment.
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?
loopy/kernel/dependency.py
Outdated
} | ||
|
||
new_insns = [] | ||
for insn in knl.instructions: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Think about transitive dependencies
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
git grep -i transitive
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: |
There was a problem hiding this comment.
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.
cededcd
to
01d3688
Compare
assert shared_inames_order_after == shared_inames_order_before | ||
shared_inames_order = shared_inames_order_after |
There was a problem hiding this comment.
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?
…ng for successive instructions
loopy/kernel/dependency.py
Outdated
def map_linear_subscript(self, expr, insn): | ||
self.rec(expr.index, insn) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably error.
loopy/kernel/dependency.py
Outdated
|
||
amf = AccessMapFinder(knl) | ||
for insn in knl.instructions: | ||
amf(insn.assignee, insn) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CallInstruction
s) have more than one assignee.
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: |
There was a problem hiding this comment.
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?
loopy/kernel/dependency.py
Outdated
|
||
def __init__(self, knl: LoopKernel) -> None: | ||
self.kernel = knl | ||
self.access_maps = defaultdict(lambda: defaultdict(lambda: None)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe avoid defaultdict
s?
loopy/kernel/dependency.py
Outdated
domain, subscript, self.kernel.assumptions | ||
) | ||
|
||
if self.access_maps[insn.id][arg_name]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if self.access_maps[insn.id][arg_name]: | |
if self.access_maps[insn.id][arg_name] is not None: |
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): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
def map_type_cast(self, expr, inames): | |
def map_type_cast(self, expr, insn): |
loopy/kernel/dependency.py
Outdated
accessed_by = reader_map.get(variable, set()) | \ | ||
writer_map.get(variable, set()) |
There was a problem hiding this comment.
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?
…fter are both specified
…hic_... and apply_single_writer...
919dc51
to
d361167
Compare
…ndency finding in narrow_dependencies [skip ci]
happens_after=( | ||
red_realize_ctx.surrounding_depends_on | ||
| frozenset([init_id, init_neutral_id])), |
There was a problem hiding this comment.
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?
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lexicographic or lexical?
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 |
There was a problem hiding this comment.
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.
loopy/kernel/dependency.py
Outdated
statements. | ||
""" | ||
|
||
assert isinstance(insn.id, str) # stop complaints |
There was a problem hiding this comment.
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
.
loopy/transform/dependency.py
Outdated
t_sort = compute_topological_order(deps_dag) | ||
|
||
for insn_id in t_sort: | ||
transitive_deps[insn_id] = reduce( |
There was a problem hiding this comment.
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.
loopy/transform/dependency.py
Outdated
lex_map = insn.happens_after[dependency].instances_rel | ||
else: | ||
lex_map = dep_map.lex_lt_map(dep_map) |
There was a problem hiding this comment.
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.
…computing dependencies
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.