PSyclone User Scripts#

The standard way to transform a codebase using psyclone is through the The psyclone command tool, which has an optional -s <SCRIPT_NAME> flag that allows users to specify a transformation user script to programmatically modify the input code:

> psyclone -s optimise.py input_source.f90

In this case, the current directory is prepended to the Python search path PYTHONPATH which will then be used to try to find the script file. Thus, the search begins in the current directory and continues over any pre-existing directories in the search path, failing if the file cannot be found.

Alternatively, script files may be specified with a path. In this case the file must exist in the specified location. This location is then added to the Python search path PYTHONPATH as before. For example:

> psyclone -s ./optimise.py input_source.f90
> psyclone -s ../scripts/optimise.py input_source.f90
> psyclone -s /home/me/PSyclone/scripts/optimise.py input_source.f90

A valid PSyclone user script file must contain a trans function which accepts a PSyIR node representing the root of the psy-layer code (as a FileContainer):

def trans(psyir):
    # Modify psyir tree

The example below adds an OpenMP directive to a specific PSyKAL kernel:

def trans(psyir):
    from psyclone.transformations import OMPParallelLoopTrans
    from psyclone.psyir.node import Routine
    for subroutine in psyir.walk(Routine):
        if subroutine.name == 'invoke_0_v3_kernel_type':
            ol = OMPParallelLoopTrans()
            ol.apply(subroutine.children[0])

The script may apply as many transformations as is required for the intended optimisation, and may also apply transformations to all the routines (i.e. invokes and/or kernels) contained within the provided tree. The examples section provides a list of psyclone user scripts and associated usage instructions for multiple applications.

Script Global Variables#

In addition to the trans function, there are special global variables that can be set to control some of the behaviours of the front-end (before the optimisation function is applied). These are:

# List of all files that psyclone will skip processing
FILES_TO_SKIP = ["broken_file1.f90", "broken_file2.f90"]

# Whether to chase the imported modules to improve symbol information (it can
# also be a list of module filenames to limit the chasing to only specific
# modules). This has to be used in combination with '-I' command flag in order
# to point to the module location directory. We also strongly recommend using
# the '--enable-cache' flag to reduce the performance overhead.
RESOLVE_IMPORTS = ["relevant_module1.f90", "relevant_module2.f90"]

def trans(psyir):
    # Modify psyir tree

PSyKAl algorithm code transformations#

When using PSyKAl, the trans functions is used to transform the PSy-layer (the layer in charge of the Parallel-System and Loops traversal orders), however, a second optional transformation entry point trans_alg can be provided to directly transform the Algorithm-layer (this is currently only implemented for GOcean, but in the future it will also affect the LFRic DSL).

def trans_alg(psyir):
    # Modify algorithm psyir tree

As with the trans` function it is up to the script what it does with the algorithm PSyIR. Note that the trans_alg transformation is applied to the algorithm layer before the PSy-layer is generated so any changes applied to the algorithm layer will be reflected in the PSy-layer PSyIR tree object that is passed to the trans function.

For example, if the trans_alg function in the script merged two invoke calls into one then the PSyIR node passed to the trans function of the script would only contain one Routine associated with the merged invoke.

An example of the use of a script making use of the trans_alg function can be found in examples/gocean/eg7.