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
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
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
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
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