-
Notifications
You must be signed in to change notification settings - Fork 73
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
Changes from 5 commits
9f097a3
779c2f0
365781d
6a58e1d
ba3fbf5
990624b
93b4126
01d3688
51c460d
f6b75dd
8327c70
999446f
f110b30
a671762
34f5b90
adb924c
a7eb364
c23eff4
1647d5a
055d7e3
888291f
b785738
457cb6f
096e68b
1b9f186
5f3a249
169e808
faa5f23
d3224d1
a215511
72ab7e7
590a8cf
5208fb6
cf4b9bd
faff25c
d967949
307aa83
808cef6
8a28e7f
5731025
e745336
b9cc691
d361167
16be472
8e0e384
69265b2
8c42f69
970feb0
5b98c84
2043233
1cea1b3
9131461
290c91e
7cd7ea0
c1a553a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
import pymbolic.primitives as p | ||
|
||
from dataclasses import dataclass | ||
from islpy import Map | ||
from typing import FrozenSet, Optional, List | ||
|
||
from loopy import LoopKernel | ||
from loopy import InstructionBase | ||
from loopy.symbolic import WalkMapper | ||
|
||
@dataclass(frozen=True) | ||
class HappensAfter: | ||
variable_name: Optional[str] | ||
instances_rel: Optional[Map] | ||
|
||
class AccessMapMapper(WalkMapper): | ||
""" | ||
TODO Update this documentation so it reflects proper formatting | ||
|
||
Used instead of BatchedAccessMapMapper to get single access maps for each | ||
instruction. | ||
""" | ||
|
||
def __init__(self, kernel, var_names): | ||
self.kernel = kernel | ||
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 commentThe reason will be displayed to describe this comment to others. Learn more. Document what the keys/values of these mappings are. |
||
defaultdict(lambda: | ||
defaultdict(lambda: None))) | ||
|
||
super.__init__() | ||
|
||
def map_subscript(self, expr, inames, insn_id): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Think about type annotation |
||
|
||
domain = self.kernel.get_inames_domain(inames) | ||
|
||
# why do we need this? | ||
WalkMapper.map_subscript(self, expr, inames) | ||
|
||
assert isinstance(expr.aggregate, p.Variable) | ||
|
||
if expr.aggregate.name not in self._var_names: | ||
return | ||
|
||
arg_name = expr.aggregate.name | ||
subscript = expr.index_tuple | ||
|
||
descriptor = self.kernel.get_var_descriptor(arg_name) | ||
|
||
from loopy.diagnostic import UnableToDetermineAccessRangeError | ||
from loopy.symbolic import get_access_map | ||
|
||
try: | ||
access_map = get_access_map(domain, subscript) | ||
except UnableToDetermineAccessRangeError: | ||
return | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this the conservative approach? |
||
|
||
if self.access_maps[insn_id][arg_name][inames] is None: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about the |
||
self.access_maps[insn_id][arg_name][inames] = access_map | ||
|
||
def compute_happens_after(knl: LoopKernel) -> LoopKernel: | ||
""" | ||
TODO Update documentation to reflect the proper format. | ||
|
||
Determine dependency relations that exist between instructions. Similar to | ||
apply_single_writer_dependency_heuristic. Extremely rough draft. | ||
""" | ||
writer_map = knl.writer_map() | ||
variables = knl.all_variable_names - knl.inames.keys() | ||
|
||
amap = AccessMapMapper(knl, variables) | ||
|
||
dep_map = { | ||
insn.id: insn.read_dependency_names() - insn.within_inames | ||
for insn in knl.instructions | ||
} | ||
|
||
new_insns = [] | ||
for insn in knl.instructions: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
current_insn = insn.id | ||
inames = insn.within_inames | ||
|
||
new_happens_after = [] | ||
for var in dep_map[insn.id]: | ||
for writer in (writer_map.get(var, set()) - { current_insn }): | ||
|
||
# get relation for current instruction and a write instruction | ||
cur_relation = amap.access_maps[current_insn][var][inames] | ||
write_relation = amap.access_maps[writer][var][inames] | ||
|
||
# compute the dependency relation | ||
dep_relation = cur_relation.apply_range(write_relation.reverse()) | ||
|
||
# create the mapping from writer -> (variable, dependency rel'n) | ||
happens_after = HappensAfter(var, dep_relation) | ||
happens_after_mapping = { writer: happens_after } | ||
|
||
# add to the new list of dependencies | ||
new_happens_after |= happens_after_mapping | ||
|
||
# update happens_after of our current instruction with the mapping | ||
insn = insn.copy(happens_after=new_happens_after) | ||
new_insns.append(insn) | ||
|
||
# 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 commentThe 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. |
||
pass | ||
|
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 definecombine
)