kerncraft/models/roofline.py
def analyze(self):
        """Run complete analysis."""
        self.results = self.calculate_cache_access()
        try:
            iaca_analysis, asm_block = self.kernel.iaca_analysis(
                micro_architecture=self.machine['micro-architecture'],
                asm_block=self.asm_block,
                pointer_increment=self.pointer_increment,
                verbose=self.verbose > 2)
        except RuntimeError as e:
            print("IACA analysis failed: " + str(e))
            sys.exit(1)

        block_throughput = iaca_analysis['throughput']
        uops = iaca_analysis['uops']
        iaca_output = iaca_analysis['output']
        port_cycles = iaca_analysis['port cycles']

        # Normalize to cycles per cacheline
        elements_per_block = abs(asm_block['pointer_increment']
                                 / self.kernel.datatypes_size[self.kernel.datatype])
        block_size = elements_per_block*self.kernel.datatypes_size[self.kernel.datatype]
        try:
            block_to_cl_ratio = float(self.machine['cacheline size'])/block_size
        except ZeroDivisionError as e:
            print("Too small block_size / pointer_increment:", e, file=sys.stderr)
            sys.exit(1)

        port_cycles = dict([(i[0], i[1]*block_to_cl_ratio) for i in list(port_cycles.items())])
        uops = uops*block_to_cl_ratio
        cl_throughput = block_throughput*block_to_cl_ratio
        flops_per_element = sum(self.kernel._flops.values())

        # Overwrite CPU-L1 stats, because they are covered by IACA
        self.results['mem bottlenecks'][0] = None

        # Reevaluate mem bottleneck
        self.results['min performance'] = self.conv_perf(PrefixedUnit(float('inf'), 'FLOP/s'))
        self.results['bottleneck level'] = None
        for level, bottleneck in enumerate(self.results['mem bottlenecks']):
            if level == 0:
                # ignoring CPU-L1
                continue
            if bottleneck['performance']['FLOP/s'] < self.results['min performance']['FLOP/s']:
                self.results['bottleneck level'] = level
                self.results['min performance'] = bottleneck['performance']

        # Create result dictionary
        self.results.update({
            'cpu bottleneck': {
                'port cycles': port_cycles,
                'cl throughput': cl_throughput,
                'uops': uops,
                'performance throughput': self.conv_perf(PrefixedUnit(
                    self.machine['clock']/block_throughput*elements_per_block*flops_per_element
                    * self.cores, "FLOP/s")),
                'IACA output': iaca_output}})
def analyze(self):
        """Run complete analysis."""
        self.results = self.calculate_cache_access()
        try:
            iaca_analysis, asm_block = self.kernel.iaca_analysis(
                micro_architecture=self.machine['micro-architecture'],
                asm_block=self.asm_block,
                pointer_increment=self.pointer_increment,
                verbose=self.verbose > 2)
        except RuntimeError as e:
            print("IACA analysis failed: " + str(e))
            sys.exit(1)

        block_throughput = iaca_analysis['throughput']
        uops = iaca_analysis['uops']
        iaca_output = iaca_analysis['output']
        port_cycles = iaca_analysis['port cycles']

        # Normalize to cycles per cacheline
        elements_per_block = abs(asm_block['pointer_increment']
                                 / self.kernel.datatypes_size[self.kernel.datatype])
        block_size = elements_per_block*self.kernel.datatypes_size[self.kernel.datatype]
        try:
            block_to_cl_ratio = float(self.machine['cacheline size'])/block_size
        except ZeroDivisionError as e:
            print("Too small block_size / pointer_increment:", e, file=sys.stderr)
            sys.exit(1)

        port_cycles = dict([(i[0], i[1]*block_to_cl_ratio) for i in list(port_cycles.items())])
        uops = uops*block_to_cl_ratio
        cl_throughput = block_throughput*block_to_cl_ratio
        flops_per_element = sum(self.kernel._flops.values())

        # Overwrite CPU-L1 stats, because they are covered by IACA
        self.results['mem bottlenecks'][0] = None

        # Reevaluate mem bottleneck
        self.results['min performance'] = self.conv_perf(PrefixedUnit(float('inf'), 'FLOP/s'))
        self.results['bottleneck level'] = None
        for level, bottleneck in enumerate(self.results['mem bottlenecks']):
            if level == 0:
                # ignoring CPU-L1
                continue
            if bottleneck['performance']['FLOP/s'] < self.results['min performance']['FLOP/s']:
                self.results['bottleneck level'] = level
                self.results['min performance'] = bottleneck['performance']

        # Create result dictionary
        self.results.update({
            'cpu bottleneck': {
                'port cycles': port_cycles,
                'cl throughput': cl_throughput,
                'uops': uops,
                'performance throughput': self.conv_perf(PrefixedUnit(
                    self.machine['clock']/block_throughput*elements_per_block*flops_per_element
                    * self.cores, "FLOP/s")),
                'IACA output': iaca_output}})
def analyze ( self ) : self . results = self . calculate_cache_access ( ) try : iaca_analysis , asm_block = self . kernel . iaca_analysis ( micro_architecture = self . machine [ 'micro-architecture' ] , asm_block = self . asm_block , pointer_increment = self . pointer_increment , verbose = self . verbose > 2 ) except RuntimeError as e : print ( "IACA analysis failed: " + str ( e ) ) sys . exit ( 1 ) block_throughput = iaca_analysis [ 'throughput' ] uops = iaca_analysis [ 'uops' ] iaca_output = iaca_analysis [ 'output' ] port_cycles = iaca_analysis [ 'port cycles' ] # Normalize to cycles per cacheline elements_per_block = abs ( asm_block [ 'pointer_increment' ] / self . kernel . datatypes_size [ self . kernel . datatype ] ) block_size = elements_per_block * self . kernel . datatypes_size [ self . kernel . datatype ] try : block_to_cl_ratio = float ( self . machine [ 'cacheline size' ] ) / block_size except ZeroDivisionError as e : print ( "Too small block_size / pointer_increment:" , e , file = sys . stderr ) sys . exit ( 1 ) port_cycles = dict ( [ ( i [ 0 ] , i [ 1 ] * block_to_cl_ratio ) for i in list ( port_cycles . items ( ) ) ] ) uops = uops * block_to_cl_ratio cl_throughput = block_throughput * block_to_cl_ratio flops_per_element = sum ( self . kernel . _flops . values ( ) ) # Overwrite CPU-L1 stats, because they are covered by IACA self . results [ 'mem bottlenecks' ] [ 0 ] = None # Reevaluate mem bottleneck self . results [ 'min performance' ] = self . conv_perf ( PrefixedUnit ( float ( 'inf' ) , 'FLOP/s' ) ) self . results [ 'bottleneck level' ] = None for level , bottleneck in enumerate ( self . results [ 'mem bottlenecks' ] ) : if level == 0 : # ignoring CPU-L1 continue if bottleneck [ 'performance' ] [ 'FLOP/s' ] < self . results [ 'min performance' ] [ 'FLOP/s' ] : self . results [ 'bottleneck level' ] = level self . results [ 'min performance' ] = bottleneck [ 'performance' ] # Create result dictionary self . results . update ( { 'cpu bottleneck' : { 'port cycles' : port_cycles , 'cl throughput' : cl_throughput , 'uops' : uops , 'performance throughput' : self . conv_perf ( PrefixedUnit ( self . machine [ 'clock' ] / block_throughput * elements_per_block * flops_per_element * self . cores , "FLOP/s" ) ) , 'IACA output' : iaca_output } } )
Run complete analysis.
Run complete analysis .