api: fix handling of multiple conditions for buffering - #2850
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #2850 +/- ##
==========================================
- Coverage 83.54% 79.25% -4.30%
==========================================
Files 257 257
Lines 53922 54159 +237
Branches 4613 4661 +48
==========================================
- Hits 45050 42923 -2127
- Misses 8074 10381 +2307
- Partials 798 855 +57
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
| return CondNe(*self.args, evaluate=False) | ||
|
|
||
| @property | ||
| def _as_min(self): |
There was a problem hiding this comment.
I would drop this and rather have a singledispatch handler for CondEq where necessary
|
|
||
| def relational_shift(expr, s): | ||
| """ | ||
| Infer shift incurred by the expression. Generally only |
There was a problem hiding this comment.
I could use an example here to quickly visualise what's it trying to do
| expr = uxreplace(expr, {d: IntDiv(index, d.symbolic_factor)}) | ||
|
|
||
| # Merge conditionals when possible. E.g if we have an implicit_dim | ||
| # and there is a dimension with the same parent, we ca merged |
There was a problem hiding this comment.
Dimension
"ca merged"
"their conditions"
you could also make the example a bit more practical
| for d in input_expr.implicit_dims: | ||
| if d not in conditionals: | ||
| continue | ||
| for cd in dict(conditionals): |
| # Replace the ConditionalDimensions in `expr` | ||
| for d, cond in conditionals.items(): | ||
| # Replace dimension with index | ||
| index = d.index |
There was a problem hiding this comment.
you can spare this line
| ispace = IterationSpace(intervals, iterators) | ||
|
|
||
| # Construct the conditionals and replace the ConditionalDimensions in `expr` | ||
| # Construct the conditionals |
There was a problem hiding this comment.
I think we should place this whole block of code, which constructs/lowers the conditionals, into its own separate functions, and a docstring with some examples
ef708e5 to
b997156
Compare
7a1a6aa to
c7786ea
Compare
|
Check out this pull request on See visual diffs & provide feedback on Jupyter Notebooks. Powered by ReviewNB |
f904760 to
0500469
Compare
| shift = relational_shift(cond, d.parent) | ||
| expr = uxreplace(expr, {d: IntDiv(index, d.symbolic_factor) + shift}) | ||
|
|
||
| # Merge conditionals when possible. E.g if we have an implicit_dim |
There was a problem hiding this comment.
btw this block imho deserves its own function
| if d is not dim: | ||
| continue | ||
|
|
||
| if d in c0.guards and not c0.guards[d].has(Mod): |
There was a problem hiding this comment.
searching for Mod is a bit meh, I'd rather add a special guard to ir/support/guards.py and look for that instead (there's quite a few already in there!)
| _actions_from_update_memcpy(c, d, clusters, actions, sregistry) | ||
| elif d.is_Custom and is_integer(c.ispace[d].size): | ||
| _actions_from_init(c, d, actions) | ||
| _actions_from_init(c, d, clusters, actions) |
|
|
||
|
|
||
| def _actions_from_init(c, d, actions): | ||
| def _actions_from_init(c, d, clusters, actions): |
0500469 to
30790f0
Compare
89aea51 to
99f0a9e
Compare
| if d not in conditionals: | ||
| continue | ||
| for cd in list(conditionals): | ||
| if cd.parent == d.parent and cd is not d: |
There was a problem hiding this comment.
nitpicking: cd.parent is d.parent ...
| continue | ||
| for cd in list(conditionals): | ||
| if cd.parent == d.parent and cd is not d: | ||
| cond = conditionals.pop(d) |
There was a problem hiding this comment.
nitpicking: you don't need this line here, you may just .pop in the else branch, and avoid the = cond in the if branch
|
|
||
| # Replace the ConditionalDimensions in `expr` | ||
| for d, cond in conditionals.items(): | ||
| # Replace dimension with index |
| def generate_conditionals(expr, input_expr, ordering): | ||
| """ | ||
| Generate the conditionals for the given expression, | ||
| based on the input expression and the ordering of dimensions. |
There was a problem hiding this comment.
nitpicking, we could take the opportunity to add some Examples to the docstring, or at least refer to ConditionalDimension.__doc__ ?
There was a problem hiding this comment.
There is additional docstring to ConditionalDimension.doc
| g = c0.guards.get(d) | ||
| # Explicit compute guards need no pipeline; memcpy clusters | ||
| # still need WithLock for the copy-back sync | ||
| if g is not None and not wraps_memcpy(c0): |
There was a problem hiding this comment.
I think a lot of the complexity inherent in this guard and the nested one could be mitigated by simply introducing somehting along the lines of c0.guards.has(d, GuardFactor)
|
|
||
| # Alias deferred entries to an existing f-buffer; create one if none | ||
| for f, deferred in extras.items(): | ||
| reusable = [mapper[(ff, kk)] for (ff, kk) in mapper if ff == f] |
| # Add all missing buffering dimensions and reorder to | ||
| # avoid duplicates with different ordering | ||
| ispaces.add(c.ispace.insert(self.dim, edims).reorder()) | ||
| elif ((self.f in c.scope.reads or self.f in c.scope.writes) and |
There was a problem hiding this comment.
self.f in c.scope.functions or in fact self.f in c.functions should suffice
|
|
||
| lhs = b.indexify()._subs(v.xd, v.first_idx.b) | ||
| rhs = f.indexify()._subs(v.dim, v.first_idx.f) | ||
| for b, vb in descriptors.items(): |
There was a problem hiding this comment.
another potential occurrence of descriptors.flatten
| ) | ||
| else: | ||
| size = async_degree | ||
| for k, ck in groupby(clusters, key=lambda c: c.guards): |
There was a problem hiding this comment.
ultra-uber-nitpicking, typically we use letter g for groups
| return p, offset | ||
|
|
||
|
|
||
| def _buffer_dim(f, key, ck): |
There was a problem hiding this comment.
this is potentially a legacy over-complication
is it basically what in PRO refer to as .hdim ?
because imho, if so, we could/should somehow abstract the concept here, and just use f.hdim (or whatever name you wanna give it)
99f0a9e to
bebbf4f
Compare
ab8cd52 to
b1147aa
Compare
|
|
||
| if not conditionals and not input_expr.implicit_dims: | ||
| return expr, conditionals | ||
| # Merge conditionals when possible. E.g., if an implicit_dim shares |
| if c.is_halo_touch: | ||
| hs = HaloScheme.union(e.rhs.halo_scheme for e in c.exprs) | ||
| queue.append(c.rebuild(exprs=[], halo_scheme=hs)) | ||
| # Peel syncs (e.g. a WaitLock) off, they must survive an unbound halo. |
There was a problem hiding this comment.
this could go one line above, then hs = shifts down here before the queue append...
also some blank lines
f0fbc35 to
3ca9d26
Compare
3ca9d26 to
b9eaa6e
Compare
No description provided.