code formatting updates
Signed-off-by: Karl W Schulz <karl.schulz@amd.com>
[ROCm/rocprofiler-compute commit: 79b877d679]
This commit is contained in:
committed by
Karl W. Schulz
parent
abdaee0a2d
commit
4bfcf9b8a8
@@ -34,6 +34,7 @@ import pandas as pd
|
||||
|
||||
MAX_SERVER_SEL_DELAY = 5000 # 5 sec connection timeout
|
||||
|
||||
|
||||
class DatabaseConnector:
|
||||
def __init__(self, args):
|
||||
self.args = args
|
||||
@@ -45,17 +46,22 @@ class DatabaseConnector:
|
||||
"port": str(self.args.port),
|
||||
"team": self.args.team,
|
||||
"workload": self.args.workload,
|
||||
"db": None
|
||||
"db": None,
|
||||
}
|
||||
self.interaction_type: str = None #set to 'import' or 'remove' based on user arguments
|
||||
self.interaction_type: str = (
|
||||
None # set to 'import' or 'remove' based on user arguments
|
||||
)
|
||||
self.client: MongoClient = None
|
||||
|
||||
@demarcate
|
||||
def prep_import(self, profile_and_export=False):
|
||||
if profile_and_export:
|
||||
self.connection_info['workload'] = os.path.join(self.connection_info['workload'], self.args.target)
|
||||
self.connection_info["workload"] = os.path.join(
|
||||
self.connection_info["workload"], self.args.target
|
||||
)
|
||||
|
||||
# Extract SoC and workload name from sysinfo.csv
|
||||
sys_info = os.path.join(self.connection_info['workload'], "sysinfo.csv")
|
||||
sys_info = os.path.join(self.connection_info["workload"], "sysinfo.csv")
|
||||
if os.path.isfile(sys_info):
|
||||
sys_info = pd.read_csv(sys_info)
|
||||
soc = sys_info["name"][0]
|
||||
@@ -63,7 +69,9 @@ class DatabaseConnector:
|
||||
else:
|
||||
error("[database] Unable to parse SoC and/or workload name from sysinfo.csv")
|
||||
|
||||
self.connection_info["db"] = "omniperf_" + str(self.args.team) + "_" + str(name) + "_" + str(soc)
|
||||
self.connection_info["db"] = (
|
||||
"omniperf_" + str(self.args.team) + "_" + str(name) + "_" + str(soc)
|
||||
)
|
||||
|
||||
@demarcate
|
||||
def db_import(self):
|
||||
@@ -72,7 +80,11 @@ class DatabaseConnector:
|
||||
file = "blank"
|
||||
for file in tqdm(os.listdir(self.connection_info["workload"])):
|
||||
if file.endswith(".csv"):
|
||||
logging.info("[database] Uploading: %s" % self.connection_info["workload"] + "/" + file)
|
||||
logging.info(
|
||||
"[database] Uploading: %s" % self.connection_info["workload"]
|
||||
+ "/"
|
||||
+ file
|
||||
)
|
||||
try:
|
||||
fileName = file[0 : file.find(".")]
|
||||
cmd = (
|
||||
@@ -101,69 +113,85 @@ class DatabaseConnector:
|
||||
|
||||
@demarcate
|
||||
def db_remove(self):
|
||||
db_to_remove = self.client[self.connection_info['workload']]
|
||||
db_to_remove = self.client[self.connection_info["workload"]]
|
||||
|
||||
# check the collection names on the database
|
||||
col_list = db_to_remove.list_collection_names()
|
||||
self.client.drop_database(db_to_remove)
|
||||
db = self.client["workload_names"]
|
||||
col = db["names"]
|
||||
col.delete_many({"name": self.connection_info['workload']})
|
||||
|
||||
logging.info("[database] Successfully removed %s" % self.connection_info['workload'])
|
||||
col.delete_many({"name": self.connection_info["workload"]})
|
||||
|
||||
logging.info(
|
||||
"[database] Successfully removed %s" % self.connection_info["workload"]
|
||||
)
|
||||
|
||||
@abstractmethod
|
||||
def pre_processing(self):
|
||||
"""Perform any pre-processing steps prior to database conncetion.
|
||||
"""
|
||||
"""Perform any pre-processing steps prior to database conncetion."""
|
||||
logging.debug("[database] pre-processing database connection")
|
||||
if not self.args.remove and not self.args.upload:
|
||||
error("Either -i/--import or -r/--remove is required in database mode")
|
||||
self.interaction_type = 'import' if self.args.upload else 'remove'
|
||||
self.interaction_type = "import" if self.args.upload else "remove"
|
||||
|
||||
# Detect interaction type
|
||||
if self.interaction_type == 'remove':
|
||||
if self.interaction_type == "remove":
|
||||
logging.debug("[database] validating arguments for --remove workflow")
|
||||
is_full_workload_name = self.args.workload.count("_") >= 3
|
||||
if not is_full_workload_name:
|
||||
error("-w/--workload is not valid. Please use full workload name as seen in GUI when removing (i.e. omniperf_asw_vcopy_mi200)")
|
||||
error(
|
||||
"-w/--workload is not valid. Please use full workload name as seen in GUI when removing (i.e. omniperf_asw_vcopy_mi200)"
|
||||
)
|
||||
|
||||
if self.connection_info['host'] == None or self.connection_info['username'] == None:
|
||||
error("-H/--host and -u/--username are required when interaction type is set to %s" % self.interaction_type)
|
||||
if self.connection_info['workload'] == "admin" or self.connection_info['workload'] == "local":
|
||||
error("Cannot remove %s. Try again." % self.connection_info['workload'])
|
||||
if (
|
||||
self.connection_info["host"] == None
|
||||
or self.connection_info["username"] == None
|
||||
):
|
||||
error(
|
||||
"-H/--host and -u/--username are required when interaction type is set to %s"
|
||||
% self.interaction_type
|
||||
)
|
||||
if (
|
||||
self.connection_info["workload"] == "admin"
|
||||
or self.connection_info["workload"] == "local"
|
||||
):
|
||||
error("Cannot remove %s. Try again." % self.connection_info["workload"])
|
||||
else:
|
||||
logging.debug("[database] validating arguments for --import workflow")
|
||||
if (
|
||||
self.connection_info['host'] == None
|
||||
or self.connection_info['team'] == None
|
||||
or self.connection_info['username'] == None
|
||||
or self.connection_info['workload'] == None
|
||||
self.connection_info["host"] == None
|
||||
or self.connection_info["team"] == None
|
||||
or self.connection_info["username"] == None
|
||||
or self.connection_info["workload"] == None
|
||||
):
|
||||
error("-H/--host, -w/--workload, -u/--username, and -t/--team are all required when interaction type is set to %s" % self.interaction_type)
|
||||
error(
|
||||
"-H/--host, -w/--workload, -u/--username, and -t/--team are all required when interaction type is set to %s"
|
||||
% self.interaction_type
|
||||
)
|
||||
|
||||
if os.path.isdir(os.path.abspath(self.connection_info['workload'])):
|
||||
is_workload_empty(self.connection_info['workload'])
|
||||
if os.path.isdir(os.path.abspath(self.connection_info["workload"])):
|
||||
is_workload_empty(self.connection_info["workload"])
|
||||
else:
|
||||
error("--workload is invalid. Please pass path to a valid directory.")
|
||||
|
||||
if len(self.args.team) > 13:
|
||||
error("--team exceeds 13 character limit. Try again.")
|
||||
|
||||
|
||||
# format path properly
|
||||
self.connection_info['workload'] = os.path.abspath(self.connection_info['workload'])
|
||||
self.connection_info["workload"] = os.path.abspath(
|
||||
self.connection_info["workload"]
|
||||
)
|
||||
|
||||
# Detect password
|
||||
if self.connection_info['password'] == "":
|
||||
if self.connection_info["password"] == "":
|
||||
try:
|
||||
self.connection_info['password'] = getpass.getpass()
|
||||
self.connection_info["password"] = getpass.getpass()
|
||||
except Exception as e:
|
||||
error("[database] PASSWORD ERROR %s" % e)
|
||||
else:
|
||||
logging.info("[database] Password recieved")
|
||||
else:
|
||||
password = self.connection_info['password']
|
||||
password = self.connection_info["password"]
|
||||
|
||||
# Establish client connection
|
||||
connection_str = (
|
||||
@@ -177,11 +205,10 @@ class DatabaseConnector:
|
||||
+ self.connection_info["port"]
|
||||
+ "/?authSource=admin"
|
||||
)
|
||||
self.client = MongoClient(connection_str, serverSelectionTimeoutMS=MAX_SERVER_SEL_DELAY)
|
||||
self.client = MongoClient(
|
||||
connection_str, serverSelectionTimeoutMS=MAX_SERVER_SEL_DELAY
|
||||
)
|
||||
try:
|
||||
self.client.server_info()
|
||||
except:
|
||||
error("[database] Unable to connect to the DB server.")
|
||||
|
||||
|
||||
|
||||
@@ -50,11 +50,12 @@ top_stats_build_in_config = {
|
||||
"id": 1,
|
||||
"title": "Dispatch List",
|
||||
"data source": [{"raw_csv_table": {"id": 2, "source": "pmc_dispatch_info.csv"}}],
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
time_units = {"s": 10**9, "ms": 10**6, "us": 10**3, "ns": 1}
|
||||
|
||||
|
||||
def load_sys_info(f):
|
||||
"""
|
||||
Load sys running info from csv file to a df.
|
||||
@@ -231,4 +232,4 @@ def is_single_panel_config(root_dir, supported_archs):
|
||||
return False
|
||||
else:
|
||||
logging.error("Found multiple panel config sets but incomplete for all archs!")
|
||||
sys.exit(1)
|
||||
sys.exit(1)
|
||||
|
||||
@@ -34,7 +34,8 @@ pd.set_option(
|
||||
"mode.chained_assignment", None
|
||||
) # ignore SettingWithCopyWarning pandas warning
|
||||
|
||||
IS_DARK = True #TODO: Remove hardcoded in favor of class property
|
||||
IS_DARK = True # TODO: Remove hardcoded in favor of class property
|
||||
|
||||
|
||||
##################
|
||||
# HELPER FUNCTIONS
|
||||
@@ -168,31 +169,31 @@ def build_bar_chart(display_df, table_config, barchart_elements, norm_filt):
|
||||
)
|
||||
# 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")
|
||||
# )
|
||||
# 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"]:
|
||||
@@ -376,4 +377,4 @@ def build_table_chart(
|
||||
# print("DATA: \n", display_df.to_dict('records'))
|
||||
d_figs.append(d_t)
|
||||
return d_figs
|
||||
# print(d_t.columns)
|
||||
# print(d_t.columns)
|
||||
|
||||
@@ -52,9 +52,9 @@ def insert_chart_data(mem_data, base_data):
|
||||
return G(
|
||||
className="data",
|
||||
children=[
|
||||
# ----------------------------------------
|
||||
# Instr Buff Block
|
||||
#TODO: double check wave_occupancy
|
||||
# ----------------------------------------
|
||||
# Instr Buff Block
|
||||
# TODO: double check wave_occupancy
|
||||
Text(
|
||||
x="52",
|
||||
y="313",
|
||||
@@ -73,8 +73,8 @@ def insert_chart_data(mem_data, base_data):
|
||||
fontWeight="bold",
|
||||
children=memchart_values["Wave Life"],
|
||||
),
|
||||
# ----------------------------------------
|
||||
# Instr Dispatch Block
|
||||
# ----------------------------------------
|
||||
# Instr Dispatch Block
|
||||
Text(
|
||||
x="386",
|
||||
y="46",
|
||||
@@ -139,8 +139,8 @@ def insert_chart_data(mem_data, base_data):
|
||||
fontSize="12px",
|
||||
children=memchart_values["BR"],
|
||||
),
|
||||
# ----------------------------------------
|
||||
# Exec Block
|
||||
# ----------------------------------------
|
||||
# Exec Block
|
||||
Text(
|
||||
x="480",
|
||||
y="99",
|
||||
@@ -198,8 +198,8 @@ def insert_chart_data(mem_data, base_data):
|
||||
fontSize="12px",
|
||||
children=memchart_values["Workgroups"],
|
||||
),
|
||||
# ----------------------------------------
|
||||
# LDS Block
|
||||
# ----------------------------------------
|
||||
# LDS Block
|
||||
Text(
|
||||
x="723",
|
||||
y="78",
|
||||
@@ -224,8 +224,8 @@ def insert_chart_data(mem_data, base_data):
|
||||
fontSize="12px",
|
||||
children=memchart_values["LDS Latency"],
|
||||
),
|
||||
# ----------------------------------------
|
||||
# Vector L1 Cache Block
|
||||
# ----------------------------------------
|
||||
# Vector L1 Cache Block
|
||||
Text(
|
||||
x="708",
|
||||
y="204",
|
||||
@@ -306,8 +306,8 @@ def insert_chart_data(mem_data, base_data):
|
||||
fontSize="12px",
|
||||
children=memchart_values["VL1_L2 Atomic"],
|
||||
),
|
||||
# ----------------------------------------
|
||||
# Scalar L1D Cache Block
|
||||
# ----------------------------------------
|
||||
# Scalar L1D Cache Block
|
||||
Text(
|
||||
x="709",
|
||||
y="384",
|
||||
@@ -356,8 +356,8 @@ def insert_chart_data(mem_data, base_data):
|
||||
fontSize="12px",
|
||||
children=memchart_values["VL1D_L2 Atomic"],
|
||||
),
|
||||
# ----------------------------------------
|
||||
# Instr L1 Cache Block
|
||||
# ----------------------------------------
|
||||
# Instr L1 Cache Block
|
||||
Text(
|
||||
x="492",
|
||||
y="498",
|
||||
@@ -390,8 +390,8 @@ def insert_chart_data(mem_data, base_data):
|
||||
fontSize="12px",
|
||||
children=memchart_values["IL1_L2 Rd"],
|
||||
),
|
||||
# ----------------------------------------
|
||||
# L2 Cache Block(inside)
|
||||
# ----------------------------------------
|
||||
# L2 Cache Block(inside)
|
||||
Text(
|
||||
x="1145",
|
||||
y="213",
|
||||
@@ -440,8 +440,8 @@ def insert_chart_data(mem_data, base_data):
|
||||
fontSize="12px",
|
||||
children=memchart_values["L2 Wr Lat"],
|
||||
),
|
||||
# ----------------------------------------
|
||||
# Fabric Block
|
||||
# ----------------------------------------
|
||||
# Fabric Block
|
||||
Text(
|
||||
x="1317",
|
||||
y="243",
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
import os
|
||||
import sys
|
||||
import logging
|
||||
import glob
|
||||
import glob
|
||||
import re
|
||||
import subprocess
|
||||
import pandas as pd
|
||||
@@ -34,6 +34,7 @@ from utils.utils import error
|
||||
|
||||
cache = dict()
|
||||
|
||||
|
||||
# Note: shortener is now dependent on a rocprof install with llvm
|
||||
def kernel_name_shortener(workload_dir, level):
|
||||
def shorten_file(df, level):
|
||||
@@ -134,6 +135,8 @@ def kernel_name_shortener(workload_dir, level):
|
||||
modified_df = shorten_file(orig_df, level)
|
||||
modified_df.to_csv(fpath, index=False)
|
||||
except pd.errors.EmptyDataError:
|
||||
logging.debug("[profiling] Skipping shortening on empty csv: %s" % str(fpath))
|
||||
logging.debug(
|
||||
"[profiling] Skipping shortening on empty csv: %s" % str(fpath)
|
||||
)
|
||||
|
||||
logging.info("[profiling] Kernel_Name shortening complete.")
|
||||
logging.info("[profiling] Kernel_Name shortening complete.")
|
||||
|
||||
@@ -1039,4 +1039,4 @@ if __name__ == "__main__":
|
||||
|
||||
arch = ""
|
||||
normal_unit = "per_kernel"
|
||||
print(plot_mem_chart(arch, normal_unit, metric_dict))
|
||||
print(plot_mem_chart(arch, normal_unit, metric_dict))
|
||||
|
||||
@@ -174,6 +174,7 @@ def to_round(a, b):
|
||||
else:
|
||||
return round(a, b)
|
||||
|
||||
|
||||
def to_quantile(a, b):
|
||||
if a is None:
|
||||
return None
|
||||
@@ -182,6 +183,7 @@ def to_quantile(a, b):
|
||||
else:
|
||||
raise Exception("to_quantile: unsupported type.")
|
||||
|
||||
|
||||
def to_mod(a, b):
|
||||
if isinstance(a, pd.core.series.Series):
|
||||
return a.mod(b)
|
||||
@@ -402,6 +404,7 @@ def gen_counter_list(formula):
|
||||
|
||||
return visited, counters
|
||||
|
||||
|
||||
def calc_builtin_var(var, sys_info):
|
||||
"""
|
||||
Calculate build-in variable based on sys_info:
|
||||
@@ -414,6 +417,7 @@ def calc_builtin_var(var, sys_info):
|
||||
print("Don't support", var)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def build_dfs(archConfigs, filter_metrics, sys_info):
|
||||
"""
|
||||
- Build dataframe for each type of data source within each panel.
|
||||
@@ -447,7 +451,6 @@ def build_dfs(archConfigs, filter_metrics, sys_info):
|
||||
type == "metric_table"
|
||||
and "metric" in data_config
|
||||
and "placeholder_range" in data_config["metric"]
|
||||
|
||||
):
|
||||
# print(data_config["metric"])
|
||||
new_metrics = {}
|
||||
@@ -475,16 +478,14 @@ def build_dfs(archConfigs, filter_metrics, sys_info):
|
||||
data_config["metric"] = new_metrics
|
||||
# print(data_config)
|
||||
# print(data_config["metric"])
|
||||
|
||||
|
||||
for panel_id, panel in archConfigs.panel_configs.items():
|
||||
for data_source in panel["data source"]:
|
||||
for type, data_config in data_source.items():
|
||||
if type == "metric_table":
|
||||
headers = ["Metric_ID"]
|
||||
data_source_idx = str(data_config["id"] // 100)
|
||||
if (data_source_idx != 0 or
|
||||
data_source_idx in filter_metrics
|
||||
):
|
||||
if data_source_idx != 0 or data_source_idx in filter_metrics:
|
||||
metric_list[data_source_idx] = panel["title"]
|
||||
if (
|
||||
"cli_style" in data_config
|
||||
@@ -506,9 +507,9 @@ def build_dfs(archConfigs, filter_metrics, sys_info):
|
||||
headers.append("coll_level")
|
||||
if "tips" in data_config["header"].keys():
|
||||
headers.append(data_config["header"]["tips"])
|
||||
|
||||
|
||||
df = pd.DataFrame(columns=headers)
|
||||
|
||||
|
||||
i = 0
|
||||
for key, entries in data_config["metric"].items():
|
||||
data_source_idx = (
|
||||
@@ -532,7 +533,7 @@ def build_dfs(archConfigs, filter_metrics, sys_info):
|
||||
):
|
||||
values.append(metric_idx)
|
||||
values.append(key)
|
||||
|
||||
|
||||
metric_list[data_source_idx] = data_config["title"]
|
||||
|
||||
if (
|
||||
@@ -687,9 +688,9 @@ def eval_metric(dfs, dfs_type, sys_info, soc_spec, raw_pmc_df, debug):
|
||||
ammolite__numWavesPerCU = sys_info.maxWavesPerCU # todo: check do we still need it
|
||||
ammolite__numSQC = sys_info.numSQC
|
||||
ammolite__L2Banks = sys_info.L2Banks
|
||||
ammolite__LDSBanks = (
|
||||
soc_spec['LDSBanks']
|
||||
) # todo: eventually switch this over to sys_info. its a new spec so trying not to break compatibility
|
||||
ammolite__LDSBanks = soc_spec[
|
||||
"LDSBanks"
|
||||
] # todo: eventually switch this over to sys_info. its a new spec so trying not to break compatibility
|
||||
ammolite__freq = sys_info.cur_sclk # todo: check do we still need it
|
||||
ammolite__mclk = sys_info.cur_mclk
|
||||
ammolite__sclk = sys_info.sclk
|
||||
@@ -910,7 +911,9 @@ def load_kernel_top(workload, dir):
|
||||
if file.exists():
|
||||
tmp[id] = pd.read_csv(file)
|
||||
else:
|
||||
logging.info("Warning: Issue loading top kernels. Check pmc_kernel_top.csv")
|
||||
logging.info(
|
||||
"Warning: Issue loading top kernels. Check pmc_kernel_top.csv"
|
||||
)
|
||||
elif "from_csv_columnwise" in df.columns:
|
||||
# NB:
|
||||
# Another way might be doing transpose in tty like metric_table.
|
||||
@@ -923,7 +926,9 @@ def load_kernel_top(workload, dir):
|
||||
# so tty could detect them and show them correctly in comparison.
|
||||
tmp[id].columns = ["Info"]
|
||||
else:
|
||||
logging.info("Warning: Issue loading top kernels. Check pmc_kernel_top.csv")
|
||||
logging.info(
|
||||
"Warning: Issue loading top kernels. Check pmc_kernel_top.csv"
|
||||
)
|
||||
workload.dfs.update(tmp)
|
||||
|
||||
|
||||
@@ -957,6 +962,7 @@ def build_comparable_columns(time_unit):
|
||||
|
||||
return comparable_columns
|
||||
|
||||
|
||||
def correct_sys_info(df, specs_correction):
|
||||
"""
|
||||
Correct system spec items manually
|
||||
@@ -1012,5 +1018,3 @@ def correct_sys_info(df, specs_correction):
|
||||
df[name_map[k]] = v
|
||||
|
||||
return df
|
||||
|
||||
|
||||
|
||||
@@ -96,35 +96,36 @@ def get_color(catagory):
|
||||
# Plot BW at each cache level
|
||||
# -------------------------------------------------------------------------------------
|
||||
def calc_ceilings(roofline_parameters, dtype, benchmark_data):
|
||||
"""Given benchmarking data, calculate ceilings (or peak performance) for empirical roofline
|
||||
"""
|
||||
"""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 roofline_parameters['mem_level'] == "ALL":
|
||||
if roofline_parameters["mem_level"] == "ALL":
|
||||
cacheHierarchy = ["HBM", "L2", "L1", "LDS"]
|
||||
else:
|
||||
cacheHierarchy = roofline_parameters['mem_level']
|
||||
cacheHierarchy = roofline_parameters["mem_level"]
|
||||
|
||||
x1 = y1 = x2 = y2 = -1
|
||||
x1_mfma = y1_mfma = x2_mfma = y2_mfma = -1
|
||||
target_precision = dtype[2:]
|
||||
|
||||
if dtype != "FP16" and dtype != "I8":
|
||||
peakOps = float(
|
||||
benchmark_data[dtype + "Flops"][roofline_parameters['device_id']]
|
||||
)
|
||||
peakOps = float(benchmark_data[dtype + "Flops"][roofline_parameters["device_id"]])
|
||||
for i in range(0, len(cacheHierarchy)):
|
||||
# Plot BW line
|
||||
# Plot BW line
|
||||
logging.debug("[roofline] Current cache level is %s" % cacheHierarchy[i])
|
||||
curr_bw = cacheHierarchy[i] + "Bw"
|
||||
peakBw = float(benchmark_data[curr_bw][roofline_parameters['device_id']])
|
||||
peakBw = float(benchmark_data[curr_bw][roofline_parameters["device_id"]])
|
||||
|
||||
if dtype == "I8":
|
||||
peakMFMA = float(benchmark_data["MFMAI8Ops"][roofline_parameters['device_id']])
|
||||
peakMFMA = float(
|
||||
benchmark_data["MFMAI8Ops"][roofline_parameters["device_id"]]
|
||||
)
|
||||
else:
|
||||
peakMFMA = float(
|
||||
benchmark_data["MFMAF{}Flops".format(target_precision)][roofline_parameters['device_id']]
|
||||
benchmark_data["MFMAF{}Flops".format(target_precision)][
|
||||
roofline_parameters["device_id"]
|
||||
]
|
||||
)
|
||||
|
||||
x1 = float(XMIN)
|
||||
@@ -173,7 +174,9 @@ def calc_ceilings(roofline_parameters, dtype, benchmark_data):
|
||||
if x2_mfma < x0_mfma:
|
||||
x0_mfma = x2_mfma
|
||||
|
||||
logging.debug("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)
|
||||
@@ -186,8 +189,7 @@ def calc_ceilings(roofline_parameters, dtype, benchmark_data):
|
||||
# -------------------------------------------------------------------------------------
|
||||
# Calculate relevant metrics for ai calculation
|
||||
def calc_ai(sort_type, ret_df):
|
||||
"""Given counter data, calculate arithmetic intensity for each kernel in the application.
|
||||
"""
|
||||
"""Given counter data, calculate arithmetic intensity for each kernel in the application."""
|
||||
df = ret_df["pmc_perf"]
|
||||
# Sort by top kernels or top dispatches?
|
||||
df = df.sort_values(by=["Kernel_Name"])
|
||||
@@ -261,7 +263,11 @@ def calc_ai(sort_type, ret_df):
|
||||
+ (df["SQ_INSTS_VALU_MFMA_MOPS_F64"][idx] * 512)
|
||||
)
|
||||
except KeyError:
|
||||
logging.debug("[roofline] {}: 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 += (
|
||||
@@ -288,7 +294,9 @@ def calc_ai(sort_type, ret_df):
|
||||
)
|
||||
)
|
||||
except KeyError:
|
||||
logging.debug("{}: Skipped valu_flops at index {}".format(kernelName[:35], idx))
|
||||
logging.debug(
|
||||
"{}: Skipped valu_flops at index {}".format(kernelName[:35], idx)
|
||||
)
|
||||
pass
|
||||
|
||||
try:
|
||||
@@ -298,7 +306,9 @@ def calc_ai(sort_type, ret_df):
|
||||
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:
|
||||
logging.debug("[roofline] {}: Skipped mfma ops at index {}".format(kernelName[:35], idx))
|
||||
logging.debug(
|
||||
"[roofline] {}: Skipped mfma ops at index {}".format(kernelName[:35], idx)
|
||||
)
|
||||
pass
|
||||
|
||||
try:
|
||||
@@ -308,13 +318,19 @@ def calc_ai(sort_type, ret_df):
|
||||
* L2_BANKS
|
||||
) # L2_BANKS = 32 (since assuming mi200)
|
||||
except KeyError:
|
||||
logging.debug("[roofline] {}: 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:
|
||||
logging.debug("[roofline] {}: Skipped L1cache_data at index {}".format(kernelName[:35], idx))
|
||||
logging.debug(
|
||||
"[roofline] {}: Skipped L1cache_data at index {}".format(
|
||||
kernelName[:35], idx
|
||||
)
|
||||
)
|
||||
pass
|
||||
|
||||
try:
|
||||
@@ -325,7 +341,11 @@ def calc_ai(sort_type, ret_df):
|
||||
+ df["TCP_TCC_READ_REQ_sum"][idx] * 64
|
||||
)
|
||||
except KeyError:
|
||||
logging.debug("[roofline] {}: 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 += (
|
||||
@@ -335,7 +355,9 @@ def calc_ai(sort_type, ret_df):
|
||||
+ ((df["TCC_EA_WRREQ_sum"][idx] - df["TCC_EA_WRREQ_64B_sum"][idx]) * 32)
|
||||
)
|
||||
except KeyError:
|
||||
logging.debug("[roofline] {}: Skipped hbm_data at index {}".format(kernelName[:35], idx))
|
||||
logging.debug(
|
||||
"[roofline] {}: Skipped hbm_data at index {}".format(kernelName[:35], idx)
|
||||
)
|
||||
pass
|
||||
|
||||
totalDuration += df["End_Timestamp"][idx] - df["Start_Timestamp"][idx]
|
||||
|
||||
@@ -37,6 +37,7 @@ from pathlib import Path as path
|
||||
from textwrap import dedent
|
||||
from utils.utils import error, get_hbm_stack_num
|
||||
|
||||
|
||||
@dataclass
|
||||
class MachineSpecs:
|
||||
hostname: str
|
||||
@@ -135,7 +136,7 @@ def gpuinfo():
|
||||
|
||||
# we get the max mclk from rocm-smi --showmclkrange
|
||||
rocm_smi_mclk = run(["rocm-smi", "--showmclkrange"], exit_on_error=True)
|
||||
gpu_info['max_mclk'] = search(r'(\d+)Mhz\s*$', rocm_smi_mclk)
|
||||
gpu_info["max_mclk"] = search(r"(\d+)Mhz\s*$", rocm_smi_mclk)
|
||||
|
||||
# Fixme: find better way to differentiate cards, GPU vs APU, etc.
|
||||
rocminfo_full = run(["rocminfo"])
|
||||
@@ -151,81 +152,85 @@ def gpuinfo():
|
||||
if not gpu_arch in SUPPORTED_ARCHS.keys():
|
||||
return gpu_info
|
||||
|
||||
gpu_info['L1'], gpu_info['L1'] = "", ""
|
||||
gpu_info["L1"], gpu_info["L1"] = "", ""
|
||||
for idx2, linetext in enumerate(rocminfo[idx1 + 1 :]):
|
||||
key = search(r"^\s*L1:\s+ ([a-zA-Z0-9]+)\s*", linetext)
|
||||
if key != None:
|
||||
gpu_info['L1'] = key
|
||||
gpu_info["L1"] = key
|
||||
continue
|
||||
|
||||
key = search(r"^\s*L2:\s+ ([a-zA-Z0-9]+)\s*", linetext)
|
||||
if key != None:
|
||||
gpu_info['L2'] = key
|
||||
gpu_info["L2"] = key
|
||||
continue
|
||||
|
||||
key = search(r"^\s*Max Clock Freq\. \(MHz\):\s+([0-9]+)", linetext)
|
||||
if key != None:
|
||||
gpu_info['max_sclk'] = key
|
||||
gpu_info["max_sclk"] = key
|
||||
continue
|
||||
|
||||
key = search(r"^\s*Compute Unit:\s+ ([a-zA-Z0-9]+)\s*", linetext)
|
||||
if key != None:
|
||||
gpu_info['num_CU'] = key
|
||||
gpu_info["num_CU"] = key
|
||||
continue
|
||||
|
||||
key = search(r"^\s*SIMDs per CU:\s+ ([a-zA-Z0-9]+)\s*", linetext)
|
||||
if key != None:
|
||||
gpu_info['num_SIMD'] = key
|
||||
gpu_info["num_SIMD"] = key
|
||||
continue
|
||||
|
||||
key = search(r"^\s*Shader Engines:\s+ ([a-zA-Z0-9]+)\s*", linetext)
|
||||
if key != None:
|
||||
gpu_info['num_SE'] = key
|
||||
gpu_info["num_SE"] = key
|
||||
continue
|
||||
|
||||
key = search(r"^\s*Wavefront Size:\s+ ([a-zA-Z0-9]+)\s*", linetext)
|
||||
if key != None:
|
||||
gpu_info['wave_size'] = key
|
||||
gpu_info["wave_size"] = key
|
||||
continue
|
||||
|
||||
key = search(r"^\s*Workgroup Max Size:\s+ ([a-zA-Z0-9]+)\s*", linetext)
|
||||
if key != None:
|
||||
gpu_info['grp_size'] = key
|
||||
gpu_info["grp_size"] = key
|
||||
continue
|
||||
|
||||
key = search(r"^\s*Max Waves Per CU:\s+ ([a-zA-Z0-9]+)\s*", linetext)
|
||||
if key != None:
|
||||
gpu_info['max_waves_per_cu'] = key
|
||||
gpu_info["max_waves_per_cu"] = key
|
||||
break
|
||||
|
||||
try:
|
||||
soc_module = importlib.import_module('omniperf_soc.soc_'+gpu_arch)
|
||||
soc_module = importlib.import_module("omniperf_soc.soc_" + gpu_arch)
|
||||
except ModuleNotFoundError as e:
|
||||
error("Arch %s marked as supported, but couldn't find class implementation %s." % (gpu_arch, e))
|
||||
|
||||
error(
|
||||
"Arch %s marked as supported, but couldn't find class implementation %s."
|
||||
% (gpu_arch, e)
|
||||
)
|
||||
|
||||
# load arch specific info
|
||||
try:
|
||||
gpu_name = list(SUPPORTED_ARCHS[gpu_arch].keys())[0].upper()
|
||||
gpu_info['L2Banks'] = str(soc_module.SOC_PARAM['L2Banks'])
|
||||
gpu_info['numSQC'] = str(soc_module.SOC_PARAM['numSQC'])
|
||||
gpu_info['LDSBanks'] = str(soc_module.SOC_PARAM['LDSBanks'])
|
||||
gpu_info['numPipes'] = str(soc_module.SOC_PARAM['numPipes'])
|
||||
gpu_info["L2Banks"] = str(soc_module.SOC_PARAM["L2Banks"])
|
||||
gpu_info["numSQC"] = str(soc_module.SOC_PARAM["numSQC"])
|
||||
gpu_info["LDSBanks"] = str(soc_module.SOC_PARAM["LDSBanks"])
|
||||
gpu_info["numPipes"] = str(soc_module.SOC_PARAM["numPipes"])
|
||||
except KeyError as e:
|
||||
error("Incomplete class definition for %s. Expected a field for %s in SOC_PARAM." % (gpu_arch, e))\
|
||||
|
||||
error(
|
||||
"Incomplete class definition for %s. Expected a field for %s in SOC_PARAM."
|
||||
% (gpu_arch, e)
|
||||
)
|
||||
# specify gpu name for gfx942 hardware
|
||||
if gpu_name == "MI300":
|
||||
gpu_name = list(SUPPORTED_ARCHS[gpu_arch].values())[0][0]
|
||||
if (gpu_info['gpu_arch'] == "gfx942") and ("MI300A" in rocminfo_full):
|
||||
if (gpu_info["gpu_arch"] == "gfx942") and ("MI300A" in rocminfo_full):
|
||||
gpu_name = "MI300A_A1"
|
||||
if (gpu_arch == "gfx942") and ("MI300A" not in rocminfo_full):
|
||||
gpu_name = "MI300X_A1"
|
||||
|
||||
|
||||
gpu_info['gpu_name'] = gpu_name
|
||||
gpu_info['gpu_arch'] = gpu_arch
|
||||
gpu_info['compute_partition'] = ""
|
||||
gpu_info['memory_partition'] = ""
|
||||
gpu_info["gpu_name"] = gpu_name
|
||||
gpu_info["gpu_arch"] = gpu_arch
|
||||
gpu_info["compute_partition"] = ""
|
||||
gpu_info["memory_partition"] = ""
|
||||
|
||||
# verify all fields are filled
|
||||
for key, value in gpu_info.items():
|
||||
@@ -235,7 +240,7 @@ def gpuinfo():
|
||||
return gpu_info
|
||||
|
||||
|
||||
def run(cmd,exit_on_error=False):
|
||||
def run(cmd, exit_on_error=False):
|
||||
p = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
if exit_on_error:
|
||||
@@ -255,24 +260,18 @@ def search(pattern, string):
|
||||
return m.group(1)
|
||||
return None
|
||||
|
||||
|
||||
def total_l2_banks(archname, L2Banks, memory_partition):
|
||||
# Fixme: support all supported partitioning mode
|
||||
# Fixme: "name" is a bad name!
|
||||
totalL2Banks = L2Banks
|
||||
if (
|
||||
archname.lower() == "mi300a_a0"
|
||||
or archname.lower() == "mi300a_a1"
|
||||
):
|
||||
totalL2Banks = L2Banks * get_hbm_stack_num(
|
||||
archname, memory_partition)
|
||||
elif (
|
||||
archname.lower() == "mi300x_a0"
|
||||
or archname.lower() == "mi300x_a1"
|
||||
):
|
||||
totalL2Banks = L2Banks * get_hbm_stack_num(
|
||||
archname, memory_partition)
|
||||
if archname.lower() == "mi300a_a0" or archname.lower() == "mi300a_a1":
|
||||
totalL2Banks = L2Banks * get_hbm_stack_num(archname, memory_partition)
|
||||
elif archname.lower() == "mi300x_a0" or archname.lower() == "mi300x_a1":
|
||||
totalL2Banks = L2Banks * get_hbm_stack_num(archname, memory_partition)
|
||||
return totalL2Banks
|
||||
|
||||
|
||||
def get_machine_specs(devicenum):
|
||||
cpuinfo = path("/proc/cpuinfo").read_text()
|
||||
meminfo = path("/proc/meminfo").read_text()
|
||||
@@ -339,8 +338,8 @@ def get_machine_specs(devicenum):
|
||||
|
||||
# these are just max's now, because the parsing was broken and this was inconsistent
|
||||
# with how we use the clocks elsewhere (all max, all the time)
|
||||
cur_sclk = gpu_info['max_sclk']
|
||||
cur_mclk = gpu_info['max_mclk']
|
||||
cur_sclk = gpu_info["max_sclk"]
|
||||
cur_mclk = gpu_info["max_mclk"]
|
||||
|
||||
# FIXME with device
|
||||
vbios = search(r"VBIOS version: (.*?)$", run(["rocm-smi", "-v"], exit_on_error=True))
|
||||
@@ -358,15 +357,16 @@ def get_machine_specs(devicenum):
|
||||
memory_partition = "NA"
|
||||
|
||||
totalL2Banks = total_l2_banks(
|
||||
gpu_info['gpu_name'], int(gpu_info['L2Banks']), memory_partition)
|
||||
gpu_info["gpu_name"], int(gpu_info["L2Banks"]), memory_partition
|
||||
)
|
||||
hbmchannels = totalL2Banks
|
||||
if (
|
||||
gpu_info['gpu_name'].lower() == "mi300a_a0"
|
||||
or gpu_info['gpu_name'].lower() == "mi300a_a1"
|
||||
gpu_info["gpu_name"].lower() == "mi300a_a0"
|
||||
or gpu_info["gpu_name"].lower() == "mi300a_a1"
|
||||
) and memory_partition.lower() == "nps1":
|
||||
# we have an extra 32 channels for the CCD
|
||||
hbmchannels += 32
|
||||
hbmBW = str(int(gpu_info['max_mclk']) / 1000 * 32 * hbmchannels)
|
||||
hbmBW = str(int(gpu_info["max_mclk"]) / 1000 * 32 * hbmchannels)
|
||||
totalL2Banks = str(totalL2Banks)
|
||||
|
||||
return MachineSpecs(
|
||||
@@ -377,26 +377,26 @@ def get_machine_specs(devicenum):
|
||||
ram,
|
||||
distro,
|
||||
rocm_version,
|
||||
gpu_info['gpu_name'],
|
||||
gpu_info['gpu_arch'],
|
||||
gpu_info["gpu_name"],
|
||||
gpu_info["gpu_arch"],
|
||||
vbios,
|
||||
gpu_info['L1'],
|
||||
gpu_info['L2'],
|
||||
gpu_info['num_CU'],
|
||||
gpu_info['num_SIMD'],
|
||||
gpu_info['num_SE'],
|
||||
gpu_info['wave_size'],
|
||||
gpu_info['grp_size'],
|
||||
gpu_info['max_sclk'],
|
||||
gpu_info['max_mclk'],
|
||||
gpu_info["L1"],
|
||||
gpu_info["L2"],
|
||||
gpu_info["num_CU"],
|
||||
gpu_info["num_SIMD"],
|
||||
gpu_info["num_SE"],
|
||||
gpu_info["wave_size"],
|
||||
gpu_info["grp_size"],
|
||||
gpu_info["max_sclk"],
|
||||
gpu_info["max_mclk"],
|
||||
cur_sclk,
|
||||
cur_mclk,
|
||||
gpu_info['max_waves_per_cu'],
|
||||
gpu_info['L2Banks'],
|
||||
gpu_info["max_waves_per_cu"],
|
||||
gpu_info["L2Banks"],
|
||||
totalL2Banks,
|
||||
gpu_info['LDSBanks'],
|
||||
gpu_info['numSQC'],
|
||||
gpu_info['numPipes'],
|
||||
gpu_info["LDSBanks"],
|
||||
gpu_info["numSQC"],
|
||||
gpu_info["numPipes"],
|
||||
hbmBW,
|
||||
compute_partition,
|
||||
memory_partition,
|
||||
|
||||
@@ -201,9 +201,9 @@ def show_all(args, runs, archConfigs, output):
|
||||
)
|
||||
|
||||
# Only show top N kernels (as specified in --max-kernel-num) in "Top Stats" section
|
||||
if(
|
||||
type == "raw_csv_table"
|
||||
and (table_config["source"] == "pmc_kernel_top.csv" or table_config["source"] == "pmc_dispatch_info.csv")
|
||||
if type == "raw_csv_table" and (
|
||||
table_config["source"] == "pmc_kernel_top.csv"
|
||||
or table_config["source"] == "pmc_dispatch_info.csv"
|
||||
):
|
||||
df = df.head(args.max_stat_num)
|
||||
# NB:
|
||||
@@ -251,7 +251,9 @@ def show_kernel_stats(args, runs, archConfigs, output):
|
||||
# sorted when load_table_data.
|
||||
if table_config["id"] == 1:
|
||||
print("\n" + "-" * 80, file=output)
|
||||
print("Detected Kernels (sorted decending by duration)", file=output)
|
||||
print(
|
||||
"Detected Kernels (sorted decending by duration)", file=output
|
||||
)
|
||||
df = pd.concat([df, single_df["Kernel_Name"]], axis=1)
|
||||
|
||||
if table_config["id"] == 2:
|
||||
@@ -268,4 +270,3 @@ def show_kernel_stats(args, runs, archConfigs, output):
|
||||
),
|
||||
file=output,
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user