brintos

brintos / llvm-project-archived public Read only

0
0
Text · 20.4 KiB · ca69bc9 Raw
589 lines · python
1#!/usr/bin/env python32 3import argparse4import sys5import os6from json import loads7from subprocess import Popen, PIPE8 9# Holds code regions statistics.10class Summary:11    def __init__(12        self,13        name,14        block_rthroughput,15        dispatch_width,16        ipc,17        instructions,18        iterations,19        total_cycles,20        total_uops,21        uops_per_cycle,22        iteration_resource_pressure,23        name_target_info_resources,24    ):25        self.name = name26        self.block_rthroughput = block_rthroughput27        self.dispatch_width = dispatch_width28        self.ipc = ipc29        self.instructions = instructions30        self.iterations = iterations31        self.total_cycles = total_cycles32        self.total_uops = total_uops33        self.uops_per_cycle = uops_per_cycle34        self.iteration_resource_pressure = iteration_resource_pressure35        self.name_target_info_resources = name_target_info_resources36 37 38# Parse the program arguments.39def parse_program_args(parser):40    parser.add_argument(41        "file_names",42        nargs="+",43        type=str,44        help="Names of files which llvm-mca tool process.",45    )46    parser.add_argument(47        "--llvm-mca-binary",48        nargs=1,49        required=True,50        type=str,51        action="store",52        metavar="[=<path to llvm-mca>]",53        help="Specified relative path to binary of llvm-mca.",54    )55    parser.add_argument(56        "--args",57        nargs=1,58        type=str,59        action="store",60        metavar="[='-option1=<arg> -option2=<arg> ...']",61        default=["-"],62        help="Forward options to lvm-mca tool.",63    )64    parser.add_argument(65        "-plot",66        action="store_true",67        default=False,68        help="Draw plots of statistics for input files.",69    )70    parser.add_argument(71        "-plot-resource-pressure",72        action="store_true",73        default=False,74        help="Draw plots of resource pressure per iterations for input files.",75    )76    parser.add_argument(77        "--plot-path",78        nargs=1,79        type=str,80        action="store",81        metavar="[=<path>]",82        default=["-"],83        help="Specify relative path where you want to save the plots.",84    )85    parser.add_argument(86        "-v",87        action="store_true",88        default=False,89        help="More details about the running lvm-mca tool.",90    )91    return parser.parse_args()92 93 94# Verify that the program inputs meet the requirements.95def verify_program_inputs(opts):96    if opts.plot_path[0] != "-" and not opts.plot and not opts.plot_resource_pressure:97        print(98            "error: Please specify --plot-path only with the -plot or -plot-resource-pressure options."99        )100        return False101 102    return True103 104 105# Returns the name of the file to be analyzed from the path it is on.106def get_filename_from_path(path):107    index_of_slash = path.rfind("/")108    return path[(index_of_slash + 1) : len(path)]109 110 111# Returns the results of the running llvm-mca tool for the input file.112def run_llvm_mca_tool(opts, file_name):113    # Get the path of the llvm-mca binary file.114    llvm_mca_cmd = opts.llvm_mca_binary[0]115 116    # The statistics llvm-mca options.117    if opts.args[0] != "-":118        llvm_mca_cmd += " " + opts.args[0]119    llvm_mca_cmd += " -json"120 121    # Set file which llvm-mca tool will process.122    llvm_mca_cmd += " " + file_name123 124    if opts.v:125        print("run: $ " + llvm_mca_cmd + "\n")126 127    # Generate the stats with the llvm-mca.128    subproc = Popen(129        llvm_mca_cmd.split(" "),130        stdin=PIPE,131        stdout=PIPE,132        stderr=PIPE,133        universal_newlines=True,134    )135 136    cmd_stdout, cmd_stderr = subproc.communicate()137 138    try:139        json_parsed = loads(cmd_stdout)140    except:141        print("error: No valid llvm-mca statistics found.")142        print(cmd_stderr)143        sys.exit(1)144 145    if opts.v:146        print("Simulation Parameters: ")147        simulation_parameters = json_parsed["SimulationParameters"]148        for key in simulation_parameters:149            print(key, ":", simulation_parameters[key])150        print("\n")151 152    code_regions_len = len(json_parsed["CodeRegions"])153    array_of_code_regions = [None] * code_regions_len154 155    for i in range(code_regions_len):156        code_region_instructions_len = len(157            json_parsed["CodeRegions"][i]["Instructions"]158        )159        target_info_resources_len = len(json_parsed["TargetInfo"]["Resources"])160        iteration_resource_pressure = ["-" for k in range(target_info_resources_len)]161        resource_pressure_info = json_parsed["CodeRegions"][i]["ResourcePressureView"][162            "ResourcePressureInfo"163        ]164 165        name_target_info_resources = json_parsed["TargetInfo"]["Resources"]166 167        for s in range(len(resource_pressure_info)):168            obj_of_resource_pressure_info = resource_pressure_info[s]169            if (170                obj_of_resource_pressure_info["InstructionIndex"]171                == code_region_instructions_len172            ):173                iteration_resource_pressure[174                    obj_of_resource_pressure_info["ResourceIndex"]175                ] = str(round(obj_of_resource_pressure_info["ResourceUsage"], 2))176 177        array_of_code_regions[i] = Summary(178            file_name,179            json_parsed["CodeRegions"][i]["SummaryView"]["BlockRThroughput"],180            json_parsed["CodeRegions"][i]["SummaryView"]["DispatchWidth"],181            json_parsed["CodeRegions"][i]["SummaryView"]["IPC"],182            json_parsed["CodeRegions"][i]["SummaryView"]["Instructions"],183            json_parsed["CodeRegions"][i]["SummaryView"]["Iterations"],184            json_parsed["CodeRegions"][i]["SummaryView"]["TotalCycles"],185            json_parsed["CodeRegions"][i]["SummaryView"]["TotaluOps"],186            json_parsed["CodeRegions"][i]["SummaryView"]["uOpsPerCycle"],187            iteration_resource_pressure,188            name_target_info_resources,189        )190 191    return array_of_code_regions192 193 194# Print statistics in console for single file or for multiple files.195def console_print_results(matrix_of_code_regions, opts):196    try:197        import termtables as tt198    except ImportError:199        print("error: termtables not found.")200        sys.exit(1)201 202    headers_names = [None] * (len(opts.file_names) + 1)203    headers_names[0] = " "204 205    max_code_regions = 0206 207    print("Input files:")208    for i in range(len(matrix_of_code_regions)):209        if max_code_regions < len(matrix_of_code_regions[i]):210            max_code_regions = len(matrix_of_code_regions[i])211        print("[f" + str(i + 1) + "]: " + get_filename_from_path(opts.file_names[i]))212        headers_names[i + 1] = "[f" + str(i + 1) + "]: "213 214    print("\nITERATIONS: " + str(matrix_of_code_regions[0][0].iterations) + "\n")215 216    for i in range(max_code_regions):217 218        print(219            "\n-----------------------------------------\nCode region: "220            + str(i + 1)221            + "\n"222        )223 224        table_values = [225            [[None] for i in range(len(matrix_of_code_regions) + 1)] for j in range(7)226        ]227 228        table_values[0][0] = "Instructions: "229        table_values[1][0] = "Total Cycles: "230        table_values[2][0] = "Total uOps: "231        table_values[3][0] = "Dispatch Width: "232        table_values[4][0] = "uOps Per Cycle: "233        table_values[5][0] = "IPC: "234        table_values[6][0] = "Block RThroughput: "235 236        for j in range(len(matrix_of_code_regions)):237            if len(matrix_of_code_regions[j]) > i:238                table_values[0][j + 1] = str(matrix_of_code_regions[j][i].instructions)239                table_values[1][j + 1] = str(matrix_of_code_regions[j][i].total_cycles)240                table_values[2][j + 1] = str(matrix_of_code_regions[j][i].total_uops)241                table_values[3][j + 1] = str(242                    matrix_of_code_regions[j][i].dispatch_width243                )244                table_values[4][j + 1] = str(245                    round(matrix_of_code_regions[j][i].uops_per_cycle, 2)246                )247                table_values[5][j + 1] = str(round(matrix_of_code_regions[j][i].ipc, 2))248                table_values[6][j + 1] = str(249                    round(matrix_of_code_regions[j][i].block_rthroughput, 2)250                )251            else:252                table_values[0][j + 1] = "-"253                table_values[1][j + 1] = "-"254                table_values[2][j + 1] = "-"255                table_values[3][j + 1] = "-"256                table_values[4][j + 1] = "-"257                table_values[5][j + 1] = "-"258                table_values[6][j + 1] = "-"259 260        tt.print(261            table_values,262            header=headers_names,263            style=tt.styles.ascii_thin_double,264            padding=(0, 1),265        )266 267        print("\nResource pressure per iteration: \n")268 269        table_values = [270            [271                [None]272                for i in range(273                    len(matrix_of_code_regions[0][0].iteration_resource_pressure) + 1274                )275            ]276            for j in range(len(matrix_of_code_regions) + 1)277        ]278 279        table_values[0] = [" "] + matrix_of_code_regions[0][280            0281        ].name_target_info_resources282 283        for j in range(len(matrix_of_code_regions)):284            if len(matrix_of_code_regions[j]) > i:285                table_values[j + 1] = [286                    "[f" + str(j + 1) + "]: "287                ] + matrix_of_code_regions[j][i].iteration_resource_pressure288            else:289                table_values[j + 1] = ["[f" + str(j + 1) + "]: "] + len(290                    matrix_of_code_regions[0][0].iteration_resource_pressure291                ) * ["-"]292 293        tt.print(294            table_values,295            style=tt.styles.ascii_thin_double,296            padding=(0, 1),297        )298        print("\n")299 300 301# Based on the obtained results (summary view) of llvm-mca tool, draws plots for multiple input files.302def draw_plot_files_summary(array_of_summary, opts):303    try:304        import matplotlib.pyplot as plt305    except ImportError:306        print("error: matplotlib.pyplot not found.")307        sys.exit(1)308    try:309        from matplotlib.cm import get_cmap310    except ImportError:311        print("error: get_cmap (matplotlib.cm) not found.")312        sys.exit(1)313 314    names = [315        "Block RThroughput",316        "Dispatch Width",317        "IPC",318        "uOps Per Cycle",319        "Instructions",320        "Total Cycles",321        "Total uOps",322    ]323 324    rows, cols = (len(opts.file_names), 7)325 326    values = [[0 for x in range(cols)] for y in range(rows)]327 328    for i in range(len(opts.file_names)):329        values[i][0] = array_of_summary[i].block_rthroughput330        values[i][1] = array_of_summary[i].dispatch_width331        values[i][2] = array_of_summary[i].ipc332        values[i][3] = array_of_summary[i].uops_per_cycle333        values[i][4] = array_of_summary[i].instructions334        values[i][5] = array_of_summary[i].total_cycles335        values[i][6] = array_of_summary[i].total_uops336 337    fig, axs = plt.subplots(4, 2)338    fig.suptitle(339        "Machine code statistics", fontsize=20, fontweight="bold", color="black"340    )341    i = 0342 343    for x in range(4):344        for y in range(2):345            cmap = get_cmap("tab20")346            colors = cmap.colors347            if not (x == 0 and y == 1) and i < 7:348                axs[x][y].grid(True, color="grey", linestyle="--")349                maxValue = 0350                if i == 0:351                    for j in range(len(opts.file_names)):352                        if maxValue < values[j][i]:353                            maxValue = values[j][i]354                        axs[x][y].bar(355                            0.3 * j,356                            values[j][i],357                            width=0.1,358                            color=colors[j],359                            label=get_filename_from_path(opts.file_names[j]),360                        )361                else:362                    for j in range(len(opts.file_names)):363                        if maxValue < values[j][i]:364                            maxValue = values[j][i]365                        axs[x][y].bar(0.3 * j, values[j][i], width=0.1, color=colors[j])366                axs[x][y].set_axisbelow(True)367                axs[x][y].set_xlim([-0.3, len(opts.file_names) / 3])368                axs[x][y].set_ylim([0, maxValue + (maxValue / 2)])369                axs[x][y].set_title(names[i], fontsize=15, fontweight="bold")370                axs[x][y].axes.xaxis.set_visible(False)371                for j in range(len(opts.file_names)):372                    axs[x][y].text(373                        0.3 * j,374                        values[j][i] + (maxValue / 40),375                        s=str(values[j][i]),376                        color="black",377                        fontweight="bold",378                        fontsize=4,379                    )380                i = i + 1381 382    axs[0][1].set_visible(False)383    fig.legend(prop={"size": 15})384    figg = plt.gcf()385    figg.set_size_inches((25, 15), forward=False)386    if opts.plot_path[0] == "-":387        plt.savefig("llvm-mca-plot.png", dpi=500)388        print("The plot was saved within llvm-mca-plot.png")389    else:390        plt.savefig(391            os.path.normpath(os.path.join(opts.plot_path[0], "llvm-mca-plot.png")),392            dpi=500,393        )394        print(395            "The plot was saved within {}.".format(396                os.path.normpath(os.path.join(opts.plot_path[0], "llvm-mca-plot.png"))397            )398        )399 400 401# Calculates the average value (summary view) per region.402def summary_average_code_region(array_of_code_regions, file_name):403    summary = Summary(file_name, 0, 0, 0, 0, 0, 0, 0, 0, None, None)404    for i in range(len(array_of_code_regions)):405        summary.block_rthroughput += array_of_code_regions[i].block_rthroughput406        summary.dispatch_width += array_of_code_regions[i].dispatch_width407        summary.ipc += array_of_code_regions[i].ipc408        summary.instructions += array_of_code_regions[i].instructions409        summary.iterations += array_of_code_regions[i].iterations410        summary.total_cycles += array_of_code_regions[i].total_cycles411        summary.total_uops += array_of_code_regions[i].total_uops412        summary.uops_per_cycle += array_of_code_regions[i].uops_per_cycle413    summary.block_rthroughput = round(414        summary.block_rthroughput / len(array_of_code_regions), 2415    )416    summary.dispatch_width = round(417        summary.dispatch_width / len(array_of_code_regions), 2418    )419    summary.ipc = round(summary.ipc / len(array_of_code_regions), 2)420    summary.instructions = round(summary.instructions / len(array_of_code_regions), 2)421    summary.iterations = round(summary.iterations / len(array_of_code_regions), 2)422    summary.total_cycles = round(summary.total_cycles / len(array_of_code_regions), 2)423    summary.total_uops = round(summary.total_uops / len(array_of_code_regions), 2)424    summary.uops_per_cycle = round(425        summary.uops_per_cycle / len(array_of_code_regions), 2426    )427    return summary428 429 430# Based on the obtained results (resource pressure per iter) of llvm-mca tool, draws plots for multiple input files.431def draw_plot_resource_pressure(432    array_average_resource_pressure_per_file, opts, name_target_info_resources433):434    try:435        import matplotlib.pyplot as plt436    except ImportError:437        print("error: matplotlib.pyplot not found.")438        sys.exit(1)439    try:440        from matplotlib.cm import get_cmap441    except ImportError:442        print("error: get_cmap (matplotlib.cm) not found.")443        sys.exit(1)444 445    fig, axs = plt.subplots()446    fig.suptitle(447        "Resource pressure per iterations",448        fontsize=20,449        fontweight="bold",450        color="black",451    )452 453    maxValue = 0454    for j in range(len(opts.file_names)):455        if maxValue < max(array_average_resource_pressure_per_file[j]):456            maxValue = max(array_average_resource_pressure_per_file[j])457 458    cmap = get_cmap("tab20")459    colors = cmap.colors460 461    xticklabels = [None] * len(opts.file_names) * len(name_target_info_resources)462    index = 0463 464    for j in range(len(name_target_info_resources)):465        for i in range(len(opts.file_names)):466            if i == 0:467                axs.bar(468                    j * len(opts.file_names) * 10 + i * 10,469                    array_average_resource_pressure_per_file[i][j],470                    width=1,471                    color=colors[j],472                    label=name_target_info_resources[j],473                )474            else:475                axs.bar(476                    j * len(opts.file_names) * 10 + i * 10,477                    array_average_resource_pressure_per_file[i][j],478                    width=1,479                    color=colors[j],480                )481            axs.text(482                j * len(opts.file_names) * 10 + i * 10,483                array_average_resource_pressure_per_file[i][j] + (maxValue / 40),484                s=str(array_average_resource_pressure_per_file[i][j]),485                color=colors[j],486                fontweight="bold",487                fontsize=3,488            )489            xticklabels[index] = opts.file_names[i]490            index = index + 1491 492    axs.set_xticks(493        [494            j * len(opts.file_names) * 10 + i * 10495            for j in range(len(name_target_info_resources))496            for i in range(len(opts.file_names))497        ]498    )499    axs.set_xticklabels(xticklabels, rotation=65)500 501    axs.set_axisbelow(True)502    axs.set_xlim([-0.5, len(opts.file_names) * len(name_target_info_resources) * 10])503    axs.set_ylim([0, maxValue + maxValue / 10])504 505    fig.legend(prop={"size": 15})506    figg = plt.gcf()507    figg.set_size_inches((25, 15), forward=False)508    if opts.plot_path[0] == "-":509        plt.savefig("llvm-mca-plot-resource-pressure.png", dpi=500)510        print("The plot was saved within llvm-mca-plot-resource-pressure.png")511    else:512        plt.savefig(513            os.path.normpath(514                os.path.join(opts.plot_path[0], "llvm-mca-plot-resource-pressure.png")515            ),516            dpi=500,517        )518        print(519            "The plot was saved within {}.".format(520                os.path.normpath(521                    os.path.join(522                        opts.plot_path[0], "llvm-mca-plot-resource-pressure.png"523                    )524                )525            )526        )527 528 529# Calculates the average value (resource pressure per iter) per region.530def average_code_region_resource_pressure(array_of_code_regions, file_name):531    resource_pressure_per_iter_one_file = [0] * len(532        array_of_code_regions[0].iteration_resource_pressure533    )534    for i in range(len(array_of_code_regions)):535        for j in range(len(array_of_code_regions[i].iteration_resource_pressure)):536            if array_of_code_regions[i].iteration_resource_pressure[j] != "-":537                resource_pressure_per_iter_one_file[j] += float(538                    array_of_code_regions[i].iteration_resource_pressure[j]539                )540    for i in range(len(resource_pressure_per_iter_one_file)):541        resource_pressure_per_iter_one_file[i] = round(542            resource_pressure_per_iter_one_file[i] / len(array_of_code_regions), 2543        )544    return resource_pressure_per_iter_one_file545 546 547def Main():548    parser = argparse.ArgumentParser()549    opts = parse_program_args(parser)550 551    if not verify_program_inputs(opts):552        parser.print_help()553        sys.exit(1)554 555    matrix_of_code_regions = [None] * len(opts.file_names)556 557    for i in range(len(opts.file_names)):558        matrix_of_code_regions[i] = run_llvm_mca_tool(opts, opts.file_names[i])559    if not opts.plot and not opts.plot_resource_pressure:560        console_print_results(matrix_of_code_regions, opts)561    else:562        if opts.plot:563            array_average_summary_per_file = [None] * len(matrix_of_code_regions)564            for j in range(len(matrix_of_code_regions)):565                array_average_summary_per_file[j] = summary_average_code_region(566                    matrix_of_code_regions[j], opts.file_names[j]567                )568            draw_plot_files_summary(array_average_summary_per_file, opts)569        if opts.plot_resource_pressure:570            array_average_resource_pressure_per_file = [None] * len(571                matrix_of_code_regions572            )573            for j in range(len(matrix_of_code_regions)):574                array_average_resource_pressure_per_file[575                    j576                ] = average_code_region_resource_pressure(577                    matrix_of_code_regions[j], opts.file_names[j]578                )579            draw_plot_resource_pressure(580                array_average_resource_pressure_per_file,581                opts,582                matrix_of_code_regions[0][0].name_target_info_resources,583            )584 585 586if __name__ == "__main__":587    Main()588    sys.exit(0)589