Beispiel #1
0
def make_args_data_from_gtir(pipeline: GtirPipeline) -> ModuleData:
    """
    Compute module data containing information about stencil arguments from gtir.

    This is no longer compatible with the legacy backends.
    """
    data = ModuleData()

    # NOTE: pipeline.gtir has not had prune_unused_parameters applied.
    all_params = pipeline.gtir.params

    node = pipeline.full()
    oir = gtir_to_oir.GTIRToOIR().visit(node)
    field_extents = compute_fields_extents(oir)
    accesses = compute_access_kinds(oir)

    for decl in (param for param in all_params
                 if isinstance(param, gtir.FieldDecl)):
        access = accesses[decl.name]
        dtype = numpy.dtype(decl.dtype.name.lower())

        if access != AccessKind.NONE:
            k_boundary = compute_k_boundary(node)[decl.name]
            boundary = Boundary(*field_extents[decl.name].to_boundary()[0:2],
                                k_boundary)
        else:
            boundary = Boundary.zeros(ndims=3)

        data.field_info[decl.name] = FieldInfo(
            access=access,
            boundary=boundary,
            axes=tuple(dimension_flags_to_names(decl.dimensions).upper()),
            data_dims=tuple(decl.data_dims),
            dtype=dtype,
        )

    for decl in (param for param in all_params
                 if isinstance(param, gtir.ScalarDecl)):
        access = accesses[decl.name]
        dtype = numpy.dtype(decl.dtype.name.lower())
        data.parameter_info[decl.name] = ParameterInfo(access=access,
                                                       dtype=dtype)

    data.unreferenced = [
        *sorted(name for name in accesses if accesses[name] == AccessKind.NONE)
    ]
    return data
def sample_args_data():
    dtype = np.dtype(np.float_)
    yield ModuleData(
        field_info={
            "in_field":
            FieldInfo(
                access=AccessKind.READ_WRITE,
                boundary=Boundary.zeros(ndims=3),
                axes=("I", "J", "K"),
                data_dims=tuple([]),
                dtype=dtype,
            )
        },
        parameter_info={
            "param": ParameterInfo(access=AccessKind.READ, dtype=dtype)
        },
    )
Beispiel #3
0
    def _run_test_implementation(cls, parameters_dict, implementation):  # noqa: C901  # too complex
        input_data, exec_info = parameters_dict

        origin = cls.origin
        max_boundary = Boundary(cls.max_boundary)
        field_params = cls.field_params
        field_masks = {}
        for name, value in input_data.items():
            if isinstance(value, np.ndarray):
                field_masks[name] = tuple(
                    ax in field_params[name][0] for ax in CartesianSpace.names
                )

        data_shape = Shape((sys.maxsize,) * 3)
        for name, data in input_data.items():
            if isinstance(data, np.ndarray):
                data_shape &= Shape(
                    interpolate_mask(data.shape, field_masks[name], default=sys.maxsize)
                )

        domain = data_shape - (
            Index(max_boundary.lower_indices) + Index(max_boundary.upper_indices)
        )

        referenced_inputs = {
            name: info for name, info in implementation.field_info.items() if info is not None
        }
        referenced_inputs.update(
            {name: info for name, info in implementation.parameter_info.items() if info is not None}
        )

        # set externals for validation method
        for k, v in implementation.constants.items():
            sys.modules[cls.__module__].__dict__[k] = v

        # copy input data
        test_values = {}
        validation_values = {}
        for name, data in input_data.items():
            data = input_data[name]
            if name in referenced_inputs:
                info = referenced_inputs[name]
                if isinstance(info, FieldInfo):
                    data_dims = field_params[name][1]
                    if data_dims:
                        dtype = (data.dtype, data_dims)
                        shape = data.shape[: -len(data_dims)]
                    else:
                        dtype = data.dtype
                        shape = data.shape
                    test_values[name] = gt_storage.from_array(
                        data,
                        dtype=dtype,
                        shape=shape,
                        mask=field_masks[name],
                        default_origin=origin,
                        backend=implementation.backend,
                    )
                    validation_values[name] = np.array(data)
                else:
                    test_values[name] = data
                    validation_values[name] = data
            else:
                test_values[name] = None
                validation_values[name] = None

        # call implementation
        implementation(**test_values, origin=origin, exec_info=exec_info)
        assert domain == exec_info["domain"]

        # for validation data, data is cropped to actually touched domain, so that origin offseting
        # does not have to be implemented for every test suite. This is done based on info
        # specified in test suite
        cropped_validation_values = {}
        for name, data in validation_values.items():
            sym = cls.symbols[name]
            if data is not None and sym.kind == SymbolKind.FIELD:
                field_extent_low = tuple(b[0] for b in sym.boundary)
                offset_low = tuple(b[0] - e for b, e in zip(max_boundary, field_extent_low))
                field_extent_high = tuple(b[1] for b in sym.boundary)
                offset_high = tuple(b[1] - e for b, e in zip(max_boundary, field_extent_high))
                validation_slice = filter_mask(
                    tuple(slice(o, s - h) for o, s, h in zip(offset_low, data_shape, offset_high)),
                    field_masks[name],
                )
                data_dims = field_params[name][1]
                if data_dims:
                    validation_slice = tuple([*validation_slice] + [slice(None)] * len(data_dims))
                cropped_validation_values[name] = data[validation_slice]
            else:
                cropped_validation_values[name] = data

        cls.validation(
            **cropped_validation_values,
            domain=domain,
            origin={
                name: info.boundary.lower_indices
                for name, info in implementation.field_info.items()
                if info is not None
            },
        )

        # Test values
        for name, value in test_values.items():
            if isinstance(value, np.ndarray):
                expected_value = validation_values[name]

                if gt_backend.from_name(value.backend).storage_info["device"] == "gpu":
                    value.synchronize()
                    value = value.data.get()
                else:
                    value = value.data

                np.testing.assert_allclose(
                    value,
                    expected_value,
                    rtol=RTOL,
                    atol=ATOL,
                    equal_nan=EQUAL_NAN,
                    err_msg="Wrong data in output field '{name}'".format(name=name),
                )
Beispiel #4
0
def make_args_data_from_gtir(pipeline: GtirPipeline,
                             legacy=False) -> ModuleData:
    """
    Compute module data containing information about stencil arguments from gtir.

    Use `legacy` parameter to ensure equality with values from :func:`make_args_data_from_iir`.
    """
    data = ModuleData()
    node = pipeline.full()

    write_fields = (node.iter_tree().if_isinstance(
        gtir.ParAssignStmt).getattr("left").if_isinstance(
            gtir.FieldAccess).getattr("name").to_set())

    read_fields: Set[str] = set()
    for expr in node.iter_tree().if_isinstance(
            gtir.ParAssignStmt).getattr("right"):
        read_fields |= expr.iter_tree().if_isinstance(
            gtir.FieldAccess).getattr("name").to_set()

    referenced_field_params = [
        param.name for param in node.params
        if isinstance(param, gtir.FieldDecl)
    ]
    field_extents = compute_legacy_extents(node, mask_inwards=legacy)
    k_boundary = (compute_k_boundary(node) if not legacy else
                  {v: (0, 0)
                   for v in referenced_field_params})
    for name in sorted(referenced_field_params):
        access = AccessKind.NONE
        if name in read_fields:
            access |= AccessKind.READ
        if name in write_fields:
            access |= AccessKind.WRITE
        boundary = Boundary(*field_extents[name].to_boundary()[0:2],
                            k_boundary[name])
        data.field_info[name] = FieldInfo(
            access=access,
            boundary=boundary,
            axes=tuple(
                dimension_flags_to_names(
                    node.symtable_[name].dimensions).upper()),
            data_dims=tuple(node.symtable_[name].data_dims),
            dtype=numpy.dtype(node.symtable_[name].dtype.name.lower()),
        )

    referenced_scalar_params = [
        param.name for param in node.params
        if param.name not in referenced_field_params
    ]
    for name in sorted(referenced_scalar_params):
        data.parameter_info[name] = ParameterInfo(
            dtype=numpy.dtype(node.symtable_[name].dtype.name.lower()))

    unref_params = get_unused_params_from_gtir(pipeline)
    for param in sorted(unref_params, key=lambda decl: decl.name):
        if isinstance(param, gtir.FieldDecl):
            data.field_info[param.name] = None
        elif isinstance(param, gtir.ScalarDecl):
            data.parameter_info[param.name] = None

    data.unreferenced = [*sorted(param.name for param in unref_params)]
    return data
Beispiel #5
0
    def _run_test_implementation(self, parameters_dict, implementation):

        cls = type(self)
        input_data, exec_info = parameters_dict

        origin = cls.origin
        max_boundary = Boundary(cls.max_boundary)

        shape_iter = (Shape(v.shape) for v in input_data.values()
                      if isinstance(v, np.ndarray))
        shape = next(shape_iter)
        assert all(shape == sh for sh in shape_iter)

        domain = shape - (Index(max_boundary.lower_indices) +
                          Index(max_boundary.upper_indices))

        referenced_inputs = {
            name: info
            for name, info in implementation.field_info.items()
            if info is not None
        }
        referenced_inputs.update({
            name: info
            for name, info in implementation.parameter_info.items()
            if info is not None
        })

        # set externals for validation method
        for k, v in implementation.constants.items():
            sys.modules[self.__module__].__dict__[k] = v

        # copy input data
        inputs = {}
        validation_inputs = {}
        for name, data in input_data.items():
            data = input_data[name]
            if name in referenced_inputs:
                info = referenced_inputs[name]
                if isinstance(info, FieldInfo):
                    inputs[name] = gt_storage.from_array(
                        data,
                        dtype=data.dtype,
                        shape=shape,
                        default_origin=origin,
                        backend=implementation.backend,
                    )
                    validation_inputs[name] = np.array(data)
                else:
                    inputs[name] = data
                    validation_inputs[name] = data
            else:
                inputs[name] = None
                validation_inputs[name] = None

        # call implementation
        implementation(**inputs, origin=origin, exec_info=exec_info)
        assert domain == exec_info["domain"]

        # for validation data, data is cropped to actually touched domain, so that origin offseting
        # does not have to be implemented for every test suite. This is done based on info
        # specified in test suite
        cropped_validation_inputs = {}
        for name, data in validation_inputs.items():
            sym = cls.symbols[name]
            if data is not None and sym.kind == SymbolKind.FIELD:
                field_extent_low = tuple(b[0] for b in sym.boundary)
                offset_low = tuple(
                    b[0] - e for b, e in zip(max_boundary, field_extent_low))
                field_extent_high = tuple(b[1] for b in sym.boundary)
                offset_high = tuple(
                    b[1] - e for b, e in zip(max_boundary, field_extent_high))
                validation_slice = tuple(
                    slice(o, s - h)
                    for o, s, h in zip(offset_low, shape, offset_high))
                cropped_validation_inputs[name] = data[validation_slice]
            else:
                cropped_validation_inputs[name] = data

        cls.validation(
            **cropped_validation_inputs,
            domain=domain,
            origin={
                name: info.boundary.lower_indices
                for name, info in implementation.field_info.items()
                if info is not None
            },
        )

        # Test values
        for name, value in inputs.items():
            if isinstance(value, np.ndarray):
                expected_value = validation_inputs[name]

                if gt_backend.from_name(
                        value.backend).storage_info["device"] == "gpu":
                    value.synchronize()
                    value = value.data.get()
                else:
                    value = value.data

                np.testing.assert_allclose(
                    value,
                    expected_value,
                    rtol=RTOL,
                    atol=ATOL,
                    equal_nan=EQUAL_NAN,
                    err_msg="Wrong data in output field '{name}'".format(
                        name=name),
                )