Skip to content

GridTools backend: write after read violation of GridTools execution model #143

Closed
@havogt

Description

@havogt

The qx_edge_west stencil in the FV3 dycore produces invalid GridTools code (see #136)

def qx_edge_west2(qin: sd, dxa: sd, qx: sd):
    with computation(PARALLEL), interval(...):
        g_in = dxa / dxa[-1, 0, 0]
        qx0 = qx
        qx = (
            3.0 * (g_in * qin[-1, 0, 0] + qin) - (g_in * qx0[-1, 0, 0] + qx0[1, 0, 0])
        ) / (2.0 + 2.0 * g_in)

A simplified example is

def trigger_bug(qx: sd):
    with computation(PARALLEL), interval(...):
        qx0 = qx
        qx = qx0[-1, 0, 0]

Here, the stage of qx0 = qx gets an extended compute domain because of the read with offset in the next line.
Currently the following GridTool code is generated:

computation_t gt_computation = gt::make_computation<backend_t>(
        make_grid(domain),
        gt::make_multistage(gt::execute::parallel(),
            gt::make_stage<stage__9_func>(
                p_qx(), p_qx0()
            ),
            gt::make_stage<stage__12_func>(
                p_qx0(), p_qx()
            )
        )
    );

This is illegal as qx is read outside the compute domain (because extended), resulting in a data race in the write. The stages would have to live in separate multistages.

A fix would be to improve the multistage merge to check for the following conditions:
A read before write in the same multi-stage is only allowed if the read is in a non-extended stage and the read is without offset. (Here, the first condition is violated.)

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions