Modify GUI roofline to accomidate standalone option

Signed-off-by: colramos425 <colramos@amd.com>
Este commit está contenido en:
colramos425
2023-01-18 11:46:12 -06:00
padre 263ca0fe77
commit fca1001a4c
Se han modificado 4 ficheros con 111 adiciones y 87 borrados
+58 -61
Ver fichero
@@ -37,7 +37,7 @@ from utils import specs
from utils.perfagg import perfmon_filter, pmc_filter
from utils import remove_workload
from utils import csv_converter # Import workload
from utils import plot_roofline # standalone roofline
from omniperf_analyze.omniperf_analyze import roofline_only
from omniperf_analyze.omniperf_analyze import analyze # CLI analysis
from common import (
@@ -212,7 +212,61 @@ def mongo_import(args, profileAndImport):
################################################
# Roofline Helpers
################################################
def roof_setup(args, my_parser):
if args.path == os.getcwd() + "/workloads":
args.path += "/" + args.name + "/" + str(get_soc())
# Verify valid axes parameters
if args.axes:
if len(args.axes) != 4:
throw_parse_error(
my_parser,
"Invalid argument for --axes.\nMust contain four values formatted as: --axes xmin xmax ymin ymax",
)
if args.axes[0] > args.axes[1] or args.axes[2] > args.axes[3]:
throw_parse_error(
my_parser,
"Invalid argument for --axes.\nBreaks required conditions: (xmax > xmin && ymax > ymin)",
)
# We need to make a directory for a new roofline
if not os.path.isdir(args.path):
os.makedirs(args.path)
# does roof data exist?
print("Checking for roofline.csv in ", args.path)
roof_path = args.path + "/roofline.csv"
roofline_exists = os.path.isfile(roof_path)
if not roofline_exists:
if get_soc() != "mi200":
throw_parse_error(
my_parser, "Invalid SoC.\nRoofline only availible on MI200."
)
mibench(args)
# does sysinfo exist?
print("Checking for sysinfo.csv in ", args.path)
sysinfo_path = args.path + "/sysinfo.csv"
sysinfo_exists = os.path.isfile(sysinfo_path)
if not sysinfo_exists:
print("sysinfo not found")
gen_sysinfo(args.name, args.path, [], args.remaining, False)
# does app data exist?
print("Checking for pmc_perf.csv in ", args.path)
app_path = args.path + "/pmc_perf.csv"
app_exists = os.path.isfile(app_path)
if not app_exists:
if get_soc() != "mi200":
throw_parse_error(
my_parser, "Invalid SoC.\nRoofline only availible on MI200."
)
if not args.remaining:
throw_parse_error(
my_parser,
"Cannot find existing application data.\nAttempting to generate application data from -- <app_cmd>.\n-- <app_cmd> option is required to generate application data.",
)
else:
characterize_app(args.path, args.remaining, args.verbose)
def detect_roofline():
mspec = specs.get_machine_specs(0)
@@ -248,7 +302,6 @@ def detect_roofline():
target_binary = {"rocm_ver": rocm_ver, "distro": distro}
return target_binary
def mibench(args):
print("No roofline data found. Generating...")
@@ -282,7 +335,6 @@ def mibench(args):
]
)
def characterize_app(path, cmd, verbose):
target = get_soc()
workload_dir = path
@@ -314,12 +366,9 @@ def characterize_app(path, cmd, verbose):
# Update pmc_perf.csv timestamps
replace_timestamps(workload_dir)
################################################
# Profiling Helpers
################################################
def run_prof(fname, workload_dir, perfmon_dir, cmd, verbose):
global rocprof_cmd
@@ -514,62 +563,10 @@ def main():
elif args.roof_only:
print("\n--------\nRoofline only\n--------\n")
if args.path == os.getcwd() + "/workloads":
args.path += "/" + args.name + "/" + str(get_soc())
# Verify valid axes parameters
if args.axes:
if len(args.axes) != 4:
throw_parse_error(
my_parser,
"Invalid argument for --axes.\nMust contain four values formatted as: --axes xmin xmax ymin ymax",
)
if args.axes[0] > args.axes[1] or args.axes[2] > args.axes[3]:
throw_parse_error(
my_parser,
"Invalid argument for --axes.\nBreaks required conditions: (xmax > xmin && ymax > ymin)",
)
# We need to make a directory for a new roofline
if not os.path.isdir(args.path):
os.makedirs(args.path)
# does roof data exist?
print("Checking for roofline.csv in ", args.path)
roof_path = args.path + "/roofline.csv"
roofline_exists = os.path.isfile(roof_path)
if not roofline_exists:
if get_soc() != "mi200":
throw_parse_error(
my_parser, "Invalid SoC.\nRoofline only availible on MI200."
)
mibench(args)
# does sysinfo exist?
print("Checking for sysinfo.csv in ", args.path)
sysinfo_path = args.path + "/sysinfo.csv"
sysinfo_exists = os.path.isfile(sysinfo_path)
if not sysinfo_exists:
print("sysinfo not found")
gen_sysinfo(args.name, args.path, [], args.remaining, False)
# does app data exist?
print("Checking for pmc_perf.csv in ", args.path)
app_path = args.path + "/pmc_perf.csv"
app_exists = os.path.isfile(app_path)
if not app_exists:
if get_soc() != "mi200":
throw_parse_error(
my_parser, "Invalid SoC.\nRoofline only availible on MI200."
)
if not args.remaining:
throw_parse_error(
my_parser,
"Cannot find existing application data.\nAttempting to generate application data from -- <app_cmd>.\n-- <app_cmd> option is required to generate application data.",
)
else:
characterize_app(args.path, args.remaining, args.verbose)
# Setup prerequisits for roofline
roof_setup(args, my_parser)
# Generate roofline
plot_roofline.empirical_roof(args)
roofline_only(args.path, args.verbose, args.device)
# Profile only
else:
+15
Ver fichero
@@ -41,6 +41,7 @@ import argparse
import os.path
from pathlib import Path
from omniperf_analyze.utils import parser, file_io
from omniperf_analyze.utils.gui_components.roofline import get_roofline
def initialize_run(args, normalization_filter=None):
@@ -209,6 +210,20 @@ def run_cli(args, runs):
)
def roofline_only(path_to_dir, verbose, dev_id):
import pandas as pd
from collections import OrderedDict
app_path = path_to_dir + "/pmc_perf.csv"
roofline_exists = os.path.isfile(app_path)
if not roofline_exists:
print("Error: {} does not exist")
sys.exit(0)
t_df = OrderedDict()
t_df["pmc_perf"] = pd.read_csv(app_path)
get_roofline(path_to_dir, t_df, dev_id, verbose, True)
def analyze(args):
if args.dependency:
print("pip3 install astunparse numpy tabulate pandas pyyaml")
@@ -164,8 +164,9 @@ def generate_plots(roof_info, ai_data, verbose, fig=None):
return fig
def get_roofline(path_to_dir, ret_df, verbose):
def get_roofline(path_to_dir, ret_df, dev_id, verbose, isStandalone=False):
# Roofline settings
# TODO: Make "sort" attribute dynamic so user can select desired sort
fp32_details = {
"path": path_to_dir,
"sort": "kernels",
@@ -185,6 +186,7 @@ def get_roofline(path_to_dir, ret_df, verbose):
ai_data = roofline_calc.plot_application("kernels", ret_df, verbose)
if verbose >= 1:
# print AI data for each mem level
print("AI at each mem level")
for i in ai_data:
print(i, "->", ai_data[i])
print("\n")
@@ -193,27 +195,37 @@ def get_roofline(path_to_dir, ret_df, verbose):
fp16_fig = generate_plots(fp16_details, ai_data, verbose)
ml_combo_fig = generate_plots(int8_details, ai_data, verbose, fp16_fig)
return html.Section(
id="roofline",
children=[
html.Div(
className="float-container",
children=[
html.Div(
className="float-child",
children=[
html.H3(children="Empirical Roofline Analysis (FP32/FP64)"),
dcc.Graph(figure=fp32_fig),
],
),
html.Div(
className="float-child",
children=[
html.H3(children="Empirical Roofline Analysis (FP16/INT8)"),
dcc.Graph(figure=ml_combo_fig),
],
),
],
)
],
)
if isStandalone:
dev_id = "ALL" if dev_id == -1 else str(dev_id)
fp32_fig.write_image(path_to_dir + "/empirRoof_gpu-{}_fp32".format(dev_id))
ml_combo_fig.write_image(path_to_dir + "empirRoof_gpu-{}_fp8_fp16".format(dev_id))
else:
return html.Section(
id="roofline",
children=[
html.Div(
className="float-container",
children=[
html.Div(
className="float-child",
children=[
html.H3(
children="Empirical Roofline Analysis (FP32/FP64)"
),
dcc.Graph(figure=fp32_fig),
],
),
html.Div(
className="float-child",
children=[
html.H3(
children="Empirical Roofline Analysis (FP16/INT8)"
),
dcc.Graph(figure=ml_combo_fig),
],
),
],
)
],
)
+1 -1
Ver fichero
@@ -89,7 +89,7 @@ def get_color(catagory):
# Plot BW at each cache level
# -------------------------------------------------------------------------------------
def plot_roof(roof_details, roof_data, verbose):
# TODO: This is where filtering by memory level will need to occur for standalone
graphPoints = {"hbm": [], "l2": [], "l1": [], "lds": [], "valu": [], "mfma": []}
cacheHierarchy = ["HBM", "L2", "L1", "LDS"]