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.

Arguments for Scripts#

Scripts can take optional keyword arguments specified on the command line using the option –script-kwargs. The keyword arguments are specified in a string containing comma-delimited keyword:value pairs. For example:

psyclone -s ./optimise.py input_source.f90 \
         --script-kwargs "omp: True, tiling: [4,4]"

This will result in the additional keyword arguments for any transformation call:

def trans(psyir, omp: bool, tiling: list[int]):
    # Modify psyir tree

The arguments specified will be converted into a Python-style dictionary, e.g. omp: True, tiling: [4,4] will be parsed as {omp: True, tiling: [4,4]}. Therefore, the specified keyword arguments must make a valid dictionary. For example, [1,2] is not a valid keyword argument, because {[1,2]} is not valid Python (a list is not hashable), and 1:2 would not be valid, because the keys of keyword arguments must be strings.

Obviously, the called transformation functions (trans, but also trans_alg, see below) must accept the specified keyword arguments. If an undeclared keyword argument is specified on the command line, the following error will be raised:

psyclone -s ./omp_gpu_profile_trans.py --script-kwargs "undeclared: True" ...
Traceback (most recent call last):
...
TypeError: trans() got an unexpected keyword argument 'undeclared'

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.

Note that the trans_alg function will receive the same keyword arguments as the trans function if the PSyclone command line option --script-kwargs is used (see Arguments for Scripts). It is therefore important that both functions accept the same keyword arguments.