From 47781a7047ebb00a47a8585147bce3e579e0f3a8 Mon Sep 17 00:00:00 2001 From: Dominic Kempf Date: Mon, 28 Nov 2016 16:21:32 +0100 Subject: [PATCH 1/5] Make instructions hashable --- loopy/kernel/instruction.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/loopy/kernel/instruction.py b/loopy/kernel/instruction.py index 417ff9dd3..c31d9d242 100644 --- a/loopy/kernel/instruction.py +++ b/loopy/kernel/instruction.py @@ -199,7 +199,7 @@ class InstructionBase(Record): new_predicates.add(pred) - predicates = new_predicates + predicates = frozenset(tuple(p for p in new_predicates)) del new_predicates # }}} @@ -431,6 +431,9 @@ class InstructionBase(Record): for field_name in sorted(self.fields): key_builder.rec(key_hash, getattr(self, field_name)) + def __hash__(self): + return hash((type(self),) + tuple(getattr(self, field) for field in self.fields)) + # }}} def copy(self, **kwargs): -- GitLab From caccaf3613ab3881b80fcd03f632ebeab9538e42 Mon Sep 17 00:00:00 2001 From: Dominic Kempf Date: Tue, 29 Nov 2016 10:49:23 +0100 Subject: [PATCH 2/5] Use ImmutableRecord instead of Record throughout loopy --- loopy/codegen/__init__.py | 16 ++++++---------- loopy/codegen/control.py | 4 ++-- loopy/codegen/result.py | 6 +++--- loopy/kernel/__init__.py | 8 ++++---- loopy/kernel/array.py | 10 +++++----- loopy/kernel/data.py | 16 ++++++++-------- loopy/kernel/instruction.py | 11 ++++------- loopy/library/random123.py | 4 ++-- loopy/options.py | 6 +++--- loopy/schedule/__init__.py | 10 +++++----- loopy/symbolic.py | 4 ++-- loopy/target/pyopencl_execution.py | 4 ++-- loopy/transform/array_buffer_map.py | 4 ++-- loopy/transform/subst.py | 4 ++-- setup.py | 2 +- 15 files changed, 51 insertions(+), 58 deletions(-) diff --git a/loopy/codegen/__init__.py b/loopy/codegen/__init__.py index ffd291d53..6f312ec79 100644 --- a/loopy/codegen/__init__.py +++ b/loopy/codegen/__init__.py @@ -25,7 +25,7 @@ THE SOFTWARE. import six from loopy.diagnostic import LoopyError, warn -from pytools import Record +from pytools import ImmutableRecord import islpy as isl from pytools.persistent_dict import PersistentDict @@ -38,7 +38,7 @@ logger = logging.getLogger(__name__) # {{{ implemented data info -class ImplementedDataInfo(Record): +class ImplementedDataInfo(ImmutableRecord): """ .. attribute:: name @@ -91,7 +91,7 @@ class ImplementedDataInfo(Record): from loopy.types import LoopyType assert isinstance(dtype, LoopyType) - Record.__init__(self, + ImmutableRecord.__init__(self, name=name, dtype=dtype, arg_class=arg_class, @@ -127,7 +127,7 @@ class VectorizationInfo(object): self.space = space -class SeenFunction(Record): +class SeenFunction(ImmutableRecord): """ .. attribute:: name .. attribute:: c_name @@ -137,15 +137,11 @@ class SeenFunction(Record): """ def __init__(self, name, c_name, arg_dtypes): - Record.__init__(self, + ImmutableRecord.__init__(self, name=name, c_name=c_name, arg_dtypes=arg_dtypes) - def __hash__(self): - return hash((type(self),) - + tuple((f, getattr(self, f)) for f in type(self).fields)) - class CodeGenerationState(object): """ @@ -365,7 +361,7 @@ code_gen_cache = PersistentDict("loopy-code-gen-cache-v3-"+DATA_MODEL_VERSION, key_builder=LoopyKeyBuilder()) -class PreambleInfo(Record): +class PreambleInfo(ImmutableRecord): """ .. attribute:: kernel .. attribute:: seen_dtypes diff --git a/loopy/codegen/control.py b/loopy/codegen/control.py index 55d4560be..d206faad5 100644 --- a/loopy/codegen/control.py +++ b/loopy/codegen/control.py @@ -255,9 +255,9 @@ def build_loop_nest(codegen_state, schedule_index): # {{{ pass 2: find admissible conditional inames for each sibling schedule item - from pytools import Record + from pytools import ImmutableRecord - class ScheduleIndexInfo(Record): + class ScheduleIndexInfo(ImmutableRecord): """ .. attribute:: schedule_index .. attribute:: admissible_cond_inames diff --git a/loopy/codegen/result.py b/loopy/codegen/result.py index c683d120d..4318ad71c 100644 --- a/loopy/codegen/result.py +++ b/loopy/codegen/result.py @@ -23,7 +23,7 @@ THE SOFTWARE. """ import six -from pytools import Record +from pytools import ImmutableRecord def process_preambles(preambles): @@ -45,7 +45,7 @@ def process_preambles(preambles): # {{{ code generation result -class GeneratedProgram(Record): +class GeneratedProgram(ImmutableRecord): """ .. attribute:: name @@ -64,7 +64,7 @@ class GeneratedProgram(Record): """ -class CodeGenerationResult(Record): +class CodeGenerationResult(ImmutableRecord): """ .. attribute:: host_program .. attribute:: device_programs diff --git a/loopy/kernel/__init__.py b/loopy/kernel/__init__.py index e71a88886..5b192934c 100644 --- a/loopy/kernel/__init__.py +++ b/loopy/kernel/__init__.py @@ -28,7 +28,7 @@ import six from six.moves import range, zip, intern import numpy as np -from pytools import RecordWithoutPickling, Record, memoize_method +from pytools import ImmutableRecordWithoutPickling, ImmutableRecord, memoize_method import islpy as isl from islpy import dim_type import re @@ -83,7 +83,7 @@ class kernel_state: # noqa SCHEDULED = 2 -class LoopKernel(RecordWithoutPickling): +class LoopKernel(ImmutableRecordWithoutPickling): """These correspond more or less directly to arguments of :func:`loopy.make_kernel`. @@ -279,7 +279,7 @@ class LoopKernel(RecordWithoutPickling): assert all(dom.get_ctx() == isl.DEFAULT_CONTEXT for dom in domains) assert assumptions.get_ctx() == isl.DEFAULT_CONTEXT - RecordWithoutPickling.__init__(self, + ImmutableRecordWithoutPickling.__init__(self, domains=domains, instructions=instructions, args=args, @@ -889,7 +889,7 @@ class LoopKernel(RecordWithoutPickling): dom_intersect_assumptions, iname_idx) .coalesce()) - class BoundsRecord(Record): + class BoundsRecord(ImmutableRecord): pass size = (upper_bound_pw_aff - lower_bound_pw_aff + 1) diff --git a/loopy/kernel/array.py b/loopy/kernel/array.py index 11392f255..a02fc58d9 100644 --- a/loopy/kernel/array.py +++ b/loopy/kernel/array.py @@ -30,7 +30,7 @@ import six from six.moves import range, zip from six import iteritems -from pytools import Record, memoize_method +from pytools import ImmutableRecord, memoize_method import numpy as np # noqa @@ -40,7 +40,7 @@ from loopy.tools import is_integer # {{{ array dimension tags -class ArrayDimImplementationTag(Record): +class ArrayDimImplementationTag(ImmutableRecord): def update_persistent_hash(self, key_hash, key_builder): """Custom hash computation function for use with :class:`pytools.persistent_dict.PersistentDict`. @@ -544,7 +544,7 @@ def _parse_shape_or_strides(x): return tuple(_pymbolic_parse_if_necessary(xi) for xi in x) -class ArrayBase(Record): +class ArrayBase(ImmutableRecord): """ .. attribute :: name @@ -787,7 +787,7 @@ class ArrayBase(Record): warn("dim_names is not a tuple when calling ArrayBase constructor", DeprecationWarning, stacklevel=2) - Record.__init__(self, + ImmutableRecord.__init__(self, name=name, dtype=dtype, shape=shape, @@ -1163,7 +1163,7 @@ class ArrayBase(Record): # {{{ access code generation -class AccessInfo(Record): +class AccessInfo(ImmutableRecord): """ .. attribute:: array_name .. attribute:: vector_index diff --git a/loopy/kernel/data.py b/loopy/kernel/data.py index b1430448d..61be55ca8 100644 --- a/loopy/kernel/data.py +++ b/loopy/kernel/data.py @@ -27,7 +27,7 @@ THE SOFTWARE. from six.moves import intern import numpy as np # noqa -from pytools import Record +from pytools import ImmutableRecord from loopy.kernel.array import ArrayBase from loopy.diagnostic import LoopyError from loopy.kernel.instruction import ( # noqa @@ -54,7 +54,7 @@ class auto(object): # noqa # {{{ iname tags -class IndexTag(Record): +class IndexTag(ImmutableRecord): __slots__ = [] def __hash__(self): @@ -93,7 +93,7 @@ class AxisTag(UniqueTag): __slots__ = ["axis"] def __init__(self, axis): - Record.__init__(self, + ImmutableRecord.__init__(self, axis=axis) @property @@ -197,7 +197,7 @@ def parse_tag(tag): # {{{ arguments -class KernelArgument(Record): +class KernelArgument(ImmutableRecord): """Base class for all argument types""" def __init__(self, **kwargs): @@ -210,7 +210,7 @@ class KernelArgument(Record): kwargs["dtype"] = to_loopy_type( dtype, allow_auto=True, allow_none=True, target=target) - Record.__init__(self, **kwargs) + ImmutableRecord.__init__(self, **kwargs) class GlobalArg(ArrayBase, KernelArgument): @@ -514,7 +514,7 @@ class TemporaryVariable(ArrayBase): # {{{ subsitution rule -class SubstitutionRule(Record): +class SubstitutionRule(ImmutableRecord): """ .. attribute:: name .. attribute:: arguments @@ -527,7 +527,7 @@ class SubstitutionRule(Record): def __init__(self, name, arguments, expression): assert isinstance(arguments, tuple) - Record.__init__(self, + ImmutableRecord.__init__(self, name=name, arguments=arguments, expression=expression) def __str__(self): @@ -548,7 +548,7 @@ class SubstitutionRule(Record): # {{{ function call mangling -class CallMangleInfo(Record): +class CallMangleInfo(ImmutableRecord): """ .. attribute:: target_name diff --git a/loopy/kernel/instruction.py b/loopy/kernel/instruction.py index c31d9d242..9e1ef233c 100644 --- a/loopy/kernel/instruction.py +++ b/loopy/kernel/instruction.py @@ -23,14 +23,14 @@ THE SOFTWARE. """ from six.moves import intern -from pytools import Record, memoize_method +from pytools import ImmutableRecord, memoize_method from loopy.diagnostic import LoopyError from warnings import warn # {{{ instructions: base class -class InstructionBase(Record): +class InstructionBase(ImmutableRecord): """A base class for all types of instruction that can occur in a kernel. @@ -199,7 +199,7 @@ class InstructionBase(Record): new_predicates.add(pred) - predicates = frozenset(tuple(p for p in new_predicates)) + predicates = frozenset(new_predicates) del new_predicates # }}} @@ -255,7 +255,7 @@ class InstructionBase(Record): assert isinstance(groups, frozenset) assert isinstance(conflicts_with_groups, frozenset) - Record.__init__(self, + ImmutableRecord.__init__(self, id=id, depends_on=depends_on, depends_on_is_final=depends_on_is_final, @@ -431,9 +431,6 @@ class InstructionBase(Record): for field_name in sorted(self.fields): key_builder.rec(key_hash, getattr(self, field_name)) - def __hash__(self): - return hash((type(self),) + tuple(getattr(self, field) for field in self.fields)) - # }}} def copy(self, **kwargs): diff --git a/loopy/library/random123.py b/loopy/library/random123.py index 7d04b8c73..b8633114d 100644 --- a/loopy/library/random123.py +++ b/loopy/library/random123.py @@ -25,14 +25,14 @@ THE SOFTWARE. """ -from pytools import Record +from pytools import ImmutableRecord from mako.template import Template import numpy as np # {{{ rng metadata -class RNGInfo(Record): +class RNGInfo(ImmutableRecord): @property def full_name(self): return "%s%dx%d" % (self.name, self.width, self.bits) diff --git a/loopy/options.py b/loopy/options.py index c88c512cb..33b216e1e 100644 --- a/loopy/options.py +++ b/loopy/options.py @@ -24,7 +24,7 @@ THE SOFTWARE. import six -from pytools import Record +from pytools import ImmutableRecord import re @@ -65,7 +65,7 @@ def _apply_legacy_map(lmap, kwargs): return result -class Options(Record): +class Options(ImmutableRecord): """ Unless otherwise specified, these options are Boolean-valued (i.e. on/off). @@ -181,7 +181,7 @@ class Options(Record): allow_terminal_colors_def = ( ALLOW_TERMINAL_COLORS and allow_terminal_colors_def) - Record.__init__( + ImmutableRecord.__init__( self, annotate_inames=kwargs.get("annotate_inames", False), diff --git a/loopy/schedule/__init__.py b/loopy/schedule/__init__.py index 1031488be..c8174d94c 100644 --- a/loopy/schedule/__init__.py +++ b/loopy/schedule/__init__.py @@ -24,7 +24,7 @@ THE SOFTWARE. import six -from pytools import Record +from pytools import ImmutableRecord import sys import islpy as isl from loopy.diagnostic import warn_with_kernel, LoopyError # noqa @@ -39,7 +39,7 @@ logger = logging.getLogger(__name__) # {{{ schedule items -class ScheduleItem(Record): +class ScheduleItem(ImmutableRecord): __slots__ = [] def update_persistent_hash(self, key_hash, key_builder): @@ -552,7 +552,7 @@ class ScheduleDebugInput(Exception): # {{{ scheduling algorithm -class SchedulerState(Record): +class SchedulerState(ImmutableRecord): """ .. attribute:: kernel @@ -1351,7 +1351,7 @@ def convert_barrier_instructions_to_barriers(kernel, schedule): # {{{ barrier insertion/verification -class DependencyRecord(Record): +class DependencyRecord(ImmutableRecord): """ .. attribute:: source @@ -1376,7 +1376,7 @@ class DependencyRecord(Record): """ def __init__(self, source, target, dep_descr, variable, var_kind): - Record.__init__(self, + ImmutableRecord.__init__(self, source=source, target=target, dep_descr=dep_descr, diff --git a/loopy/symbolic.py b/loopy/symbolic.py index b1743cb1a..430c65158 100644 --- a/loopy/symbolic.py +++ b/loopy/symbolic.py @@ -28,7 +28,7 @@ THE SOFTWARE. import six from six.moves import range, zip, reduce, intern -from pytools import memoize, memoize_method, Record +from pytools import memoize, memoize_method, ImmutableRecord import pytools.lex import pymbolic.primitives as p @@ -559,7 +559,7 @@ def parse_tagged_name(expr): raise RuntimeError("subst rule name not understood: %s" % expr) -class ExpansionState(Record): +class ExpansionState(ImmutableRecord): """ .. attribute:: kernel .. attribute:: instruction diff --git a/loopy/target/pyopencl_execution.py b/loopy/target/pyopencl_execution.py index 540cad000..61e8e4f39 100644 --- a/loopy/target/pyopencl_execution.py +++ b/loopy/target/pyopencl_execution.py @@ -25,7 +25,7 @@ THE SOFTWARE. import six from six.moves import range, zip -from pytools import Record, memoize_method +from pytools import ImmutableRecord, memoize_method from loopy.diagnostic import ParameterFinderWarning from pytools.py_codegen import ( Indentation, PythonFunctionGenerator) @@ -610,7 +610,7 @@ def generate_invoker(kernel, codegen_result): # {{{ kernel executor -class _CLKernelInfo(Record): +class _CLKernelInfo(ImmutableRecord): pass diff --git a/loopy/transform/array_buffer_map.py b/loopy/transform/array_buffer_map.py index 3c7bfed43..f4e6526a7 100644 --- a/loopy/transform/array_buffer_map.py +++ b/loopy/transform/array_buffer_map.py @@ -28,11 +28,11 @@ from islpy import dim_type from loopy.symbolic import (get_dependencies, SubstitutionMapper) from pymbolic.mapper.substitutor import make_subst_func -from pytools import Record, memoize_method +from pytools import ImmutableRecord, memoize_method from pymbolic import var -class AccessDescriptor(Record): +class AccessDescriptor(ImmutableRecord): """ .. attribute:: identifier diff --git a/loopy/transform/subst.py b/loopy/transform/subst.py index b2b76ae9f..79ceff9fd 100644 --- a/loopy/transform/subst.py +++ b/loopy/transform/subst.py @@ -31,7 +31,7 @@ from loopy.symbolic import ( from loopy.diagnostic import LoopyError from pymbolic.mapper.substitutor import make_subst_func -from pytools import Record +from pytools import ImmutableRecord from pymbolic import var @@ -39,7 +39,7 @@ import logging logger = logging.getLogger(__name__) -class ExprDescriptor(Record): +class ExprDescriptor(ImmutableRecord): __slots__ = ["insn", "expr", "unif_var_dict"] diff --git a/setup.py b/setup.py index 5c8f377a6..742abee02 100644 --- a/setup.py +++ b/setup.py @@ -37,7 +37,7 @@ setup(name="loo.py", ], install_requires=[ - "pytools>=2016.1", + "pytools>=2016.2.5", "pymbolic>=2016.2", "genpy>=2016.1.2", "cgen>=2016.1", -- GitLab From de8adddf78c9539c15808710d72b122cc13cec21 Mon Sep 17 00:00:00 2001 From: Dominic Kempf Date: Tue, 29 Nov 2016 11:50:22 +0100 Subject: [PATCH 3/5] Switch some forgotten Record to ImmutableRecord --- loopy/execution.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/loopy/execution.py b/loopy/execution.py index abb71325e..5680fdbfe 100644 --- a/loopy/execution.py +++ b/loopy/execution.py @@ -25,13 +25,13 @@ THE SOFTWARE. import six import numpy as np -from pytools import Record, memoize_method +from pytools import ImmutableRecord, memoize_method from loopy.diagnostic import LoopyError # {{{ object array argument packing -class _PackingInfo(Record): +class _PackingInfo(ImmutableRecord): """ .. attribute:: name .. attribute:: sep_shape -- GitLab From c3db22368aa1d0df144a122ca26f749299b240d3 Mon Sep 17 00:00:00 2001 From: Dominic Kempf Date: Tue, 29 Nov 2016 11:51:10 +0100 Subject: [PATCH 4/5] Remove MultiAssignmentBase.__eq__ It does not do something fundamentally different than Record.__eq__ and its definition deletes the implementation of __hash__ in python3. --- loopy/kernel/instruction.py | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/loopy/kernel/instruction.py b/loopy/kernel/instruction.py index 9e1ef233c..93642103e 100644 --- a/loopy/kernel/instruction.py +++ b/loopy/kernel/instruction.py @@ -407,19 +407,6 @@ class InstructionBase(ImmutableRecord): # {{{ comparison, hashing - def __eq__(self, other): - if not type(self) == type(other): - return False - - for field_name in self.fields: - if getattr(self, field_name) != getattr(other, field_name): - return False - - return True - - def __ne__(self, other): - return not self.__eq__(other) - def update_persistent_hash(self, key_hash, key_builder): """Custom hash computation function for use with :class:`pytools.persistent_dict.PersistentDict`. -- GitLab From 5285bb93546d92165a9d1dca7e65677ddd03c1a7 Mon Sep 17 00:00:00 2001 From: Dominic Kempf Date: Tue, 29 Nov 2016 16:10:13 +0100 Subject: [PATCH 5/5] Bump pytools versio after upstream fix --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 742abee02..a941eecd2 100644 --- a/setup.py +++ b/setup.py @@ -37,7 +37,7 @@ setup(name="loo.py", ], install_requires=[ - "pytools>=2016.2.5", + "pytools>=2016.2.6", "pymbolic>=2016.2", "genpy>=2016.1.2", "cgen>=2016.1", -- GitLab