Exemple #1
0
def trans(psy):
    ''' PSyclone transformation script for the dynamo0p3 API to apply
    loop fusion and OpenMP for a particular example.'''
    otrans = DynamoOMPParallelLoopTrans()
    ftrans = DynamoLoopFuseTrans()

    invoke = psy.invokes.invoke_list[0]
    schedule = invoke.schedule

    from psyclone.configuration import Config
    config = Config.get()
    if config.api_conf("dynamo0.3").compute_annexed_dofs and \
       config.distributed_memory:
        # We can't loop fuse as the loop bounds differ so add
        # OpenMP parallel do directives to the loops
        schedule, _ = otrans.apply(schedule.children[0])
        schedule, _ = otrans.apply(schedule.children[1])
    else:
        # Loop fuse the two built-in kernels. The 'same_space' flag needs to
        # be set as built-ins are over ANY_SPACE.
        ftrans.same_space = True
        schedule, _ = ftrans.apply(schedule[0], schedule[1])

        # Add an OpenMP parallel do directive to the resultant loop-fused loop
        schedule, _ = otrans.apply(schedule.children[0])

    # take a look at what we've done
    schedule.view()
    schedule.dag(file_format="png")

    return psy
Exemple #2
0
def trans(psy):
    ''' PSyclone transformation script for the dynamo0p3 api to apply
    colouring and OpenMP generically.'''
    ctrans = Dynamo0p3ColourTrans()
    otrans = DynamoOMPParallelLoopTrans()

    # Loop over all of the Invokes in the PSy object
    for invoke in psy.invokes.invoke_list:

        print("Transforming invoke '" + invoke.name + "'...")
        schedule = invoke.schedule

        # Colour all of the loops over cells unless they are on
        # discontinuous spaces (W3, WTHETA and W2V)
        cschedule = schedule
        for child in schedule.children:
            if isinstance(child, Loop) \
               and child.field_space.orig_name \
               not in DISCONTINUOUS_FUNCTION_SPACES \
               and child.iteration_space == "cells":
                cschedule, _ = ctrans.apply(child)
        # Then apply OpenMP to each of the colour loops
        schedule = cschedule
        for child in schedule.children:
            if isinstance(child, Loop):
                if child.loop_type == "colours":
                    schedule, _ = otrans.apply(child.children[0])
                else:
                    schedule, _ = otrans.apply(child)

        schedule.view()
        invoke.schedule = schedule

    return psy
Exemple #3
0
def test_no_colours_loop_dynamo0p3():
    ''' Test that applying LFRicExtractTrans on a Loop over cells
    in a colour without its parent Loop over colours in Dynamo0.3 API
    raises a TransformationError. '''

    etrans = LFRicExtractTrans()
    ctrans = Dynamo0p3ColourTrans()
    otrans = DynamoOMPParallelLoopTrans()

    _, invoke = get_invoke("1_single_invoke.f90",
                           DYNAMO_API,
                           idx=0,
                           dist_mem=False)
    schedule = invoke.schedule

    # Colour first loop that calls testkern_code (loop is over cells and
    # is not on a discontinuous space)
    ctrans.apply(schedule.children[0])
    colour_loop = schedule.children[0].loop_body[0]
    # Apply OMP Parallel DO Directive to the colour Loop
    otrans.apply(colour_loop)
    directive = schedule[0].loop_body
    # Try to extract the region between the Loop over cells in a colour
    # and the exterior Loop over colours
    with pytest.raises(TransformationError) as excinfo:
        _, _ = etrans.apply(directive)
    assert ("Dynamo0.3 API: Extraction of a Loop over cells in a "
            "colour without its ancestor Loop over colours is not "
            "allowed.") in str(excinfo.value)
Exemple #4
0
def trans(psy):
    '''PSyclone transformation script for the dynamo0p3 API that applies
    OpenMP parallel loop parallelisation. It also outputs a textual
    representation of the transformated PSyIR.

    :param psy: a PSyclone PSy object which captures the algorithm and \
        kernel information required by PSyclone.
    :type psy: subclass of :py:class:`psyclone.psyGen.PSy`

    '''
    otrans = DynamoOMPParallelLoopTrans()

    for invoke in psy.invokes.invoke_list:
        schedule = invoke.schedule

        # Add OpenMP parallel do directives to the loops
        for loop in schedule.loops():
            try:
                otrans.apply(loop)
            except TransformationError as info:
                print(str(info.value))

        # take a look at what we've done
        schedule.view()

        return psy
Exemple #5
0
def test_no_colours_loop_dynamo0p3():
    ''' Test that applying DynamoExtractRegionTrans on a Loop over cells
    in a colour without its parent Loop over colours in Dynamo0.3 API
    raises a TransformationError. '''
    from psyclone.transformations import Dynamo0p3ColourTrans, \
        DynamoOMPParallelLoopTrans

    etrans = DynamoExtractRegionTrans()
    ctrans = Dynamo0p3ColourTrans()
    otrans = DynamoOMPParallelLoopTrans()

    _, invoke_info = parse(os.path.join(DYNAMO_BASE_PATH,
                                        "1_single_invoke.f90"),
                           api=DYNAMO_API)
    psy = PSyFactory(DYNAMO_API, distributed_memory=False).create(invoke_info)
    invoke = psy.invokes.invoke_list[0]
    schedule = invoke.schedule

    # Colour first loop that calls testkern_code (loop is over cells and
    # is not on a discontinuous space)
    schedule, _ = ctrans.apply(schedule.children[0])
    colour_loop = schedule.children[0].loop_body[0]
    # Apply OMP Parallel DO Directive to the colour Loop
    schedule, _ = otrans.apply(colour_loop)
    directive = schedule.children[0].children[0]
    # Try to extract the region between the Loop over cells in a colour
    # and the exterior Loop over colours
    with pytest.raises(TransformationError) as excinfo:
        _, _ = etrans.apply(directive)
    assert ("Dynamo0.3 API: Extraction of a Loop over cells in a "
            "colour without its ancestor Loop over colours is not "
            "allowed.") in str(excinfo)
Exemple #6
0
def trans(psy):
    ''' PSyclone transformation script for the dynamo0p3 api to apply
    colouring and OpenMP generically.'''
    ctrans = Dynamo0p3ColourTrans()
    otrans = DynamoOMPParallelLoopTrans()

    # Loop over all of the Invokes in the PSy object
    for invoke in psy.invokes.invoke_list:

        print "Transforming invoke '" + invoke.name + "'..."
        schedule = invoke.schedule

        # Colour all of the loops over cells unless they are on W3
        cschedule = schedule
        for child in schedule.children:
            if isinstance(child, Loop) and child.field_space != "w3" \
               and child.iteration_space == "cells":
                cschedule, _ = ctrans.apply(child)

        # Then apply OpenMP to each of the colour loops
        schedule = cschedule
        for child in schedule.children:
            if isinstance(child, Loop):
                if child.loop_type == "colours":
                    schedule, _ = otrans.apply(child.children[0])
                else:
                    schedule, _ = otrans.apply(child)

        schedule.view()
        invoke.schedule = schedule

    return psy
Exemple #7
0
def test_extract_single_builtin_dynamo0p3():
    ''' Test that extraction of a BuiltIn in an Invoke produces the
    correct result in Dynamo0.3 API without and with optimisations. '''
    from psyclone.transformations import DynamoOMPParallelLoopTrans

    etrans = DynamoExtractRegionTrans()
    otrans = DynamoOMPParallelLoopTrans()

    # Test extract without optimisations
    _, invoke_info = parse(os.path.join(
        DYNAMO_BASE_PATH, "15.1.2_builtin_and_normal_kernel_invoke.f90"),
                           api=DYNAMO_API)
    psy = PSyFactory(DYNAMO_API, distributed_memory=False).create(invoke_info)
    invoke = psy.invokes.invoke_list[0]
    schedule = invoke.schedule

    schedule, _ = etrans.apply(schedule.children[1])
    code = str(psy.gen)
    output = ("      ! ExtractStart\n"
              "      ! CALL write_extract_arguments(argument_list)\n"
              "      !\n"
              "      DO df=1,undf_any_space_1_f2\n"
              "        f2_proxy%data(df) = 0.0\n"
              "      END DO \n"
              "      !\n"
              "      ! ExtractEnd\n")
    assert output in code

    # Test extract with OMP Parallel optimisation
    _, invoke_info = parse(os.path.join(
        DYNAMO_BASE_PATH, "15.1.1_builtin_and_normal_kernel_invoke_2.f90"),
                           api=DYNAMO_API)
    psy = PSyFactory(DYNAMO_API, distributed_memory=False).create(invoke_info)
    invoke = psy.invokes.invoke_list[0]
    schedule = invoke.schedule

    schedule, _ = otrans.apply(schedule.children[1])
    schedule, _ = etrans.apply(schedule.children[1])
    code = str(psy.gen)
    output = ("      ! ExtractStart\n"
              "      ! CALL write_extract_arguments(argument_list)\n"
              "      !\n"
              "      !$omp parallel do default(shared), private(df), "
              "schedule(static)\n"
              "      DO df=1,undf_any_space_1_f1\n"
              "        f1_proxy%data(df) = 0.5*f1_proxy%data(df) + "
              "f2_proxy%data(df)\n"
              "      END DO \n"
              "      !$omp end parallel do\n"
              "      !\n"
              "      ! ExtractEnd\n")
    assert output in code
Exemple #8
0
def test_loop_no_directive_dynamo0p3():
    ''' Test that applying Extract Transformation on a Loop without its
    parent Directive when optimisations are applied in Dynamo0.3 API
    raises a TransformationError. '''
    etrans = LFRicExtractTrans()

    # Test a Loop nested within the OMP Parallel DO Directive
    _, invoke = get_invoke("4.13_multikernel_invokes_w3_anyd.f90",
                           DYNAMO_API, idx=0, dist_mem=False)
    schedule = invoke.schedule
    # Apply DynamoOMPParallelLoopTrans to the second Loop
    otrans = DynamoOMPParallelLoopTrans()
    schedule, _ = otrans.apply(schedule[1])
    loop = schedule.children[1].dir_body[0]
    # Try extracting the Loop inside the OMP Parallel DO region
    with pytest.raises(TransformationError) as excinfo:
        _, _ = etrans.apply(loop)
    assert "Error in LFRicExtractTrans: Application to a Loop without its " \
           "parent Directive is not allowed." in str(excinfo.value)
Exemple #9
0
def trans(psy):
    '''PSyclone transformation script for the dynamo0p3 API that applies
    loop colouring and OpenMP parallel loop parallelisation. It also
    outputs a textual representation of the transformated PSyIR.

    :param psy: a PSyclone PSy object which captures the algorithm and \
        kernel information required by PSyclone.
    :type psy: subclass of :py:class:`psyclone.psyGen.PSy`

    '''
    otrans = DynamoOMPParallelLoopTrans()
    ctrans = Dynamo0p3ColourTrans()
    ptrans = OMPParallelTrans()
    ltrans = Dynamo0p3OMPLoopTrans()
    const = LFRicConstants()

    for invoke in psy.invokes.invoke_list:
        schedule = invoke.schedule

        # Colour any loops that need colouring
        for loop in schedule.walk(Loop):
            if (loop.field_space.orig_name
                    not in const.VALID_DISCONTINUOUS_NAMES
                    and loop.iteration_space == "cell_column"):
                ctrans.apply(loop)

        # Add OpenMP parallel do directives to the loops
        for loop in schedule.walk(Loop):
            try:
                # Make sure reductions are reproducible
                if loop.reductions():
                    ptrans.apply(loop)
                    ltrans.apply(loop, {"reprod": True})
                else:
                    otrans.apply(loop)
            except TransformationError as info:
                print(str(info.value))

        # take a look at what we've done
        schedule.view()

        return psy
Exemple #10
0
def trans(psy):
    ''' PSyclone transformation script for the dynamo0p3 api to apply
    colouring and OpenMP generically.'''
    ctrans = Dynamo0p3ColourTrans()
    otrans = DynamoOMPParallelLoopTrans()
    const = LFRicConstants()

    # Loop over all of the Invokes in the PSy object
    for invoke in psy.invokes.invoke_list:

        print("Transforming invoke '" + invoke.name + "'...")
        schedule = invoke.schedule

        # Colour all of the loops over cells unless they are on
        # discontinuous spaces
        for child in schedule.children:
            if isinstance(child, Loop) \
               and child.field_space.orig_name \
               not in const.VALID_DISCONTINUOUS_NAMES \
               and child.iteration_space == "cell_column":
                ctrans.apply(child)
        # Then apply OpenMP to each of the colour loops
        for child in schedule.children:
            if isinstance(child, Loop):
                if child.loop_type == "colours":
                    otrans.apply(child.loop_body[0])
                else:
                    otrans.apply(child)

        schedule.view()

    return psy
Exemple #11
0
def test_loop_no_directive_dynamo0p3():
    ''' Test that applying Extract Transformation on a Loop without its
    parent Directive when optimisations are applied in Dynamo0.3 API
    raises a TransformationError. '''
    etrans = DynamoExtractRegionTrans()

    from psyclone.transformations import DynamoOMPParallelLoopTrans

    # Test a Loop nested within the OMP Parallel DO Directive
    _, invoke_info = parse(os.path.join(
        DYNAMO_BASE_PATH, "4.13_multikernel_invokes_w3_anyd.f90"),
                           api=DYNAMO_API)
    psy = PSyFactory(DYNAMO_API, distributed_memory=False).create(invoke_info)
    invoke = psy.invokes.invoke_list[0]
    schedule = invoke.schedule
    # Apply DynamoOMPParallelLoopTrans to the second Loop
    otrans = DynamoOMPParallelLoopTrans()
    schedule, _ = otrans.apply(schedule.children[1])
    loop = schedule.children[1].children[0]
    # Try extracting the Loop inside the OMP Parallel DO region
    with pytest.raises(TransformationError) as excinfo:
        _, _ = etrans.apply(loop)
    assert ("Extraction of a Loop without its parent Directive is not "
            "allowed.") in str(excinfo)
Exemple #12
0
def test_restrict_prolong_chain_anyd(tmpdir):
    ''' Test that we generate correct code for an invoke containing a
    chain of discontinuous restrictions and continuous prolongations.

    '''
    _, invoke_info = parse(os.path.join(BASE_PATH,
                                        "22.2.1_intergrid_3levels_anyd.f90"),
                           api=API)
    psy = PSyFactory(API, distributed_memory=True).create(invoke_info)
    schedule = psy.invokes.invoke_list[0].schedule
    output = str(psy.gen)
    # Check maps for any_discontinuous_space
    expected = (
        "      map_adspc1_fld_m => fld_m_proxy%vspace%get_whole_dofmap()\n"
        "      map_adspc2_fld_f => fld_f_proxy%vspace%get_whole_dofmap()\n"
        "      map_adspc1_fld_c => fld_c_proxy%vspace%get_whole_dofmap()\n"
        "      map_adspc2_fld_m => fld_m_proxy%vspace%get_whole_dofmap()\n")
    assert expected in output
    # Check ndf and undf initialisations the second restrict kernel
    # (fld_m to fld_c)
    expected = ("      ! Initialise number of DoFs for adspc1_fld_c\n"
                "      !\n"
                "      ndf_adspc1_fld_c = fld_c_proxy%vspace%get_ndf()\n"
                "      undf_adspc1_fld_c = fld_c_proxy%vspace%get_undf()\n"
                "      !\n"
                "      ! Initialise number of DoFs for adspc2_fld_m\n"
                "      !\n"
                "      ndf_adspc2_fld_m = fld_m_proxy%vspace%get_ndf()\n"
                "      undf_adspc2_fld_m = fld_m_proxy%vspace%get_undf()\n")
    assert expected in output
    # Check an example of restrict loop and all upper loop bounds
    expected = (
        "      ! Call kernels and communication routines\n"
        "      !\n"
        "      DO cell=1,mesh_fld_m%get_last_edge_cell()\n"
        "        !\n"
        "        CALL restrict_kernel_code(nlayers, cell_map_fld_m(:,cell), "
        "ncpc_fld_f_fld_m, ncell_fld_f, fld_m_proxy%data, fld_f_proxy%data, "
        "undf_adspc1_fld_m, map_adspc1_fld_m(:,cell), ndf_adspc2_fld_f, "
        "undf_adspc2_fld_f, map_adspc2_fld_f)\n"
        "      END DO\n")
    assert expected in output
    assert "DO cell=1,mesh_fld_c%get_last_edge_cell()" in output
    assert "DO cell=1,mesh_fld_c%get_last_halo_cell(1)" in output
    assert "DO cell=1,mesh_fld_m%get_last_halo_cell(1)" in output
    # Check compilation
    assert LFRicBuild(tmpdir).code_compiles(psy)

    # Now do some transformations
    from psyclone.transformations import Dynamo0p3ColourTrans, \
        DynamoOMPParallelLoopTrans, TransformationError
    otrans = DynamoOMPParallelLoopTrans()
    ctrans = Dynamo0p3ColourTrans()
    # Apply OMP to the first restrict kernel
    _, _ = otrans.apply(schedule.children[0])
    # Apply colouring and OMP to the first prolong kernel
    _, _ = ctrans.apply(schedule.children[4])
    _, _ = otrans.apply(schedule.children[4].loop_body[0])
    output = str(psy.gen)
    expected = ("      !$omp parallel do default(shared), private(cell), "
                "schedule(static)\n"
                "      DO cell=1,mesh_fld_m%get_last_edge_cell()\n"
                "        !\n"
                "        CALL restrict_kernel_code")
    assert expected in output
    expected = ("      DO colour=1,ncolour_fld_m\n"
                "        !$omp parallel do default(shared), private(cell), "
                "schedule(static)\n"
                "        DO cell=1,mesh_fld_c%get_last_halo_cell_per_colour"
                "(colour,1)\n"
                "          !\n"
                "          CALL prolong_test_kernel_code")
    assert expected in output
    # Try to apply colouring to the second restrict kernel
    with pytest.raises(TransformationError) as excinfo:
        _, _ = ctrans.apply(schedule.children[1])
    assert ("Loops iterating over a discontinuous function space "
            "are not currently supported." in str(excinfo.value))
Exemple #13
0
def test_extract_colouring_omp_dynamo0p3():
    ''' Test that extraction of a Kernel in an Invoke after applying
    colouring and OpenMP optimisations produces the correct result
    in Dynamo0.3 API. '''

    const = LFRicConstants()
    etrans = LFRicExtractTrans()
    ctrans = Dynamo0p3ColourTrans()
    otrans = DynamoOMPParallelLoopTrans()

    psy, invoke = get_invoke("4.8_multikernel_invokes.f90",
                             DYNAMO_API,
                             idx=0,
                             dist_mem=False)
    schedule = invoke.schedule

    # First colour all of the loops over cells unless they are on
    # discontinuous spaces
    for child in schedule.children:
        if isinstance(child, Loop) and child.field_space.orig_name \
           not in const.VALID_DISCONTINUOUS_NAMES \
           and child.iteration_space == "cell_column":
            ctrans.apply(child)
    # Then apply OpenMP to each of the colour loops
    for child in schedule.children:
        if isinstance(child, Loop):
            if child.loop_type == "colours":
                otrans.apply(child.loop_body[0])
            else:
                otrans.apply(child)

    # Extract the second instance of ru_kernel_type after colouring
    # and OpenMP are applied
    child = schedule.children[2]
    etrans.apply(child)

    code = str(psy.gen)
    output = ("""
      ! ExtractStart
      !
      CALL extract_psy_data%PreStart("multikernel_invokes_7_psy", """
              """"invoke_0:ru_code:r0", 26, 3)
      CALL extract_psy_data%PreDeclareVariable("a", a)
      CALL extract_psy_data%PreDeclareVariable("b", b)
      CALL extract_psy_data%PreDeclareVariable("basis_w0_qr", basis_w0_qr)
      CALL extract_psy_data%PreDeclareVariable("basis_w2_qr", basis_w2_qr)
      CALL extract_psy_data%PreDeclareVariable("basis_w3_qr", basis_w3_qr)
      CALL extract_psy_data%PreDeclareVariable("c", c)
      CALL extract_psy_data%PreDeclareVariable("cmap", cmap)
      CALL extract_psy_data%PreDeclareVariable("diff_basis_w0_qr", """
              """diff_basis_w0_qr)
      CALL extract_psy_data%PreDeclareVariable("diff_basis_w2_qr", """
              """diff_basis_w2_qr)
      CALL extract_psy_data%PreDeclareVariable("e", e)
      CALL extract_psy_data%PreDeclareVariable("istp", istp)
      CALL extract_psy_data%PreDeclareVariable("map_w0", map_w0)
      CALL extract_psy_data%PreDeclareVariable("map_w2", map_w2)
      CALL extract_psy_data%PreDeclareVariable("map_w3", map_w3)
      CALL extract_psy_data%PreDeclareVariable("ndf_w0", ndf_w0)
      CALL extract_psy_data%PreDeclareVariable("ndf_w2", ndf_w2)
      CALL extract_psy_data%PreDeclareVariable("ndf_w3", ndf_w3)
      CALL extract_psy_data%PreDeclareVariable("nlayers", nlayers)
      CALL extract_psy_data%PreDeclareVariable("np_xy_qr", np_xy_qr)
      CALL extract_psy_data%PreDeclareVariable("np_z_qr", np_z_qr)
      CALL extract_psy_data%PreDeclareVariable("rdt", rdt)
      CALL extract_psy_data%PreDeclareVariable("undf_w0", undf_w0)
      CALL extract_psy_data%PreDeclareVariable("undf_w2", undf_w2)
      CALL extract_psy_data%PreDeclareVariable("undf_w3", undf_w3)
      CALL extract_psy_data%PreDeclareVariable("weights_xy_qr", weights_xy_qr)
      CALL extract_psy_data%PreDeclareVariable("weights_z_qr", weights_z_qr)
      CALL extract_psy_data%PreDeclareVariable("b_post", b)
      CALL extract_psy_data%PreDeclareVariable("cell_post", cell)
      CALL extract_psy_data%PreDeclareVariable("colour_post", colour)
      CALL extract_psy_data%PreEndDeclaration
      CALL extract_psy_data%ProvideVariable("a", a)
      CALL extract_psy_data%ProvideVariable("b", b)
      CALL extract_psy_data%ProvideVariable("basis_w0_qr", basis_w0_qr)
      CALL extract_psy_data%ProvideVariable("basis_w2_qr", basis_w2_qr)
      CALL extract_psy_data%ProvideVariable("basis_w3_qr", basis_w3_qr)
      CALL extract_psy_data%ProvideVariable("c", c)
      CALL extract_psy_data%ProvideVariable("cmap", cmap)
      CALL extract_psy_data%ProvideVariable("diff_basis_w0_qr", """
              """diff_basis_w0_qr)
      CALL extract_psy_data%ProvideVariable("diff_basis_w2_qr", """
              """diff_basis_w2_qr)
      CALL extract_psy_data%ProvideVariable("e", e)
      CALL extract_psy_data%ProvideVariable("istp", istp)
      CALL extract_psy_data%ProvideVariable("map_w0", map_w0)
      CALL extract_psy_data%ProvideVariable("map_w2", map_w2)
      CALL extract_psy_data%ProvideVariable("map_w3", map_w3)
      CALL extract_psy_data%ProvideVariable("ndf_w0", ndf_w0)
      CALL extract_psy_data%ProvideVariable("ndf_w2", ndf_w2)
      CALL extract_psy_data%ProvideVariable("ndf_w3", ndf_w3)
      CALL extract_psy_data%ProvideVariable("nlayers", nlayers)
      CALL extract_psy_data%ProvideVariable("np_xy_qr", np_xy_qr)
      CALL extract_psy_data%ProvideVariable("np_z_qr", np_z_qr)
      CALL extract_psy_data%ProvideVariable("rdt", rdt)
      CALL extract_psy_data%ProvideVariable("undf_w0", undf_w0)
      CALL extract_psy_data%ProvideVariable("undf_w2", undf_w2)
      CALL extract_psy_data%ProvideVariable("undf_w3", undf_w3)
      CALL extract_psy_data%ProvideVariable("weights_xy_qr", weights_xy_qr)
      CALL extract_psy_data%ProvideVariable("weights_z_qr", weights_z_qr)
      CALL extract_psy_data%PreEnd
      DO colour=1,ncolour
        !$omp parallel do default(shared), private(cell), schedule(static)
        DO cell=1,mesh%get_last_edge_cell_per_colour(colour)
          !
          CALL ru_code(nlayers, b_proxy%data, a_proxy%data, istp, rdt, """
              "c_proxy%data, e_proxy(1)%data, e_proxy(2)%data, "
              "e_proxy(3)%data, ndf_w2, undf_w2, "
              "map_w2(:,cmap(colour, cell)), "
              "basis_w2_qr, diff_basis_w2_qr, ndf_w3, undf_w3, "
              "map_w3(:,cmap(colour, cell)), basis_w3_qr, ndf_w0, undf_w0, "
              "map_w0(:,cmap(colour, cell)), basis_w0_qr, diff_basis_w0_qr, "
              """np_xy_qr, np_z_qr, weights_xy_qr, weights_z_qr)
        END DO
        !$omp end parallel do
      END DO
      CALL extract_psy_data%PostStart
      CALL extract_psy_data%ProvideVariable("b_post", b)
      CALL extract_psy_data%ProvideVariable("cell_post", cell)
      CALL extract_psy_data%ProvideVariable("colour_post", colour)
      CALL extract_psy_data%PostEnd
      !
      ! ExtractEnd""")
    assert output in code
Exemple #14
0
def test_extract_single_builtin_dynamo0p3():
    ''' Test that extraction of a BuiltIn in an Invoke produces the
    correct result in Dynamo0.3 API without and with optimisations.

    '''
    etrans = LFRicExtractTrans()

    otrans = DynamoOMPParallelLoopTrans()

    psy, invoke = get_invoke("15.1.2_builtin_and_normal_kernel_invoke.f90",
                             DYNAMO_API,
                             idx=0,
                             dist_mem=False)
    schedule = invoke.schedule

    etrans.apply(schedule.children[1])
    code = str(psy.gen)
    output = """! ExtractStart
      !
      CALL extract_psy_data%PreStart("single_invoke_builtin_then_kernel_psy", """ \
      """"invoke_0:setval_c:r0", 0, 1)
      CALL extract_psy_data%PreDeclareVariable("df_post", df)
      CALL extract_psy_data%PreEndDeclaration
      CALL extract_psy_data%PreEnd
      DO df=1,undf_aspc1_f2
        f2_proxy%data(df) = 0.0
      END DO
      CALL extract_psy_data%PostStart
      CALL extract_psy_data%ProvideVariable("df_post", df)
      CALL extract_psy_data%PostEnd
      !
      ! ExtractEnd"""

    assert output in code

    # Test extract with OMP Parallel optimisation
    psy, invoke = get_invoke("15.1.1_builtin_and_normal_kernel_invoke_2.f90",
                             DYNAMO_API,
                             idx=0,
                             dist_mem=False)
    schedule = invoke.schedule

    otrans.apply(schedule.children[1])
    etrans.apply(schedule.children[1])
    code_omp = str(psy.gen)
    output = """
      ! ExtractStart
      !
      CALL extract_psy_data%PreStart("single_invoke_psy", """ \
      """"invoke_0:inc_ax_plus_y:r0", 0, 1)
      CALL extract_psy_data%PreDeclareVariable("df_post", df)
      CALL extract_psy_data%PreEndDeclaration
      CALL extract_psy_data%PreEnd
      !$omp parallel do default(shared), private(df), schedule(static)
      DO df=1,undf_aspc1_f1
        f1_proxy%data(df) = 0.5_r_def*f1_proxy%data(df) + f2_proxy%data(df)
      END DO
      !$omp end parallel do
      CALL extract_psy_data%PostStart
      CALL extract_psy_data%ProvideVariable("df_post", df)
      CALL extract_psy_data%PostEnd
      !
      ! ExtractEnd"""
    assert output in code_omp

    # TODO #637 (no builtin support)
    # Builtins are not yet support, so some arguments are missing. This
    # is an excerpt of missing lines, which will cause this test to x-fail
    not_yet_working = [
        'CALL extract_psy_data%ProvideVariable("f1", f1)',
        'CALL extract_psy_data%ProvideVariable("f2", f2)'
    ]
    for line in not_yet_working:
        if line not in code:
            pytest.xfail("#637 LFRic builtins are not supported yet.")
        if line not in code_omp:
            pytest.xfail("#637 LFRic builtins are not supported yet.")
    assert False, "X-failing test suddenly working: #637 lfric builtins."
Exemple #15
0
def test_extract_colouring_omp_dynamo0p3(tmpdir):
    ''' Test that extraction of a Kernel in an Invoke after applying
    colouring and OpenMP optimisations produces the correct result
    in Dynamo0.3 API. '''
    from psyclone.transformations import Dynamo0p3ColourTrans, \
        DynamoOMPParallelLoopTrans
    from psyclone.dynamo0p3 import VALID_DISCONTINUOUS_FUNCTION_SPACE_NAMES

    etrans = DynamoExtractRegionTrans()
    ctrans = Dynamo0p3ColourTrans()
    otrans = DynamoOMPParallelLoopTrans()

    _, invoke_info = parse(os.path.join(DYNAMO_BASE_PATH,
                                        "4.8_multikernel_invokes.f90"),
                           api=DYNAMO_API)
    psy = PSyFactory(DYNAMO_API, distributed_memory=False).create(invoke_info)
    invoke = psy.invokes.invoke_list[0]
    schedule = invoke.schedule

    # First colour all of the loops over cells unless they are on
    # discontinuous spaces
    cschedule = schedule
    for child in schedule.children:
        if isinstance(child, Loop) and child.field_space.orig_name \
           not in VALID_DISCONTINUOUS_FUNCTION_SPACE_NAMES \
           and child.iteration_space == "cells":
            cschedule, _ = ctrans.apply(child)
    # Then apply OpenMP to each of the colour loops
    schedule = cschedule
    for child in schedule.children:
        if isinstance(child, Loop):
            if child.loop_type == "colours":
                schedule, _ = otrans.apply(child.loop_body[0])
            else:
                schedule, _ = otrans.apply(child)

    # Extract the second instance of ru_kernel_type after colouring
    # and OpenMP are applied
    child = schedule.children[2]
    schedule, _ = etrans.apply(child)

    code = str(psy.gen)
    output = (
        "      ! ExtractStart\n"
        "      ! CALL write_extract_arguments(argument_list)\n"
        "      !\n"
        "      DO colour=1,ncolour\n"
        "        !$omp parallel do default(shared), private(cell), "
        "schedule(static)\n"
        "        DO cell=1,mesh%get_last_edge_cell_per_colour(colour)\n"
        "          !\n"
        "          CALL ru_code(nlayers, b_proxy%data, a_proxy%data, istp, "
        "rdt, c_proxy%data, e_proxy(1)%data, e_proxy(2)%data, "
        "e_proxy(3)%data, ndf_w2, undf_w2, map_w2(:,cmap(colour, cell)), "
        "basis_w2_qr, diff_basis_w2_qr, ndf_w3, undf_w3, "
        "map_w3(:,cmap(colour, cell)), basis_w3_qr, ndf_w0, undf_w0, "
        "map_w0(:,cmap(colour, cell)), basis_w0_qr, diff_basis_w0_qr, "
        "np_xy_qr, np_z_qr, weights_xy_qr, weights_z_qr)\n"
        "        END DO \n"
        "        !$omp end parallel do\n"
        "      END DO \n"
        "      !\n"
        "      ! ExtractEnd\n")
    assert output in code

    assert Dynamo0p3Build(tmpdir).code_compiles(psy)