Skip to content
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

(Closes #2774) Refactor matmul2code to allow for more permutations of full ranges #2795

Open
wants to merge 23 commits into
base: master
Choose a base branch
from

Conversation

DrTVockerodtMO
Copy link
Collaborator

Fixes #2774.

There was a hardcoded standard in PSyclone where for matrix multiplications, the first one or two indices must be full ranges (i.e.: the Fortran would be written as matrix(:,:,...) or vector(:,...)). However, Fortran can perform matrix multiplications with the full ranges in different orderings, as long as the shape conforms.

When recent LFRic changes re-ordered some of the operator index accesses, this shifted the full ranges into forbidden permutations.

This change addresses this issue by allowing more permutations that produce valid Fortran matmul code.

Description of changes
Added a new private method _get_full_range_split to matmul2code_trans.py, which splits information about full range and non full range nodes as well as performs some validation. For a given array, the method iterates over the children, and checks whether or not they are Range nodes. If the Range node is a full range, we append its position in the array to a list. If not, we throw an error. If it is not a Range node then its position and the node itself are appended to two different lists.

After the children are iterated over, if we have more than two full ranges then this array is not a valid input for matmul, so we throw an error. Otherwise, return the two lists containing the positions of the full range and non full range nodes in the array, as well as the non full range node list.

Some further validation is performed to ensure that the first matrix involved in the matmul has exactly two full ranges, and that the second matrix has one or two (since it can be a vector or matrix).

The orderings and list of non full range nodes are fed to the modified _create_matrix_ref to make the matrix reference.

Testing
A new test test_apply_matmat_reordered has been added which tests the expected behaviour directly, by feeding the PSyIR some Fortran code with spatially conforming but re-ordered (with respect to the old standard) matrices. Other tests will be modified since a lot of them tested aspects of the old standard that no longer apply.

@DrTVockerodtMO DrTVockerodtMO added bug enhancement LFRic Issue relates to the LFRic domain adjoint labels Nov 20, 2024
@DrTVockerodtMO DrTVockerodtMO self-assigned this Nov 20, 2024
Copy link

codecov bot commented Nov 20, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 99.88%. Comparing base (4cb5070) to head (8a5caa9).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #2795   +/-   ##
=======================================
  Coverage   99.88%   99.88%           
=======================================
  Files         356      356           
  Lines       49481    49511   +30     
=======================================
+ Hits        49423    49455   +32     
+ Misses         58       56    -2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.


🚨 Try these New Features:

@DrTVockerodtMO DrTVockerodtMO marked this pull request as ready for review November 20, 2024 14:23
Copy link
Member

@arporter arporter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good stuff @DrTVockerodtMO.
I think the fix/extension is good. Just a few minor things to tidy up and I've requested an extra test.
Although not strictly your fault, I note that the associated test file does not give 100% coverage - lines 424-425 are missed. You can see this by doing pytest --cov psyclone.psyir.transformations.intrinsics.matmul2code_trans -- cov-report term-missing psyir/transformations/intrinsics/matmul2code_trans_test.py. Could you take a look?
Please could you also update the class docstring of apply() to mention the restriction to full ranges and simple arrays (i.e. structures of arrays etc.).
I've fired off the integration tests so these can run in the meantime.

"multiplication, the second index of the 2nd argument 'y' must "
"be a full range." in str(excinfo.value))
assert ("Transformation Error: To use matmul2code_trans on matmul, "
"no more than two indices of the argument 'x' "
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

debug_string() again.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 10d5abb.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see now that I might have confused you here - apologies. I meant 'use debug_string() when creating the error message', not when testing it!

@arporter arporter added reviewed with actions Release Planning and creating PSyclone releases and removed under review labels Nov 21, 2024
@arporter
Copy link
Member

Just a note to say integration tests were OK (barring the expected failures).

@DrTVockerodtMO
Copy link
Collaborator Author

Good stuff @DrTVockerodtMO. I think the fix/extension is good. Just a few minor things to tidy up and I've requested an extra test. Although not strictly your fault, I note that the associated test file does not give 100% coverage - lines 424-425 are missed. You can see this by doing pytest --cov psyclone.psyir.transformations.intrinsics.matmul2code_trans -- cov-report term-missing psyir/transformations/intrinsics/matmul2code_trans_test.py. Could you take a look? Please could you also update the class docstring of apply() to mention the restriction to full ranges and simple arrays (i.e. structures of arrays etc.). I've fired off the integration tests so these can run in the meantime.

Changes should all be addressed. Regarding not covering lines 424-425, these lines have been replaced in favour of the new method of generating array references, which are tested by the new test that was requested.

assert ("To use matmul2code_trans on matmul, exactly two indices of the "
"1st argument 'x' must be full ranges "
"but found 1." in str(excinfo.value))
assert (f"To use {trans.name} on matmul, exactly two indices of the "
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please could you change this so that it checks that the output string is what we expect, rather than what we coded. i.e. this doesn't need to be an f-string - just hardwire in the values that we expect.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in c4d60bc.

assert ("Transformation Error: To use matmul2code_trans on matmul, "
"one or two indices of the 2nd argument 'y' "
"must be full ranges but found 0." in str(excinfo.value))
assert (f"Transformation Error: To use {trans.name} on matmul, "
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, no f-string here please.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in c4d60bc.

assert ("Transformation Error: To use matmul2code_trans on matmul, "
"each Range index of the argument 'x' must be a full range "
"but found non full range at position 2." in str(excinfo.value))
assert (f"Transformation Error: To use {trans.name} on matmul, "
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No f-string...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in c4d60bc.

assert ("Transformation Error: To use matmul2code_trans on matmul, "
"each Range index of the argument 'y' must be a full range "
"but found non full range at position 2." in str(excinfo.value))
assert (f"Transformation Error: To use {trans.name} on matmul, "
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No f-string...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in c4d60bc.

assert ("Transformation Error: To use matmul2code_trans on matmul, "
"no more than two indices of the argument 'x' "
"must be full ranges but found 3." in str(excinfo.value))
assert (f"Transformation Error: To use {trans.name} on matmul, "
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No f-string...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in c4d60bc.

assert ("Transformation Error: To use matmul2code_trans on matmul, "
"no more than two indices of the argument 'y' "
"must be full ranges but found 3." in str(excinfo.value))
assert (f"Transformation Error: To use {trans.name} on matmul, "
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No f-string...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in c4d60bc.

assert ("To use matmul2code_trans on matmul, each range on the result "
"variable 'result' must be a full range but found "
"result(2:4,2:5)" in str(excinfo.value))
assert (f"To use {trans.name} on matmul, each range on the result "
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"No f-string"

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in c4d60bc.

@arporter
Copy link
Member

Changes should all be addressed. Regarding not covering lines 424-425, these lines have been replaced in favour of the new method of generating array references, which are tested by the new test that was requested.

That's good but those lines are still there and are still not covered? On closer examination it looks as though this code will only work for something of the form result(:,:,any,other,indices) = matmul(....) but this isn't checked in validate. If it's not too hard, do you think you could generalise this bit too? Alternatively, we should check for this situation in validate and reject it.

Copy link
Member

@arporter arporter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Terry. Apologies for the confusion over the strings (KGOs) in the tests.
Apart from that, looking at the missed lines made me realise that we still seem to have an implicit assumption in the code about the form of the result array that we support.
We can either generalise this too or we can make the assumption explicit by checking for it in validate.
The good news is that the integration tests were all fine :-)

@@ -994,3 +998,40 @@ def test_apply_matmat_reordered(tmpdir, fortran_reader, fortran_writer):
" enddo\n"
" enddo\n" in out)
assert Compile(tmpdir).string_compiles(out)


def test_apply_matmat_varexpr_index(tmpdir, fortran_reader, fortran_writer):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding this test but note that it is actually 'matvec' and please update the doc string too - the second argument is a 1D slice.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 4629275.

:returns: the new reference to a matrix element.
:param List[int] loop_idx_order: list of indices in the original array \
where the loop_idx_symbols are.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was going to let this go but since there are other changes required, please could you rm this blank line and there's no need for the line-continuation chars (\) - we used to think they were necessary but Joerg pointed out that all we have to do is suitably indent any continued lines.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 4629275.

@DrTVockerodtMO
Copy link
Collaborator Author

Thanks Terry. Apologies for the confusion over the strings (KGOs) in the tests. Apart from that, looking at the missed lines made me realise that we still seem to have an implicit assumption in the code about the form of the result array that we support. We can either generalise this too or we can make the assumption explicit by checking for it in validate. The good news is that the integration tests were all fine :-)

Addressed in 4629275 and 703c3e1 which now has a different permutation of the result matrix in the calculation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
adjoint bug enhancement LFRic Issue relates to the LFRic domain Release Planning and creating PSyclone releases reviewed with actions
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[LFRic] [PSyAD] Change in operator index ordering does not match PSyAD's matmul standard
2 participants