def set_options(kernel, *args, **kwargs): """Return a new kernel with the options given as keyword arguments, or from a string representation passed in as the first (and only) positional argument. See also :class:`Options`. """ if args and kwargs: raise TypeError("cannot pass both positional and keyword arguments") new_opt = kernel.options.copy() if kwargs: from loopy.options import _apply_legacy_map, Options kwargs = _apply_legacy_map(Options._legacy_options_map, kwargs) for key, val in kwargs.items(): if not hasattr(new_opt, key): raise ValueError("unknown option '%s'" % key) setattr(new_opt, key, val) else: if len(args) != 1: raise TypeError("exactly one positional argument is required if " "no keyword args are given") arg, = args from loopy.options import make_options new_opt.update(make_options(arg)) return kernel.copy(options=new_opt)
def set_options(kernel, *args, **kwargs): """Return a new kernel with the options given as keyword arguments, or from a string representation passed in as the first (and only) positional argument. See also :class:`Options`. """ if args and kwargs: raise TypeError("cannot pass both positional and keyword arguments") new_opt = kernel.options.copy() if kwargs: for key, val in six.iteritems(kwargs): if not hasattr(new_opt, key): raise ValueError("unknown option '%s'" % key) setattr(new_opt, key, val) else: if len(args) != 1: raise TypeError("exactly one positional argument is required if " "no keyword args are given") arg, = args from loopy.options import make_options new_opt.update(make_options(arg)) return kernel.copy(options=new_opt)
def make_kernel(domains, instructions, kernel_data=["..."], **kwargs): """User-facing kernel creation entrypoint. :arg domains: :class:`islpy.BasicSet` :arg instructions: :arg kernel_data: A list of :class:`ValueArg`, :class:`GlobalArg`, ... (etc.) instances. The order of these arguments determines the order of the arguments to the generated kernel. May also contain :class:`TemporaryVariable` instances(which do not give rise to kernel-level arguments). The string ``"..."`` may be passed as one of the entries of the list, in which case loopy will infer names, shapes, and types of arguments from the kernel code. It is possible to just pass the list ``["..."]``, in which case all arguments are inferred. In Python 3, the string ``"..."`` may be spelled somewhat more sensibly as just ``...`` (the ellipsis), for the same meaning. As an additional option, each argument may be specified as just a name (a string). This is useful to specify argument ordering. All other characteristics of the named arguments are inferred. The following keyword arguments are recognized: :arg preambles: a list of (tag, code) tuples that identify preamble snippets. Each tag's snippet is only included once, at its first occurrence. The preambles will be inserted in order of their tags. :arg preamble_generators: a list of functions of signature (seen_dtypes, seen_functions) where seen_functions is a set of (name, c_name, arg_dtypes), generating extra entries for *preambles*. :arg defines: a dictionary of replacements to be made in instructions given as strings before parsing. A macro instance intended to be replaced should look like "MACRO" in the instruction code. The expansion given in this parameter is allowed to be a list. In this case, instructions are generated for *each* combination of macro values. These defines may also be used in the domain and in argument shapes and strides. They are expanded only upon kernel creation. :arg default_order: "C" (default) or "F" :arg default_offset: 0 or :class:`loopy.auto`. The default value of *offset* in :attr:`loopy.kernel.data.GlobalArg` for guessed arguments. Defaults to 0. :arg function_manglers: list of functions of signature (name, arg_dtypes) returning a tuple (result_dtype, c_name) or a tuple (result_dtype, c_name, arg_dtypes), where c_name is the C-level function to be called. :arg symbol_manglers: list of functions of signature (name) returning a tuple (result_dtype, c_name), where c_name is the C-level symbol to be evaluated. :arg assumptions: the initial implemented_domain, captures assumptions on loop domain parameters. (an isl.Set or a string in :ref:`isl-syntax`. If given as a string, only the CONDITIONS part of the set notation should be given.) :arg local_sizes: A dictionary from integers to integers, mapping workgroup axes to their sizes, e.g. *{0: 16}* forces axis 0 to be length 16. :arg silenced_warnings: a list (or semicolon-separated string) or warnings to silence :arg options: an instance of :class:`loopy.Options` or an equivalent string representation :arg target: an instance of :class:`loopy.target.TargetBase`, or *None*, to use an OpenCL target. """ defines = kwargs.pop("defines", {}) default_order = kwargs.pop("default_order", "C") default_offset = kwargs.pop("default_offset", 0) silenced_warnings = kwargs.pop("silenced_warnings", []) options = kwargs.pop("options", None) flags = kwargs.pop("flags", None) target = kwargs.pop("target", None) if target is None: try: import pyopencl # noqa except ImportError: from loopy.target.opencl import OpenCLTarget target = OpenCLTarget() else: from loopy.target.pyopencl import PyOpenCLTarget target = PyOpenCLTarget() if flags is not None: if options is not None: raise TypeError("may not pass both 'options' and 'flags'") from warnings import warn warn("'flags' is deprecated. Use 'options' instead", DeprecationWarning, stacklevel=2) options = flags from loopy.options import make_options options = make_options(options) if isinstance(silenced_warnings, str): silenced_warnings = silenced_warnings.split(";") # {{{ separate temporary variables and arguments, take care of names with commas from loopy.kernel.data import TemporaryVariable, ArrayBase if isinstance(kernel_data, str): kernel_data = kernel_data.split(",") kernel_args = [] temporary_variables = kwargs.pop("temporary_variables", {}).copy() for dat in kernel_data: if dat is Ellipsis or isinstance(dat, str): kernel_args.append(dat) continue if isinstance(dat, ArrayBase) and isinstance(dat.shape, tuple): new_shape = [] for shape_axis in dat.shape: if shape_axis is not None: new_shape.append(expand_defines_in_expr(shape_axis, defines)) else: new_shape.append(shape_axis) dat = dat.copy(shape=tuple(new_shape)) for arg_name in dat.name.split(","): arg_name = arg_name.strip() if not arg_name: continue my_dat = dat.copy(name=arg_name) if isinstance(dat, TemporaryVariable): temporary_variables[my_dat.name] = dat else: kernel_args.append(my_dat) del kernel_data # }}} # {{{ instruction/subst parsing parsed_instructions = [] kwargs["substitutions"] = substitutions = {} inames_to_dup = [] if isinstance(instructions, str): instructions = [instructions] for insn in instructions: for new_insn, insn_inames_to_dup in parse_if_necessary(insn, defines): if isinstance(new_insn, InstructionBase): parsed_instructions.append(new_insn) # Need to maintain 1-to-1 correspondence to instructions inames_to_dup.append(insn_inames_to_dup) elif isinstance(new_insn, SubstitutionRule): substitutions[new_insn.name] = new_insn assert not insn_inames_to_dup else: raise RuntimeError("unexpected type in instruction parsing") instructions = parsed_instructions del parsed_instructions # }}} # {{{ find/create isl_context for domain in domains: if isinstance(domain, isl.BasicSet): assert domain.get_ctx() == isl.DEFAULT_CONTEXT # }}} domains = parse_domains(domains, defines) arg_guesser = ArgumentGuesser(domains, instructions, temporary_variables, substitutions, default_offset) kernel_args = arg_guesser.convert_names_to_full_args(kernel_args) kernel_args = arg_guesser.guess_kernel_args_if_requested(kernel_args) from loopy.kernel import LoopKernel knl = LoopKernel(domains, instructions, kernel_args, temporary_variables=temporary_variables, silenced_warnings=silenced_warnings, options=options, target=target, **kwargs) from loopy import duplicate_inames for insn, insn_inames_to_dup in zip(knl.instructions, inames_to_dup): for old_iname, new_iname in insn_inames_to_dup: knl = duplicate_inames(knl, old_iname, within=insn.id, new_inames=new_iname) check_for_nonexistent_iname_deps(knl) knl = tag_reduction_inames_as_sequential(knl) knl = create_temporaries(knl, default_order) knl = determine_shapes_of_temporaries(knl) knl = expand_cses(knl) knl = expand_defines_in_shapes(knl, defines) knl = guess_arg_shape_if_requested(knl, default_order) knl = apply_default_order_to_args(knl, default_order) knl = resolve_wildcard_deps(knl) # ------------------------------------------------------------------------- # Ordering dependency: # ------------------------------------------------------------------------- # Must create temporaries before checking for writes to temporary variables # that are domain parameters. # ------------------------------------------------------------------------- check_for_multiple_writes_to_loop_bounds(knl) check_for_duplicate_names(knl) check_written_variable_names(knl) from loopy.preprocess import prepare_for_caching knl = prepare_for_caching(knl) return knl