Modify GUI roofline to accomidate standalone option
Signed-off-by: colramos425 <colramos@amd.com>
Este commit está contenido en:
+58
-61
@@ -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:
|
||||
|
||||
@@ -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),
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
@@ -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"]
|
||||
|
||||
Referencia en una nueva incidencia
Block a user