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

(Towards #2271, closes #2278, closes #2849) Generalise reference_accesses() and use to tidy KernelModuleInlineTrans. #2825

Merged
merged 51 commits into from
Jan 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
4435fa8
#2271 add reference_accesses() to Literal, CodeBlock and ScopingNode
arporter Dec 11, 2024
ec4045f
#2271 improve ScopingNode implementation
arporter Dec 11, 2024
76026ac
#2271 remove all Kern.local_vars() methods and tests
arporter Dec 11, 2024
b765e55
#2271 fix issue with CodeBlock and add test
arporter Dec 11, 2024
0920bf9
#2271 WIP adding ScopingNode tests [skip ci]
arporter Dec 11, 2024
8501cba
#2271 add support and tests for symbols within ArrayTypes [skip ci]
arporter Dec 12, 2024
d1127e8
#2271 fix all tests
arporter Dec 12, 2024
0b1d398
#2271 fix linting
arporter Dec 12, 2024
4651016
#2271 update docstring
arporter Dec 13, 2024
d8e639b
#2271 add new AccessType.CALL and use to distinguish symbols that are…
arporter Dec 17, 2024
f031e65
#2271 fix flake8
arporter Dec 17, 2024
300c563
#2271 rm include_calls argument
arporter Dec 17, 2024
1846fa6
Merge branch 'master' into 2271_ref_accesses
arporter Dec 17, 2024
0d4846c
#2825 add COMPILE_TIME and INQUIRY AccessTypes. Remove special option…
arporter Dec 19, 2024
26eabf5
#2271 fix linting
arporter Dec 19, 2024
f417bc1
Merge branch 'master' into 2271_ref_accesses
arporter Dec 20, 2024
5a7671e
#2271 work through implications of adding various inquiry access type…
arporter Dec 20, 2024
7991f62
#2271 fix remaining test failures
arporter Dec 20, 2024
c55c45e
#2271 fixes for linting
arporter Dec 20, 2024
b568451
#2271 fix implementation and test of change_read_to_write()
arporter Dec 20, 2024
e541be5
Merge branch 'master' into 2271_ref_accesses
arporter Jan 6, 2025
bf242e6
#2271 improvements for review
arporter Jan 6, 2025
278b82e
#2271 fix linting
arporter Jan 6, 2025
b646667
#2271 final changes for review
arporter Jan 6, 2025
1ed438e
#2271 fix linting
arporter Jan 6, 2025
3bab6b7
#2271 fix type hint for older python
arporter Jan 6, 2025
e389463
#2271 address coverage
arporter Jan 7, 2025
1b583ff
Merge branch 'master' into 2271_ref_accesses
arporter Jan 7, 2025
8541f08
Merge branch 'master' into 2271_ref_accesses
arporter Jan 8, 2025
ce58e0c
#2271 extend ScopingNode.reference_accesses to handle UnsupportedFort…
arporter Jan 8, 2025
c5ee43f
Merge branch 'master' into 2271_ref_accesses
arporter Jan 14, 2025
125db1a
#2271 add new hoist_trans test from #2849
arporter Jan 15, 2025
ade8c70
#2271 bring in SymbolTable fix from 2845 branch
arporter Jan 17, 2025
c947427
#2271 fix OMPDirective.infer_sharing_attributes now that reference_ac…
arporter Jan 20, 2025
d59a610
#2271 fix bug in new code and extend test
arporter Jan 20, 2025
598bcd2
Merge branch 'master' into 2271_ref_accesses
arporter Jan 20, 2025
497f589
#2271 replace COMPILE_TIME with TYPE_INFO
arporter Jan 22, 2025
542c4b6
#2271 update text output from VAI for vars with no data access
arporter Jan 22, 2025
d28c8eb
#2271 update Dev Guide
arporter Jan 22, 2025
91e7ec2
#2271 updates for review
arporter Jan 22, 2025
9893b42
#2271 rm unused PSyDataTrans.get_default_options
arporter Jan 22, 2025
4a49d15
#2271 rm options from call_tree_utils methods
arporter Jan 22, 2025
bc22823
#2271 fix compilation target of nemo/eg6
arporter Jan 22, 2025
8394dc1
#2271 update AccessType tests
arporter Jan 22, 2025
2fabb05
#2271 Makefile fixes to ensure read_only psydata lib is cleaned
arporter Jan 22, 2025
21fe020
Merge branch 'master' into 2271_ref_accesses
arporter Jan 22, 2025
b731073
#2271 add allclean target to nemo/eg6/Makefile
arporter Jan 23, 2025
c09254e
#2271 change NO DATA ACCESS to NO_DATA_ACCESS
arporter Jan 23, 2025
23199f3
#2271 ensure F90FLAGS passed to compiler for final link in nemo eg6
arporter Jan 23, 2025
0884cbb
#2271 rm is_query() method from SVAI
arporter Jan 23, 2025
e4c1ad3
#2271 Update changelog
sergisiso Jan 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelog
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
13) PR #2862 for #2858. Change to PSyIR frontend and backend to ensure
existing parentheses in expressions are preserved.

14) PR #2825 for #2278 and #2849. Signatures AccessType now indentifies
INQUIRY and TYPE_INFO, for inquiry intrinsic accesses and precision symbols.

release 3.0.0 6th of December 2024

1) PR #2477 for #2463. Add support for Fortran Namelist statements.
Expand Down
46 changes: 20 additions & 26 deletions doc/developer_guide/dependency.rst
Original file line number Diff line number Diff line change
Expand Up @@ -263,16 +263,17 @@ DataAccess class i.e. the `_field_write_arguments()` and
Variable Accesses
=================

Especially in the NEMO API, it is not possible to rely on pre-defined
kernel information to determine dependencies between loops. So an additional,
somewhat lower-level API has been implemented that can be used to determine
variable accesses (READ, WRITE etc.), which is based on the PSyIR information.
The only exception to this is if a kernel is called, in which case the
metadata for the kernel declaration will be used to determine the variable
accesses for the call statement. The information about all variable usage
of a PSyIR node or a list of nodes can be gathered by creating an object of
type `psyclone.core.VariablesAccessInfo`.
This class uses a `Signature` object to keep track of the variables used.
When using PSyclone with generic Fortran code, it is not possible to
rely on pre-defined kernel information to determine dependencies
between loops. So an additional, somewhat lower-level API has been
implemented that can be used to determine variable accesses (READ,
WRITE etc.), which is based on the PSyIR information. The only
exception to this is if a kernel is called, in which case the metadata
for the kernel declaration will be used to determine the variable
accesses for the call statement. The information about all variable
usage of a PSyIR node or a list of nodes can be gathered by creating
an object of type `psyclone.core.VariablesAccessInfo`. This class
uses a `Signature` object to keep track of the variables used.

Signature
---------
Expand All @@ -289,6 +290,14 @@ a single component.
:members:
:special-members: __hash__, __eq__, __lt__

AccessType
----------

An individual access to a ``Signature`` is described by an instance of the
``AccessType`` enumeration:

.. autoclass:: psyclone.core.access_type.AccessType
:members:

VariablesAccessInfo
-------------------
Expand Down Expand Up @@ -319,22 +328,7 @@ instance is holding information about.
VariablesAccessInfo Options
+++++++++++++++++++++++++++

By default, `VariablesAccessInfo` will not report the first argument of
the PSyIR operators `lbound`, `ubound`, or `size` as read accesses,
since these functions do not actually access the content of the array,
they only query the size. If these accesses are required (e.g. in kernel
extraction this could be important if an array is only used in these
intrinsic - a driver would still need these arrays in order to query
the size), the optional `options` parameter of the `VariablesAccessInfo`
constructor can be used: add the key
`COLLECT-ARRAY-SHAPE-READS` and set it to true::

vai = VariablesAccessInfo(options={'COLLECT-ARRAY-SHAPE-READS': True})

In this case all arrays specified as first parameter to one of the
PSyIR operators above will be reported as read access.

Fortran also allows to rename a symbol locally when it is being imported,
Fortran allows an imported symbol to be renamed locally
(`use some_mod, only: renamed => original_name`). Depending on use case,
it might be useful to get the non-local, original name. By default,
`VariablesAccessInfo` will report the local name (i.e. the renamed name),
Expand Down
5 changes: 4 additions & 1 deletion examples/nemo/eg5/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,14 @@ kernels: extract_kernels.py
$(PSYCLONE) -l all -s ./extract_kernels.py -o psy.f90 ../code/tra_adv.F90

$(EXTRACT_DIR)/$(LIB_NAME):
make -C $(EXTRACT_DIR)
${MAKE} -C $(EXTRACT_DIR)

# Compilation uses the 'kernels' transformed code
psy.f90: kernels
psy.o: $(EXTRACT_DIR)/$(LIB_NAME)

%.o: %.f90
$(F90) $(F90FLAGS) -c $<

allclean: clean
${MAKE} -C ${EXTRACT_DIR} allclean
11 changes: 1 addition & 10 deletions examples/nemo/eg5/extract_kernels.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,16 +88,7 @@ def trans(psyir):
if not isinstance(kern, Loop):
continue
try:
# TODO #2080: once this is fixed, the option can be removed
# The example contains array expressions, e.g.:
# zwx(:,:,jpk) = 0.e0
# PSyclone represents this internally using Range with LBOUND
# and UBOUND intrinsics and currently this results in several
# occurrences of zws on the left hand side, which will trigger
# an exception in the dependency analysis. Therefore, disable
# the collection of read accesses for the shape of an array.
extract.apply(kern,
options={"COLLECT-ARRAY-SHAPE-READS": False})
extract.apply(kern)
except TransformationError as err:
# Typically that's caused by a kernel having a CodeBlock
# inside.
Expand Down
9 changes: 6 additions & 3 deletions examples/nemo/eg6/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ run: compile
./dummy

dummy: psy.o $(READ_ONLY_CHECK_DIR)/$(LIB_NAME)
$(F90) psy.o -o dummy $(READ_ONLY_CHECK_DIR)/$(LIB_NAME) $(LDFLAGS)
$(F90) $(F90FLAGS) psy.o -o dummy $(READ_ONLY_CHECK_DIR)/$(LIB_NAME) $(LDFLAGS)

transform: kernels

Expand All @@ -73,11 +73,14 @@ kernels: read_only_check.py
$(PSYCLONE) -l all -s ./read_only_check.py -o psy.f90 dummy.f90

$(READ_ONLY_CHECK_DIR)/$(LIB_NAME):
make -C $(READ_ONLY_CHECK_DIR)
$(MAKE) -C $(READ_ONLY_CHECK_DIR)

# Compilation uses the 'kernels' transformed code
psy.f90: dummy.f90 read_only_check.py
psy.f90: dummy.f90 read_only_check.py kernels
psy.o: $(READ_ONLY_CHECK_DIR)/$(LIB_NAME)

%.o: %.f90
$(F90) $(F90FLAGS) -c $<

allclean: clean
${MAKE} -C $(READ_ONLY_CHECK_DIR) allclean
2 changes: 1 addition & 1 deletion lib/read_only/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ read_only_base.o: psy_data_base.o
clean:
rm -f read_only_base.f90 psy_data_base.f90 *.o *.mod

allclean:
allclean: clean
$(MAKE) -C dl_esm_inf allclean
$(MAKE) -C lfric allclean
$(MAKE) -C generic allclean
62 changes: 45 additions & 17 deletions src/psyclone/core/access_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,54 +37,73 @@

'''This module implements the AccessType used throughout PSyclone.'''

from __future__ import print_function, absolute_import
from enum import Enum
from psyclone.configuration import Config


class AccessType(Enum):
'''A simple enum-class for the various valid access types.
'''

#: Data associated with the symbol is read.
READ = 1
#: Data associated with the symbols is written.
WRITE = 2
#: Data associated with the symbol is both read and written (e.g. is passed
#: to a routine with intent(inout)).
READWRITE = 3
#: Incremented from more than one cell column (see the LFRic API section
#: of the User Guide).
INC = 4
#: Read before incrementing. Requires that the outermost halo be clean (see
#: the LFRic API section of the User Guide).
READINC = 5
#: Is the output of a SUM reduction.
SUM = 6
# This is used internally to indicate unknown access type of
# a variable, e.g. when a variable is passed to a subroutine
# and the access type of this variable in the subroutine
# is unknown
#: This is used internally to indicate unknown access type of
#: a variable, e.g. when a variable is passed to a subroutine
#: and the access type of this variable in the subroutine
#: is unknown.
#: TODO #2863 - VariablesAccessInfo does not currently consider
#: UNKNOWN accesses and it should!
UNKNOWN = 7
#: A symbol representing a routine is called.
CALL = 8
#: The property/ies of a symbol is/are queried but the data it
#: represents is not accessed (e.g. 'var' in SIZE(var, dim=1)).
INQUIRY = 9
#: The symbol is used to access its type information (available at compile
#: time) - e.g. precision values such as 'wp' in 1.0_wp.
TYPE_INFO = 10

def __str__(self):
def __str__(self) -> str:
'''Convert to a string representation, returning just the
enum (e.g. 'WRITE')..
:return: API name for this string.
:rtype: str
sergisiso marked this conversation as resolved.
Show resolved Hide resolved
enum (e.g. 'WRITE').
'''
# pylint complains without str() that the return type is not a str
return str(self.name)

def api_specific_name(self):
def api_specific_name(self) -> str:
'''This convenience function returns the name of the type in the
current API. E.g. in a lfric API, WRITE --> "gh_write"
current API. E.g. in the lfric API, WRITE --> "gh_write". If no
mapping is available then the generic name is returned.

:returns: The API specific name.
:rtype: str
'''
api_config = Config.get().api_conf()
rev_access_mapping = api_config.get_reverse_access_mapping()
return rev_access_mapping[self]
return rev_access_mapping.get(self, str(self).lower())

@staticmethod
def from_string(access_string):
def from_string(access_string: str):
'''Convert a string (e.g. "read") into the corresponding
AccessType enum value (AccessType.READ).

:param str access_string: Access type as string.
:param access_string: Access type as a string.

:returns: Corresponding AccessType enum.
:Raises: ValueError if access_string is not a valid access type.
:rtype: :py:class:`psyclone.core.access_type.AccessType`
sergisiso marked this conversation as resolved.
Show resolved Hide resolved

:raises ValueError: if access_string is not a valid access type.
'''
for access in AccessType:
if access.name == access_string.upper():
Expand Down Expand Up @@ -128,6 +147,15 @@ def get_valid_reduction_names():
return [access.api_specific_name() for access in
AccessType.get_valid_reduction_modes()]

@staticmethod
def non_data_accesses():
'''
:returns: all access types that do not touch any data associated with
a symbol.
:rtype: list[:py:class:`psyclone.core.AccessType`]
'''
return [AccessType.CALL, AccessType.TYPE_INFO, AccessType.INQUIRY]


# ---------- Documentation utils -------------------------------------------- #
# The list of module members that we wish AutoAPI to generate
Expand Down
Loading
Loading