kerncraft/iaca.py
def iaca_analyse_instrumented_binary(instrumented_binary_file, micro_architecture):
    """
    Run IACA analysis on an instrumented binary.

    :param instrumented_binary_file: path of binary that was built with IACA markers
    :param micro_architecture: micro architecture string as taken by IACA.
                               one of: NHM, WSM, SNB, IVB, HSW, BDW
    :return: a dictionary with the following keys:
        - 'output': the output of the iaca executable
        - 'throughput': the block throughput in cycles for one possibly vectorized loop iteration
        - 'port cycles': dict, mapping port name to number of active cycles
        - 'uops': total number of Uops
    """
    # Select IACA version and executable based on micro_architecture:
    arch_map = {
        # arch: (binary name, version string, required additional arguments)
        'NHM': ('iaca2.2', 'v2.2', ['-64']),
        'WSM': ('iaca2.2', 'v2.2', ['-64']),
        'SNB': ('iaca2.3', 'v2.3', ['-64']),
        'IVB': ('iaca2.3', 'v2.3', ['-64']),
        'HSW': ('iaca3.0', 'v3.0', []),
        'BDW': ('iaca3.0', 'v3.0', []),
        'SKL': ('iaca3.0', 'v3.0', []),
        'SKX': ('iaca3.0', 'v3.0', []),
    }

    if micro_architecture not in arch_map:
        raise ValueError('Invalid micro_architecture selected ({}), valid options are {}'.format(
            micro_architecture, ', '.join(arch_map.keys())))

    iaca_path = iaca_get.find_iaca()  # Throws exception if not found
    os.environ['PATH'] += ':' + iaca_path

    iaca_exec, iaca_version, base_args = arch_map[micro_architecture]
    if find_executable(iaca_exec) is None:
        raise RuntimeError("{0} executable was not found. Make sure that {0} is found in "
                           "{1}. Install using iaca_get.".format(iaca_exec, iaca_path))

    result = {}

    cmd = [iaca_exec] + base_args + ['-arch', micro_architecture, instrumented_binary_file]
    try:
        iaca_output = subprocess.check_output(cmd).decode('utf-8')
        result['output'] = iaca_output
    except OSError as e:
        raise RuntimeError("IACA execution failed:" + ' '.join(cmd) + '\n' + str(e))
    except subprocess.CalledProcessError as e:
        raise RuntimeError("IACA throughput analysis failed:" + str(e))

    # Get total cycles per loop iteration
    match = re.search(r'^Block Throughput: ([0-9.]+) Cycles', iaca_output, re.MULTILINE)
    assert match, "Could not find Block Throughput in IACA output."
    throughput = float(match.groups()[0])
    result['throughput'] = throughput

    # Find ports and cycles per port
    ports = [l for l in iaca_output.split('\n') if l.startswith('|  Port  |')]
    cycles = [l for l in iaca_output.split('\n') if l.startswith('| Cycles |')]
    assert ports and cycles, "Could not find ports/cycles lines in IACA output."
    ports = [p.strip() for p in ports[0].split('|')][2:]
    cycles = [c.strip() for c in cycles[0].split('|')][2:]
    port_cycles = []
    for i in range(len(ports)):
        if '-' in ports[i] and ' ' in cycles[i]:
            subports = [p.strip() for p in ports[i].split('-')]
            subcycles = [c for c in cycles[i].split(' ') if bool(c)]
            port_cycles.append((subports[0], float(subcycles[0])))
            port_cycles.append((subports[0] + subports[1], float(subcycles[1])))
        elif ports[i] and cycles[i]:
            port_cycles.append((ports[i], float(cycles[i])))
    result['port cycles'] = dict(port_cycles)

    match = re.search(r'^Total Num Of Uops: ([0-9]+)', iaca_output, re.MULTILINE)
    assert match, "Could not find Uops in IACA output."
    result['uops'] = float(match.groups()[0])
    return result
def iaca_analyse_instrumented_binary(instrumented_binary_file, micro_architecture):
    """
    Run IACA analysis on an instrumented binary.

    :param instrumented_binary_file: path of binary that was built with IACA markers
    :param micro_architecture: micro architecture string as taken by IACA.
                               one of: NHM, WSM, SNB, IVB, HSW, BDW
    :return: a dictionary with the following keys:
        - 'output': the output of the iaca executable
        - 'throughput': the block throughput in cycles for one possibly vectorized loop iteration
        - 'port cycles': dict, mapping port name to number of active cycles
        - 'uops': total number of Uops
    """
    # Select IACA version and executable based on micro_architecture:
    arch_map = {
        # arch: (binary name, version string, required additional arguments)
        'NHM': ('iaca2.2', 'v2.2', ['-64']),
        'WSM': ('iaca2.2', 'v2.2', ['-64']),
        'SNB': ('iaca2.3', 'v2.3', ['-64']),
        'IVB': ('iaca2.3', 'v2.3', ['-64']),
        'HSW': ('iaca3.0', 'v3.0', []),
        'BDW': ('iaca3.0', 'v3.0', []),
        'SKL': ('iaca3.0', 'v3.0', []),
        'SKX': ('iaca3.0', 'v3.0', []),
    }

    if micro_architecture not in arch_map:
        raise ValueError('Invalid micro_architecture selected ({}), valid options are {}'.format(
            micro_architecture, ', '.join(arch_map.keys())))

    iaca_path = iaca_get.find_iaca()  # Throws exception if not found
    os.environ['PATH'] += ':' + iaca_path

    iaca_exec, iaca_version, base_args = arch_map[micro_architecture]
    if find_executable(iaca_exec) is None:
        raise RuntimeError("{0} executable was not found. Make sure that {0} is found in "
                           "{1}. Install using iaca_get.".format(iaca_exec, iaca_path))

    result = {}

    cmd = [iaca_exec] + base_args + ['-arch', micro_architecture, instrumented_binary_file]
    try:
        iaca_output = subprocess.check_output(cmd).decode('utf-8')
        result['output'] = iaca_output
    except OSError as e:
        raise RuntimeError("IACA execution failed:" + ' '.join(cmd) + '\n' + str(e))
    except subprocess.CalledProcessError as e:
        raise RuntimeError("IACA throughput analysis failed:" + str(e))

    # Get total cycles per loop iteration
    match = re.search(r'^Block Throughput: ([0-9.]+) Cycles', iaca_output, re.MULTILINE)
    assert match, "Could not find Block Throughput in IACA output."
    throughput = float(match.groups()[0])
    result['throughput'] = throughput

    # Find ports and cycles per port
    ports = [l for l in iaca_output.split('\n') if l.startswith('|  Port  |')]
    cycles = [l for l in iaca_output.split('\n') if l.startswith('| Cycles |')]
    assert ports and cycles, "Could not find ports/cycles lines in IACA output."
    ports = [p.strip() for p in ports[0].split('|')][2:]
    cycles = [c.strip() for c in cycles[0].split('|')][2:]
    port_cycles = []
    for i in range(len(ports)):
        if '-' in ports[i] and ' ' in cycles[i]:
            subports = [p.strip() for p in ports[i].split('-')]
            subcycles = [c for c in cycles[i].split(' ') if bool(c)]
            port_cycles.append((subports[0], float(subcycles[0])))
            port_cycles.append((subports[0] + subports[1], float(subcycles[1])))
        elif ports[i] and cycles[i]:
            port_cycles.append((ports[i], float(cycles[i])))
    result['port cycles'] = dict(port_cycles)

    match = re.search(r'^Total Num Of Uops: ([0-9]+)', iaca_output, re.MULTILINE)
    assert match, "Could not find Uops in IACA output."
    result['uops'] = float(match.groups()[0])
    return result
def iaca_analyse_instrumented_binary ( instrumented_binary_file , micro_architecture ) : # Select IACA version and executable based on micro_architecture: arch_map = { # arch: (binary name, version string, required additional arguments) 'NHM' : ( 'iaca2.2' , 'v2.2' , [ '-64' ] ) , 'WSM' : ( 'iaca2.2' , 'v2.2' , [ '-64' ] ) , 'SNB' : ( 'iaca2.3' , 'v2.3' , [ '-64' ] ) , 'IVB' : ( 'iaca2.3' , 'v2.3' , [ '-64' ] ) , 'HSW' : ( 'iaca3.0' , 'v3.0' , [ ] ) , 'BDW' : ( 'iaca3.0' , 'v3.0' , [ ] ) , 'SKL' : ( 'iaca3.0' , 'v3.0' , [ ] ) , 'SKX' : ( 'iaca3.0' , 'v3.0' , [ ] ) , } if micro_architecture not in arch_map : raise ValueError ( 'Invalid micro_architecture selected ({}), valid options are {}' . format ( micro_architecture , ', ' . join ( arch_map . keys ( ) ) ) ) iaca_path = iaca_get . find_iaca ( ) # Throws exception if not found os . environ [ 'PATH' ] += ':' + iaca_path iaca_exec , iaca_version , base_args = arch_map [ micro_architecture ] if find_executable ( iaca_exec ) is None : raise RuntimeError ( "{0} executable was not found. Make sure that {0} is found in " "{1}. Install using iaca_get." . format ( iaca_exec , iaca_path ) ) result = { } cmd = [ iaca_exec ] + base_args + [ '-arch' , micro_architecture , instrumented_binary_file ] try : iaca_output = subprocess . check_output ( cmd ) . decode ( 'utf-8' ) result [ 'output' ] = iaca_output except OSError as e : raise RuntimeError ( "IACA execution failed:" + ' ' . join ( cmd ) + '\n' + str ( e ) ) except subprocess . CalledProcessError as e : raise RuntimeError ( "IACA throughput analysis failed:" + str ( e ) ) # Get total cycles per loop iteration match = re . search ( r'^Block Throughput: ([0-9.]+) Cycles' , iaca_output , re . MULTILINE ) assert match , "Could not find Block Throughput in IACA output." throughput = float ( match . groups ( ) [ 0 ] ) result [ 'throughput' ] = throughput # Find ports and cycles per port ports = [ l for l in iaca_output . split ( '\n' ) if l . startswith ( '|  Port  |' ) ] cycles = [ l for l in iaca_output . split ( '\n' ) if l . startswith ( '| Cycles |' ) ] assert ports and cycles , "Could not find ports/cycles lines in IACA output." ports = [ p . strip ( ) for p in ports [ 0 ] . split ( '|' ) ] [ 2 : ] cycles = [ c . strip ( ) for c in cycles [ 0 ] . split ( '|' ) ] [ 2 : ] port_cycles = [ ] for i in range ( len ( ports ) ) : if '-' in ports [ i ] and ' ' in cycles [ i ] : subports = [ p . strip ( ) for p in ports [ i ] . split ( '-' ) ] subcycles = [ c for c in cycles [ i ] . split ( ' ' ) if bool ( c ) ] port_cycles . append ( ( subports [ 0 ] , float ( subcycles [ 0 ] ) ) ) port_cycles . append ( ( subports [ 0 ] + subports [ 1 ] , float ( subcycles [ 1 ] ) ) ) elif ports [ i ] and cycles [ i ] : port_cycles . append ( ( ports [ i ] , float ( cycles [ i ] ) ) ) result [ 'port cycles' ] = dict ( port_cycles ) match = re . search ( r'^Total Num Of Uops: ([0-9]+)' , iaca_output , re . MULTILINE ) assert match , "Could not find Uops in IACA output." result [ 'uops' ] = float ( match . groups ( ) [ 0 ] ) return result
Run IACA analysis on an instrumented binary.

    :param instrumented_binary_file: path of binary that was built with IACA markers
    :param micro_architecture: micro architecture string as taken by IACA.
                               one of: NHM, WSM, SNB, IVB, HSW, BDW
    :return: a dictionary with the following keys:
        - 'output': the output of the iaca executable
        - 'throughput': the block throughput in cycles for one possibly vectorized loop iteration
        - 'port cycles': dict, mapping port name to number of active cycles
        - 'uops': total number of Uops
Run IACA analysis on an instrumented binary .