def __init__(self, name, arguments, expression): assert isinstance(arguments, tuple) ImmutableRecord.__init__(self, name=name, arguments=arguments, expression=expression)
def __init__(self, target, name, dtype, arg_class, base_name=None, shape=None, strides=None, unvec_shape=None, unvec_strides=None, offset_for_name=None, stride_for_name_and_axis=None, allows_offset=None, is_written=None): from loopy.types import LoopyType assert isinstance(dtype, LoopyType) ImmutableRecord.__init__( self, name=name, dtype=dtype, arg_class=arg_class, base_name=base_name, shape=shape, strides=strides, unvec_shape=unvec_shape, unvec_strides=unvec_strides, offset_for_name=offset_for_name, stride_for_name_and_axis=stride_for_name_and_axis, allows_offset=allows_offset, is_written=is_written)
def __init__(self, **kwargs): kwargs["name"] = intern(kwargs.pop("name")) target = kwargs.pop("target", None) dtype = kwargs.pop("dtype", None) if 'for_atomic' in kwargs: for_atomic = kwargs['for_atomic'] else: for_atomic = False from loopy.types import to_loopy_type dtype = to_loopy_type( dtype, allow_auto=True, allow_none=True, for_atomic=for_atomic, target=target) import loopy as lp if dtype is lp.auto: warn("Argument/temporary data type should be None if unspecified, " "not auto. This usage will be disallowed in 2018.", DeprecationWarning, stacklevel=2) dtype = None kwargs["dtype"] = dtype ImmutableRecord.__init__(self, **kwargs)
def __init__(self, name='', kernel_args=[], lang='c'): docs = self.init_docs(lang) ImmutableRecord.__init__(self, name=name, kernel_args=kernel_args, lang=lang, docs=docs)
def __init__(self, **kwargs): kwargs["name"] = intern(kwargs.pop("name")) target = kwargs.pop("target", None) dtype = kwargs.pop("dtype", None) if 'for_atomic' in kwargs: for_atomic = kwargs['for_atomic'] else: for_atomic = False from loopy.types import to_loopy_type dtype = to_loopy_type( dtype, allow_auto=True, allow_none=True, for_atomic=for_atomic, target=target) import loopy as lp if dtype is lp.auto: warn("Argument/temporary data type for '%s' should be None if " "unspecified, not auto. This usage will be disallowed in 2018." % kwargs["name"], DeprecationWarning, stacklevel=2) dtype = None kwargs["dtype"] = dtype ImmutableRecord.__init__(self, **kwargs)
def __init__( # All Boolean flags in here should default to False for the # string-based interface of make_options (below) to make sense. # All defaults are further required to be False when cast to bool # for the update() functionality to work. self, **kwargs): kwargs = _apply_legacy_map(self._legacy_options_map, kwargs) try: import colorama # noqa except ImportError: allow_terminal_colors_def = False else: allow_terminal_colors_def = True allow_terminal_colors_def = (ALLOW_TERMINAL_COLORS and allow_terminal_colors_def) import sys ImmutableRecord.__init__( self, annotate_inames=kwargs.get("annotate_inames", False), trace_assignments=kwargs.get("trace_assignments", False), trace_assignment_values=kwargs.get("trace_assignment_values", False), skip_arg_checks=kwargs.get( "skip_arg_checks", sys.flags.optimize # Not considered a documented env var: Only used to test # the skip_arg_checks branch during CI, which can't use # python -O. # # Considered enabled if non-empty. or bool(os.environ.get("_LOOPY_SKIP_ARG_CHECKS"))), no_numpy=kwargs.get("no_numpy", False), cl_exec_manage_array_events=kwargs.get("no_numpy", True), return_dict=kwargs.get("return_dict", False), write_wrapper=kwargs.get("write_wrapper", False), write_code=kwargs.get("write_code", False), edit_code=kwargs.get("edit_code", False), build_options=kwargs.get("build_options", []), allow_terminal_colors=kwargs.get("allow_terminal_colors", allow_terminal_colors_def), disable_global_barriers=kwargs.get("disable_global_barriers", False), check_dep_resolution=kwargs.get("check_dep_resolution", True), enforce_variable_access_ordered=kwargs.get( "enforce_variable_access_ordered", True), enforce_array_accesses_within_bounds=kwargs.get( "enforce_array_accesses_within_bounds", True), )
def __init__(self, **kwargs): kwargs["name"] = intern(kwargs.pop("name")) target = kwargs.pop("target", None) dtype = kwargs.pop("dtype", None) from loopy.types import to_loopy_type kwargs["dtype"] = to_loopy_type(dtype, allow_auto=True, allow_none=True, target=target) ImmutableRecord.__init__(self, **kwargs)
def __init__(self, args=[], local=[], readonly=[], constants=[], valueargs=[], host_constants=[], kernel_data=[]): ImmutableRecord.__init__(self, args=args, local=local, readonly=readonly, constants=constants, valueargs=valueargs, host_constants=host_constants, kernel_data=kernel_data)
def __init__( # All Boolean flags in here should default to False for the # string-based interface of make_options (below) to make sense. # All defaults are further required to be False when cast to bool # for the update() functionality to work. self, **kwargs): kwargs = _apply_legacy_map(self._legacy_options_map, kwargs) try: import colorama # noqa except ImportError: allow_terminal_colors_def = False else: allow_terminal_colors_def = True allow_terminal_colors_def = ( ALLOW_TERMINAL_COLORS and allow_terminal_colors_def) ImmutableRecord.__init__( self, annotate_inames=kwargs.get("annotate_inames", False), trace_assignments=kwargs.get("trace_assignments", False), trace_assignment_values=kwargs.get("trace_assignment_values", False), ignore_boostable_into=kwargs.get("ignore_boostable_into", False), skip_arg_checks=kwargs.get("skip_arg_checks", False), no_numpy=kwargs.get("no_numpy", False), cl_exec_manage_array_events=kwargs.get("no_numpy", True), return_dict=kwargs.get("return_dict", False), write_wrapper=kwargs.get("write_wrapper", False), write_code=kwargs.get("write_code", False), edit_code=kwargs.get("edit_code", False), build_options=kwargs.get("build_options", []), allow_terminal_colors=kwargs.get("allow_terminal_colors", allow_terminal_colors_def), disable_global_barriers=kwargs.get("disable_global_barriers", False), check_dep_resolution=kwargs.get("check_dep_resolution", True), enforce_variable_access_ordered=kwargs.get( "enforce_variable_access_ordered", False), )
def __init__( # All Boolean flags in here should default to False for the # string-based interface of make_options (below) to make sense. # All defaults are further required to be False when cast to bool # for the update() functionality to work. self, **kwargs): kwargs = _apply_legacy_map(self._legacy_options_map, kwargs) try: import colorama # noqa except ImportError: allow_terminal_colors_def = False else: allow_terminal_colors_def = True allow_terminal_colors_def = ( ALLOW_TERMINAL_COLORS and allow_terminal_colors_def) ImmutableRecord.__init__( self, annotate_inames=kwargs.get("annotate_inames", False), trace_assignments=kwargs.get("trace_assignments", False), trace_assignment_values=kwargs.get("trace_assignment_values", False), skip_arg_checks=kwargs.get("skip_arg_checks", False), no_numpy=kwargs.get("no_numpy", False), cl_exec_manage_array_events=kwargs.get("no_numpy", True), return_dict=kwargs.get("return_dict", False), write_wrapper=kwargs.get("write_wrapper", False), write_code=kwargs.get("write_code", False), edit_code=kwargs.get("edit_code", False), build_options=kwargs.get("build_options", []), allow_terminal_colors=kwargs.get("allow_terminal_colors", allow_terminal_colors_def), disable_global_barriers=kwargs.get("disable_global_barriers", False), check_dep_resolution=kwargs.get("check_dep_resolution", True), enforce_variable_access_ordered=kwargs.get( "enforce_variable_access_ordered", True), )
def __init__(self, name='', libname='', include_dirs=[], package_lang='c', wrapper='', lang='', build_dir='', libraries=[], libdirs=[]): ImmutableRecord.__init__(self, name=name, lang=lang, libname=libname, include_dirs=include_dirs, libraries=libraries, package_lang=package_lang, wrapper=wrapper, build_dir=build_dir, libdirs=libdirs)
def __init__(self, target, name, dtype, arg_class, base_name=None, shape=None, strides=None, unvec_shape=None, unvec_strides=None, offset_for_name=None, stride_for_name_and_axis=None, allows_offset=None, is_written=None): from loopy.types import LoopyType assert isinstance(dtype, LoopyType) ImmutableRecord.__init__(self, name=name, dtype=dtype, arg_class=arg_class, base_name=base_name, shape=shape, strides=strides, unvec_shape=unvec_shape, unvec_strides=unvec_strides, offset_for_name=offset_for_name, stride_for_name_and_axis=stride_for_name_and_axis, allows_offset=allows_offset, is_written=is_written)
def __init__(self, id, depends_on, depends_on_is_final, groups, conflicts_with_groups, no_sync_with, within_inames_is_final, within_inames, priority, boostable, boostable_into, predicates, tags, insn_deps=None, insn_deps_is_final=None, forced_iname_deps=None, forced_iname_deps_is_final=None): # {{{ backwards compatibility goop if depends_on is not None and insn_deps is not None: raise LoopyError("may not specify both insn_deps and depends_on") elif insn_deps is not None: warn("insn_deps is deprecated, use depends_on", DeprecationWarning, stacklevel=2) depends_on = insn_deps depends_on_is_final = insn_deps_is_final if forced_iname_deps is not None and within_inames is not None: raise LoopyError("may not specify both forced_iname_deps " "and within_inames") elif forced_iname_deps is not None: warn("forced_iname_deps is deprecated, use within_inames", DeprecationWarning, stacklevel=2) within_inames = forced_iname_deps within_inames_is_final = forced_iname_deps_is_final if predicates is None: predicates = frozenset() new_predicates = set() for pred in predicates: if isinstance(pred, str): from pymbolic.primitives import LogicalNot from loopy.symbolic import parse if pred.startswith("!"): warn("predicates starting with '!' are deprecated. " "Simply use 'not' instead") pred = LogicalNot(parse(pred[1:])) else: pred = parse(pred) new_predicates.add(pred) predicates = frozenset(new_predicates) del new_predicates # }}} if depends_on is None: depends_on = frozenset() if groups is None: groups = frozenset() if conflicts_with_groups is None: conflicts_with_groups = frozenset() if no_sync_with is None: no_sync_with = frozenset() if within_inames is None: within_inames = frozenset() if within_inames_is_final is None: within_inames_is_final = False if isinstance(depends_on, str): depends_on = frozenset(s.strip() for s in depends_on.split(",") if s.strip()) if depends_on_is_final is None: depends_on_is_final = False if depends_on_is_final and not isinstance(depends_on, frozenset): raise LoopyError("Setting depends_on_is_final to True requires " "actually specifying depends_on") if tags is None: tags = frozenset() if priority is None: priority = 0 if not isinstance(tags, frozenset): # was previously allowed to be tuple tags = frozenset(tags) # Periodically reenable these and run the tests to ensure all # performance-relevant identifiers are interned. # # from loopy.tools import is_interned # assert is_interned(id) # assert all(is_interned(dep) for dep in depends_on) # assert all(is_interned(grp) for grp in groups) # assert all(is_interned(grp) for grp in conflicts_with_groups) # assert all(is_interned(iname) for iname in within_inames) # assert all(is_interned(pred) for pred in predicates) assert isinstance(within_inames, frozenset) assert isinstance(depends_on, frozenset) or depends_on is None assert isinstance(groups, frozenset) assert isinstance(conflicts_with_groups, frozenset) ImmutableRecord.__init__(self, id=id, depends_on=depends_on, depends_on_is_final=depends_on_is_final, no_sync_with=no_sync_with, groups=groups, conflicts_with_groups=conflicts_with_groups, within_inames_is_final=within_inames_is_final, within_inames=within_inames, priority=priority, boostable=boostable, boostable_into=boostable_into, predicates=predicates, tags=tags)
def __init__(self, name, c_name, arg_dtypes): ImmutableRecord.__init__(self, name=name, c_name=c_name, arg_dtypes=arg_dtypes)
def __init__(self, name, dtype=None, shape=None, dim_tags=None, offset=0, dim_names=None, strides=None, order=None, for_atomic=False, target=None, alignment=None, **kwargs): """ All of the following (except *name*) are optional. Specify either strides or shape. :arg name: When passed to :class:`loopy.make_kernel`, this may contain multiple names separated by commas, in which case multiple arguments, each with identical properties, are created for each name. :arg shape: May be any of the things specified under :attr:`shape`, or a string which can be parsed into the previous form. :arg dim_tags: A comma-separated list of tags as understood by :func:`loopy.kernel.array.parse_array_dim_tags`. :arg strides: May be one of the following: * None * :class:`loopy.auto`. The strides will be determined by *order* and the access footprint. * a tuple like like :attr:`numpy.ndarray.shape`. Each entry of the tuple is also allowed to be a :mod:`pymbolic` expression involving kernel parameters, or a (potentially-comma separated) or a string that can be parsed to such an expression. * A string which can be parsed into the previous form. :arg order: "F" or "C" for C (row major) or Fortran (column major). Defaults to the *default_order* argument passed to :func:`loopy.make_kernel`. :arg for_atomic: Whether the array is declared for atomic access, and, if necessary, using atomic-capable data types. :arg offset: (See :attr:`offset`) :arg alignment: memory alignment in bytes """ for kwarg_name in kwargs: if kwarg_name not in self.allowed_extra_kwargs: raise TypeError("invalid kwarg: %s" % kwarg_name) import loopy as lp from loopy.types import to_loopy_type dtype = to_loopy_type(dtype, allow_auto=True, allow_none=True, for_atomic=for_atomic, target=target) if dtype is lp.auto: from warnings import warn warn( "Argument/temporary data type for '%s' should be None if " "unspecified, not auto. This usage will be disallowed in 2018." % name, DeprecationWarning, stacklevel=2) dtype = None strides_known = strides is not None and strides is not lp.auto shape_known = shape is not None and shape is not lp.auto if strides_known: strides = _parse_shape_or_strides(strides) if shape_known: shape = _parse_shape_or_strides(shape) # {{{ check dim_names if dim_names is not None: if len(dim_names) != len(set(dim_names)): raise LoopyError("dim_names are not unique") for n in dim_names: if not isinstance(n, str): raise LoopyError("found non-string '%s' in dim_names" % type(n).__name__) # }}} # {{{ convert strides to dim_tags (Note: strides override order) if dim_tags is not None and strides_known: raise TypeError("may not specify both strides and dim_tags") if dim_tags is None and strides_known: dim_tags = [FixedStrideArrayDimTag(s) for s in strides] strides = None # }}} if dim_tags is not None: dim_tags = parse_array_dim_tags( dim_tags, n_axes=(len(shape) if shape_known else None), use_increasing_target_axes=self.max_target_axes > 1, dim_names=dim_names) # {{{ determine number of user axes num_user_axes = None if shape_known: num_user_axes = len(shape) for dim_iterable in [dim_tags, dim_names]: if dim_iterable is not None: new_num_user_axes = len(dim_iterable) if num_user_axes is None: num_user_axes = new_num_user_axes else: if new_num_user_axes != num_user_axes: raise LoopyError( "contradictory values for number of " "dimensions of array '%s' from shape, strides, " "dim_tags, or dim_names" % name) del new_num_user_axes # }}} # {{{ convert order to dim_tags if order is None and self.max_target_axes > 1: # FIXME: Hackety hack. ImageArgs need to generate dim_tags even # if no order is specified. Plus they don't care that much. order = "C" if dim_tags is None and num_user_axes is not None and order is not None: dim_tags = parse_array_dim_tags( num_user_axes * [order], n_axes=num_user_axes, use_increasing_target_axes=self.max_target_axes > 1, dim_names=dim_names) order = None # }}} if dim_tags is not None: # {{{ find number of target axes target_axes = set() for dim_tag in dim_tags: if isinstance(dim_tag, _StrideArrayDimTagBase): target_axes.add(dim_tag.target_axis) if target_axes != set(range(len(target_axes))): raise LoopyError("target axes for variable '%s' are non-" "contiguous" % self.name) num_target_axes = len(target_axes) del target_axes # }}} if not (self.min_target_axes <= num_target_axes <= self.max_target_axes): raise LoopyError( "%s only supports between %d and %d target axes " "('%s' has %d)" % (type(self).__name__, self.min_target_axes, self.max_target_axes, self.name, num_target_axes)) new_dim_tags = convert_computed_to_fixed_dim_tags( name, num_user_axes, num_target_axes, shape, dim_tags) if new_dim_tags is not None: # successfully normalized dim_tags = new_dim_tags del new_dim_tags if dim_tags is not None: # for hashability dim_tags = tuple(dim_tags) order = None if strides is not None: # Preserve strides if we weren't able to process them yet. # That only happens if they're set to loopy.auto (and 'guessed' # in loopy.kernel.creation). kwargs["strides"] = strides if dim_names is not None and not isinstance(dim_names, tuple): from warnings import warn warn("dim_names is not a tuple when calling ArrayBase constructor", DeprecationWarning, stacklevel=2) ImmutableRecord.__init__(self, name=name, dtype=dtype, shape=shape, dim_tags=dim_tags, offset=offset, dim_names=dim_names, order=order, alignment=alignment, for_atomic=for_atomic, **kwargs)
def __init__(self, axis): ImmutableRecord.__init__(self, axis=axis)
def __init__(self, id, depends_on, depends_on_is_final, groups, conflicts_with_groups, no_sync_with, within_inames_is_final, within_inames, priority, boostable, boostable_into, predicates, tags, insn_deps=None, insn_deps_is_final=None, forced_iname_deps=None, forced_iname_deps_is_final=None): # {{{ backwards compatibility goop if depends_on is not None and insn_deps is not None: raise LoopyError("may not specify both insn_deps and depends_on") elif insn_deps is not None: warn("insn_deps is deprecated, use depends_on", DeprecationWarning, stacklevel=2) depends_on = insn_deps depends_on_is_final = insn_deps_is_final if forced_iname_deps is not None and within_inames is not None: raise LoopyError("may not specify both forced_iname_deps " "and within_inames") elif forced_iname_deps is not None: warn("forced_iname_deps is deprecated, use within_inames", DeprecationWarning, stacklevel=2) within_inames = forced_iname_deps within_inames_is_final = forced_iname_deps_is_final if predicates is None: predicates = frozenset() new_predicates = set() for pred in predicates: if isinstance(pred, str): from pymbolic.primitives import LogicalNot from loopy.symbolic import parse if pred.startswith("!"): warn("predicates starting with '!' are deprecated. " "Simply use 'not' instead") pred = LogicalNot(parse(pred[1:])) else: pred = parse(pred) new_predicates.add(pred) predicates = frozenset(new_predicates) del new_predicates # }}} if depends_on is None: depends_on = frozenset() if groups is None: groups = frozenset() if conflicts_with_groups is None: conflicts_with_groups = frozenset() if no_sync_with is None: no_sync_with = frozenset() if within_inames is None: within_inames = frozenset() if within_inames_is_final is None: within_inames_is_final = False if isinstance(depends_on, str): depends_on = frozenset( s.strip() for s in depends_on.split(",") if s.strip()) if depends_on_is_final is None: depends_on_is_final = False if depends_on_is_final and not isinstance(depends_on, frozenset): raise LoopyError("Setting depends_on_is_final to True requires " "actually specifying depends_on") if tags is None: tags = frozenset() if priority is None: priority = 0 if not isinstance(tags, frozenset): # was previously allowed to be tuple tags = frozenset(tags) # Periodically reenable these and run the tests to ensure all # performance-relevant identifiers are interned. # # from loopy.tools import is_interned # assert is_interned(id) # assert all(is_interned(dep) for dep in depends_on) # assert all(is_interned(grp) for grp in groups) # assert all(is_interned(grp) for grp in conflicts_with_groups) # assert all(is_interned(iname) for iname in within_inames) # assert all(is_interned(pred) for pred in predicates) assert isinstance(within_inames, frozenset) assert isinstance(depends_on, frozenset) or depends_on is None assert isinstance(groups, frozenset) assert isinstance(conflicts_with_groups, frozenset) ImmutableRecord.__init__(self, id=id, depends_on=depends_on, depends_on_is_final=depends_on_is_final, no_sync_with=no_sync_with, groups=groups, conflicts_with_groups=conflicts_with_groups, within_inames_is_final=within_inames_is_final, within_inames=within_inames, priority=priority, boostable=boostable, boostable_into=boostable_into, predicates=predicates, tags=tags)
def __init__(self, name, dtype=None, shape=None, dim_tags=None, offset=0, dim_names=None, strides=None, order=None, for_atomic=False, target=None, alignment=None, **kwargs): """ All of the following (except *name*) are optional. Specify either strides or shape. :arg name: When passed to :class:`loopy.make_kernel`, this may contain multiple names separated by commas, in which case multiple arguments, each with identical properties, are created for each name. :arg shape: May be any of the things specified under :attr:`shape`, or a string which can be parsed into the previous form. :arg dim_tags: A comma-separated list of tags as understood by :func:`parse_array_dim_tag`. :arg strides: May be one of the following: * None * :class:`loopy.auto`. The strides will be determined by *order* and the access footprint. * a tuple like like :attr:`numpy.ndarray.shape`. Each entry of the tuple is also allowed to be a :mod:`pymbolic` expression involving kernel parameters, or a (potentially-comma separated) or a string that can be parsed to such an expression. * A string which can be parsed into the previous form. :arg order: "F" or "C" for C (row major) or Fortran (column major). Defaults to the *default_order* argument passed to :func:`loopy.make_kernel`. :arg for_atomic: Whether the array is declared for atomic access, and, if necessary, using atomic-capable data types. :arg offset: (See :attr:`offset`) :arg alignment: memory alignment in bytes """ for kwarg_name in kwargs: if kwarg_name not in self.allowed_extra_kwargs: raise TypeError("invalid kwarg: %s" % kwarg_name) import loopy as lp from loopy.types import to_loopy_type dtype = to_loopy_type(dtype, allow_auto=True, allow_none=True, for_atomic=for_atomic, target=target) if dtype is lp.auto: from warnings import warn warn("Argument/temporary data type for '%s' should be None if " "unspecified, not auto. This usage will be disallowed in 2018." % name, DeprecationWarning, stacklevel=2) dtype = None strides_known = strides is not None and strides is not lp.auto shape_known = shape is not None and shape is not lp.auto if strides_known: strides = _parse_shape_or_strides(strides) if shape_known: shape = _parse_shape_or_strides(shape) # {{{ check dim_names if dim_names is not None: if len(dim_names) != len(set(dim_names)): raise LoopyError("dim_names are not unique") for n in dim_names: if not isinstance(n, str): raise LoopyError("found non-string '%s' in dim_names" % type(n).__name__) # }}} # {{{ convert strides to dim_tags (Note: strides override order) if dim_tags is not None and strides_known: raise TypeError("may not specify both strides and dim_tags") if dim_tags is None and strides_known: dim_tags = [FixedStrideArrayDimTag(s) for s in strides] strides = None # }}} if dim_tags is not None: dim_tags = parse_array_dim_tags(dim_tags, n_axes=(len(shape) if shape_known else None), use_increasing_target_axes=self.max_target_axes > 1, dim_names=dim_names) # {{{ determine number of user axes num_user_axes = None if shape_known: num_user_axes = len(shape) for dim_iterable in [dim_tags, dim_names]: if dim_iterable is not None: new_num_user_axes = len(dim_iterable) if num_user_axes is None: num_user_axes = new_num_user_axes else: if new_num_user_axes != num_user_axes: raise LoopyError("contradictory values for number of " "dimensions of array '%s' from shape, strides, " "dim_tags, or dim_names" % name) del new_num_user_axes # }}} # {{{ convert order to dim_tags if order is None and self.max_target_axes > 1: # FIXME: Hackety hack. ImageArgs need to generate dim_tags even # if no order is specified. Plus they don't care that much. order = "C" if dim_tags is None and num_user_axes is not None and order is not None: dim_tags = parse_array_dim_tags(num_user_axes*[order], n_axes=num_user_axes, use_increasing_target_axes=self.max_target_axes > 1, dim_names=dim_names) order = None # }}} if dim_tags is not None: # {{{ find number of target axes target_axes = set() for dim_tag in dim_tags: if isinstance(dim_tag, _StrideArrayDimTagBase): target_axes.add(dim_tag.target_axis) if target_axes != set(range(len(target_axes))): raise LoopyError("target axes for variable '%s' are non-" "contiguous" % self.name) num_target_axes = len(target_axes) del target_axes # }}} if not (self.min_target_axes <= num_target_axes <= self.max_target_axes): raise LoopyError("%s only supports between %d and %d target axes " "('%s' has %d)" % (type(self).__name__, self.min_target_axes, self.max_target_axes, self.name, num_target_axes)) new_dim_tags = convert_computed_to_fixed_dim_tags( name, num_user_axes, num_target_axes, shape, dim_tags) if new_dim_tags is not None: # successfully normalized dim_tags = new_dim_tags del new_dim_tags if dim_tags is not None: # for hashability dim_tags = tuple(dim_tags) order = None if strides is not None: # Preserve strides if we weren't able to process them yet. # That only happens if they're set to loopy.auto (and 'guessed' # in loopy.kernel.creation). kwargs["strides"] = strides if dim_names is not None and not isinstance(dim_names, tuple): from warnings import warn warn("dim_names is not a tuple when calling ArrayBase constructor", DeprecationWarning, stacklevel=2) ImmutableRecord.__init__(self, name=name, dtype=dtype, shape=shape, dim_tags=dim_tags, offset=offset, dim_names=dim_names, order=order, alignment=alignment, for_atomic=for_atomic, **kwargs)
def __init__(self, name, dtype=None, shape=None, dim_tags=None, offset=0, dim_names=None, strides=None, order=None, for_atomic=False, target=None, **kwargs): """ All of the following (except *name*) are optional. Specify either strides or shape. :arg name: May contain multiple names separated by commas, in which case multiple arguments, each with identical properties, are created for each name. :arg dtype: the :class:`numpy.dtype` of the array. If this is *None*, :mod:`loopy` will try to continue without knowing the type of this array, where the idea is that precise knowledge of the type will become available at invocation time. :class:`loopy.CompiledKernel` (and thereby :meth:`loopy.LoopKernel.__call__`) automatically add this type information based on invocation arguments. Note that some transformations, such as :func:`loopy.add_padding` cannot be performed without knowledge of the exact *dtype*. :arg shape: May be one of the following: * *None*. In this case, no shape is intended to be specified, only the strides will be used to access the array. Bounds checking will not be performed. * :class:`loopy.auto`. The shape will be determined by finding the access footprint. * a tuple like like :attr:`numpy.ndarray.shape`. Each entry of the tuple is also allowed to be a :mod:`pymbolic` expression involving kernel parameters, or a (potentially-comma separated) or a string that can be parsed to such an expression. Any element of the shape tuple not used to compute strides may be *None*. * A string which can be parsed into the previous form. :arg dim_tags: A comma-separated list of tags as understood by :func:`parse_array_dim_tag`. :arg strides: May be one of the following: * None * :class:`loopy.auto`. The strides will be determined by *order* and the access footprint. * a tuple like like :attr:`numpy.ndarray.shape`. Each entry of the tuple is also allowed to be a :mod:`pymbolic` expression involving kernel parameters, or a (potentially-comma separated) or a string that can be parsed to such an expression. * A string which can be parsed into the previous form. :arg order: "F" or "C" for C (row major) or Fortran (column major). Defaults to the *default_order* argument passed to :func:`loopy.make_kernel`. :arg for_atomic: Whether the array is declared for atomic access, and, if necessary, using atomic-capable data types. :arg offset: Offset from the beginning of the buffer to the point from which the strides are counted. May be one of * 0 or None * a string (that is interpreted as an argument name). * a pymbolic expression * :class:`loopy.auto`, in which case an offset argument is added automatically, immediately following this argument. :class:`loopy.CompiledKernel` is even smarter in its treatment of this case and will compile custom versions of the kernel based on whether the passed arrays have offsets or not. """ for kwarg_name in kwargs: if kwarg_name not in self.allowed_extra_kwargs: raise TypeError("invalid kwarg: %s" % kwarg_name) import loopy as lp from loopy.types import to_loopy_type dtype = to_loopy_type(dtype, allow_auto=True, allow_none=True, for_atomic=for_atomic, target=target) strides_known = strides is not None and strides is not lp.auto shape_known = shape is not None and shape is not lp.auto if strides_known: strides = _parse_shape_or_strides(strides) if shape_known: shape = _parse_shape_or_strides(shape) # {{{ check dim_names if dim_names is not None: if len(dim_names) != len(set(dim_names)): raise LoopyError("dim_names are not unique") for n in dim_names: if not isinstance(n, str): raise LoopyError("found non-string '%s' in dim_names" % type(n).__name__) # }}} # {{{ convert strides to dim_tags (Note: strides override order) if dim_tags is not None and strides_known: raise TypeError("may not specify both strides and dim_tags") if dim_tags is None and strides_known: dim_tags = [FixedStrideArrayDimTag(s) for s in strides] strides = None # }}} if dim_tags is not None: dim_tags = parse_array_dim_tags(dim_tags, n_axes=(len(shape) if shape_known else None), use_increasing_target_axes=self.max_target_axes > 1, dim_names=dim_names) # {{{ determine number of user axes num_user_axes = None if shape_known: num_user_axes = len(shape) for dim_iterable in [dim_tags, dim_names]: if dim_iterable is not None: new_num_user_axes = len(dim_iterable) if num_user_axes is None: num_user_axes = new_num_user_axes else: if new_num_user_axes != num_user_axes: raise LoopyError("contradictory values for number of " "dimensions of array '%s' from shape, strides, " "dim_tags, or dim_names" % name) del new_num_user_axes # }}} # {{{ convert order to dim_tags if order is None and self.max_target_axes > 1: # FIXME: Hackety hack. ImageArgs need to generate dim_tags even # if no order is specified. Plus they don't care that much. order = "C" if dim_tags is None and num_user_axes is not None and order is not None: dim_tags = parse_array_dim_tags(num_user_axes*[order], n_axes=num_user_axes, use_increasing_target_axes=self.max_target_axes > 1, dim_names=dim_names) order = None # }}} if dim_tags is not None: # {{{ find number of target axes target_axes = set() for dim_tag in dim_tags: if isinstance(dim_tag, _StrideArrayDimTagBase): target_axes.add(dim_tag.target_axis) if target_axes != set(range(len(target_axes))): raise LoopyError("target axes for variable '%s' are non-" "contiguous" % self.name) num_target_axes = len(target_axes) del target_axes # }}} if not (self.min_target_axes <= num_target_axes <= self.max_target_axes): raise LoopyError("%s only supports between %d and %d target axes " "('%s' has %d)" % (type(self).__name__, self.min_target_axes, self.max_target_axes, self.name, num_target_axes)) new_dim_tags = convert_computed_to_fixed_dim_tags( name, num_user_axes, num_target_axes, shape, dim_tags) if new_dim_tags is not None: # successfully normalized dim_tags = new_dim_tags del new_dim_tags if dim_tags is not None: # for hashability dim_tags = tuple(dim_tags) order = None if strides is not None: # Preserve strides if we weren't able to process them yet. # That only happens if they're set to loopy.auto (and 'guessed' # in loopy.kernel.creation). kwargs["strides"] = strides if dim_names is not None and not isinstance(dim_names, tuple): from warnings import warn warn("dim_names is not a tuple when calling ArrayBase constructor", DeprecationWarning, stacklevel=2) ImmutableRecord.__init__(self, name=name, dtype=dtype, shape=shape, dim_tags=dim_tags, offset=offset, dim_names=dim_names, order=order, **kwargs)