Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
a14809d
#3334 update docs
arporter Mar 26, 2026
7e04b46
#3334 update examples
arporter Mar 26, 2026
799d38c
#3334 update src files and 3_sequential tutorial
arporter Mar 26, 2026
08ce93b
#3334 fix missing import
arporter Mar 26, 2026
8db0256
#3334 add CalleeTransformationMixin
arporter Mar 26, 2026
aa5afc3
Merge branch 'master' into 3334_take_two
arporter Mar 26, 2026
998c87e
#3334 more code updates from old branch [skip ci]
arporter Mar 26, 2026
50facef
Merge branch '3334_take_two' of github.com:stfc/PSyclone into 3334_ta…
arporter Mar 26, 2026
3d5b9fd
#3334 WIP fixing GOcean tests [skip ci]
arporter Mar 27, 2026
6b94663
#3334 fix gocean transformation tests [skip ci]
arporter Mar 27, 2026
4a98a8d
#3334 fix domain/lfric tests [skip ci]
arporter Mar 27, 2026
947d946
#3334 fix psyir tests [skip ci]
arporter Mar 27, 2026
2b9f018
#3334 fix top-level tests [skip ci]
arporter Mar 27, 2026
1db152e
#3334 remove todo and add compilation check
arporter Mar 27, 2026
6c5d0ef
#3334 linting and add compilation check to second test
arporter Mar 27, 2026
4468e33
#3334 fix docs and revert some changes
arporter Mar 27, 2026
9930a79
#3334 mv pre-declaration of Routine symbols in bare file to _program_…
arporter Mar 27, 2026
373c5e6
#4333 make InlineTrans inherit from CalleeTransformationMixin
arporter Mar 27, 2026
bdf88f4
#3334 add new test file for CalleeTransformationMixin
arporter Mar 30, 2026
be4bdd0
#3334 add parent argument to Routine.create() method and use in fpars…
arporter Mar 30, 2026
eacfe37
#3334 minor tidying
arporter Mar 30, 2026
5032ef7
#3334 rm un-needed Kernel name setter
arporter Mar 30, 2026
41923ab
Merge branch 'master' into 3334_take_two
arporter Apr 15, 2026
7305d42
#3388 update configuration and generator
arporter Apr 15, 2026
745218b
#3334 update missed docs
arporter Apr 15, 2026
28151f6
#3334 update the globalstoargs validation and put back test
arporter Apr 15, 2026
37d5219
Merge branch 'master' into 3334_take_two
arporter Apr 15, 2026
9f8bd35
#3334 Update changelog
sergisiso Apr 20, 2026
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
4 changes: 4 additions & 0 deletions changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
4) PR #3388 for #3334. Remove the functionality to write (and rename)
kernel files from the invoke. Now to modify kernels they must be inlinded
first or modified directy in their file (e.g. with lfric transmute pass).

3) PR #3351 towards #3083. Adds scaffolding for new Treesitter-based
frontend.

Expand Down
31 changes: 0 additions & 31 deletions doc/developer_guide/APIs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -949,37 +949,6 @@ exchange before the loop) or add existing halo exchanges after a loop
(as an increase in depth will only make it more likely that a halo
exchange is no longer required after the loop).

Kernel Transformations
++++++++++++++++++++++

Since PSyclone is invoked separately for each Algorithm file in an
application, the naming of the new, transformed kernels is done with
reference to the kernel output directory. All transformed kernels (and
the modules that contain them) are re-named following the PSyclone
Fortran naming conventions (:ref:`lfric-conventions`). This enables the
reliable identification of transformed versions of any given kernel
within the output directory.

If the "multiple" kernel-renaming scheme is in use, PSyclone simply
appends an integer to the original kernel name, checks whether such a
kernel is present in the output directory and if not, creates it. If a
kernel with the generated name is present then the integer is
incremented and the process repeated. If the "single" kernel-renaming
scheme is in use, the same procedure is followed but if a matching
kernel is already present in the output directory then the new kernel
is not written (and we check that the contents of the existing kernel
are the same as the one we would create).

If an application is being built in parallel then it is possible that
different invocations of PSyclone will happen simultaneously and
therefore we must take care to avoid race conditions when querying the
filesystem. For this reason we use ``os.open``::

fd = os.open(<filename>, os.O_CREAT | os.O_WRONLY | os.O_EXCL)

The ``os.O_CREATE`` and ``os.O_EXCL`` flags in combination mean that
``open()`` raises an error if the file in question already exists.

Colouring
+++++++++

Expand Down
19 changes: 0 additions & 19 deletions doc/developer_guide/transformations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,25 +45,6 @@
Transformations
###############

Kernel Transformations
======================

PSyclone is able to perform kernel transformations by obtaining the PSyIR
representation of the kernel with:

.. automethod:: psyclone.psyGen.CodedKern.get_callees
:no-index:

The result of `psyclone.psyGen.Kern.get_callees` is a list of
`psyclone.psyir.nodes.KernelSchedule` objects. `KernelSchedule` is a
specialisation of the `Routine` class with the `is_program` and `return_type`
properties set to False` and `None`, respectively.

In addition to modifying the kernel PSyIR with the desired transformations,
the `modified` flag of the `CodedKern` node has to be set. This will let
PSyclone know which kernel files it may have to rename and rewrite
during the code generation.

Raising Transformations
=======================

Expand Down
8 changes: 4 additions & 4 deletions doc/developer_guide/working_practises.rst
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,12 @@ fortran_writer Provides a Fortran PSyIR back-end object to convert PSyIR
have_graphviz True if the Python bindings to the graphviz package (used when
generating DAG visualisations) are available. Does *not* check
that the underlying graphviz library is installed.
kernel_outputdir Sets the output directory used by PSyclone for transformed
kernel_outputdir Sets the output directory used by PSyclone for generated
kernels to be `tmpdir` (a built-in pytest fixture) and then
returns `tmpdir`. Any test that directly or indirectly causes
kernels to be transformed needs to use this fixture in order
to avoid having unwanted files created within the git working
tree.
OpenCL versions of kernels to be created must use this fixture
in order to avoid having unwanted files created within the git
working tree.
parser Creates an fparser2 parser for the Fortran2008 standard. This
is an expensive operation so this fixture is only run once
per test session.
Expand Down
5 changes: 1 addition & 4 deletions doc/user_guide/getting_going.rst
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,6 @@ command. To list the available options run: ``psyclone -h``, it should output::
[--backend {disable-validation,disable-indentation}] [-o OUTPUT_FILE]
[-api DSL] [-oalg OUTPUT_ALGORITHM_FILE] [-opsy OUTPUT_PSY_FILE]
[-okern OUTPUT_KERNEL_PATH] [-dm] [-nodm]
[--kernel-renaming {multiple,single}]
[--log-level {OFF,DEBUG,INFO,WARNING,ERROR,CRITICAL}] [--log-file LOG_FILE]
[--keep-comments] [--keep-directives] [-I INCLUDE] [-d DIRECTORY]
[--modman-file-ignore IGNORE_PATTERN] [--free-form | --fixed-form]
Expand Down Expand Up @@ -216,12 +215,10 @@ command. To list the available options run: ``psyclone -h``, it should output::
-opsy OUTPUT_PSY_FILE
(psykal mode) filename of generated PSy-layer code
-okern OUTPUT_KERNEL_PATH
(psykal mode) directory in which to put transformed kernels, default
(psykal mode) directory in which to put any generated kernels, default
is the current working directory
-dm, --dist_mem (psykal mode) generate distributed memory code
-nodm, --no_dist_mem (psykal mode) do not generate distributed memory code
--kernel-renaming {multiple,single}
(psykal mode) naming scheme to use when re-naming transformed kernels
--log-level {OFF,DEBUG,INFO,WARNING,ERROR,CRITICAL}
sets the level of the logging (defaults to OFF).
--log-file LOG_FILE sets the output file to use for logging (defaults to stderr).
Expand Down
35 changes: 3 additions & 32 deletions doc/user_guide/psyclone_command.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ by the command:
[-l {off,all,output}] [-p {invokes,routines,kernels}]
[-o OUTPUT_FILE] [-api DSL] [-oalg OUTPUT_ALGORITHM_FILE] [-opsy OUTPUT_PSY_FILE]
[-okern OUTPUT_KERNEL_PATH] [-dm] [-nodm]
[--kernel-renaming {multiple,single}]
[--log-level {OFF,DEBUG,INFO,WARNING,ERROR,CRITICAL}] [--log-file LOG_FILE]
[--keep-comments] [--keep-directives] [--keep-conditional-openmp-statements]
[-I INCLUDE] [-d DIRECTORY]
Expand Down Expand Up @@ -98,12 +97,10 @@ by the command:
-opsy OUTPUT_PSY_FILE
(psykal mode) filename of generated PSy-layer code
-okern OUTPUT_KERNEL_PATH
(psykal mode) directory in which to put transformed kernels, default
(psykal mode) directory in which to put any generated kernels, default
is the current working directory
-dm, --dist_mem (psykal mode) generate distributed memory code
-nodm, --no_dist_mem (psykal mode) do not generate distributed memory code
--kernel-renaming {multiple,single}
(psykal mode) naming scheme to use when re-naming transformed kernels
Comment thread
sergisiso marked this conversation as resolved.
--log-level {OFF,DEBUG,INFO,WARNING,ERROR,CRITICAL}
sets the level of the logging (defaults to OFF).
--log-file LOG_FILE sets the output file to use for logging (defaults to stderr).
Expand Down Expand Up @@ -389,6 +386,8 @@ For example the following command will generate GOcean PSyKAl code with DM:
See :ref:`psyclone usage for PSyKAl <psykal_usage>` section for more information
about how to use PSyKAl DSLs.

.. _psykal-file-output:

PSyKAl file output
^^^^^^^^^^^^^^^^^^

Expand Down Expand Up @@ -489,34 +488,6 @@ specified directory:
only one instance of the specified file within (or below) the
specified directories.

Transforming PSyKAl Kernels
^^^^^^^^^^^^^^^^^^^^^^^^^^^

When transforming kernels there are two use-cases to consider:

1. a given kernel will be transformed only once and that version
then used from multiple, different Invokes and Algorithms;
2. a given kernel is used from multiple, different Invokes and
Algorithms and is transformed differently, depending on the
Invoke.

Whenever PSyclone is used to transform a kernel, the new kernel must
be re-named in order to avoid clashing with other possible calls to
the original. By default (``--kernel-renaming multiple``), PSyclone
generates a new, unique name for each kernel that is
transformed. Since PSyclone is run on one Algorithm file at a time, it
uses the chosen kernel output directory (``-okern``) to ensure that
names created by different invocations do not clash. Therefore, when
building a single application, the same kernel output directory must
be used for each separate invocation of PSyclone.

Alternatively, in order to support use case 1, a user may specify
``--kernel-renaming single``: now, before transforming a kernel,
PSyclone will check the kernel output directory and if a transformed
version of that kernel is already present then that will be
used. Note, if the kernel file on disk does not match with what would
be generated then PSyclone will raise an exception.

Enabling the Logging Infrastructure
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down
103 changes: 46 additions & 57 deletions doc/user_guide/transformations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,9 @@ alphabetical order below (a number of these have specialisations which
can be found in the API-specific sections).

.. note:: PSyclone currently only supports OpenCL and
KernelImportsToArguments transformations for the GOcean 1.0
KernelImportsToArguments transformations for the GOcean
API, the OpenACC Data transformation is limited to
the generic code transformation and the GOcean 1.0 API and the
the generic code transformation and the GOcean API and the
OpenACC Kernels transformation is limited to the generic code
transformation and the LFRic API.

Expand Down Expand Up @@ -547,50 +547,36 @@ at this time no relevant transformations have been developed.
Kernels
-------

PSyclone supports the transformation of Kernels as well as PSy-layer
code. However, the transformation of kernels to produce new kernels
brings with it additional considerations, especially regarding the
naming of the resulting kernels. PSyclone supports two use cases:

1. the HPC expert wishes to optimise the same kernel in different ways,
depending on where/how it is called;
2. the HPC expert wishes to transform the kernel just once and have the
new version used throughout the Algorithm file.

The second case is really an optimisation of the first for the case
where the same set of transformations is applied to every instance of
a given kernel.

Since PSyclone is run separately for each Algorithm in a given
application, ensuring that there are no name clashes for kernels in
the application as a whole requires that some state is maintained
between PSyclone invocations. This is achieved by requiring that the
same kernel output directory is used for every invocation of PSyclone
when building a given application. However, this is under the control
of the user and therefore it is possible to use the same output
directory for a subset of algorithms that require the same kernel
transformation and then a different directory for another subset
requiring a different transformation. Of course, such use would
require care when building and linking the application since the
differently-optimised kernels would have the same names.

By default, transformed kernels are written to the current working
directory. Alternatively, the user may specify the location to which
to write the modified code via the ``-okern`` command-line flag.

In order to support the two use cases given above, PSyclone supports
two different kernel-renaming schemes: "multiple" and "single"
(specified via the ``--kernel-renaming`` command-line flag). In the
default, "multiple" scheme, PSyclone ensures that each transformed
kernel is given a unique name (with reference to the contents of the
kernel output directory). In the "single" scheme, it is assumed that
any given kernel that is transformed is always transformed in the same
way (or left unchanged) and thus just one transformed version of it is
created. This assumption is checked by examining the Fortran code for
any pre-existing transformed version of that kernel. If another
transformed version of that kernel exists and does not match that
created by the current transformation then PSyclone will raise an
exception.
In order to transform a PSyKAl Kernel while applying transformations to a
generated PSy layer, the kernel routine must first be brought into the
same source module as the PSy-layer subroutine from which it is called.
This is achieved using ``KernelModuleInlineTrans``:

.. autoclass:: psyclone.domain.common.transformations.KernelModuleInlineTrans
:noindex:

Once the PSy-layer has its own, private copy of the Kernel, it may
subsequently be transformed.

.. note:: Currently ``KernelModuleInlineTrans`` does not support re-naming
the in-lined Kernel routine. This means that *all* calls to that
Kernel in that source file are updated so as to call the same,
local copy. #2846 will lift this limitation.

To transform a kernel, one must first obtain its PSyIR with:

.. automethod:: psyclone.psyGen.CodedKern.get_callees
:no-index:

The result of ``psyclone.psyGen.Kern.get_callees`` is a list of
``psyclone.psyir.nodes.KernelSchedule`` objects. ``KernelSchedule`` is a
specialisation of the ``Routine`` class with the ``is_program`` and
``return_type`` properties set to ``False`` and ``None``, respectively.

.. note:: A Kernel can of course be transformed independently of constructing
a PSy layer by running PSyclone on the source file and treating it
as generic Fortran rather than a DSL Kernel. This is a matter for an
application's build system.

Rules
+++++
Expand Down Expand Up @@ -724,8 +710,8 @@ specified in the Kernel metadata (see the API-specific sections for
details) then PSyclone ensures the appropriate reduction is performed.

In the case of distributed memory, PSyclone will add **GlobalReduction**
nodes at the appropriate locations. These can be one of summation, mimimum value
or maximum value.
nodes at the appropriate locations. These can be one of summation, minimum
value or maximum value.

In the case of an OpenMP parallel loop, the standard reduction support
will be used by default. For example
Expand Down Expand Up @@ -774,6 +760,8 @@ caused by Taskloops, and adds OpenMP Taskwait statements to satisfy those
dependencies. An example of using OpenMP tasking is available in
`PSyclone/examples/nemo/eg1/openmp_taskloop_trans.py`.

.. _opencl:

OpenCL
------

Expand All @@ -791,9 +779,9 @@ OpenCL functionality. It also relies upon the device acceleration support
provided by the dl_esm_inf library (https://github.com/stfc/dl_esm_inf).


.. note:: The generated OpenCL kernels are written in a file called
opencl_kernels_<index>.cl where the index keeps increasing if the
file name already exist.
.. note:: The generated OpenCL kernels are written to the kernel output directory
(see :ref:`psykal-file-output`) in a file called ``opencl_kernels_<index>.cl``
where the index keeps increasing if the file name already exists.


The ``GOOpenCLTrans`` transformation accepts an `options` argument with a
Expand Down Expand Up @@ -905,12 +893,13 @@ porting and/or debugging of an OpenACC application as it provides
explicit control over what data is present on a device for a given
(part of an) Invoke routine.

The NVIDIA compiler compiler provides an alternative approach to controlling
data movement through its 'managed memory' option
(``-gpu=mem:managed``). When this is enabled the compiler itself takes
on the task of ensuring that data is copied to/from the GPU when
required. (Note that this approach can struggle with Fortran code
containing derived types however.)
GPU vendors often provide an alternative approach to controlling
data movement through a 'managed memory' option (``-gpu=mem:managed`` for
NVIDIA). When this is enabled, data is copied to/from the
GPU using the operating system's page-fault mechanism.
(Note that this approach can suffer from 'thrashing' if both CPU and GPU
frequently access data held in the same page. This can be a particular
issue for Fortran code containing derived types.)

As well as ensuring the correct data is copied to and from the remote
device, OpenACC directives must also be added to a code in order to
Expand Down
4 changes: 1 addition & 3 deletions examples/gocean/eg1/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,6 @@ dag:
openacc:
$(ENV) ${PYTHON} ./runme_openacc.py

# The "--kernel-renaming single" parameter avoids generating duplicate
# versions of OpenCL kernels called multiple times.
opencl:
${PSYCLONE} -nodm -s ./opencl_transformation.py --kernel-renaming single \
${PSYCLONE} -nodm -s ./opencl_transformation.py \
-api gocean -I${INF_INC} shallow_alg.f90
20 changes: 12 additions & 8 deletions examples/gocean/eg1/opencl_transformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,24 +36,26 @@
''' Module providing a PSyclone transformation script that converts the
Schedule of each Invoke to use OpenCL. '''

from psyclone.psyGen import TransInfo, InvokeSchedule
from psyclone.domain.gocean.transformations import GOOpenCLTrans, \
GOMoveIterationBoundariesInsideKernelTrans
from psyclone.psyGen import InvokeSchedule
from psyclone.domain.common.transformations import KernelModuleInlineTrans
from psyclone.domain.gocean.transformations import (
GOOpenCLTrans, GOMoveIterationBoundariesInsideKernelTrans)
from psyclone.psyir.nodes import FileContainer
from psyclone.transformations import KernelImportsToArguments


def trans(psyir):
def trans(psyir: FileContainer):
'''
Transformation routine for use with PSyclone. Converts any imported-
variable accesses into kernel arguments and then applies the OpenCL
transformation to the PSy layer.

:param psyir: the PSyIR of the PSy-layer.
:type psyir: :py:class:`psyclone.psyir.nodes.FileContainer`

'''
# Get the necessary transformations
tinfo = TransInfo()
import_trans = tinfo.get_trans_name('KernelImportsToArguments')
import_trans = KernelImportsToArguments()
mod_inline_trans = KernelModuleInlineTrans()
move_boundaries_trans = GOMoveIterationBoundariesInsideKernelTrans()
cltrans = GOOpenCLTrans()

Expand All @@ -67,9 +69,11 @@ def trans(psyir):
continue

# Remove the imports from inside each kernel and move PSy-layer
# loop boundaries inside the kernel as a mask.
# loop boundaries inside the kernel as a mask. To do this we must
# first module-inline the kernel into the PSy layer module.
for kern in schedule.kernels():
print("Update kernel: " + kern.name)
mod_inline_trans.apply(kern)
move_boundaries_trans.apply(kern)
import_trans.apply(kern)

Expand Down
Loading
Loading