Enabling Standalone GUI on 2.x (#214)
* Initial overhaul of Analyze mode. Basic CLI is enabled.
Signed-off-by: colramos-amd <colramos@amd.com>
* Merge branch '2.x' of github.com:AMDResearch/omniperf into 2.x-dev
Signed-off-by: colramos-amd <colramos@amd.com>
* fix comment typo
Signed-off-by: Karl W Schulz <karl.schulz@amd.com>
* Move error logging to util.py
Signed-off-by: colramos-amd <colramos@amd.com>
* Move perfmon_configs dir into omniperf_soc dir. Rename config dirs for clarity
Signed-off-by: colramos-amd <colramos@amd.com>
* Add a supported_archs property to Omniperf base class
Signed-off-by: colramos-amd <colramos@amd.com>
* Add css assets for GUI styling
Signed-off-by: colramos-amd <colramos@amd.com>
* Re-organize roofline class. Improved useability
Signed-off-by: colramos-amd <colramos@amd.com>
* Enable standalone GUI
Signed-off-by: colramos-amd <colramos@amd.com>
* Remove outdated metric_configs. This was moved to omniperf_soc dir
Signed-off-by: colramos-amd <colramos@amd.com>
* Fix small bug in GUI to enable Mi100 visualization
Signed-off-by: colramos-amd <colramos@amd.com>
---------
Signed-off-by: colramos-amd <colramos@amd.com>
Signed-off-by: Karl W Schulz <karl.schulz@amd.com>
Signed-off-by: Cole Ramos <colramos@amd.com>
Co-authored-by: Karl W Schulz <karl.schulz@amd.com>
[ROCm/rocprofiler-compute commit: 7d93a086c2]
Cette révision appartient à :
@@ -0,0 +1,379 @@
|
||||
##############################################################################bl
|
||||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2021 - 2023 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
##############################################################################el
|
||||
|
||||
import sys
|
||||
import pandas as pd
|
||||
from dash import html, dash_table
|
||||
import plotly.express as px
|
||||
import colorlover
|
||||
|
||||
from utils import schema
|
||||
|
||||
pd.set_option(
|
||||
"mode.chained_assignment", None
|
||||
) # ignore SettingWithCopyWarning pandas warning
|
||||
|
||||
IS_DARK = True #TODO: Remove hardcoded in favor of class property
|
||||
|
||||
##################
|
||||
# HELPER FUNCTIONS
|
||||
##################
|
||||
def filter_df(column, df, filt):
|
||||
filt_df = df
|
||||
if filt != []:
|
||||
filt_df = df.loc[df[schema.pmc_perf_file_prefix][column].astype(str).isin(filt)]
|
||||
return filt_df
|
||||
|
||||
|
||||
def multi_bar_chart(table_id, display_df):
|
||||
if table_id == 1604:
|
||||
nested_bar = {"NC": {}, "UC": {}, "RW": {}, "CC": {}}
|
||||
for index, row in display_df.iterrows():
|
||||
nested_bar[row["Coherency"]][row["Xfer"]] = row["Avg"]
|
||||
if table_id == 1704:
|
||||
nested_bar = {"Read": {}, "Write": {}}
|
||||
for index, row in display_df.iterrows():
|
||||
nested_bar[row["Transaction"]][row["Type"]] = row["Avg"]
|
||||
|
||||
return nested_bar
|
||||
|
||||
|
||||
def discrete_background_color_bins(df, n_bins=5, columns="all"):
|
||||
bounds = [i * (1.0 / n_bins) for i in range(n_bins + 1)]
|
||||
if columns == "all":
|
||||
if "id" in df:
|
||||
df_numeric_columns = df.select_dtypes("number").drop(["id"], axis=1)
|
||||
else:
|
||||
df_numeric_columns = df.select_dtypes("number")
|
||||
else:
|
||||
df_numeric_columns = df[columns]
|
||||
df_max = df_numeric_columns.max().max()
|
||||
df_min = df_numeric_columns.min().min()
|
||||
ranges = [((df_max - df_min) * i) + df_min for i in bounds]
|
||||
styles = []
|
||||
legend = []
|
||||
for i in range(1, len(bounds)):
|
||||
min_bound = ranges[i - 1]
|
||||
max_bound = ranges[i]
|
||||
backgroundColor = colorlover.scales[str(n_bins)]["seq"]["Blues"][i - 1]
|
||||
color = "white" if i > len(bounds) / 2.0 else "inherit"
|
||||
|
||||
for column in df_numeric_columns:
|
||||
styles.append(
|
||||
{
|
||||
"if": {
|
||||
"filter_query": (
|
||||
"{{{column}}} >= {min_bound}"
|
||||
+ (
|
||||
" && {{{column}}} < {max_bound}"
|
||||
if (i < len(bounds) - 1)
|
||||
else ""
|
||||
)
|
||||
).format(column=column, min_bound=min_bound, max_bound=max_bound),
|
||||
"column_id": column,
|
||||
},
|
||||
"backgroundColor": backgroundColor,
|
||||
"color": color,
|
||||
}
|
||||
)
|
||||
legend.append(
|
||||
html.Div(
|
||||
style={"display": "inline-block", "width": "60px"},
|
||||
children=[
|
||||
html.Div(
|
||||
style={
|
||||
"backgroundColor": backgroundColor,
|
||||
"borderLeft": "1px rgb(50, 50, 50) solid",
|
||||
"height": "10px",
|
||||
}
|
||||
),
|
||||
html.Small(round(min_bound, 2), style={"paddingLeft": "2px"}),
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
return (styles, html.Div(legend, style={"padding": "5px 0 5px 0"}))
|
||||
|
||||
|
||||
####################
|
||||
# GRAPHICAL ELEMENTS
|
||||
####################
|
||||
def build_bar_chart(display_df, table_config, barchart_elements, norm_filt):
|
||||
"""
|
||||
Read data into a bar chart. ID will determine which subtype of barchart.
|
||||
"""
|
||||
d_figs = []
|
||||
|
||||
# Insr Mix bar chart
|
||||
if table_config["id"] in barchart_elements["instr_mix"]:
|
||||
display_df["Avg"] = [
|
||||
x.astype(int) if x != "" else int(0) for x in display_df["Avg"]
|
||||
]
|
||||
df_unit = display_df["Unit"][0]
|
||||
d_figs.append(
|
||||
px.bar(
|
||||
display_df,
|
||||
x="Avg",
|
||||
y="Metric",
|
||||
color="Avg",
|
||||
labels={"Avg": "# of {}".format(df_unit.lower())},
|
||||
height=400,
|
||||
orientation="h",
|
||||
)
|
||||
)
|
||||
|
||||
# Multi bar chart
|
||||
elif table_config["id"] in barchart_elements["multi_bar"]:
|
||||
display_df["Avg"] = [
|
||||
x.astype(int) if x != "" else int(0) for x in display_df["Avg"]
|
||||
]
|
||||
df_unit = display_df["Unit"][0]
|
||||
nested_bar = multi_bar_chart(table_config["id"], display_df)
|
||||
# generate chart for each coherency
|
||||
for group, metric in nested_bar.items():
|
||||
d_figs.append(
|
||||
px.bar(
|
||||
title=group,
|
||||
x=metric.values(),
|
||||
y=metric.keys(),
|
||||
labels={"x": df_unit, "y": ""},
|
||||
text=metric.values(),
|
||||
orientation="h",
|
||||
height=200,
|
||||
)
|
||||
.update_xaxes(showgrid=False, rangemode="nonnegative")
|
||||
.update_yaxes(showgrid=False)
|
||||
.update_layout(title_x=0.5)
|
||||
)
|
||||
# L2 Cache per channel
|
||||
elif table_config["id"] in barchart_elements["l2_cache_per_chan"]:
|
||||
nested_bar = {}
|
||||
channels = []
|
||||
for colName, colData in display_df.items():
|
||||
if colName == "Channel":
|
||||
channels = list(colData.values)
|
||||
else:
|
||||
display_df[colName] = [
|
||||
x.astype(float) if x != "" and x != None else float(0)
|
||||
for x in display_df[colName]
|
||||
]
|
||||
nested_bar[colName] = list(display_df[colName])
|
||||
for group, metric in nested_bar.items():
|
||||
d_figs.append(
|
||||
px.bar(
|
||||
title=group[0 : group.rfind("(")],
|
||||
x=channels,
|
||||
y=metric,
|
||||
labels={
|
||||
"x": "Channel",
|
||||
"y": group[group.rfind("(") + 1 : len(group) - 1].replace(
|
||||
"per", norm_filt
|
||||
),
|
||||
},
|
||||
).update_yaxes(rangemode="nonnegative")
|
||||
)
|
||||
|
||||
# Speed-of-light bar chart
|
||||
elif table_config["id"] in barchart_elements["sol"]:
|
||||
display_df["Value"] = [
|
||||
x.astype(float) if x != "" else float(0) for x in display_df["Value"]
|
||||
]
|
||||
if table_config["id"] == 1701:
|
||||
# special layout for L2 Cache SOL
|
||||
d_figs.append(
|
||||
px.bar(
|
||||
display_df[display_df["Unit"] == "Pct"],
|
||||
x="Value",
|
||||
y="Metric",
|
||||
color="Value",
|
||||
range_color=[0, 100],
|
||||
labels={"Value": "%"},
|
||||
height=220,
|
||||
orientation="h",
|
||||
).update_xaxes(range=[0, 110], ticks="inside")
|
||||
) # append first % chart
|
||||
d_figs.append(
|
||||
px.bar(
|
||||
display_df[display_df["Unit"] == "Gb/s"],
|
||||
x="Value",
|
||||
y="Metric",
|
||||
color="Value",
|
||||
range_color=[0, 1638],
|
||||
labels={"Value": "GB/s"},
|
||||
height=220,
|
||||
orientation="h",
|
||||
).update_xaxes(range=[0, 1638])
|
||||
) # append second GB/s chart
|
||||
else:
|
||||
d_figs.append(
|
||||
px.bar(
|
||||
display_df,
|
||||
x="Value",
|
||||
y="Metric",
|
||||
color="Value",
|
||||
range_color=[0, 100],
|
||||
labels={"Value": "%"},
|
||||
height=400,
|
||||
orientation="h",
|
||||
).update_xaxes(range=[0, 110])
|
||||
)
|
||||
else:
|
||||
print(
|
||||
"ERROR: Table id {}. Cannot determine barchart type.".format(
|
||||
table_config["id"]
|
||||
)
|
||||
)
|
||||
sys.exit(-1)
|
||||
|
||||
# update layout for each of the charts
|
||||
for fig in d_figs:
|
||||
fig.update_layout(
|
||||
margin=dict(l=50, r=50, b=50, t=50, pad=4),
|
||||
paper_bgcolor="rgba(0,0,0,0)",
|
||||
plot_bgcolor="rgba(0,0,0,0)",
|
||||
font={"color": "#ffffff"},
|
||||
)
|
||||
return d_figs
|
||||
|
||||
|
||||
def build_table_chart(
|
||||
display_df, table_config, original_df, display_columns, comparable_columns, decimal
|
||||
):
|
||||
"""
|
||||
Read data into a DashTable
|
||||
"""
|
||||
d_figs = []
|
||||
# build comlumns/header with formatting
|
||||
formatted_columns = []
|
||||
for col in display_df.columns:
|
||||
if (
|
||||
str(col).lower() == "pct"
|
||||
or str(col).lower() == "pop"
|
||||
or str(col).lower() == "percentage"
|
||||
):
|
||||
formatted_columns.append(
|
||||
dict(
|
||||
id=col,
|
||||
name=col,
|
||||
type="numeric",
|
||||
format={"specifier": ".{}f".format(decimal)},
|
||||
)
|
||||
)
|
||||
elif col in comparable_columns:
|
||||
formatted_columns.append(
|
||||
dict(
|
||||
id=col,
|
||||
name=col,
|
||||
type="numeric",
|
||||
format={"specifier": ".{}f".format(decimal)},
|
||||
)
|
||||
)
|
||||
else:
|
||||
formatted_columns.append(dict(id=col, name=col, type="text"))
|
||||
|
||||
# tooltip shows only on the 1st col for now if 'Tips' available
|
||||
table_tooltip = (
|
||||
[
|
||||
{
|
||||
column: {
|
||||
"value": str(row["Tips"])
|
||||
if column == display_columns[0] and row["Tips"]
|
||||
else "",
|
||||
"type": "markdown",
|
||||
}
|
||||
for column, value in row.items()
|
||||
}
|
||||
for row in original_df.to_dict("records")
|
||||
]
|
||||
if "Tips" in original_df.columns.values.tolist()
|
||||
else None
|
||||
)
|
||||
|
||||
# build data table with columns, tooltip, df and other properties
|
||||
d_t = dash_table.DataTable(
|
||||
id=str(table_config["id"]),
|
||||
sort_action="native",
|
||||
sort_mode="multi",
|
||||
columns=formatted_columns,
|
||||
tooltip_data=table_tooltip,
|
||||
# left-aligning the text of the 1st col
|
||||
style_cell_conditional=[
|
||||
{"if": {"column_id": display_columns[0]}, "textAlign": "left"}
|
||||
],
|
||||
# style cell
|
||||
style_cell={"maxWidth": "500px"},
|
||||
# display style
|
||||
style_header={
|
||||
"backgroundColor": "rgb(30, 30, 30)",
|
||||
"color": "white",
|
||||
"fontWeight": "bold",
|
||||
}
|
||||
if IS_DARK
|
||||
else {},
|
||||
style_data={
|
||||
"backgroundColor": "rgb(50, 50, 50)",
|
||||
"color": "white",
|
||||
"whiteSpace": "normal",
|
||||
"height": "auto",
|
||||
}
|
||||
if IS_DARK
|
||||
else {},
|
||||
style_data_conditional=[
|
||||
{"if": {"row_index": "odd"}, "backgroundColor": "rgb(60, 60, 60)"},
|
||||
{
|
||||
"if": {"column_id": "PoP", "filter_query": "{PoP} > 50"},
|
||||
"backgroundColor": "#ffa90a",
|
||||
"color": "white",
|
||||
},
|
||||
{
|
||||
"if": {"column_id": "PoP", "filter_query": "{PoP} > 80"},
|
||||
"backgroundColor": "#ff120a",
|
||||
"color": "white",
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"column_id": "Avg",
|
||||
"filter_query": "{Unit} = Pct && {Avg} > 50",
|
||||
},
|
||||
"backgroundColor": "#ffa90a",
|
||||
"color": "white",
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"column_id": "Avg",
|
||||
"filter_query": "{Unit} = Pct && {Avg} > 80",
|
||||
},
|
||||
"backgroundColor": "#ff120a",
|
||||
"color": "white",
|
||||
},
|
||||
]
|
||||
if IS_DARK
|
||||
else [],
|
||||
# the df to display
|
||||
data=display_df.to_dict("records"),
|
||||
)
|
||||
# print("DATA: \n", display_df.to_dict('records'))
|
||||
d_figs.append(d_t)
|
||||
return d_figs
|
||||
# print(d_t.columns)
|
||||
@@ -0,0 +1,341 @@
|
||||
##############################################################################bl
|
||||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2021 - 2023 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
##############################################################################el
|
||||
|
||||
from dash import html, dcc
|
||||
import dash_bootstrap_components as dbc
|
||||
|
||||
from utils import schema
|
||||
|
||||
avail_normalizations = ["per_wave", "per_cycle", "per_second", "per_kernel"]
|
||||
|
||||
|
||||
# List all the unique column values for desired column in df, 'target_col'
|
||||
def list_unique(orig_list, is_numeric):
|
||||
list_set = set(orig_list)
|
||||
unique_list = list(list_set)
|
||||
if is_numeric:
|
||||
unique_list.sort()
|
||||
return unique_list
|
||||
|
||||
|
||||
def create_span(input):
|
||||
elmt = {}
|
||||
elmt["label"] = (html.Span(str(input), title=str(input)),)
|
||||
elmt["value"] = str(input)
|
||||
return elmt
|
||||
|
||||
|
||||
def get_header(raw_pmc, input_filters, kernel_names):
|
||||
return html.Header(
|
||||
id="home",
|
||||
children=[
|
||||
html.Nav(
|
||||
id="nav-wrap",
|
||||
children=[
|
||||
html.Ul(
|
||||
id="nav",
|
||||
children=[
|
||||
html.Div(
|
||||
className="nav-left",
|
||||
children=[
|
||||
dbc.DropdownMenu(
|
||||
[
|
||||
dbc.DropdownMenuItem("Overview", header=True),
|
||||
dbc.DropdownMenuItem(
|
||||
"Roofline",
|
||||
href="#roofline",
|
||||
external_link=True,
|
||||
),
|
||||
dbc.DropdownMenuItem(
|
||||
"Top Stat",
|
||||
href="#top_stat",
|
||||
external_link=True,
|
||||
),
|
||||
dbc.DropdownMenuItem(
|
||||
"System Info",
|
||||
href="#system_info",
|
||||
external_link=True,
|
||||
),
|
||||
dbc.DropdownMenuItem(
|
||||
"System Speed-of-Light",
|
||||
href="#system_speed-of-light",
|
||||
external_link=True,
|
||||
),
|
||||
dbc.DropdownMenuItem("Compute", header=True),
|
||||
dbc.DropdownMenuItem(
|
||||
"Command Processor (CPF/CPC)",
|
||||
href="#command_processor_cpccpf",
|
||||
external_link=True,
|
||||
),
|
||||
dbc.DropdownMenuItem(
|
||||
"Shader Processor Input (SPI)",
|
||||
href="#shader_processor_input_spi",
|
||||
external_link=True,
|
||||
),
|
||||
dbc.DropdownMenuItem(
|
||||
"Wavefront",
|
||||
href="#wavefront",
|
||||
external_link=True,
|
||||
),
|
||||
dbc.DropdownMenuItem(
|
||||
"Compute Units - Instruction Mix",
|
||||
href="#compute_units_-_instruction_mix",
|
||||
external_link=True,
|
||||
),
|
||||
dbc.DropdownMenuItem(
|
||||
"Compute Units - Compute Pipeline",
|
||||
href="#compute_units_-_compute_pipeline",
|
||||
external_link=True,
|
||||
),
|
||||
dbc.DropdownMenuItem("Cache", header=True),
|
||||
dbc.DropdownMenuItem(
|
||||
"Local Data Share (LDS)",
|
||||
href="#local_data_share_lds",
|
||||
external_link=True,
|
||||
),
|
||||
dbc.DropdownMenuItem(
|
||||
"Instruction Cache",
|
||||
href="#instruction_cache",
|
||||
external_link=True,
|
||||
),
|
||||
dbc.DropdownMenuItem(
|
||||
"Scalar L1 Data Cache",
|
||||
href="#scalar_l1_data_cache",
|
||||
external_link=True,
|
||||
),
|
||||
dbc.DropdownMenuItem(
|
||||
"Texture Addresser & Texture Data (TA/TD)",
|
||||
href="#texture_addresser_and_texture_data_tatd",
|
||||
external_link=True,
|
||||
),
|
||||
dbc.DropdownMenuItem(
|
||||
"Vector L1 Data Cache",
|
||||
href="#vector_l1_data_cache",
|
||||
external_link=True,
|
||||
),
|
||||
dbc.DropdownMenuItem(
|
||||
"L2 Cache",
|
||||
href="#l2_cache",
|
||||
external_link=True,
|
||||
),
|
||||
dbc.DropdownMenuItem(
|
||||
"L2 Cache (per channel)",
|
||||
href="#l2_cache_per_channel",
|
||||
external_link=True,
|
||||
),
|
||||
],
|
||||
label="Menu",
|
||||
menu_variant="dark",
|
||||
),
|
||||
],
|
||||
),
|
||||
html.Li(
|
||||
className="filter",
|
||||
children=[
|
||||
html.Div(
|
||||
children=[
|
||||
html.A(
|
||||
className="smoothscroll",
|
||||
children=["Normalization:"],
|
||||
),
|
||||
dcc.Dropdown(
|
||||
avail_normalizations,
|
||||
id="norm-filt",
|
||||
value=input_filters["normalization"],
|
||||
clearable=False,
|
||||
style={"width": "150px"},
|
||||
),
|
||||
]
|
||||
)
|
||||
],
|
||||
),
|
||||
html.Li(
|
||||
className="filter",
|
||||
children=[
|
||||
html.Div(
|
||||
children=[
|
||||
html.A(
|
||||
className="smoothscroll",
|
||||
children=["GCD:"],
|
||||
),
|
||||
dcc.Dropdown(
|
||||
list_unique(
|
||||
list(
|
||||
map(
|
||||
str,
|
||||
raw_pmc[
|
||||
schema.pmc_perf_file_prefix
|
||||
]["gpu-id"],
|
||||
)
|
||||
),
|
||||
True,
|
||||
), # list avail gcd ids
|
||||
id="gcd-filt",
|
||||
multi=True,
|
||||
value=input_filters[
|
||||
"gpu"
|
||||
], # default to any gpu filters passed as args
|
||||
placeholder="ALL",
|
||||
clearable=False,
|
||||
style={"width": "60px"},
|
||||
),
|
||||
]
|
||||
)
|
||||
],
|
||||
),
|
||||
html.Li(
|
||||
className="filter",
|
||||
children=[
|
||||
html.Div(
|
||||
children=[
|
||||
html.A(
|
||||
className="smoothscroll",
|
||||
children=["Dispatch Filter:"],
|
||||
),
|
||||
dcc.Dropdown(
|
||||
list(
|
||||
map(
|
||||
str,
|
||||
raw_pmc[
|
||||
schema.pmc_perf_file_prefix
|
||||
]["Index"],
|
||||
)
|
||||
),
|
||||
id="disp-filt",
|
||||
multi=True,
|
||||
value=input_filters[
|
||||
"dispatch"
|
||||
], # default to any dispatch filters passed as args
|
||||
placeholder="ALL",
|
||||
style={"width": "150px"},
|
||||
),
|
||||
]
|
||||
)
|
||||
],
|
||||
),
|
||||
html.Li(
|
||||
className="filter",
|
||||
children=[
|
||||
html.Div(
|
||||
children=[
|
||||
html.A(
|
||||
className="smoothscroll",
|
||||
children=["Top N:"],
|
||||
),
|
||||
dcc.Dropdown(
|
||||
[1, 5, 10, 15, 20, 50, 100],
|
||||
id="top-n-filt",
|
||||
value=input_filters[
|
||||
"top_n"
|
||||
], # default to any dispatch filters passed as args
|
||||
clearable=False,
|
||||
style={"width": "50px"},
|
||||
),
|
||||
]
|
||||
)
|
||||
],
|
||||
),
|
||||
html.Li(
|
||||
className="filter",
|
||||
children=[
|
||||
html.Div(
|
||||
children=[
|
||||
html.A(
|
||||
className="smoothscroll",
|
||||
children=["Kernels:"],
|
||||
),
|
||||
dcc.Dropdown(
|
||||
list(
|
||||
map(
|
||||
create_span,
|
||||
list_unique(
|
||||
list(
|
||||
map(
|
||||
str,
|
||||
raw_pmc[
|
||||
schema.pmc_perf_file_prefix
|
||||
]["KernelName"],
|
||||
)
|
||||
),
|
||||
False,
|
||||
), # list avail kernel names
|
||||
)
|
||||
),
|
||||
id="kernel-filt",
|
||||
multi=True,
|
||||
value=kernel_names,
|
||||
optionHeight=150,
|
||||
placeholder="ALL",
|
||||
style={
|
||||
"width": "600px", # TODO: Change these widths to % rather than fixed value
|
||||
},
|
||||
),
|
||||
]
|
||||
)
|
||||
],
|
||||
),
|
||||
html.Div(
|
||||
className="nav-right",
|
||||
children=[
|
||||
html.Li(
|
||||
children=[
|
||||
# Report bug button
|
||||
html.A(
|
||||
href="",
|
||||
children=[
|
||||
html.Button(
|
||||
className="report",
|
||||
children=["Report Bug"],
|
||||
)
|
||||
],
|
||||
)
|
||||
]
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
html.Div(
|
||||
className="row banner",
|
||||
children=[
|
||||
html.H3(
|
||||
children=["Placeholder. Guided Analysis coming soon..."],
|
||||
style={"color": "white"},
|
||||
),
|
||||
],
|
||||
),
|
||||
html.P(
|
||||
className="scrolldown",
|
||||
children=[
|
||||
html.A(
|
||||
className="smoothscroll",
|
||||
href="#roofline",
|
||||
children=[html.I(className="icon-down-circle")],
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
Fichier diff supprimé car celui-ci est trop grand
Voir la Diff
@@ -22,9 +22,10 @@
|
||||
# SOFTWARE.
|
||||
##############################################################################el
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
from dataclasses import dataclass
|
||||
import logging
|
||||
import csv
|
||||
|
||||
################################################
|
||||
@@ -94,43 +95,42 @@ def get_color(catagory):
|
||||
# -------------------------------------------------------------------------------------
|
||||
# Plot BW at each cache level
|
||||
# -------------------------------------------------------------------------------------
|
||||
def calc_ceilings(roof_specs, benchmark_data, targ_mem_level, verbose):
|
||||
def calc_ceilings(roofline_parameters, dtype, benchmark_data):
|
||||
"""Given benchmarking data, calculate ceilings (or peak performance) for empirical roofline
|
||||
"""
|
||||
# TODO: This is where filtering by memory level will need to occur for standalone
|
||||
graphPoints = {"hbm": [], "l2": [], "l1": [], "lds": [], "valu": [], "mfma": []}
|
||||
|
||||
if targ_mem_level == "ALL":
|
||||
if roofline_parameters['mem_level'] == "ALL":
|
||||
cacheHierarchy = ["HBM", "L2", "L1", "LDS"]
|
||||
else:
|
||||
cacheHierarchy = targ_mem_level
|
||||
cacheHierarchy = roofline_parameters['mem_level']
|
||||
|
||||
x1 = y1 = x2 = y2 = -1
|
||||
x1_mfma = y1_mfma = x2_mfma = y2_mfma = -1
|
||||
target_precision = roof_specs["dtype"][2:]
|
||||
target_precision = dtype[2:]
|
||||
|
||||
if roof_specs["dtype"] != "FP16" and roof_specs["dtype"] != "I8":
|
||||
if dtype != "FP16" and dtype != "I8":
|
||||
peakOps = float(
|
||||
benchmark_data[roof_specs["dtype"] + "Flops"][roof_specs["device"]]
|
||||
benchmark_data[dtype + "Flops"][roofline_parameters['device_id']]
|
||||
)
|
||||
for i in range(0, len(cacheHierarchy)):
|
||||
# Plot BW line
|
||||
if verbose >= 3:
|
||||
print("Current cache level is ", cacheHierarchy[i])
|
||||
# Plot BW line
|
||||
logging.debug("[roofline] Current cache level is ", cacheHierarchy[i])
|
||||
curr_bw = cacheHierarchy[i] + "Bw"
|
||||
peakBw = float(benchmark_data[curr_bw][roof_specs["device"]])
|
||||
peakBw = float(benchmark_data[curr_bw][roofline_parameters['device_id']])
|
||||
|
||||
if roof_specs["dtype"] == "I8":
|
||||
peakMFMA = float(benchmark_data["MFMAI8Ops"][roof_specs["device"]])
|
||||
if dtype == "I8":
|
||||
peakMFMA = float(benchmark_data["MFMAI8Ops"][roofline_parameters['device_id']])
|
||||
else:
|
||||
peakMFMA = float(
|
||||
benchmark_data["MFMAF{}Flops".format(target_precision)][roof_specs["device"]]
|
||||
benchmark_data["MFMAF{}Flops".format(target_precision)][roofline_parameters['device_id']]
|
||||
)
|
||||
|
||||
x1 = float(XMIN)
|
||||
y1 = float(XMIN) * peakBw
|
||||
# Note: No reg peakOps for FP16 or INT8
|
||||
if roof_specs["dtype"] != "FP16" and roof_specs["dtype"] != "I8":
|
||||
if dtype != "FP16" and dtype != "I8":
|
||||
x2 = peakOps / peakBw
|
||||
y2 = peakOps
|
||||
|
||||
@@ -142,9 +142,9 @@ def calc_ceilings(roof_specs, benchmark_data, targ_mem_level, verbose):
|
||||
y2_mfma = peakMFMA
|
||||
|
||||
# These are the points to use:
|
||||
if verbose >= 3:
|
||||
print("x = [{}, {}]".format(x1, x2_mfma))
|
||||
print("y = [{}, {}]".format(y1, y2_mfma))
|
||||
logging.debug("[roofline] coordinate points:")
|
||||
logging.debug("x = [{}, {}]".format(x1, x2_mfma))
|
||||
logging.debug("y = [{}, {}]".format(y1, y2_mfma))
|
||||
|
||||
graphPoints[cacheHierarchy[i].lower()].append([x1, x2_mfma])
|
||||
graphPoints[cacheHierarchy[i].lower()].append([y1, y2_mfma])
|
||||
@@ -154,28 +154,26 @@ def calc_ceilings(roof_specs, benchmark_data, targ_mem_level, verbose):
|
||||
# Plot computing roof
|
||||
# -------------------------------------------------------------------------------------
|
||||
# Note: No FMA roof for FP16 or INT8
|
||||
if roof_specs["dtype"] != "FP16" and roof_specs["dtype"] != "I8":
|
||||
if dtype != "FP16" and dtype != "I8":
|
||||
# Plot FMA roof
|
||||
x0 = XMAX
|
||||
if x2 < x0:
|
||||
x0 = x2
|
||||
|
||||
if verbose >= 3:
|
||||
print("FMA ROOF [{}, {}], [{},{}]".format(x0, XMAX, peakOps, peakOps))
|
||||
logging.debug("FMA ROOF [{}, {}], [{},{}]".format(x0, XMAX, peakOps, peakOps))
|
||||
graphPoints["valu"].append([x0, XMAX])
|
||||
graphPoints["valu"].append([peakOps, peakOps])
|
||||
graphPoints["valu"].append(peakOps)
|
||||
|
||||
# Plot MFMA roof
|
||||
if (
|
||||
x1_mfma != -1 or roof_specs["dtype"] == "FP16" or roof_specs["dtype"] == "I8"
|
||||
x1_mfma != -1 or dtype == "FP16" or dtype == "I8"
|
||||
): # assert that mfma has been assigned
|
||||
x0_mfma = XMAX
|
||||
if x2_mfma < x0_mfma:
|
||||
x0_mfma = x2_mfma
|
||||
|
||||
if verbose >= 3:
|
||||
print("MFMA ROOF [{}, {}], [{},{}]".format(x0_mfma, XMAX, peakMFMA, peakMFMA))
|
||||
logging.debug("MFMA ROOF [{}, {}], [{},{}]".format(x0_mfma, XMAX, peakMFMA, peakMFMA))
|
||||
graphPoints["mfma"].append([x0_mfma, XMAX])
|
||||
graphPoints["mfma"].append([peakMFMA, peakMFMA])
|
||||
graphPoints["mfma"].append(peakMFMA)
|
||||
@@ -187,7 +185,7 @@ def calc_ceilings(roof_specs, benchmark_data, targ_mem_level, verbose):
|
||||
# Overlay application performance
|
||||
# -------------------------------------------------------------------------------------
|
||||
# Calculate relevent metrics for ai calculation
|
||||
def calc_ai(sort_type, ret_df, verbose):
|
||||
def calc_ai(sort_type, ret_df):
|
||||
"""Given counter data, caclulate arithmetic intensity for each kernel in the application.
|
||||
"""
|
||||
df = ret_df["pmc_perf"]
|
||||
@@ -263,8 +261,7 @@ def calc_ai(sort_type, ret_df, verbose):
|
||||
+ (df["SQ_INSTS_VALU_MFMA_MOPS_F64"][idx] * 512)
|
||||
)
|
||||
except KeyError:
|
||||
if verbose >= 3:
|
||||
print("{}: Skipped total_flops at index {}".format(kernelName[:35], idx))
|
||||
logging.debug("[roofline] {}: Skipped total_flops at index {}".format(kernelName[:35], idx))
|
||||
pass
|
||||
try:
|
||||
valu_flops += (
|
||||
@@ -291,8 +288,7 @@ def calc_ai(sort_type, ret_df, verbose):
|
||||
)
|
||||
)
|
||||
except KeyError:
|
||||
if verbose >= 3:
|
||||
print("{}: Skipped valu_flops at index {}".format(kernelName[:35], idx))
|
||||
logging.debug("{}: Skipped valu_flops at index {}".format(kernelName[:35], idx))
|
||||
pass
|
||||
|
||||
try:
|
||||
@@ -302,8 +298,7 @@ def calc_ai(sort_type, ret_df, verbose):
|
||||
mfma_flops_f64 += df["SQ_INSTS_VALU_MFMA_MOPS_F64"][idx] * 512
|
||||
mfma_iops_i8 += df["SQ_INSTS_VALU_MFMA_MOPS_I8"][idx] * 512
|
||||
except KeyError:
|
||||
if verbose >= 3:
|
||||
print("{}: Skipped mfma ops at index {}".format(kernelName[:35], idx))
|
||||
logging.debug("[roofline] {}: Skipped mfma ops at index {}".format(kernelName[:35], idx))
|
||||
pass
|
||||
|
||||
try:
|
||||
@@ -313,15 +308,13 @@ def calc_ai(sort_type, ret_df, verbose):
|
||||
* L2_BANKS
|
||||
) # L2_BANKS = 32 (since assuming mi200)
|
||||
except KeyError:
|
||||
if verbose >= 3:
|
||||
print("{}: Skipped lds_data at index {}".format(kernelName[:35], idx))
|
||||
logging.debug("[roofline] {}: Skipped lds_data at index {}".format(kernelName[:35], idx))
|
||||
pass
|
||||
|
||||
try:
|
||||
L1cache_data += df["TCP_TOTAL_CACHE_ACCESSES_sum"][idx] * 64
|
||||
except KeyError:
|
||||
if verbose >= 3:
|
||||
print("{}: Skipped L1cache_data at index {}".format(kernelName[:35], idx))
|
||||
logging.debug("[roofline] {}: Skipped L1cache_data at index {}".format(kernelName[:35], idx))
|
||||
pass
|
||||
|
||||
try:
|
||||
@@ -332,8 +325,7 @@ def calc_ai(sort_type, ret_df, verbose):
|
||||
+ df["TCP_TCC_READ_REQ_sum"][idx] * 64
|
||||
)
|
||||
except KeyError:
|
||||
if verbose >= 3:
|
||||
print("{}: Skipped L2cache_data at index {}".format(kernelName[:35], idx))
|
||||
logging.debug("[roofline] {}: Skipped L2cache_data at index {}".format(kernelName[:35], idx))
|
||||
pass
|
||||
try:
|
||||
hbm_data += (
|
||||
@@ -343,8 +335,7 @@ def calc_ai(sort_type, ret_df, verbose):
|
||||
+ ((df["TCC_EA_WRREQ_sum"][idx] - df["TCC_EA_WRREQ_64B_sum"][idx]) * 32)
|
||||
)
|
||||
except KeyError:
|
||||
if verbose >= 3:
|
||||
print("{}: Skipped hbm_data at index {}".format(kernelName[:35], idx))
|
||||
logging.debug("[roofline] {}: Skipped hbm_data at index {}".format(kernelName[:35], idx))
|
||||
pass
|
||||
|
||||
totalDuration += df["EndNs"][idx] - df["BeginNs"][idx]
|
||||
@@ -372,12 +363,11 @@ def calc_ai(sort_type, ret_df, verbose):
|
||||
avgDuration / calls,
|
||||
)
|
||||
)
|
||||
if verbose >= 2:
|
||||
print(
|
||||
"Just added {} to AI_Data at index {}. # of calls: {}".format(
|
||||
kernelName, idx, calls
|
||||
)
|
||||
logging.debug(
|
||||
"Just added {} to AI_Data at index {}. # of calls: {}".format(
|
||||
kernelName, idx, calls
|
||||
)
|
||||
)
|
||||
total_flops = (
|
||||
valu_flops
|
||||
) = (
|
||||
@@ -487,8 +477,8 @@ def calc_ai(sort_type, ret_df, verbose):
|
||||
return intensityPoints
|
||||
|
||||
|
||||
def constuct_roof(roof_specs, targ_mem_level, verbose):
|
||||
benchmark_results = roof_specs["path"] + "/roofline.csv"
|
||||
def constuct_roof(roofline_parameters, dtype):
|
||||
benchmark_results = os.path.join(roofline_parameters["path_to_dir"], "roofline.csv")
|
||||
# -----------------------------------------------------
|
||||
# Initialize roofline data dictionary from roofline.csv
|
||||
# -----------------------------------------------------
|
||||
@@ -526,8 +516,6 @@ def constuct_roof(roof_specs, targ_mem_level, verbose):
|
||||
# ------------------
|
||||
# Generate Roofline
|
||||
# ------------------
|
||||
results = calc_ceilings(roof_specs, benchmark_data, targ_mem_level, verbose)
|
||||
# for key in results:
|
||||
# print(key, "->", results[key])
|
||||
results = calc_ceilings(roofline_parameters, dtype, benchmark_data)
|
||||
|
||||
return results
|
||||
|
||||
@@ -135,7 +135,6 @@ def show_all(args, runs, archConfigs, output):
|
||||
)
|
||||
# show value + percentage
|
||||
# TODO: better alignment
|
||||
|
||||
t_df = (
|
||||
cur_df[header]
|
||||
.astype(float)
|
||||
|
||||
Référencer dans un nouveau ticket
Bloquer un utilisateur