def calculate_cache_access(self):
<EOL>element_size = self.kernel.datatypes_size[self.kernel.datatype]<EOL>results = {'<STR_LIT>': {}}<EOL>def sympy_compare(a, b):<EOL><INDENT>c = <NUM_LIT:0><EOL>for i in range(min(len(a), len(b))):<EOL><INDENT>s = a[i] - b[i]<EOL>if sympy.simplify(s > <NUM_LIT:0>):<EOL><INDENT>c = -<NUM_LIT:1><EOL><DEDENT>elif sympy.simplify(s == <NUM_LIT:0>):<EOL><INDENT>c = <NUM_LIT:0><EOL><DEDENT>else:<EOL><INDENT>c = <NUM_LIT:1><EOL><DEDENT>if c != <NUM_LIT:0>:<EOL><INDENT>break<EOL><DEDENT><DEDENT>return c<EOL><DEDENT>accesses = defaultdict(list)<EOL>sympy_accesses = defaultdict(list)<EOL>for var_name in self.kernel.variables:<EOL><INDENT>for r in self.kernel.sources.get(var_name, []):<EOL><INDENT>if r is None:<EOL><INDENT>continue<EOL><DEDENT>accesses[var_name].append(r)<EOL>sympy_accesses[var_name].append(self.kernel.access_to_sympy(var_name, r))<EOL><DEDENT>for w in self.kernel.destinations.get(var_name, []):<EOL><INDENT>if w is None:<EOL><INDENT>continue<EOL><DEDENT>accesses[var_name].append(w)<EOL>sympy_accesses[var_name].append(self.kernel.access_to_sympy(var_name, w))<EOL><DEDENT>accesses[var_name].sort(key=cmp_to_key(sympy_compare), reverse=True)<EOL><DEDENT>results['<STR_LIT>'] = accesses<EOL>results['<STR_LIT>'] = sympy_accesses<EOL>for dimension in range(<NUM_LIT:1>, len(list(self.kernel.get_loop_stack()))+<NUM_LIT:1>):<EOL><INDENT>results['<STR_LIT>'][dimension] = {}<EOL>slices = defaultdict(list)<EOL>slices_accesses = defaultdict(list)<EOL>for var_name in accesses:<EOL><INDENT>for a in accesses[var_name]:<EOL><INDENT>slice_id = tuple([var_name, tuple(a[:-dimension])])<EOL>slices[slice_id].append(a)<EOL>slices_accesses[slice_id].append(self.kernel.access_to_sympy(var_name, a))<EOL><DEDENT><DEDENT>results['<STR_LIT>'][dimension]['<STR_LIT>'] = slices<EOL>results['<STR_LIT>'][dimension]['<STR_LIT>'] = slices_accesses<EOL>slices_distances = defaultdict(list)<EOL>for k, v in slices_accesses.items():<EOL><INDENT>for i in range(<NUM_LIT:1>, len(v)):<EOL><INDENT>slices_distances[k].append((v[i] - v[i-<NUM_LIT:1>]).simplify())<EOL><DEDENT><DEDENT>results['<STR_LIT>'][dimension]['<STR_LIT>'] = slices_distances<EOL>for dist in chain(*slices_distances.values()):<EOL><INDENT>if any([s not in self.kernel.constants.keys() for s in dist.free_symbols]):<EOL><INDENT>raise ValueError("<STR_LIT>"+str(dist))<EOL><DEDENT><DEDENT>slices_sum = sum([sum(dists) for dists in slices_distances.values()])<EOL>results['<STR_LIT>'][dimension]['<STR_LIT>'] = slices_sum<EOL>def FuckedUpMax(*args):<EOL><INDENT>if len(args) == <NUM_LIT:1>:<EOL><INDENT>return args[<NUM_LIT:0>]<EOL><DEDENT>args = [a.expand() for a in args]<EOL>max_symbols = max([len(a.free_symbols) for a in args])<EOL>args = list(filter(lambda a: len(a.free_symbols) == max_symbols, args))<EOL>if max_symbols == <NUM_LIT:0>:<EOL><INDENT>return sympy.Max(*args)<EOL><DEDENT>max_coeffs = <NUM_LIT:0><EOL>for a in args:<EOL><INDENT>for s in a.free_symbols:<EOL><INDENT>max_coeffs = max(max_coeffs, len(sympy.Poly(a, s).all_coeffs()))<EOL><DEDENT><DEDENT>def coeff_filter(a):<EOL><INDENT>return max(<EOL><NUM_LIT:0>, <NUM_LIT:0>,<EOL>*[len(sympy.Poly(a, s).all_coeffs()) for s in a.free_symbols]) == max_coeffs<EOL><DEDENT>args = list(filter(coeff_filter, args))<EOL>m = sympy.Max(*args)<EOL>return m<EOL><DEDENT>slices_max = FuckedUpMax(sympy.Integer(<NUM_LIT:0>),<EOL>*[FuckedUpMax(*dists) for dists in slices_distances.values()])<EOL>results['<STR_LIT>'][dimension]['<STR_LIT>'] = slices_max<EOL>slices_count = len(slices_accesses)<EOL>results['<STR_LIT>'][dimension]['<STR_LIT>'] = slices_count<EOL>cache_requirement_bytes = (slices_sum + slices_max*slices_count)*element_size<EOL>results['<STR_LIT>'][dimension]['<STR_LIT>'] = cache_requirement_bytes<EOL>csim = self.machine.get_cachesim(self._args.cores)<EOL>results['<STR_LIT>'][dimension]['<STR_LIT>'] = {}<EOL>for cl in csim.levels(with_mem=False):<EOL><INDENT>cache_equation = sympy.Eq(cache_requirement_bytes, cl.size())<EOL>if len(self.kernel.constants.keys()) <= <NUM_LIT:1>:<EOL><INDENT>inequality = sympy.solve(sympy.LessThan(cache_requirement_bytes, cl.size()),<EOL>*self.kernel.constants.keys())<EOL><DEDENT>else:<EOL><INDENT>inequality = sympy.LessThan(cache_requirement_bytes, cl.size())<EOL><DEDENT>try:<EOL><INDENT>eq = sympy.solve(inequality, *self.kernel.constants.keys(), dict=True)<EOL><DEDENT>except NotImplementedError:<EOL><INDENT>eq = None<EOL><DEDENT>results['<STR_LIT>'][dimension]['<STR_LIT>'][cl.name] = {<EOL>'<STR_LIT>': cl.size(),<EOL>'<STR_LIT>': cache_equation,<EOL>'<STR_LIT>': inequality,<EOL>'<STR_LIT>': eq<EOL>}<EOL><DEDENT><DEDENT>return results<EOL>
Apply layer condition model to calculate cache accesses.