Example #1
0
def make_copy_kernel(new_dim_tags, old_dim_tags=None):
    """Returns a :class:`LoopKernel` that changes the data layout
    of a variable (called "input") to the new layout specified by
    *new_dim_tags* from the one specified by *old_dim_tags*.
    *old_dim_tags* defaults to an all-C layout of the same rank
    as the one given by *new_dim_tags*.
    """

    from loopy.kernel.array import (parse_array_dim_tags,
            SeparateArrayArrayDimTag, VectorArrayDimTag)
    new_dim_tags = parse_array_dim_tags(new_dim_tags, n_axes=None)

    rank = len(new_dim_tags)
    if old_dim_tags is None:
        old_dim_tags = parse_array_dim_tags(
                ",".join(rank * ["c"]), n_axes=None)
    elif isinstance(old_dim_tags, str):
        old_dim_tags = parse_array_dim_tags(
                old_dim_tags, n_axes=None)

    indices = ["i%d" % i for i in range(rank)]
    shape = ["n%d" % i for i in range(rank)]
    commad_indices = ", ".join(indices)
    bounds = " and ".join(
            f"0<={ind}<{shape_i}"
            for ind, shape_i in zip(indices, shape))

    set_str = "{{[{}]: {}}}".format(
                commad_indices,
                bounds
                )
    result = make_kernel(set_str,
            "output[%s] = input[%s]"
            % (commad_indices, commad_indices),
            lang_version=MOST_RECENT_LANGUAGE_VERSION)

    result = tag_array_axes(result, "input", old_dim_tags)
    result = tag_array_axes(result, "output", new_dim_tags)

    unrolled_tags = (SeparateArrayArrayDimTag, VectorArrayDimTag)
    for i in range(rank):
        if (isinstance(new_dim_tags[i], unrolled_tags)
                or isinstance(old_dim_tags[i], unrolled_tags)):
            result = tag_inames(result, {indices[i]: "unr"})

    return result
Example #2
0
def make_copy_kernel(new_dim_tags, old_dim_tags=None):
    """Returns a :class:`LoopKernel` that changes the data layout
    of a variable (called "input") to the new layout specified by
    *new_dim_tags* from the one specified by *old_dim_tags*.
    *old_dim_tags* defaults to an all-C layout of the same rank
    as the one given by *new_dim_tags*.
    """

    from loopy.kernel.array import (parse_array_dim_tags,
            SeparateArrayArrayDimTag, VectorArrayDimTag)
    new_dim_tags = parse_array_dim_tags(new_dim_tags, n_axes=None)

    rank = len(new_dim_tags)
    if old_dim_tags is None:
        old_dim_tags = parse_array_dim_tags(
                ",".join(rank * ["c"]), n_axes=None)
    elif isinstance(old_dim_tags, str):
        old_dim_tags = parse_array_dim_tags(
                old_dim_tags, n_axes=None)

    indices = ["i%d" % i for i in range(rank)]
    shape = ["n%d" % i for i in range(rank)]
    commad_indices = ", ".join(indices)
    bounds = " and ".join(
            "0<=%s<%s" % (ind, shape_i)
            for ind, shape_i in zip(indices, shape))

    set_str = "{[%s]: %s}" % (
                commad_indices,
                bounds
                )
    result = make_kernel(set_str,
            "output[%s] = input[%s]"
            % (commad_indices, commad_indices))

    result = tag_data_axes(result, "input", old_dim_tags)
    result = tag_data_axes(result, "output", new_dim_tags)

    unrolled_tags = (SeparateArrayArrayDimTag, VectorArrayDimTag)
    for i in range(rank):
        if (isinstance(new_dim_tags[i], unrolled_tags)
                or isinstance(old_dim_tags[i], unrolled_tags)):
            result = tag_inames(result, {indices[i]: "unr"})

    return result
Example #3
0
def make_einsum(spec, arg_names, **knl_creation_kwargs):
    r"""Returns a :class:`LoopKernel` for evaluating array-based
    operations using Einstein summation convention.

    :param spec: a string denoting the subscripts for
        summation as a comma-separated list of subscript labels.
        This follows the usual :func:`numpy.einsum` convention.
        Note that the explicit indicator `->` for the precise output
        form is required.
    :param arg_names: a sequence of string types denoting
        the names of the array operands.
    :param \**knl_creation_kwargs: keyword arguments for kernel creation.
        See :func:`make_kernel` for a list of acceptable keyword
        parameters.

    .. note::

        No attempt is being made to reduce the complexity
        of the resulting expression. This should be dealt with
        as part of a separate transformation.
    """
    arg_spec, out_spec = spec.split("->")
    arg_specs = arg_spec.split(",")

    if len(arg_names) != len(arg_specs):
        raise ValueError(
            f"Number of arg names ({arg_names}) should match the number "
            f"of arg specs: {arg_specs}. Length of arg names is {len(arg_names)}; "
            f"expecting {len(arg_specs)} arg names."
        )

    out_indices = set(out_spec)
    if len(out_indices) != len(out_spec):
        raise ValueError(
            f"Output subscripts '{out_spec}' does not contain all unique indices."
        )

    all_indices = {
        idx
        for argsp in arg_specs
        for idx in argsp} | out_indices

    sum_indices = all_indices - out_indices

    from pymbolic import var
    lhs = var("out")[tuple(var(i) for i in out_spec)]

    rhs = 1
    for arg_name, argsp in zip(arg_names, arg_specs):
        rhs = rhs * var(arg_name)[tuple(var(i) for i in argsp)]

    if sum_indices:
        rhs = Reduction("sum", tuple(var(idx) for idx in sum_indices), rhs)

    constraints = " and ".join(
        "0 <= %s < N%s" % (idx, idx)
        for idx in all_indices
        )

    if "name" not in knl_creation_kwargs:
        knl_creation_kwargs["name"] = "einsum%dto%d_kernel" % (
                len(all_indices), len(out_indices))

    return make_kernel("{[%s]: %s}" % (",".join(all_indices), constraints),
                       [Assignment(lhs, rhs)],
                       **knl_creation_kwargs)