diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a09e5d830da839b741a6ba8f0f8ff64641ed5ac2..a6f81e5b6e19af6362b51aec26f277a8d83bb829 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -103,6 +103,18 @@ Python 3 POCL Examples: except: - tags +Pylint: + script: + # Needed to avoid name shadowing issues when running from source directory. + - PROJECT_INSTALL_FLAGS="--editable" + - export PY_EXE=python3 + - EXTRA_INSTALL="pybind11 numpy mako matplotlib ipykernel ply fparser" + - curl -L -O -k https://gitlab.tiker.net/inducer/ci-support/raw/master/prepare-and-run-pylint.sh + - ". ./prepare-and-run-pylint.sh loopy test/test_*.py" + tags: + - python3 + except: + - tags CentOS binary: script: diff --git a/.pylintrc-local.yml b/.pylintrc-local.yml new file mode 100644 index 0000000000000000000000000000000000000000..32f9604dcd465513c7ccfe9b692657a39d3a406e --- /dev/null +++ b/.pylintrc-local.yml @@ -0,0 +1,6 @@ +- arg: extension-pkg-whitelist + val: islpy +- arg: ignore + val: compyte +- arg: init-hook + val: sys.setrecursionlimit(5000) diff --git a/loopy/auto_test.py b/loopy/auto_test.py index 015c82dd1fa5f81665f062f974149c2e93a324a9..92c01addb27dd232fd41f40048cb15d5510d765a 100644 --- a/loopy/auto_test.py +++ b/loopy/auto_test.py @@ -514,7 +514,6 @@ def auto_test_vs_ref( queue = cl.CommandQueue(ctx, properties=cl.command_queue_properties.PROFILING_ENABLE) - args = None from loopy.kernel import KernelState from loopy.target.pyopencl import PyOpenCLTarget if test_knl.state not in [ @@ -542,12 +541,12 @@ def auto_test_vs_ref( compiled = CompiledKernel(ctx, kernel) - if args is None: - kernel_info = compiled.kernel_info(frozenset()) + kernel_info = compiled.kernel_info(frozenset()) + + args = make_args(kernel, + kernel_info.implemented_data_info, + queue, ref_arg_data, parameters) - args = make_args(kernel, - kernel_info.implemented_data_info, - queue, ref_arg_data, parameters) args["out_host"] = False if not quiet: @@ -558,8 +557,23 @@ def auto_test_vs_ref( print(compiled.get_highlighted_code()) print(75*"-") if dump_binary: - print(type(compiled.cl_program)) - print(compiled.cl_program.binaries[0]) + # {{{ find cl program + + for name in dir(kernel_info.cl_kernels): + if name.startswith("__"): + continue + cl_kernel = getattr(kernel_info.cl_kernels, name) + cl_program = cl_kernel.get_info(cl.kernel_info.PROGRAM) + break + else: + assert False, "could not find cl_program" + + # }}} + + print(type(cl_program)) + if hasattr(cl_program, "binaries"): + print(cl_program.binaries[0]) + print(75*"-") logger.info("%s: run warmup" % (knl.name)) diff --git a/loopy/codegen/control.py b/loopy/codegen/control.py index 45e2a18c4b93665275cc61f84b221a2a0e504d32..e1520a82ed69fa2aed729d9b1d849a78d658c4e1 100644 --- a/loopy/codegen/control.py +++ b/loopy/codegen/control.py @@ -503,7 +503,7 @@ def build_loop_nest(codegen_state, schedule_index): prev_gen_code = gen_code - def gen_code(inner_codegen_state): + def gen_code(inner_codegen_state): # noqa pylint:disable=function-redefined condition_exprs = [ constraint_to_cond_expr(cns) for cns in bounds_checks] + [ diff --git a/loopy/codegen/loop.py b/loopy/codegen/loop.py index ebddf315373403b8afaf174d149872f5dcb4518e..58f055b7b5042ff28f7bf9674b0e7dc5ff1b6269 100644 --- a/loopy/codegen/loop.py +++ b/loopy/codegen/loop.py @@ -175,7 +175,7 @@ def generate_vectorize_loop(codegen_state, sched_index): warn(kernel, "vec_upper_not_const", "upper bound for vectorized loop '%s' is not a constant, " "cannot vectorize--unrolling instead") - return generate_unroll_loop(kernel, sched_index, codegen_state) + return generate_unroll_loop(codegen_state, sched_index) length = int(pw_aff_to_expr(length_aff)) @@ -190,7 +190,7 @@ def generate_vectorize_loop(codegen_state, sched_index): warn(kernel, "vec_lower_not_0", "lower bound for vectorized loop '%s' is not zero, " "cannot vectorize--unrolling instead") - return generate_unroll_loop(kernel, sched_index, codegen_state) + return generate_unroll_loop(codegen_state, sched_index) # {{{ 'implement' vectorization bounds diff --git a/loopy/frontend/fortran/translator.py b/loopy/frontend/fortran/translator.py index bcbe41874d8613eaabd84ae71dd65317558f0185..d7a1b2498af583bc9ff97ba743ccc5ed8bd25d3a 100644 --- a/loopy/frontend/fortran/translator.py +++ b/loopy/frontend/fortran/translator.py @@ -199,7 +199,7 @@ class Scope(object): class F2LoopyTranslator(FTreeWalkerBase): def __init__(self, filename, target=None): - FTreeWalkerBase.__init__(self) + FTreeWalkerBase.__init__(self, filename) self.target = target @@ -214,8 +214,6 @@ class F2LoopyTranslator(FTreeWalkerBase): self.conditions = [] self.conditions_data = [] - self.filename = filename - self.index_dtype = None self.block_nest = [] @@ -307,9 +305,9 @@ class F2LoopyTranslator(FTreeWalkerBase): ("integer", "8"): np.int64, } if hasattr(np, "float128"): - TYPE_MAP[("real", "16")] = np.float128 + TYPE_MAP[("real", "16")] = np.float128 # pylint:disable=no-member if hasattr(np, "complex256"): - TYPE_MAP[("complex", "32")] = np.complex256 + TYPE_MAP[("complex", "32")] = np.complex256 # pylint:disable=no-member def dtype_from_stmt(self, stmt): length, kind = stmt.selector diff --git a/loopy/frontend/fortran/tree.py b/loopy/frontend/fortran/tree.py index 6939bb6ad8727b3e9f11966285b6a22de84bb032..c7389677489f1cf1c77c2a47c395badd35de230e 100644 --- a/loopy/frontend/fortran/tree.py +++ b/loopy/frontend/fortran/tree.py @@ -28,9 +28,10 @@ from loopy.diagnostic import LoopyError class FTreeWalkerBase(object): - def __init__(self): + def __init__(self, filename): from loopy.frontend.fortran.expression import FortranExpressionParser self.expr_parser = FortranExpressionParser(self) + self.filename = filename def rec(self, expr, *args, **kwargs): mro = list(type(expr).__mro__) diff --git a/loopy/isl_helpers.py b/loopy/isl_helpers.py index 5a747d070a47ff89336c22c8237ff03e567d0a8a..664d09d2ec74f9f898cfa9a3910c9267659b28b7 100644 --- a/loopy/isl_helpers.py +++ b/loopy/isl_helpers.py @@ -56,8 +56,9 @@ def pw_aff_to_aff(pw_aff): def dump_space(ls): - return " ".join("%s: %d" % (dt, ls.dim(getattr(dim_type, dt))) - for dt in dim_type.names) + return " ".join( + "%s: %d" % (dim_type.find_value(dt), ls.dim(dt)) + for dt in range(1 + dim_type.all)) # {{{ make_slab @@ -451,7 +452,7 @@ def obj_involves_variable(obj, var_name): return True for idiv in obj.dim(dim_type.div): - if obj_involves_variable(obj.get_div(idiv)): + if obj_involves_variable(obj.get_div(idiv), var_name): return True return False diff --git a/loopy/kernel/__init__.py b/loopy/kernel/__init__.py index e3342d0f9d0cac2ef3c4e3d56423ce4b4ba0ac8a..42d7c0f1e2062f84ee171c8c6274a0aa74601a4a 100644 --- a/loopy/kernel/__init__.py +++ b/loopy/kernel/__init__.py @@ -121,15 +121,15 @@ class kernel_state(object): # noqa """ @_deperecated_kernel_state_class_method - def INITIAL(): - return KernelState.INITITAL + def INITIAL(): # pylint:disable=no-method-argument + return KernelState.INITIAL @_deperecated_kernel_state_class_method - def PREPROCESSED(): + def PREPROCESSED(): # pylint:disable=no-method-argument return KernelState.PREPROCESSED @_deperecated_kernel_state_class_method - def SCHEDULED(): + def SCHEDULED(): # pylint:disable=no-method-argument return KernelState.SCHEDULED # }}} @@ -1456,13 +1456,11 @@ class LoopKernel(ImmutableRecordWithoutPickling): # {{{ check that 'reconstituted' object has same hash from loopy.tools import LoopyKeyBuilder - LoopyKeyBuilder()(self) - - assert p_hash_digest == self._pytools_persistent_hash_digest + assert p_hash_digest == LoopyKeyBuilder()(self) # }}} - else: - self._pytools_persistent_hash_digest = p_hash_digest + + self._pytools_persistent_hash_digest = p_hash_digest from loopy.kernel.tools import SetOperationCacheManager self.cache_manager = SetOperationCacheManager() diff --git a/loopy/kernel/creation.py b/loopy/kernel/creation.py index 2175b5f364796fed58d2373d82ae18ea7128ef2f..5ba147dfdb2e6e9a4bd30ee1b37c31b002da9982 100644 --- a/loopy/kernel/creation.py +++ b/loopy/kernel/creation.py @@ -765,15 +765,14 @@ def parse_instructions(instructions, defines): local_w_inames = insn_options_stack[-1]["within_inames"] if insn.within_inames_is_final: - if not ( - local_w_inames <= insn.within_inames): + if not (local_w_inames <= insn.within_inames): raise LoopyError("non-parsed instruction '%s' without " "inames '%s' (but with final iname dependencies) " "found inside 'for'/'with' block for inames " - "'%s'" - % (insn.id, + "'%s'" % ( + insn.id, ", ".join(local_w_inames - insn.within_inames), - insn_options_stack[-1].within_inames)) + local_w_inames)) else: # not final, add inames from current scope @@ -2044,14 +2043,14 @@ def make_kernel(domains, instructions, kernel_data=["..."], **kwargs): kernel_args.append(dat) continue - if isinstance(dat, ArrayBase) and isinstance(dat.shape, tuple): + if isinstance(dat, ArrayBase) and isinstance(dat.shape, tuple): # noqa pylint:disable=no-member new_shape = [] - for shape_axis in dat.shape: + for shape_axis in dat.shape: # pylint:disable=no-member 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)) + dat = dat.copy(shape=tuple(new_shape)) # pylint:disable=no-member for arg_name in dat.name.split(","): arg_name = arg_name.strip() diff --git a/loopy/kernel/data.py b/loopy/kernel/data.py index 8103029dc5f86896b4e08dd9e277b81b01e9ca27..dd68c950e04e29fc99c456412d9dc4a53dbc61b2 100644 --- a/loopy/kernel/data.py +++ b/loopy/kernel/data.py @@ -286,15 +286,15 @@ class temp_var_scope(object): # noqa """ @_deprecated_temp_var_scope_class_method - def PRIVATE(): + def PRIVATE(): # pylint:disable=no-method-argument return AddressSpace.PRIVATE @_deprecated_temp_var_scope_class_method - def LOCAL(): + def LOCAL(): # pylint:disable=no-method-argument return AddressSpace.LOCAL @_deprecated_temp_var_scope_class_method - def GLOBAL(): + def GLOBAL(): # pylint:disable=no-method-argument return AddressSpace.GLOBAL @classmethod diff --git a/loopy/kernel/instruction.py b/loopy/kernel/instruction.py index 4d3b25497f10e3f385734f520fdbaf44842339a8..5dee96e75d36eace37efd1ea1fcaa98cfef7d0ec 100644 --- a/loopy/kernel/instruction.py +++ b/loopy/kernel/instruction.py @@ -474,7 +474,7 @@ class InstructionBase(ImmutableRecord): from loopy.tools import intern_frozenset_of_ids - if self.id is not None: + if self.id is not None: # pylint:disable=access-member-before-definition self.id = intern(self.id) self.depends_on = intern_frozenset_of_ids(self.depends_on) self.groups = intern_frozenset_of_ids(self.groups) @@ -575,23 +575,23 @@ class memory_ordering(object): # noqa """ @_deprecated_memory_ordering_class_method - def RELAXED(): + def RELAXED(): # pylint:disable=no-method-argument return MemoryOrdering.RELAXED @_deprecated_memory_ordering_class_method - def ACQUIRE(): + def ACQUIRE(): # pylint:disable=no-method-argument return MemoryOrdering.ACQUIRE @_deprecated_memory_ordering_class_method - def RELEASE(): + def RELEASE(): # pylint:disable=no-method-argument return MemoryOrdering.RELEASE @_deprecated_memory_ordering_class_method - def ACQ_REL(): + def ACQ_REL(): # pylint:disable=no-method-argument return MemoryOrdering.ACQ_REL @_deprecated_memory_ordering_class_method - def SEQ_CST(): + def SEQ_CST(): # pylint:disable=no-method-argument return MemoryOrdering.SEQ_CST @staticmethod @@ -652,23 +652,23 @@ class memory_scope(object): # noqa """ @_deprecated_memory_scope_class_method - def WORK_ITEM(): - return MemoryScope.PRIVATE + def WORK_ITEM(): # pylint:disable=no-method-argument + return MemoryScope.WORK_ITEM @_deprecated_memory_scope_class_method - def WORK_GROUP(): + def WORK_GROUP(): # pylint:disable=no-method-argument return MemoryScope.WORK_GROUP @_deprecated_memory_scope_class_method - def DEVICE(): + def DEVICE(): # pylint:disable=no-method-argument return MemoryScope.DEVICE @_deprecated_memory_scope_class_method - def ALL_SVM_DEVICES(): + def ALL_SVM_DEVICES(): # pylint:disable=no-method-argument return MemoryScope.ALL_SVM_DEVICES @_deprecated_memory_scope_class_method - def auto(): + def auto(): # pylint:disable=no-method-argument return MemoryScope.auto @staticmethod @@ -735,6 +735,10 @@ class OrderedAtomic(VarAtomicity): and self.ordering == other.ordering and self.scope == other.scope) + @property + def op_name(self): + raise NotImplementedError + def __str__(self): return "%s[%s]%s/%s" % ( self.op_name, diff --git a/loopy/library/reduction.py b/loopy/library/reduction.py index 8ed5cbe56064a3818f0b576a0d757afa3e7d5b26..2658b8cd743d335323dab7dd9aebd82ef5830652 100644 --- a/loopy/library/reduction.py +++ b/loopy/library/reduction.py @@ -226,6 +226,14 @@ class _SegmentedScalarReductionOperation(ReductionOperation): def __init__(self, **kwargs): self.inner_reduction = self.base_reduction_class(**kwargs) + @property + def base_reduction_class(self): + raise NotImplementedError + + @property + def which(self): + raise NotImplementedError + @property def arg_count(self): return 2 @@ -301,6 +309,15 @@ class ArgExtOp(ReductionOpFunction): class _ArgExtremumReductionOperation(ReductionOperation): + + @property + def which(self): + raise NotImplementedError + + @property + def neutral_sign(self): + raise NotImplementedError + def prefix(self, scalar_dtype, index_dtype): return "loopy_arg%s_%s_%s" % (self.which, scalar_dtype.numpy_dtype.type.__name__, diff --git a/loopy/maxima.py b/loopy/maxima.py index 22d0c085c0edd5a96b6b45b457957f4be50e49d7..c74360a731fa06644065e743fb9397ea170fb7f3 100644 --- a/loopy/maxima.py +++ b/loopy/maxima.py @@ -1,3 +1,4 @@ +# pylint: disable=all # This code needs porting to modern loopy """Export to maxima.""" from __future__ import division diff --git a/loopy/target/c/__init__.py b/loopy/target/c/__init__.py index 83efecf0eed38b2abc225ae0a892edd4c905214f..17dd9dc1034f4572e2bcf1d3abc806354c73336e 100644 --- a/loopy/target/c/__init__.py +++ b/loopy/target/c/__init__.py @@ -381,7 +381,7 @@ def c_math_mangler(target, name, arg_dtypes, modify_name=True): pass # fabs elif dtype == np.float32: name = name + "f" # fabsf - elif dtype == np.float128: + elif dtype == np.float128: # pylint:disable=no-member name = name + "l" # fabsl else: raise LoopyTypeError("%s does not support type %s" % (name, dtype)) @@ -407,7 +407,7 @@ def c_math_mangler(target, name, arg_dtypes, modify_name=True): pass # fmin elif dtype == np.float32: name = name + "f" # fminf - elif dtype == np.float128: + elif dtype == np.float128: # pylint:disable=no-member name = name + "l" # fminl else: raise LoopyTypeError("%s does not support type %s" diff --git a/loopy/target/cuda.py b/loopy/target/cuda.py index d6f55091a3ba994781e87f180faa49629a049772..8f14738c307ce7f2d98a47ef0dc086b4c69f7910 100644 --- a/loopy/target/cuda.py +++ b/loopy/target/cuda.py @@ -262,24 +262,6 @@ class CUDACASTBuilder(CASTBuilder): return FunctionDeclarationWrapper(fdecl) - def generate_code(self, kernel, codegen_state, impl_arg_info): - code, implemented_domains = ( - super(CudaTarget, self).generate_code( - kernel, codegen_state, impl_arg_info)) - - return code, implemented_domains - - def generate_body(self, kernel, codegen_state): - body, implemented_domains = ( - super(CudaTarget, self).generate_body(kernel, codegen_state)) - - from loopy.kernel.data import ImageArg - - if any(isinstance(arg, ImageArg) for arg in kernel.args): - raise NotImplementedError("not yet: texture arguments in CUDA") - - return body, implemented_domains - # }}} # {{{ code generation guts diff --git a/loopy/target/ispc.py b/loopy/target/ispc.py index 5e59dff48de85626e01b7caf456a74a725ea508d..cccee2301e44b16e2454bda5e98af7db7893c003 100644 --- a/loopy/target/ispc.py +++ b/loopy/target/ispc.py @@ -404,7 +404,7 @@ class ISPCASTBuilder(CASTBuilder): simplify_using_aff(kernel, idx) for idx in lhs.index_tuple) access_info = get_access_info(kernel.target, ary, index_tuple, - lambda expr: evaluate(expr, self.codegen_state.var_subst_map), + lambda expr: evaluate(expr, codegen_state.var_subst_map), codegen_state.vectorization_info) from loopy.kernel.data import ArrayArg, TemporaryVariable diff --git a/loopy/target/opencl.py b/loopy/target/opencl.py index 81292fe6086d8034ca75c381af9cfa78d1415013..8a6e5284258d864d19d7f1353ec9dfaaa7d72a9b 100644 --- a/loopy/target/opencl.py +++ b/loopy/target/opencl.py @@ -607,7 +607,7 @@ class OpenCLCASTBuilder(CASTBuilder): var_kind = "__global" else: raise LoopyError("unexpected kind of variable '%s' in " - "atomic operation: " + "atomic operation: '%s'" % (lhs_var.name, type(lhs_var).__name__)) old_val = "*(%s *) &" % ctype + old_val diff --git a/loopy/tools.py b/loopy/tools.py index 470921e31293192b6e96e90b02ec41968bc5fad9..0fc6d1bf9b3885db86cc1f4642a4e1342fcfd5a0 100644 --- a/loopy/tools.py +++ b/loopy/tools.py @@ -42,7 +42,7 @@ from six.moves import intern if six.PY2: def is_integer(obj): - return isinstance(obj, (int, long, np.integer)) # noqa + return isinstance(obj, (int, long, np.integer)) # noqa pylint:disable=undefined-variable else: def is_integer(obj): return isinstance(obj, (int, np.integer)) diff --git a/loopy/transform/iname.py b/loopy/transform/iname.py index 83598dcc26646261703ce9b24fecebdd8a975774..51de1119112b9ce4e311a743d2cd7405398179ed 100644 --- a/loopy/transform/iname.py +++ b/loopy/transform/iname.py @@ -675,7 +675,12 @@ def tag_inames(kernel, iname_to_tag, force=False, ignore_nonexistent=False): iname_to_tag = list(six.iteritems(iname_to_tag)) # flatten iterables of tags for each iname - from collections import Iterable + + try: + from collections.abc import Iterable + except ImportError: + from collections import Iterable # pylint:disable=no-name-in-module + unpack_iname_to_tag = [] for iname, tags in iname_to_tag: if isinstance(tags, Iterable) and not isinstance(tags, str): diff --git a/loopy/transform/precompute.py b/loopy/transform/precompute.py index 52d568975216699f53b6a038d0ce775b89dbc4b0..f2b184a4119485e53d7dee14b1a322be45a0bfe3 100644 --- a/loopy/transform/precompute.py +++ b/loopy/transform/precompute.py @@ -997,13 +997,13 @@ def precompute(kernel, subst_use, sweep_inames=[], within=None, if len(temp_var.shape) != len(new_temp_shape): raise LoopyError("Existing and new temporary '%s' do not " - "have matching number of dimensions " + "have matching number of dimensions ('%d' vs. '%d') " % (temporary_name, len(temp_var.shape), len(new_temp_shape))) if temp_var.base_indices != (0,) * len(new_temp_shape): raise LoopyError("Existing and new temporary '%s' do not " - "have matching number of dimensions " + "have matching number of dimensions ('%d' vs. '%d') " % (temporary_name, len(temp_var.shape), len(new_temp_shape))) diff --git a/test/test_loopy.py b/test/test_loopy.py index defd27dc0dd0d14789a8f569c297ac1f86572abc..80af89f3bb09f2d2bf394279115acfa0fe928e2b 100644 --- a/test/test_loopy.py +++ b/test/test_loopy.py @@ -2927,6 +2927,23 @@ def test_backwards_dep_printing_and_error(): print(knl) +def test_dump_binary(ctx_factory): + ctx = ctx_factory() + + knl = lp.make_kernel( + "{ [i]: 0<=i