-
Notifications
You must be signed in to change notification settings - Fork 31
(closes #1320) Convert component indices to method #3164
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: master
Are you sure you want to change the base?
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #3164 +/- ##
==========================================
- Coverage 99.90% 99.90% -0.01%
==========================================
Files 376 374 -2
Lines 53048 52823 -225
==========================================
- Hits 52996 52771 -225
Misses 52 52 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
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.
Thanks Sergi, that's an impressive amount of code removed.
While I think it's a considerable improvement, I'm worried that it might break some of @hiker's workflows that aren't in our test suite. If so, we'll need to think about how we can handle that.
src/psyclone/domain/gocean/transformations/gocean_loop_fuse_trans.py
Outdated
Show resolved
Hide resolved
| # The stencil is 100, 110, 123 - test that appropriate | ||
| # accesses were added for each direction | ||
| expected = { | ||
| # First stencil direction of 123: 1 |
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.
So we no longer have information on the stencil accesses of this kernel as provided by the metadata?Obviously this hasn't broken anything in the test suite but does it break anything for @hiker (e.g. in training/tutorials)?
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.
Let me know if it does and I can have a look
|
I've set the integration tests going as that will help to set my mind at rest :-) |
|
@arporter This is ready for another review.
I am happy to have a look if something is reported, generally this can be solved by inlining. But I also have some ideas how we can handle it without inlining. |
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.
Thanks Sergi, very nearly there now.
I've pinged @hiker in Teams in case there's anything relating to GOcean stencils not covered by our test suite.
Just a bit of tidying to do.
| a tuple of each index expression in that compoment. For example, | ||
| for a scalar it returns `(())`, for `a%b` it returns ((),()) - two | ||
| components with 0 indicies in each, and for `a(i)%b(j,k+1)` it | ||
| :returns: a tuple of tuples of index expressions; one for every |
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.
To save confusion, I think it would be better to specialise this text for the class in question. i.e. "...expressions; since Member has no indices we return a tuple containing an empty tuple."
| a tuple of each index expression in that compoment. For example, | ||
| for a scalar it returns `(())`, for `a%b` it returns ((),()) - two | ||
| components with 0 indicies in each, and for `a(i)%b(j,k+1)` it | ||
| :returns: a tuple of tuples of index expressions; one for every |
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.
Again, please specialise this text (can be the same as Member).
| :param set_of_vars: set with name of all variables. | ||
| :return: a list of sets with all variables used in the | ||
| corresponding array subscripts as strings. |
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.
Strictly, this returns a list of lists of tuples now. Also the type-hint on the return type doesn't match.
| for i1, idx_exprs in enumerate(comp_ind1): | ||
| for i2, _ in enumerate(idx_exprs): | ||
| try: | ||
| partition_infos.append( |
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 description at L300 needs updating now that the content of partition_infos has changed.
|
|
||
| # Verify that the index expression is correct. First replace its | ||
| # strings with references to that symbol | ||
| # The elements in the paratrized indices are string names, but |
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.
"parameterised"
|
I have debugged why loop fusion in my training is now failing. Core reason is that (with this PR merged in) fields as kernel parameters are now detected to be scalars. E.g.: will now consider and that seems a likely candidate, since previously this function would ask its ComponentIndices :) In the past, I've added implicitly accesses to And then a gocen field is not considered an array (when checking the symbol info), and it fails. Should be easy to reproduce, fusing two gocean loops should trigger this problem (I am actually surprised that this was not picked up by the testing). If you need a test case, merge in branch |
|
I checked, surprisingly we seem to have NO tests for fusing gocean loops :(: |
|
Thanks for checking @hiker , I was expecting this at some point, so it is good to have an example. I'm happy for the training to be merged first if it's close to being ready. This is expected behaviour, let me explain.
Not quite. To know the datatype you would do arg.datatype, and this should return ArrayaType or UnresolvedType, but not ScalarType. Or arg.datatype.is_array (with None and False having different meaning) The 'has_indices' should return False to be consistent with the psyir because it has no indices, e.g. "call kernel1(arg1%data, ...)" To fix fusing there are 3 options (coming in the next comment as I need to get off the bus) |
|
I just describe two options I am thinking are (the third is not fleshed out):
This is the most similar to your current solution, and is resilient to kernels that can not be inlined, or that even inlinlined have complex bodies that can not be analysed. And because lowering the kernel replaces it, we get rid of the prototype assignment anyway. This also fixes #3124 If we do this I also want to consider lfric (where we need to do better fusion) and things like having indices in the algorithm invoke field, which the previous implementation didn't. What do you think @hiker? |
Correct me from wrong, but doesn't inlining need lowering first? Last time I tried (and that was a week or two ago), inlining gocean kernel did not work (in the training I actually overwrote the validate function to accept inlining gocean if the error is the known one). While I agree that inlining is beneficial, I am:
Hmm - yes. that looks very similar to what we have, but I wonder if that might not cause issues with other tools working on the tree if there is suddenly an additional statements? E.g. thinking of moving kernels etc. In this particular case, wouldn't it be easier to just use the information that we are in the gocean API, and that therefore the variable is an array? Now that I am writing this, that would probably only get us over the first hurdle (to detect that the fields are arrays). The next step in the array validation would take the indices into account (atm the validation for loop fusion is simplified in that it only allows same index expressions, e.g. I'll see if I can come up with a better idea? ATM ... I have nothing :) |
|
Oh, we have some gocean fuse tests in ./domain/gocean/transformations/gocean1p0_transformations_test.py, but they are mostly (all?) only testing errors :( |
Yes, this is why I said order matters, basically you need need to do in the script psykal_transfomrations->lowering->psyir_generic transformations. Following this order worked in Nemolite2D. But I agree with your points above, I was proposing this as a solution that works now, while we implement the other solution that may take longer.
Again, I don't think this is a hurdle, using arg.datatype should already give you this info. But has_indices should be False (as they don't have them :))
Moving the kernel is still fine (it moves together with its children). The one that requires a bit of care is hoisting, but even now it shouldn't let it hoist it across an unexpected kernel, like the kernelcall. The KernelCall is a high level kernel and we can define its children as we like. It can also be The advantage of the assignment is that we don't need to specialise reference_accesses for it. |
|
Ah, I actually didn't think it all the way through. I thought you were adding the accesses 'after' (i.e. next to the) kernel, but as child of the kernel that makes a lot more sense, I totally missed that. That sounds actually good, thanks! |
This is a step to reduce internal state of Signatures so they operatate on top of the PSyIR. In thi PR I removed the ComponentIndices class (and associated infrastructure) and the argument in add_accesses. Instead I moved the logic to a method of Reference. So now, we just need to do:
access_sequence.add_access(AccessType.READ, ArrayReference(Symbol("a")))and once the component_indices are needed the AccessSequence can do self.node.component_indicies()