Esempio n. 1
0
    def parents_per_domain(self):
        """Return a list corresponding to self.domains (by index)
        containing domain indices which are nested around this
        domain.

        Each domains nest list walks from the leaves of the nesting
        tree to the root.
        """

        # The stack of iname sets records which inames are active
        # as we step through the linear list of domains. It also
        # determines the granularity of inames to be popped/decactivated
        # if we ascend a level.

        iname_set_stack = []
        result = []

        from loopy.kernel.tools import is_domain_dependent_on_inames

        for dom_idx, dom in enumerate(self.domains):
            inames = set(dom.get_var_names(dim_type.set))

            # This next domain may be nested inside the previous domain.
            # Or it may not, in which case we need to figure out how many
            # levels of parents we need to discard in order to find the
            # true parent.

            discard_level_count = 0
            while discard_level_count < len(iname_set_stack):
                last_inames = iname_set_stack[-1-discard_level_count]

                if is_domain_dependent_on_inames(self, dom_idx, last_inames):
                    break

                discard_level_count += 1

            if discard_level_count:
                iname_set_stack = iname_set_stack[:-discard_level_count]

            if result:
                parent = len(result)-1
            else:
                parent = None

            for i in range(discard_level_count):
                assert parent is not None
                parent = result[parent]

            # found this domain's parent
            result.append(parent)

            if iname_set_stack:
                parent_inames = iname_set_stack[-1]
            else:
                parent_inames = set()
            iname_set_stack.append(parent_inames | inames)

        return result
Esempio n. 2
0
    def parents_per_domain(self):
        """Return a list corresponding to self.domains (by index)
        containing domain indices which are nested around this
        domain.

        Each domains nest list walks from the leaves of the nesting
        tree to the root.
        """

        # The stack of iname sets records which inames are active
        # as we step through the linear list of domains. It also
        # determines the granularity of inames to be popped/decactivated
        # if we ascend a level.

        iname_set_stack = []
        result = []

        from loopy.kernel.tools import is_domain_dependent_on_inames

        for dom_idx, dom in enumerate(self.domains):
            inames = set(dom.get_var_names(dim_type.set))

            # This next domain may be nested inside the previous domain.
            # Or it may not, in which case we need to figure out how many
            # levels of parents we need to discard in order to find the
            # true parent.

            discard_level_count = 0
            while discard_level_count < len(iname_set_stack):
                last_inames = iname_set_stack[-1 - discard_level_count]

                if is_domain_dependent_on_inames(self, dom_idx, last_inames):
                    break

                discard_level_count += 1

            if discard_level_count:
                iname_set_stack = iname_set_stack[:-discard_level_count]

            if result:
                parent = len(result) - 1
            else:
                parent = None

            for i in range(discard_level_count):
                assert parent is not None
                parent = result[parent]

            # found this domain's parent
            result.append(parent)

            if iname_set_stack:
                parent_inames = iname_set_stack[-1]
            else:
                parent_inames = set()
            iname_set_stack.append(parent_inames | inames)

        return result
Esempio n. 3
0
def merge_loop_domains(kernel):
    # FIXME: This should be moved to loopy.transforms.iname
    from loopy.kernel.tools import is_domain_dependent_on_inames

    while True:
        lnm = potential_loop_nest_map(kernel)
        parents_per_domain = kernel.parents_per_domain()
        all_parents_per_domain = kernel.all_parents_per_domain()

        iname_to_insns = kernel.iname_to_insns()

        new_domains = None

        for inner_iname, outer_inames in lnm.items():
            for outer_iname in outer_inames:
                # {{{ check if it's safe to merge

                inner_domain_idx = kernel.get_home_domain_index(inner_iname)
                outer_domain_idx = kernel.get_home_domain_index(outer_iname)

                if inner_domain_idx == outer_domain_idx:
                    break

                if (not iname_to_insns[inner_iname]
                        or not iname_to_insns[outer_iname]):
                    # Inames without instructions occur when used in
                    # a SubArrayRef. We don't want monster SubArrayRef domains,
                    # so refuse to merge those.
                    continue

                if iname_to_insns[inner_iname] != iname_to_insns[outer_iname]:
                    # The two inames are imperfectly nested. Domain fusion
                    # might be invalid when the inner loop is empty, leading to
                    # the outer loop also being empty.

                    # FIXME: Not fully correct, does not consider reductions
                    # https://gitlab.tiker.net/inducer/loopy/issues/172
                    continue

                if (outer_domain_idx
                        in all_parents_per_domain[inner_domain_idx]
                        and not outer_domain_idx
                        == parents_per_domain[inner_domain_idx]):
                    # Outer domain is not a direct parent of the inner
                    # domain. Unable to merge.
                    continue

                outer_dom = kernel.domains[outer_domain_idx]
                inner_dom = kernel.domains[inner_domain_idx]

                outer_inames = set(outer_dom.get_var_names(isl.dim_type.set))
                if is_domain_dependent_on_inames(kernel, inner_domain_idx,
                                                 outer_inames):
                    # Bounds of inner domain depend on outer domain.
                    # Unable to merge.
                    continue

                # }}}

                new_domains = kernel.domains[:]
                min_idx = min(inner_domain_idx, outer_domain_idx)
                max_idx = max(inner_domain_idx, outer_domain_idx)

                del new_domains[max_idx]
                del new_domains[min_idx]

                outer_dom, inner_dom = isl.align_two(outer_dom, inner_dom)

                new_domains.insert(min_idx, inner_dom & outer_dom)
                break

            if new_domains:
                break

        if not new_domains:
            # Nothing was accomplished in the last loop trip, time to quit.
            break

        kernel = kernel.copy(domains=new_domains)

    return kernel
Esempio n. 4
0
def fuse_loop_domains(kernel):
    from loopy.kernel.tools import is_domain_dependent_on_inames

    while True:
        lnm = potential_loop_nest_map(kernel)
        parents_per_domain = kernel.parents_per_domain()
        all_parents_per_domain = kernel.all_parents_per_domain()

        new_domains = None

        for inner_iname, outer_inames in six.iteritems(lnm):
            for outer_iname in outer_inames:
                # {{{ check if it's safe to fuse

                inner_domain_idx = kernel.get_home_domain_index(inner_iname)
                outer_domain_idx = kernel.get_home_domain_index(outer_iname)

                if inner_domain_idx == outer_domain_idx:
                    break

                if (
                        outer_domain_idx in all_parents_per_domain[inner_domain_idx]
                        and not
                        outer_domain_idx == parents_per_domain[inner_domain_idx]):
                    # Outer domain is not a direct parent of the inner
                    # domain. Unable to fuse.
                    continue

                outer_dom = kernel.domains[outer_domain_idx]
                inner_dom = kernel.domains[inner_domain_idx]

                outer_inames = set(outer_dom.get_var_names(isl.dim_type.set))
                if is_domain_dependent_on_inames(kernel, inner_domain_idx,
                        outer_inames):
                    # Bounds of inner domain depend on outer domain.
                    # Unable to fuse.
                    continue

                # }}}

                new_domains = kernel.domains[:]
                min_idx = min(inner_domain_idx, outer_domain_idx)
                max_idx = max(inner_domain_idx, outer_domain_idx)

                del new_domains[max_idx]
                del new_domains[min_idx]

                outer_dom, inner_dom = isl.align_two(outer_dom, inner_dom)

                new_domains.insert(min_idx, inner_dom & outer_dom)
                break

            if new_domains:
                break

        if not new_domains:
            # Nothing was accomplished in the last loop trip, time to quit.
            break

        kernel = kernel.copy(domains=new_domains)

    return kernel
Esempio n. 5
0
def fuse_loop_domains(kernel):
    from loopy.kernel.tools import is_domain_dependent_on_inames

    while True:
        lnm = potential_loop_nest_map(kernel)
        parents_per_domain = kernel.parents_per_domain()
        all_parents_per_domain = kernel.all_parents_per_domain()

        new_domains = None

        for inner_iname, outer_inames in six.iteritems(lnm):
            for outer_iname in outer_inames:
                # {{{ check if it's safe to fuse

                inner_domain_idx = kernel.get_home_domain_index(inner_iname)
                outer_domain_idx = kernel.get_home_domain_index(outer_iname)

                if inner_domain_idx == outer_domain_idx:
                    break

                if (outer_domain_idx
                        in all_parents_per_domain[inner_domain_idx]
                        and not outer_domain_idx
                        == parents_per_domain[inner_domain_idx]):
                    # Outer domain is not a direct parent of the inner
                    # domain. Unable to fuse.
                    continue

                outer_dom = kernel.domains[outer_domain_idx]
                inner_dom = kernel.domains[inner_domain_idx]

                outer_inames = set(outer_dom.get_var_names(isl.dim_type.set))
                if is_domain_dependent_on_inames(kernel, inner_domain_idx,
                                                 outer_inames):
                    # Bounds of inner domain depend on outer domain.
                    # Unable to fuse.
                    continue

                # }}}

                new_domains = kernel.domains[:]
                min_idx = min(inner_domain_idx, outer_domain_idx)
                max_idx = max(inner_domain_idx, outer_domain_idx)

                del new_domains[max_idx]
                del new_domains[min_idx]

                outer_dom, inner_dom = isl.align_two(outer_dom, inner_dom)

                new_domains.insert(min_idx, inner_dom & outer_dom)
                break

            if new_domains:
                break

        if not new_domains:
            # Nothing was accomplished in the last loop trip, time to quit.
            break

        kernel = kernel.copy(domains=new_domains)

    return kernel