kerncraft/models/ecm.py
def calculate_cycles(self):
        """
        Calculate performance model cycles from cache stats.

        calculate_cache_access() needs to have been execute before.
        """
        element_size = self.kernel.datatypes_size[self.kernel.datatype]
        elements_per_cacheline = float(self.machine['cacheline size']) // element_size
        iterations_per_cacheline = (sympy.Integer(self.machine['cacheline size']) /
                                    sympy.Integer(self.kernel.bytes_per_iteration))
        self.results['iterations per cacheline'] = iterations_per_cacheline
        cacheline_size = float(self.machine['cacheline size'])

        loads, stores = (self.predictor.get_loads(), self.predictor.get_stores())

        for cache_level, cache_info in list(enumerate(self.machine['memory hierarchy']))[1:]:
            throughput, duplexness = cache_info['non-overlap upstream throughput']

            if type(throughput) is str and throughput == 'full socket memory bandwidth':
                # Memory transfer
                # we use bandwidth to calculate cycles and then add panalty cycles (if given)

                # choose bw according to cache level and problem
                # first, compile stream counts at current cache level
                # write-allocate is allready resolved in cache predictor
                read_streams = loads[cache_level]
                write_streams = stores[cache_level]
                # second, try to find best fitting kernel (closest to stream seen stream counts):
                threads_per_core = 1
                bw, measurement_kernel = self.machine.get_bandwidth(
                    cache_level, read_streams, write_streams, threads_per_core)

                # calculate cycles
                if duplexness == 'half-duplex':
                    cycles = float(loads[cache_level] + stores[cache_level]) * \
                             float(elements_per_cacheline) * float(element_size) * \
                             float(self.machine['clock']) / float(bw)
                else:  # full-duplex
                    raise NotImplementedError(
                        "full-duplex mode is not (yet) supported for memory transfers.")
                # add penalty cycles for each read stream
                if 'penalty cycles per read stream' in cache_info:
                    cycles += stores[cache_level] * \
                              cache_info['penalty cycles per read stream']

                self.results.update({
                    'memory bandwidth kernel': measurement_kernel,
                    'memory bandwidth': bw})
            else:
                # since throughput is given in B/cy, and we need CL/cy:
                throughput = float(throughput) / cacheline_size
                # only cache cycles count
                if duplexness == 'half-duplex':
                    cycles = (loads[cache_level] + stores[cache_level]) / float(throughput)
                elif duplexness == 'full-duplex':
                    cycles = max(loads[cache_level] / float(throughput),
                                 stores[cache_level] / float(throughput))
                else:
                    raise ValueError("Duplexness of cache throughput may only be 'half-duplex'"
                                     "or 'full-duplex', found {} in {}.".format(
                        duplexness, cache_info['name']))

            self.results['cycles'].append((cache_info['level'], cycles))

            self.results[cache_info['level']] = cycles

        return self.results
def calculate_cycles(self):
        element_size = self.kernel.datatypes_size[self.kernel.datatype]
        elements_per_cacheline = float(self.machine['cacheline size']) // element_size
        iterations_per_cacheline = (sympy.Integer(self.machine['cacheline size']) /
                                    sympy.Integer(self.kernel.bytes_per_iteration))
        self.results['iterations per cacheline'] = iterations_per_cacheline
        cacheline_size = float(self.machine['cacheline size'])

        loads, stores = (self.predictor.get_loads(), self.predictor.get_stores())

        for cache_level, cache_info in list(enumerate(self.machine['memory hierarchy']))[1:]:
            throughput, duplexness = cache_info['non-overlap upstream throughput']

            if type(throughput) is str and throughput == 'full socket memory bandwidth':
                # Memory transfer
                # we use bandwidth to calculate cycles and then add panalty cycles (if given)

                # choose bw according to cache level and problem
                # first, compile stream counts at current cache level
                # write-allocate is allready resolved in cache predictor
                read_streams = loads[cache_level]
                write_streams = stores[cache_level]
                # second, try to find best fitting kernel (closest to stream seen stream counts):
                threads_per_core = 1
                bw, measurement_kernel = self.machine.get_bandwidth(
                    cache_level, read_streams, write_streams, threads_per_core)

                # calculate cycles
                if duplexness == 'half-duplex':
                    cycles = float(loads[cache_level] + stores[cache_level]) * \
                             float(elements_per_cacheline) * float(element_size) * \
                             float(self.machine['clock']) / float(bw)
                else:  # full-duplex
                    raise NotImplementedError(
                        "full-duplex mode is not (yet) supported for memory transfers.")
                # add penalty cycles for each read stream
                if 'penalty cycles per read stream' in cache_info:
                    cycles += stores[cache_level] * \
                              cache_info['penalty cycles per read stream']

                self.results.update({
                    'memory bandwidth kernel': measurement_kernel,
                    'memory bandwidth': bw})
            else:
                # since throughput is given in B/cy, and we need CL/cy:
                throughput = float(throughput) / cacheline_size
                # only cache cycles count
                if duplexness == 'half-duplex':
                    cycles = (loads[cache_level] + stores[cache_level]) / float(throughput)
                elif duplexness == 'full-duplex':
                    cycles = max(loads[cache_level] / float(throughput),
                                 stores[cache_level] / float(throughput))
                else:
                    raise ValueError("Duplexness of cache throughput may only be 'half-duplex'"
                                     "or 'full-duplex', found {} in {}.".format(
                        duplexness, cache_info['name']))

            self.results['cycles'].append((cache_info['level'], cycles))

            self.results[cache_info['level']] = cycles

        return self.results
def calculate_cycles ( self ) : element_size = self . kernel . datatypes_size [ self . kernel . datatype ] elements_per_cacheline = float ( self . machine [ 'cacheline size' ] ) // element_size iterations_per_cacheline = ( sympy . Integer ( self . machine [ 'cacheline size' ] ) / sympy . Integer ( self . kernel . bytes_per_iteration ) ) self . results [ 'iterations per cacheline' ] = iterations_per_cacheline cacheline_size = float ( self . machine [ 'cacheline size' ] ) loads , stores = ( self . predictor . get_loads ( ) , self . predictor . get_stores ( ) ) for cache_level , cache_info in list ( enumerate ( self . machine [ 'memory hierarchy' ] ) ) [ 1 : ] : throughput , duplexness = cache_info [ 'non-overlap upstream throughput' ] if type ( throughput ) is str and throughput == 'full socket memory bandwidth' : # Memory transfer # we use bandwidth to calculate cycles and then add panalty cycles (if given) # choose bw according to cache level and problem # first, compile stream counts at current cache level # write-allocate is allready resolved in cache predictor read_streams = loads [ cache_level ] write_streams = stores [ cache_level ] # second, try to find best fitting kernel (closest to stream seen stream counts): threads_per_core = 1 bw , measurement_kernel = self . machine . get_bandwidth ( cache_level , read_streams , write_streams , threads_per_core ) # calculate cycles if duplexness == 'half-duplex' : cycles = float ( loads [ cache_level ] + stores [ cache_level ] ) * float ( elements_per_cacheline ) * float ( element_size ) * float ( self . machine [ 'clock' ] ) / float ( bw ) else : # full-duplex raise NotImplementedError ( "full-duplex mode is not (yet) supported for memory transfers." ) # add penalty cycles for each read stream if 'penalty cycles per read stream' in cache_info : cycles += stores [ cache_level ] * cache_info [ 'penalty cycles per read stream' ] self . results . update ( { 'memory bandwidth kernel' : measurement_kernel , 'memory bandwidth' : bw } ) else : # since throughput is given in B/cy, and we need CL/cy: throughput = float ( throughput ) / cacheline_size # only cache cycles count if duplexness == 'half-duplex' : cycles = ( loads [ cache_level ] + stores [ cache_level ] ) / float ( throughput ) elif duplexness == 'full-duplex' : cycles = max ( loads [ cache_level ] / float ( throughput ) , stores [ cache_level ] / float ( throughput ) ) else : raise ValueError ( "Duplexness of cache throughput may only be 'half-duplex'" "or 'full-duplex', found {} in {}." . format ( duplexness , cache_info [ 'name' ] ) ) self . results [ 'cycles' ] . append ( ( cache_info [ 'level' ] , cycles ) ) self . results [ cache_info [ 'level' ] ] = cycles return self . results
Calculate performance model cycles from cache stats.

        calculate_cache_access() needs to have been execute before.
Calculate performance model cycles from cache stats .