-
Notifications
You must be signed in to change notification settings - Fork 79
Dependency finding #704
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
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.
CallInstructions) 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 defaultdicts?
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.