Ejemplo n.º 1
0
def argument(a: Union[Argument, SelfArgument, TensorOptionsArguments], *,
             is_out: bool) -> List[Binding]:
    # Ideally, we NEVER default native functions.  However, there are a number
    # of functions that call native:: directly and rely on the defaulting
    # existing.  So for BC, we generate defaults for non-out variants (but not
    # for out variants, where it is impossible to generate an appropriate
    # default)
    should_default = not is_out
    if isinstance(a, Argument):
        default: Optional[str] = None
        if should_default and a.default is not None:
            default = cpp.default_expr(a.default, a.type)
        return [
            Binding(
                nctype=argument_type(a, binds=a.name),
                name=a.name,
                default=default,
                argument=a,
            )
        ]
    elif isinstance(a, SelfArgument):
        # Erase SelfArgument from the distinction
        return argument(a.argument, is_out=is_out)
    elif isinstance(a, TensorOptionsArguments):
        default = None
        if should_default:
            default = '{}'
        # TODO: Not sure why the arguments assigned here are for
        # TensorOptionsArguments and not the constituent pieces.  It seems
        # to matter
        return [
            Binding(
                nctype=NamedCType('dtype',
                                  OptionalCType(BaseCType(scalarTypeT))),
                name='dtype',
                default=default,
                argument=a,
            ),
            Binding(
                nctype=NamedCType('layout', OptionalCType(BaseCType(layoutT))),
                name='layout',
                default=default,
                argument=a,
            ),
            Binding(
                nctype=NamedCType('device', OptionalCType(BaseCType(deviceT))),
                name='device',
                default=default,
                argument=a,
            ),
            Binding(
                nctype=NamedCType('pin_memory',
                                  OptionalCType(BaseCType(boolT))),
                name='pin_memory',
                default=default,
                argument=a,
            )
        ]
    else:
        assert_never(a)
Ejemplo n.º 2
0
def argument(a: Union[Argument, TensorOptionsArguments, SelfArgument], *,
             cpp_no_default_args: Set[str], method: bool, faithful: bool,
             has_tensor_options: bool) -> List[Binding]:
    def sub_argument(
        a: Union[Argument, TensorOptionsArguments,
                 SelfArgument]) -> List[Binding]:
        return argument(a,
                        cpp_no_default_args=cpp_no_default_args,
                        method=method,
                        faithful=faithful,
                        has_tensor_options=has_tensor_options)

    if isinstance(a, Argument):
        binds: ArgName
        if a.name == "memory_format" and has_tensor_options:
            binds = SpecialArgName.possibly_redundant_memory_format
        else:
            binds = a.name
        default: Optional[str] = None
        if a.name not in cpp_no_default_args and a.default is not None:
            default = default_expr(a.default, a.type)
        return [
            Binding(
                nctype=argument_type(a, binds=binds),
                name=a.name,
                default=default,
                argument=a,
            )
        ]
    elif isinstance(a, TensorOptionsArguments):
        if faithful:
            return sub_argument(a.dtype) + sub_argument(a.layout) + \
                sub_argument(a.device) + sub_argument(a.pin_memory)
        else:
            default = None
            # Enforced by NativeFunction.__post_init__
            assert 'options' not in cpp_no_default_args
            if all(x.default == "None" for x in a.all()):
                default = '{}'
            elif a.dtype.default == "long":
                default = 'at::kLong'  # TODO: this is wrong
            return [
                Binding(
                    nctype=NamedCType('options', BaseCType(tensorOptionsT)),
                    name='options',
                    default=default,
                    argument=a,
                )
            ]
    elif isinstance(a, SelfArgument):
        if method:
            # Caller is responsible for installing implicit this in context!
            return []
        else:
            return sub_argument(a.argument)
    else:
        assert_never(a)
Ejemplo n.º 3
0
def ufunctor_ctor_argument(a: Argument, scalar_t: BaseCppType) -> Binding:
    return Binding(
        nctype=ufunctor_ctor_type(a.type, binds=a.name, scalar_t=scalar_t),
        name=a.name,
        default=None,
        argument=a,
    )
Ejemplo n.º 4
0
def ufunc_argument(a: Argument, compute_t: CType) -> Binding:
    return Binding(
        nctype=ufunc_type(a.type, binds=a.name, compute_t=compute_t),
        name=a.name,
        default=None,
        argument=a,
    )
Ejemplo n.º 5
0
def arguments(func: FunctionSchema) -> List[Binding]:
    return [
        Binding(
            nctype=argument_type(a, binds=a.name),
            name=a.name,
            argument=a,
        ) for a in jit_arguments(func)
    ]
Ejemplo n.º 6
0
def argument(a: Union[Argument, SelfArgument, TensorOptionsArguments]) -> List[Binding]:
    if isinstance(a, Argument):
        return [Binding(
            nctype=argument_type(a, binds=a.name),
            name=a.name,
            default=None,
            argument=a,
        )]
    elif isinstance(a, SelfArgument):
        return argument(a.argument)
    elif isinstance(a, TensorOptionsArguments):
        raise AssertionError("structured kernels don't support TensorOptions yet")
    else:
        assert_never(a)
Ejemplo n.º 7
0
def argument(
        a: Union[Argument, TensorOptionsArguments,
                 SelfArgument]) -> List[Binding]:
    if isinstance(a, Argument):
        return [
            Binding(
                ctype=argument_type(a, binds=a.name),
                name=a.name,
                argument=a,
            )
        ]
    elif isinstance(a, SelfArgument):
        return argument(a.argument)
    elif isinstance(a, TensorOptionsArguments):
        return argument(a.dtype) + argument(a.layout) + argument(
            a.device) + argument(a.pin_memory)
    else:
        assert_never(a)
def unpack_args(f: NativeFunction) -> Tuple[List[str], List[Binding]]:
    body: List[str] = []
    unpacked_bindings: List[Binding] = []

    bindings = [
        r for a in f.func.schema_order_arguments()
        for r in cpp.argument(a,
                              method=False,
                              cpp_no_default_args=set(),
                              faithful=False,
                              has_tensor_options=False)
    ]

    for i, binding in enumerate(bindings):
        assert not isinstance(binding.argument, SelfArgument)
        if isinstance(binding.argument, TensorOptionsArguments):
            raise RuntimeError("VariableKernel shouldn't take TensorOptions")

        is_nullable = binding.argument.type.is_nullable()
        if not binding.argument.type.is_tensor_like() or is_nullable:
            unpacked_bindings.append(binding)
            continue

        is_tensor_list = is_tensor_list_type(binding.argument.type)
        ref = (not is_nullable) and not is_tensor_list
        suffix = '_opt' if is_nullable and not is_tensor_list else ''
        body.append(
            UNPACK_TENSOR.substitute(
                arg_name=binding.name,
                arg_pos=i,
                suffix=suffix,
                ref='&' if ref else '',
            ))
        unpacked_bindings.append(
            Binding(
                name=unpacked_name(binding.name),
                nctype=binding.nctype,
                argument=binding.argument,
                default=binding.default,
            ))

    return body, unpacked_bindings
Ejemplo n.º 9
0
def compute_ufunc_cpu_dtype_body(g: NativeFunctionsGroup, dtype: ScalarType,
                                 inner_loops: Dict[UfuncKey, UfuncSignature],
                                 parent_ctx: Sequence[Binding]) -> str:
    assert UfuncKey.CPUScalar in inner_loops, f"{dtype}, {inner_loops.keys()}"
    assert inner_loops.keys() <= {UfuncKey.CPUScalar, UfuncKey.CPUVector}
    scalar_loop = inner_loops[UfuncKey.CPUScalar]
    vec_loop = None
    if UfuncKey.CPUVector in inner_loops:
        vec_loop = inner_loops[UfuncKey.CPUVector]

    # NB: We DON'T use translate here, because translate is
    # incapable of CSE'ing the scalar accesses in case it is also
    # used by Vectorized; also, the unpacking here is very simple
    # and only affects Scalar; everything else is implicitly captured
    # by the lambda

    # Setup scalar in scope
    body = []
    ctx = []
    for b in parent_ctx:
        if isinstance(b.argument,
                      Argument) and b.argument.type != BaseType(BaseTy.Scalar):
            continue
        body.append(f"auto _s_{b.name} = {b.name}.to<scalar_t>();")
        ctx.append(
            Expr(f"_s_{b.name}", NamedCType(b.nctype.name,
                                            BaseCType(scalar_t))))
    if vec_loop is not None:
        for b in parent_ctx:
            if isinstance(
                    b.argument,
                    Argument) and b.argument.type != BaseType(BaseTy.Scalar):
                continue
            body.append(
                f"auto _v_{b.name} = at::vec::Vectorized<scalar_t>(_s_{b.name});"
            )
            ctx.append(
                Expr(
                    f"_v_{b.name}",
                    NamedCType(b.nctype.name,
                               VectorizedCType(BaseCType(scalar_t)))))

    # Setup lambda signature
    # NB: simplified version of ufunctor_arguments
    scalar_bindings = []
    vec_bindings = []
    for a in g.functional.func.arguments.flat_non_out:
        if not a.type.is_tensor_like():
            continue
        assert a.type == BaseType(BaseTy.Tensor)
        scalar_bindings.append(
            Binding(
                name=a.name,
                nctype=NamedCType(a.name, BaseCType(scalar_t)),
                argument=a,
            ))
        if vec_loop is not None:
            vec_bindings.append(
                Binding(
                    name=a.name,
                    nctype=NamedCType(a.name,
                                      VectorizedCType(BaseCType(scalar_t))),
                    argument=a,
                ))

    def with_ctx(b: Sequence[Binding]) -> List[Union[Expr, Binding]]:
        r: List[Union[Expr, Binding]] = []
        r.extend(ctx)
        r.extend(b)
        return r

    body_str = '\n'.join(body)
    if vec_loop is not None:
        return f"""
{body_str}
cpu_kernel_vec(iter,
  [=]({', '.join(b.decl() for b in scalar_bindings)}) {{ return {scalar_loop.call(with_ctx(scalar_bindings))}; }},
  [=]({', '.join(b.decl() for b in vec_bindings)}) {{ return {vec_loop.call(with_ctx(vec_bindings))}; }}
);
"""
    else:
        return f"""
Ejemplo n.º 10
0
# - While the forward lambda just directly calls into the at::_ops API
#   (following the dispatcher convention), the logic here for the reverse lambda
#   is responsible for generating both the call-site, and the declarations
#   (which are implemented manually in the at::functionalization::impl namespace).

# The lambdas generated for each view op in the functionalization pass are of the form
# [capture_arguments](outer_arguments) -> returns_type {
#     return name(inner_arguments);
# }

# Define some specific lambda input arguments.
base_binding = Binding(name='base',
                       nctype=NamedCType(name='base',
                                         type=ConstRefCType(
                                             BaseCType(tensorT))),
                       argument=Argument(name='base',
                                         type=BaseType(BaseTy.Tensor),
                                         default=None,
                                         annotation=None),
                       default=None)
mutated_view_binding = Binding(name='mutated_view',
                               nctype=NamedCType(name='mutated_view',
                                                 type=ConstRefCType(
                                                     BaseCType(tensorT))),
                               argument=Argument(name='base',
                                                 type=BaseType(BaseTy.Tensor),
                                                 default=None,
                                                 annotation=None),
                               default=None)
mutated_view_idx_binding = Binding(name='mutated_view_idx',
                                   nctype=NamedCType(name='mutated_view_idx',
Ejemplo n.º 11
0
def argument(a: Argument, *, remove_non_owning_ref_types: bool = False) -> Binding:
    return Binding(
        nctype=argument_type(a, binds=a.name, remove_non_owning_ref_types=remove_non_owning_ref_types),
        name=a.name,
        argument=a
    )