diff --git a/MEMO b/MEMO index aeeb733a0eb40fd76a4e40e0798fb308337452ba..d9d823b6561a36025cef136f9b684e88fdcf52e6 100644 --- a/MEMO +++ b/MEMO @@ -41,8 +41,6 @@ Things to consider To-do ^^^^^ -- Clean up loopy.kernel. - - Group instructions by dependency/inames for scheduling, to increase sched. scalability @@ -51,10 +49,6 @@ To-do - What if no universally valid precompute base index expression is found? (test_intel_matrix_mul with n = 6*16, e.g.?) -- Add dependencies after the fact - -- Scalar insn priority - - If finding a maximum proves troublesome, move parameters into the domain - : (as in, Matlab full-slice) in prefetches @@ -111,6 +105,10 @@ Future ideas Dealt with ^^^^^^^^^^ +- Add dependencies after the fact + +- Scalar insn priority + - ScalarArg is a bad name -> renamed to ValueArg diff --git a/doc/reference.rst b/doc/reference.rst index 69b1b0fe2405ce3c7a6c6e9f2be1cb8d3a1c03b5..9b9784beff7ecbb2b7bc376382f9bad2ab20a5b3 100644 --- a/doc/reference.rst +++ b/doc/reference.rst @@ -182,6 +182,13 @@ Manipulating Reductions .. autofunction:: realize_reduction +Manipulating Instructions +------------------------- + +.. autofunction:: set_instruction_priority + +.. autofunction:: add_dependency + Finishing up ------------ diff --git a/loopy/__init__.py b/loopy/__init__.py index 43c13f8f6242a37e265726f74b1bf48ef06cd156..dc6c10c85142d9b0136975caa00565da11070d03 100644 --- a/loopy/__init__.py +++ b/loopy/__init__.py @@ -263,6 +263,9 @@ def tag_dimensions(kernel, iname_to_tag, force=False): new_iname_to_tag = kernel.iname_to_tag.copy() for iname, new_tag in iname_to_tag.iteritems(): + if iname not in kernel.all_inames(): + raise RuntimeError("iname '%s' does not exist" % iname) + old_tag = kernel.iname_to_tag.get(iname) retag_ok = False @@ -422,6 +425,79 @@ def add_prefetch(kernel, var_name, sweep_inames=[], dim_arg_names=None, else: return new_kernel +# }}} + +# {{{ instruction processing + +class _IdMatch(object): + def __init__(self, value): + self.value = value + +class _ExactIdMatch(_IdMatch): + def __call__(self, insn): + return insn.id == self.value + +class _ReIdMatch: + def __call__(self, insn): + return self.value.match(insn.id) is not None + +def _parse_insn_match(insn_match): + import re + colon_idx = insn_match.find(":") + if colon_idx == -1: + return _ExactIdMatch(insn_match) + + match_tp = insn_match[:colon_idx] + match_val = insn_match[colon_idx+1:] + + if match_tp == "glob": + from fnmatch import translate + return _ReIdMatch(re.compile(translate(match_val))) + elif match_tp == "re": + return _ReIdMatch(re.compile(match_val)) + else: + raise ValueError("match type '%s' not understood" % match_tp) + + + + +def find_instructions(kernel, insn_match): + match = _parse_insn_match(insn_match) + return [insn for insn in kernel.instructions if match(insn)] + +def map_instructions(kernel, insn_match, f): + match = _parse_insn_match(insn_match) + + new_insns = [] + + for insn in kernel.instructions: + if match(insn): + new_insns.append(f(insn)) + else: + new_insns.append(insn) + + return kernel.copy(instructions=new_insns) + +def set_instruction_priority(kernel, insn_match, priority): + """Set the priority of instructions matching *insn_match* to *priority*. + + *insn_match* may be an instruction id, a regular expression prefixed by `re:`, + or a file-name-style glob prefixed by `glob:`. + """ + + def set_prio(insn): return insn.copy(priority=priority) + return map_instructions(kernel, insn_match, set_prio) + +def add_dependency(kernel, insn_match, dependency): + """Add the instruction dependency *dependency* to the instructions matched + by *insn_match*. + + *insn_match* may be an instruction id, a regular expression prefixed by `re:`, + or a file-name-style glob prefixed by `glob:`. + """ + + def add_dep(insn): return insn.copy(insn_deps=insn.insn_deps + [dependency]) + return map_instructions(kernel, insn_match, add_dep) # }}} diff --git a/loopy/kernel.py b/loopy/kernel.py index a6d8095bb27614a5d700d91c21121d7d55f4b6cc..c14459298175fff48a900716e053b115880140d8 100644 --- a/loopy/kernel.py +++ b/loopy/kernel.py @@ -296,6 +296,7 @@ class Instruction(Record): of the program. Allowed values are *None* (for unknown), *True*, and *False*. :ivar boostable_into: a set of inames into which the instruction may need to be boosted, as a heuristic help for the scheduler. + :ivar priority: scheduling priority The following two instance variables are only used until :func:`loopy.make_kernel` is finished: @@ -309,7 +310,8 @@ class Instruction(Record): id, assignee, expression, forced_iname_deps=frozenset(), insn_deps=set(), boostable=None, boostable_into=None, - temp_var_type=None, duplicate_inames_and_tags=[]): + temp_var_type=None, duplicate_inames_and_tags=[], + priority=0): from loopy.symbolic import parse if isinstance(assignee, str): @@ -325,7 +327,9 @@ class Instruction(Record): forced_iname_deps=forced_iname_deps, insn_deps=insn_deps, boostable=boostable, boostable_into=boostable_into, - temp_var_type=temp_var_type, duplicate_inames_and_tags=duplicate_inames_and_tags) + temp_var_type=temp_var_type, + duplicate_inames_and_tags=duplicate_inames_and_tags, + priority=priority) @memoize_method def reduction_inames(self): @@ -358,8 +362,12 @@ class Instruction(Record): else: raise RuntimeError("unexpected value for Instruction.boostable") + options = [] + if self.insn_deps: - result += "\n : " + ", ".join(self.insn_deps) + options.append("deps="+":".join(self.insn_deps)) + if self.priority: + options.append("priority=%d" % self.priority) return result @@ -644,7 +652,7 @@ class LoopKernel(Record): were applied to the kernel. These are stored so that they may be repeated on expressions the user specifies later. :ivar cache_manager: - :ivar lowest_priority_inames: + :ivar lowest_priority_inames: (used internally to realize ILP) :ivar breakable_inames: these inames' loops may be broken up by the scheduler The following instance variables are only used until :func:`loopy.make_kernel` is @@ -695,14 +703,13 @@ class LoopKernel(Record): INAME_ENTRY_RE = re.compile( r"^\s*(?P\w+)\s*(?:\:\s*(?P[\w.]+))?\s*$") INSN_RE = re.compile( - r"^\s*(?:(?P