diff --git a/src/argparser.py b/src/argparser.py
index 714252e3bc..150095e8d1 100644
--- a/src/argparser.py
+++ b/src/argparser.py
@@ -26,12 +26,14 @@ import argparse
import shutil
import os
+
def print_avail_arch(avail_arch: list):
ret_str = "\t\tList all available metrics for analysis on specified arch:"
for arch in avail_arch:
ret_str += "\n\t\t {}".format(arch)
return ret_str
+
def omniarg_parser(parser, omniperf_home, supported_archs, omniperf_version):
# -----------------------------------------
# Parse arguments (dependent on mode)
@@ -42,8 +44,12 @@ def omniarg_parser(parser, omniperf_home, supported_archs, omniperf_version):
general_group = parser.add_argument_group("General Options")
parser._positionals.title = "Modes"
parser._optionals.title = "Help"
- general_group.add_argument("-v", "--version", action="version", version=omniperf_version["ver_pretty"])
- general_group.add_argument("-s", "--specs", action="store_true", help="Print system specs.")
+ general_group.add_argument(
+ "-v", "--version", action="version", version=omniperf_version["ver_pretty"]
+ )
+ general_group.add_argument(
+ "-s", "--specs", action="store_true", help="Print system specs."
+ )
subparsers = parser.add_subparsers(
dest="mode", help="Select mode of interaction with the target application:"
@@ -78,7 +84,9 @@ def omniarg_parser(parser, omniperf_home, supported_archs, omniperf_version):
profile_group = profile_parser.add_argument_group("Profile Options")
roofline_group = profile_parser.add_argument_group("Standalone Roofline Options")
- general_group.add_argument("-v", "--version", action="version", version=omniperf_version["ver_pretty"])
+ general_group.add_argument(
+ "-v", "--version", action="version", version=omniperf_version["ver_pretty"]
+ )
general_group.add_argument(
"-V", "--verbose", help="Increase output verbosity", action="count", default=0
)
@@ -283,11 +291,15 @@ def omniarg_parser(parser, omniperf_home, supported_archs, omniperf_version):
interaction_group = db_parser.add_argument_group("Interaction Type")
connection_group = db_parser.add_argument_group("Connection Options")
- general_group.add_argument("-v", "--version", action="version", version=omniperf_version["ver_pretty"])
+ general_group.add_argument(
+ "-v", "--version", action="version", version=omniperf_version["ver_pretty"]
+ )
general_group.add_argument(
"-V", "--verbose", help="Increase output verbosity", action="count", default=0
)
- general_group.add_argument("-s", "--specs", action="store_true", help="Print system specs.")
+ general_group.add_argument(
+ "-s", "--specs", action="store_true", help="Print system specs."
+ )
interaction_group.add_argument(
"-i",
@@ -374,11 +386,15 @@ def omniarg_parser(parser, omniperf_home, supported_archs, omniperf_version):
analyze_group = analyze_parser.add_argument_group("Analyze Options")
analyze_advanced_group = analyze_parser.add_argument_group("Advanced Options")
- general_group.add_argument("-v", "--version", action="version", version=omniperf_version["ver_pretty"])
+ general_group.add_argument(
+ "-v", "--version", action="version", version=omniperf_version["ver_pretty"]
+ )
general_group.add_argument(
"-V", "--verbose", help="Increase output verbosity", action="count", default=0
)
- general_group.add_argument("-s", "--specs", action="store_true", help="Print system specs.")
+ general_group.add_argument(
+ "-s", "--specs", action="store_true", help="Print system specs."
+ )
analyze_group.add_argument(
"-p",
@@ -398,7 +414,7 @@ def omniarg_parser(parser, omniperf_home, supported_archs, omniperf_version):
analyze_group.add_argument(
"--list-metrics",
metavar="",
- choices=supported_archs.keys(),#["gfx906", "gfx908", "gfx90a"],
+ choices=supported_archs.keys(), # ["gfx906", "gfx908", "gfx90a"],
help=print_avail_arch(supported_archs.keys()),
)
analyze_group.add_argument(
@@ -460,7 +476,7 @@ def omniarg_parser(parser, omniperf_home, supported_archs, omniperf_version):
metavar="",
type=int,
default=10,
- help="\t\tSpecify the maximum number of stats shown in \"Top Stats\" tables (DEFAULT: 10)",
+ help='\t\tSpecify the maximum number of stats shown in "Top Stats" tables (DEFAULT: 10)',
)
analyze_advanced_group.add_argument(
"-n",
@@ -508,7 +524,9 @@ def omniarg_parser(parser, omniperf_home, supported_archs, omniperf_version):
nargs="+",
help="\t\tSpecify column indices to display.",
)
- analyze_advanced_group.add_argument("-g", dest="debug", action="store_true", help="\t\tDebug single metric.")
+ analyze_advanced_group.add_argument(
+ "-g", dest="debug", action="store_true", help="\t\tDebug single metric."
+ )
analyze_advanced_group.add_argument(
"--dependency", action="store_true", help="\t\tList the installation dependency."
)
@@ -527,5 +545,5 @@ def omniarg_parser(parser, omniperf_home, supported_archs, omniperf_version):
"--specs-correction",
type=str,
metavar="",
- help="\t\tSpecify the specs to correct."
- )
\ No newline at end of file
+ help="\t\tSpecify the specs to correct.",
+ )
diff --git a/src/config.py b/src/config.py
index fcb017aae9..6cd07ff1c2 100644
--- a/src/config.py
+++ b/src/config.py
@@ -26,4 +26,4 @@ from pathlib import Path
# NB: Creating a new module to share global vars across modules
omniperf_home = Path(__file__).resolve().parent
-prog = "omniperf"
\ No newline at end of file
+prog = "omniperf"
diff --git a/src/docs/conf.py b/src/docs/conf.py
index f1f26ff802..81e6bd3f2b 100644
--- a/src/docs/conf.py
+++ b/src/docs/conf.py
@@ -116,7 +116,7 @@ html_theme = "sphinx_rtd_theme"
html_static_path = ["_static"]
latex_elements = {
- "sphinxsetup": 'verbatimwrapslines=true, verbatimforcewraps=true',
+ "sphinxsetup": "verbatimwrapslines=true, verbatimforcewraps=true",
}
diff --git a/src/omniperf_analyze/analysis_base.py b/src/omniperf_analyze/analysis_base.py
index d9c166b8c2..18cab8b55a 100644
--- a/src/omniperf_analyze/analysis_base.py
+++ b/src/omniperf_analyze/analysis_base.py
@@ -34,26 +34,31 @@ from utils import schema, file_io, parser
import pandas as pd
from tabulate import tabulate
-class OmniAnalyze_Base():
- def __init__(self,args,supported_archs):
+
+class OmniAnalyze_Base:
+ def __init__(self, args, supported_archs):
self.__args = args
- self._runs = OrderedDict()
- self._arch_configs = {}
+ self._runs = OrderedDict()
+ self._arch_configs = {}
self.__supported_archs = supported_archs
- self._output = None
- self.__socs = None # available OmniSoC objs
+ self._output = None
+ self.__socs = None # available OmniSoC objs
def get_args(self):
return self.__args
+
def set_soc(self, omni_socs):
self.__socs = omni_socs
+
def get_socs(self):
return self.__socs
-
+
@demarcate
def generate_configs(self, arch, config_dir, list_stats, filter_metrics, sys_info):
- single_panel_config = file_io.is_single_panel_config(Path(config_dir), self.__supported_archs)
-
+ single_panel_config = file_io.is_single_panel_config(
+ Path(config_dir), self.__supported_archs
+ )
+
ac = schema.ArchConfig()
if list_stats:
ac.panel_configs = file_io.top_stats_build_in_config
@@ -66,22 +71,26 @@ class OmniAnalyze_Base():
# TODO: filter_metrics should/might be one per arch
# print(ac)
- parser.build_dfs(
- archConfigs=ac,
- filter_metrics=filter_metrics,
- sys_info=sys_info
- )
+ parser.build_dfs(archConfigs=ac, filter_metrics=filter_metrics, sys_info=sys_info)
self._arch_configs[arch] = ac
return self._arch_configs
-
+
@demarcate
def list_metrics(self):
args = self.__args
if args.list_metrics in self.__supported_archs.keys():
arch = args.list_metrics
if arch not in self._arch_configs.keys():
- sys_info = file_io.load_sys_info(Path(self.__args.path[0][0], "sysinfo.csv"))
- self.generate_configs(arch, args.config_dir, args.list_stats, args.filter_metrics, sys_info.iloc[0])
+ sys_info = file_io.load_sys_info(
+ Path(self.__args.path[0][0], "sysinfo.csv")
+ )
+ self.generate_configs(
+ arch,
+ args.config_dir,
+ args.list_stats,
+ args.filter_metrics,
+ sys_info.iloc[0],
+ )
for key, value in self._arch_configs[args.list_metrics].metric_list.items():
prefix = ""
@@ -100,11 +109,13 @@ class OmniAnalyze_Base():
def load_options(self, normalization_filter):
if not normalization_filter:
for k, v in self._arch_configs.items():
- parser.build_metric_value_string(v.dfs, v.dfs_type, self.__args.normal_unit)
+ parser.build_metric_value_string(
+ v.dfs, v.dfs_type, self.__args.normal_unit
+ )
else:
for k, v in self._arch_configs.items():
parser.build_metric_value_string(v.dfs, v.dfs_type, normalization_filter)
-
+
args = self.__args
# Error checking for multiple runs and multiple gpu_kernel filters
if args.gpu_kernel and (len(args.path) != len(args.gpu_kernel)):
@@ -112,27 +123,37 @@ class OmniAnalyze_Base():
for i in range(len(args.path) - 1):
args.gpu_kernel.extend(args.gpu_kernel)
else:
- error("Error: the number of --filter-kernels doesn't match the number of --dir.")
-
+ error(
+ "Error: the number of --filter-kernels doesn't match the number of --dir."
+ )
+
@demarcate
def initalize_runs(self, normalization_filter=None):
if self.__args.list_metrics:
self.list_metrics()
-
+
# load required configs
for d in self.__args.path:
sys_info = file_io.load_sys_info(Path(d[0], "sysinfo.csv"))
arch = sys_info.iloc[0]["gpu_soc"]
args = self.__args
- self.generate_configs(arch, args.config_dir, args.list_stats, args.filter_metrics, sys_info.iloc[0])
+ self.generate_configs(
+ arch,
+ args.config_dir,
+ args.list_stats,
+ args.filter_metrics,
+ sys_info.iloc[0],
+ )
self.load_options(normalization_filter)
-
+
for d in self.__args.path:
w = schema.Workload()
w.sys_info = file_io.load_sys_info(Path(d[0], "sysinfo.csv"))
if self.__args.specs_correction:
- w.sys_info = parser.correct_sys_info(w.sys_info, self.__args.specs_correction)
+ w.sys_info = parser.correct_sys_info(
+ w.sys_info, self.__args.specs_correction
+ )
w.avail_ips = w.sys_info["ip_blocks"].item().split("|")
arch = w.sys_info.iloc[0]["gpu_soc"]
w.dfs = copy.deepcopy(self._arch_configs[arch].dfs)
@@ -142,11 +163,9 @@ class OmniAnalyze_Base():
return self._runs
-
@demarcate
def sanitize(self):
- """Perform sanitization of inputs
- """
+ """Perform sanitization of inputs"""
if not self.__args.path:
error("The following arguments are required: -p/--path")
# verify not accessing parent directories
@@ -160,23 +179,23 @@ class OmniAnalyze_Base():
error("Invalid directory {}\nPlease try again.".format(dir[0]))
# validate profiling data
is_workload_empty(dir[0])
-
-
- #----------------------------------------------------
+
+ # ----------------------------------------------------
# Required methods to be implemented by child classes
- #----------------------------------------------------
+ # ----------------------------------------------------
@abstractmethod
def pre_processing(self):
- """Perform initialization prior to analysis.
- """
+ """Perform initialization prior to analysis."""
logging.debug("[analysis] prepping to do some analysis")
logging.info("[analysis] deriving Omniperf metrics...")
# initalize output file
- self._output = open(self.__args.output_file, "w+") if self.__args.output_file else sys.stdout
-
+ self._output = (
+ open(self.__args.output_file, "w+") if self.__args.output_file else sys.stdout
+ )
+
# initalize runs
self._runs = self.initalize_runs()
-
+
# set filters
if self.__args.gpu_kernel:
for d, gk in zip(self.__args.path, self.__args.gpu_kernel):
@@ -196,6 +215,5 @@ class OmniAnalyze_Base():
@abstractmethod
def run_analysis(self):
- """Run analysis.
- """
+ """Run analysis."""
logging.debug("[analysis] generating analysis")
diff --git a/src/omniperf_analyze/analysis_cli.py b/src/omniperf_analyze/analysis_cli.py
index 422b7ea912..b240b72460 100644
--- a/src/omniperf_analyze/analysis_cli.py
+++ b/src/omniperf_analyze/analysis_cli.py
@@ -27,15 +27,14 @@ from utils.utils import demarcate, error
from utils import file_io, parser, tty
from utils.kernel_name_shortener import kernel_name_shortener
-class cli_analysis(OmniAnalyze_Base):
- #-----------------------
+class cli_analysis(OmniAnalyze_Base):
+ # -----------------------
# Required child methods
- #-----------------------
+ # -----------------------
@demarcate
def pre_processing(self):
- """Perform any pre-processing steps prior to analysis.
- """
+ """Perform any pre-processing steps prior to analysis."""
super().pre_processing()
if self.get_args().random_port:
error("--gui flag is required to enable --random-port")
@@ -48,7 +47,7 @@ class cli_analysis(OmniAnalyze_Base):
filter_gpu_ids=self._runs[d[0]].filter_gpu_ids,
filter_dispatch_ids=self._runs[d[0]].filter_dispatch_ids,
time_unit=self.get_args().time_unit,
- max_stat_num=self.get_args().max_stat_num
+ max_stat_num=self.get_args().max_stat_num,
)
# create 'mega dataframe'
self._runs[d[0]].raw_pmc = file_io.create_df_pmc(
@@ -56,30 +55,32 @@ class cli_analysis(OmniAnalyze_Base):
)
# create the loaded table
parser.load_table_data(
- workload=self._runs[d[0]],
- dir=d[0],
+ workload=self._runs[d[0]],
+ dir=d[0],
is_gui=False,
- debug=self.get_args().debug,
- verbose=self.get_args().verbose
+ debug=self.get_args().debug,
+ verbose=self.get_args().verbose,
)
-
@demarcate
def run_analysis(self):
- """Run CLI analysis.
- """
+ """Run CLI analysis."""
super().run_analysis()
if self.get_args().list_stats:
tty.show_kernel_stats(
self.get_args(),
self._runs,
- self._arch_configs[self._runs[self.get_args().path[0][0]].sys_info.iloc[0]["gpu_soc"]],
- self._output
+ self._arch_configs[
+ self._runs[self.get_args().path[0][0]].sys_info.iloc[0]["gpu_soc"]
+ ],
+ self._output,
)
else:
tty.show_all(
self.get_args(),
self._runs,
- self._arch_configs[self._runs[self.get_args().path[0][0]].sys_info.iloc[0]["gpu_soc"]],
- self._output
+ self._arch_configs[
+ self._runs[self.get_args().path[0][0]].sys_info.iloc[0]["gpu_soc"]
+ ],
+ self._output,
)
diff --git a/src/omniperf_base.py b/src/omniperf_base.py
index 512d1535be..71cf5ade48 100644
--- a/src/omniperf_base.py
+++ b/src/omniperf_base.py
@@ -29,7 +29,15 @@ import os
from pathlib import Path
import shutil
from utils.specs import get_machine_specs
-from utils.utils import demarcate, trace_logger, get_version, get_version_display, detect_rocprof, error, get_submodules
+from utils.utils import (
+ demarcate,
+ trace_logger,
+ get_version,
+ get_version_display,
+ detect_rocprof,
+ error,
+ get_submodules,
+)
from argparser import omniarg_parser
import config
import pandas as pd
@@ -44,13 +52,16 @@ SUPPORTED_ARCHS = {
"gfx942": {"mi300": ["MI300A_A1", "MI300X_A1"]},
}
+
class Omniperf:
def __init__(self):
self.__args = None
self.__profiler_mode = None
self.__analyze_mode = None
- self.__soc_name = set() # gpu name, or in case of analyze mode, all loaded gpu name(s)
- self.__soc = dict() # set of key, value pairs. Where arch->OmniSoc() obj
+ self.__soc_name = (
+ set()
+ ) # gpu name, or in case of analyze mode, all loaded gpu name(s)
+ self.__soc = dict() # set of key, value pairs. Where arch->OmniSoc() obj
self.__version = {
"ver": None,
"ver_pretty": None,
@@ -68,22 +79,21 @@ class Omniperf:
self.detect_profiler()
elif self.__mode == "analyze":
self.detect_analyze()
-
+
logging.info("Execution mode = %s" % self.__mode)
-
+
def print_graphic(self):
- """Log program name as ascii art to terminal.
- """
- ascii_art = '''
+ """Log program name as ascii art to terminal."""
+ ascii_art = """
___ _ __
/ _ \ _ __ ___ _ __ (_)_ __ ___ _ __ / _|
| | | | '_ ` _ \| '_ \| | '_ \ / _ \ '__| |_
| |_| | | | | | | | | | | |_) | __/ | | _|
\___/|_| |_| |_|_| |_|_| .__/ \___|_| |_|
|_|
-'''
+"""
logging.info(ascii_art)
-
+
def setup_logging(self):
# register a trace level logger
logging.TRACE = logging.DEBUG - 5
@@ -92,16 +102,16 @@ class Omniperf:
setattr(logging, "trace", trace_logger)
# demonstrate override of default loglevel via env variable
- loglevel=logging.INFO
+ loglevel = logging.INFO
if "OMNIPERF_LOGLEVEL" in os.environ.keys():
- loglevel = os.environ['OMNIPERF_LOGLEVEL']
- if loglevel in {"DEBUG","debug"}:
+ loglevel = os.environ["OMNIPERF_LOGLEVEL"]
+ if loglevel in {"DEBUG", "debug"}:
loglevel = logging.DEBUG
- elif loglevel in {"TRACE","trace"}:
+ elif loglevel in {"TRACE", "trace"}:
loglevel = logging.TRACE
- elif loglevel in {"INFO","info"}:
+ elif loglevel in {"INFO", "info"}:
loglevel = logging.INFO
- elif loglevel in {"ERROR","error"}:
+ elif loglevel in {"ERROR", "error"}:
loglevel = logging.ERROR
else:
print("Ignoring unsupported OMNIPERF_LOGLEVEL setting (%s)" % loglevel)
@@ -111,15 +121,21 @@ class Omniperf:
def get_mode(self):
return self.__mode
-
+
def set_version(self):
vData = get_version(config.omniperf_home)
self.__version["ver"] = vData["version"]
- self.__version["ver_pretty"] = get_version_display(vData["version"], vData["sha"], vData["mode"])
+ self.__version["ver_pretty"] = get_version_display(
+ vData["version"], vData["sha"], vData["mode"]
+ )
return
-
+
def detect_profiler(self):
- if self.__args.lucky == True or self.__args.summaries == True or self.__args.use_rocscope:
+ if (
+ self.__args.lucky == True
+ or self.__args.summaries == True
+ or self.__args.use_rocscope
+ ):
if not shutil.which("rocscope"):
logging.error("Rocscope must be in PATH")
sys.exit(1)
@@ -132,10 +148,13 @@ class Omniperf:
elif str(rocprof_cmd).endswith("rocprofv2"):
self.__profiler_mode = "rocprofv2"
else:
- error("Incompatible profiler: %s. Supported profilers include: %s" % (rocprof_cmd, get_submodules('omniperf_profile')))
-
+ error(
+ "Incompatible profiler: %s. Supported profilers include: %s"
+ % (rocprof_cmd, get_submodules("omniperf_profile"))
+ )
return
+
def detect_analyze(self):
if self.__args.gui:
self.__analyze_mode = "web_ui"
@@ -145,8 +164,7 @@ class Omniperf:
@demarcate
def detect_soc(self, sys_info=pd.DataFrame()):
- """Load OmniSoC instance for Omniperf run
- """
+ """Load OmniSoC instance for Omniperf run"""
# in case of analyze mode, we can explicitly specify an arch
# rather than detect from rocminfo
if sys_info.empty:
@@ -163,11 +181,11 @@ class Omniperf:
error("%s is an unsupported SoC" % arch)
else:
self.__soc_name.add(target)
- if hasattr(self.__args, 'target'):
+ if hasattr(self.__args, "target"):
self.__args.target = target
- soc_module = importlib.import_module('omniperf_soc.soc_'+arch)
- soc_class = getattr(soc_module, arch+'_soc')
+ soc_module = importlib.import_module("omniperf_soc.soc_" + arch)
+ soc_class = getattr(soc_module, arch + "_soc")
self.__soc[arch] = soc_class(self.__args)
logging.info("SoC = %s" % self.__soc_name)
@@ -176,14 +194,16 @@ class Omniperf:
@demarcate
def parse_args(self):
parser = argparse.ArgumentParser(
- description="Command line interface for AMD's GPU profiler, Omniperf",
- prog="tool",
- formatter_class=lambda prog: argparse.RawTextHelpFormatter(
+ description="Command line interface for AMD's GPU profiler, Omniperf",
+ prog="tool",
+ formatter_class=lambda prog: argparse.RawTextHelpFormatter(
prog, max_help_position=30
),
usage="omniperf [mode] [options]",
)
- omniarg_parser(parser, config.omniperf_home, self.__supported_archs ,self.__version)
+ omniarg_parser(
+ parser, config.omniperf_home, self.__supported_archs, self.__version
+ )
self.__args = parser.parse_args()
if self.__args.specs:
@@ -202,27 +222,38 @@ class Omniperf:
# Update default path
if self.__args.path == os.path.join(os.getcwd(), "workloads"):
- self.__args.path = os.path.join(self.__args.path, self.__args.name, self.__args.target)
+ self.__args.path = os.path.join(
+ self.__args.path, self.__args.name, self.__args.target
+ )
logging.info("Profiler choice = %s" % self.__profiler_mode)
# instantiate desired profiler
if self.__profiler_mode == "rocprofv1":
from omniperf_profile.profiler_rocprof_v1 import rocprof_v1_profiler
- profiler = rocprof_v1_profiler(self.__args, self.__profiler_mode, self.__soc[targ_arch])
+
+ profiler = rocprof_v1_profiler(
+ self.__args, self.__profiler_mode, self.__soc[targ_arch]
+ )
elif self.__profiler_mode == "rocprofv2":
from omniperf_profile.profiler_rocprof_v2 import rocprof_v2_profiler
- profiler = rocprof_v2_profiler(self.__args, self.__profiler_mode, self.__soc[targ_arch])
+
+ profiler = rocprof_v2_profiler(
+ self.__args, self.__profiler_mode, self.__soc[targ_arch]
+ )
elif self.__profiler_mode == "rocscope":
from omniperf_profile.profiler_rocscope import rocscope_profiler
- profiler = rocscope_profiler(self.__args, self.__profiler_mode, self.__soc[targ_arch])
+
+ profiler = rocscope_profiler(
+ self.__args, self.__profiler_mode, self.__soc[targ_arch]
+ )
else:
logging.error("Unsupported profiler")
sys.exit(1)
- #-----------------------
+ # -----------------------
# run profiling workflow
- #-----------------------
+ # -----------------------
self.__soc[targ_arch].profiling_setup()
profiler.pre_processing()
profiler.run_profiling(self.__version["ver"], config.prog)
@@ -235,17 +266,18 @@ class Omniperf:
def update_db(self):
self.print_graphic()
from utils.db_connector import DatabaseConnector
+
db_connection = DatabaseConnector(self.__args)
-
- #-----------------------
+
+ # -----------------------
# run database workflow
- #-----------------------
+ # -----------------------
db_connection.pre_processing()
if self.__args.upload:
db_connection.db_import()
else:
db_connection.db_remove()
-
+
return
@demarcate
@@ -256,18 +288,20 @@ class Omniperf:
if self.__analyze_mode == "cli":
from omniperf_analyze.analysis_cli import cli_analysis
+
analyzer = cli_analysis(self.__args, self.__supported_archs)
elif self.__analyze_mode == "web_ui":
from omniperf_analyze.analysis_webui import webui_analysis
+
analyzer = webui_analysis(self.__args, self.__supported_archs)
else:
error("Unsupported anlaysis mode -> %s" % self.__analyze_mode)
- #-----------------------
+ # -----------------------
# run analysis workflow
- #-----------------------
+ # -----------------------
analyzer.sanitize()
-
+
# Load required SoC(s) from input
for d in analyzer.get_args().path:
sys_info = pd.read_csv(Path(d[0], "sysinfo.csv"))
@@ -278,4 +312,3 @@ class Omniperf:
analyzer.run_analysis()
return
-
diff --git a/src/omniperf_profile/profiler_base.py b/src/omniperf_profile/profiler_base.py
index 5fbf8ebe16..3915425bca 100644
--- a/src/omniperf_profile/profiler_base.py
+++ b/src/omniperf_profile/profiler_base.py
@@ -28,31 +28,44 @@ import glob
import sys
import os
import re
-from utils.utils import capture_subprocess_output, run_prof, gen_sysinfo, run_rocscope, error, demarcate
+from utils.utils import (
+ capture_subprocess_output,
+ run_prof,
+ gen_sysinfo,
+ run_rocscope,
+ error,
+ demarcate,
+)
import config
import pandas as pd
-class OmniProfiler_Base():
+
+class OmniProfiler_Base:
def __init__(self, args, profiler_mode, soc):
self.__args = args
self.__profiler = profiler_mode
- self._soc = soc # OmniSoC obj
- self.__perfmon_dir = os.path.join(str(config.omniperf_home), "omniperf_soc", "profile_configs")
+ self._soc = soc # OmniSoC obj
+ self.__perfmon_dir = os.path.join(
+ str(config.omniperf_home), "omniperf_soc", "profile_configs"
+ )
def get_args(self):
return self.__args
+
def get_profiler_options(self, fname):
- """Fetch any version specific arguments required by profiler
- """
+ """Fetch any version specific arguments required by profiler"""
# assume no SoC specific options and return empty list by default
return []
-
+
@demarcate
def pmc_perf_split(self):
- """Avoid default rocprof join utility by spliting each line into a separate input file
- """
+ """Avoid default rocprof join utility by spliting each line into a separate input file"""
workload_perfmon_dir = os.path.join(self.__args.path, "perfmon")
- lines = open(os.path.join(workload_perfmon_dir, "pmc_perf.txt"), "r").read().splitlines()
+ lines = (
+ open(os.path.join(workload_perfmon_dir, "pmc_perf.txt"), "r")
+ .read()
+ .splitlines()
+ )
# Iterate over each line in pmc_perf.txt
mpattern = r"^pmc:(.*)"
@@ -83,8 +96,7 @@ class OmniProfiler_Base():
@demarcate
def join_prof(self, out=None):
- """Manually join separated rocprof runs
- """
+ """Manually join separated rocprof runs"""
# Set default output directory if not specified
if type(self.__args.path) == str:
if out is None:
@@ -105,7 +117,11 @@ class OmniProfiler_Base():
elif self.__args.join_type == "grid":
key = _df.groupby(["Kernel_Name", "Grid_Size"]).cumcount()
_df["key"] = (
- _df["Kernel_Name"] + " - " + _df["Grid_Size"].astype(str) + " - " + key.astype(str)
+ _df["Kernel_Name"]
+ + " - "
+ + _df["Grid_Size"].astype(str)
+ + " - "
+ + key.astype(str)
)
else:
print("ERROR: Unrecognized --join-type")
@@ -121,9 +137,15 @@ class OmniProfiler_Base():
duplicate_cols = {
"GPU_ID": [col for col in df.columns if col.startswith("GPU_ID")],
"Grid_Size": [col for col in df.columns if col.startswith("Grid_Size")],
- "Workgroup_Size": [col for col in df.columns if col.startswith("Workgroup_Size")],
- "LDS_Per_Workgroup": [col for col in df.columns if col.startswith("LDS_Per_Workgroup")],
- "Scratch_Per_Workitem": [col for col in df.columns if col.startswith("Scratch_Per_Workitem")],
+ "Workgroup_Size": [
+ col for col in df.columns if col.startswith("Workgroup_Size")
+ ],
+ "LDS_Per_Workgroup": [
+ col for col in df.columns if col.startswith("LDS_Per_Workgroup")
+ ],
+ "Scratch_Per_Workitem": [
+ col for col in df.columns if col.startswith("Scratch_Per_Workitem")
+ ],
"SGPR": [col for col in df.columns if col.startswith("SGPR")],
}
# Check for vgpr counter in ROCm < 5.3
@@ -131,15 +153,17 @@ class OmniProfiler_Base():
duplicate_cols["vgpr"] = [col for col in df.columns if col.startswith("vgpr")]
# Check for vgpr counter in ROCm >= 5.3
else:
- duplicate_cols["Arch_VGPR"] = [col for col in df.columns if col.startswith("Arch_VGPR")]
- duplicate_cols["Accum_VGPR"] = [col for col in df.columns if col.startswith("Accum_VGPR")]
+ duplicate_cols["Arch_VGPR"] = [
+ col for col in df.columns if col.startswith("Arch_VGPR")
+ ]
+ duplicate_cols["Accum_VGPR"] = [
+ col for col in df.columns if col.startswith("Accum_VGPR")
+ ]
for key, cols in duplicate_cols.items():
_df = df[cols]
if not test_df_column_equality(_df):
- msg = (
- "WARNING: Detected differing {} values while joining pmc_perf.csv".format(
- key
- )
+ msg = "WARNING: Detected differing {} values while joining pmc_perf.csv".format(
+ key
)
logging.warning(msg + "\n")
else:
@@ -157,7 +181,7 @@ class OmniProfiler_Base():
if not any(
k.startswith(check)
for check in [
- # rocprofv2 headers
+ # rocprofv2 headers
"GPU_ID_",
"Grid_Size_",
"Workgroup_Size_",
@@ -236,31 +260,42 @@ class OmniProfiler_Base():
else:
return df
- #----------------------------------------------------
+ # ----------------------------------------------------
# Required methods to be implemented by child classes
- #----------------------------------------------------
+ # ----------------------------------------------------
@abstractmethod
def pre_processing(self):
- """Perform any pre-processing steps prior to profiling.
- """
+ """Perform any pre-processing steps prior to profiling."""
logging.debug("[profiling] pre-processing using %s profiler" % self.__profiler)
-
+
# verify soc compatibility
if self.__profiler not in self._soc.get_compatible_profilers():
- error("%s is not enabled in %s. Available profilers include: %s" % (self._soc.get_soc_name(), self.__profiler, self._soc.get_compatible_profilers()))
+ error(
+ "%s is not enabled in %s. Available profilers include: %s"
+ % (
+ self._soc.get_soc_name(),
+ self.__profiler,
+ self._soc.get_compatible_profilers(),
+ )
+ )
# verify not accessing parent directories
if ".." in str(self.__args.path):
error("Access denied. Cannot access parent directories in path (i.e. ../)")
-
+
# verify correct formatting for application binary
self.__args.remaining = self.__args.remaining[1:]
if self.__args.remaining:
if not os.path.isfile(self.__args.remaining[0]):
- error("Your command %s doesn't point to a executable. Please verify." % self.__args.remaining[0])
+ error(
+ "Your command %s doesn't point to a executable. Please verify."
+ % self.__args.remaining[0]
+ )
self.__args.remaining = " ".join(self.__args.remaining)
else:
- error("Profiling command required. Pass application executable after -- at the end of options.\n\t\ti.e. omniperf profile -n vcopy -- ./vcopy 1048576 256")
-
+ error(
+ "Profiling command required. Pass application executable after -- at the end of options.\n\t\ti.e. omniperf profile -n vcopy -- ./vcopy 1048576 256"
+ )
+
# verify name meets MongoDB length requirements and no illegal chars
if len(self.__args.name) > 35:
error("-n/--name exceeds 35 character limit. Try again.")
@@ -268,11 +303,12 @@ class OmniProfiler_Base():
error("'-' and '.' are not permitted in -n/--name")
@abstractmethod
- def run_profiling(self, version:str, prog:str):
- """Run profiling.
- """
- logging.debug("[profiling] performing profiling using %s profiler" % self.__profiler)
-
+ def run_profiling(self, version: str, prog: str):
+ """Run profiling."""
+ logging.debug(
+ "[profiling] performing profiling using %s profiler" % self.__profiler
+ )
+
# log basic info
logging.info(str(prog) + " ver: " + str(version))
logging.info("Path: " + str(os.path.abspath(self.__args.path)))
@@ -283,7 +319,7 @@ class OmniProfiler_Base():
if self.__args.ipblocks == None:
logging.info("IP Blocks: All")
else:
- logging.info("IP Blocks: "+ str(self.__args.ipblocks))
+ logging.info("IP Blocks: " + str(self.__args.ipblocks))
if self.__args.kernel_verbose > 5:
logging.info("KernelName verbose: DISABLED")
else:
@@ -298,7 +334,10 @@ class OmniProfiler_Base():
"sed",
"-i",
"-r",
- "s%^(kernel:).*%" + "kernel: " + ",".join(self.__args.kernel) + "%g",
+ "s%^(kernel:).*%"
+ + "kernel: "
+ + ",".join(self.__args.kernel)
+ + "%g",
fname,
]
)
@@ -315,7 +354,10 @@ class OmniProfiler_Base():
"sed",
"-i",
"-r",
- "s%^(range:).*%" + "range: " + " ".join(self.__args.dispatch) + "%g",
+ "s%^(range:).*%"
+ + "range: "
+ + " ".join(self.__args.dispatch)
+ + "%g",
fname,
]
)
@@ -325,42 +367,44 @@ class OmniProfiler_Base():
else:
logging.debug(output)
logging.info("\nCurrent input file: %s" % fname)
-
+
# Fetch any SoC/profiler specific profiling options
options = self._soc.get_profiler_options()
options += self.get_profiler_options(fname)
if self.__profiler == "rocprofv1" or self.__profiler == "rocprofv2":
run_prof(
- fname=fname,
- # workload_dir=self.get_args().path,
- # perfmon_dir=self.__perfmon_dir,
+ fname=fname,
+ # workload_dir=self.get_args().path,
+ # perfmon_dir=self.__perfmon_dir,
# cmd=self.__args.remaining,
# target=self.__args.target,
profiler_options=options,
target=self.__args.target,
- workload_dir=self.get_args().path
+ workload_dir=self.get_args().path,
)
elif self.__profiler == "rocscope":
run_rocscope(self.__args, fname)
else:
- #TODO: Finish logic
+ # TODO: Finish logic
error("profiler not supported")
@abstractmethod
def post_processing(self):
- """Perform any post-processing steps prior to profiling.
- """
- logging.debug("[profiling] performing post-processing using %s profiler" % self.__profiler)
+ """Perform any post-processing steps prior to profiling."""
+ logging.debug(
+ "[profiling] performing post-processing using %s profiler" % self.__profiler
+ )
gen_sysinfo(
- workload_name=self.__args.name,
- workload_dir=self.get_args().path,
- ip_blocks=self.__args.ipblocks,
- app_cmd=self.__args.remaining,
- skip_roof=self.__args.no_roof,
+ workload_name=self.__args.name,
+ workload_dir=self.get_args().path,
+ ip_blocks=self.__args.ipblocks,
+ app_cmd=self.__args.remaining,
+ skip_roof=self.__args.no_roof,
roof_only=self.__args.roof_only,
)
+
def test_df_column_equality(df):
return df.eq(df.iloc[:, 0], axis=0).all(1).all()
diff --git a/src/omniperf_profile/profiler_rocprof_v1.py b/src/omniperf_profile/profiler_rocprof_v1.py
index dd21fe5e03..bcc40b6a75 100644
--- a/src/omniperf_profile/profiler_rocprof_v1.py
+++ b/src/omniperf_profile/profiler_rocprof_v1.py
@@ -31,39 +31,42 @@ from utils.kernel_name_shortener import kernel_name_shortener
class rocprof_v1_profiler(OmniProfiler_Base):
- def __init__(self,profiling_args,profiler_mode,soc):
- super().__init__(profiling_args,profiler_mode,soc)
- self.ready_to_profile = (self.get_args().roof_only and not os.path.isfile(os.path.join(self.get_args().path, "pmc_perf.csv"))
- or not self.get_args().roof_only)
+ def __init__(self, profiling_args, profiler_mode, soc):
+ super().__init__(profiling_args, profiler_mode, soc)
+ self.ready_to_profile = (
+ self.get_args().roof_only
+ and not os.path.isfile(os.path.join(self.get_args().path, "pmc_perf.csv"))
+ or not self.get_args().roof_only
+ )
def get_profiler_options(self, fname):
fbase = os.path.splitext(os.path.basename(fname))[0]
app_cmd = self.get_args().remaining
args = [
# v1 requires request for timestamps
- "--timestamp", "on",
+ "--timestamp",
+ "on",
# v1 requires csv extension
- "-o", self.get_args().path + "/" + fbase + ".csv",
+ "-o",
+ self.get_args().path + "/" + fbase + ".csv",
# v1 does require quotes on app cmd
'"' + app_cmd + '"',
]
return args
- #-----------------------
+ # -----------------------
# Required child methods
- #-----------------------
+ # -----------------------
@demarcate
def pre_processing(self):
- """Perform any pre-processing steps prior to profiling.
- """
+ """Perform any pre-processing steps prior to profiling."""
super().pre_processing()
if self.ready_to_profile:
self.pmc_perf_split()
@demarcate
- def run_profiling(self, version:str, prog:str):
- """Run profiling.
- """
+ def run_profiling(self, version: str, prog: str):
+ """Run profiling."""
if self.ready_to_profile:
if self.get_args().roof_only:
logging.info("[roofline] Generating pmc_perf.csv")
@@ -71,11 +74,10 @@ class rocprof_v1_profiler(OmniProfiler_Base):
super().run_profiling(version, prog)
else:
logging.info("[roofline] Detected existing pmc_perf.csv")
-
+
@demarcate
def post_processing(self):
- """Perform any post-processing steps prior to profiling.
- """
+ """Perform any post-processing steps prior to profiling."""
super().post_processing()
if self.ready_to_profile:
diff --git a/src/omniperf_profile/profiler_rocprof_v2.py b/src/omniperf_profile/profiler_rocprof_v2.py
index ffd2349116..a833cca82c 100644
--- a/src/omniperf_profile/profiler_rocprof_v2.py
+++ b/src/omniperf_profile/profiler_rocprof_v2.py
@@ -28,39 +28,44 @@ from omniperf_profile.profiler_base import OmniProfiler_Base
from utils.utils import demarcate
from utils.kernel_name_shortener import kernel_name_shortener
+
class rocprof_v2_profiler(OmniProfiler_Base):
- def __init__(self,profiling_args,profiler_mode,soc):
- super().__init__(profiling_args,profiler_mode,soc)
- self.ready_to_profile = (self.get_args().roof_only and not os.path.isfile(os.path.join(self.get_args().path, "pmc_perf.csv"))
- or not self.get_args().roof_only)
+ def __init__(self, profiling_args, profiler_mode, soc):
+ super().__init__(profiling_args, profiler_mode, soc)
+ self.ready_to_profile = (
+ self.get_args().roof_only
+ and not os.path.isfile(os.path.join(self.get_args().path, "pmc_perf.csv"))
+ or not self.get_args().roof_only
+ )
def get_profiler_options(self, fname):
fbase = os.path.splitext(os.path.basename(fname))[0]
app_cmd = self.get_args().remaining
args = [
# v2 requires output directory argument
- "-d", self.get_args().path + "/" + "out",
+ "-d",
+ self.get_args().path + "/" + "out",
# v2 does not require csv extension
- "-o", fbase,
+ "-o",
+ fbase,
# v2 doen not require quotes on cmd
- app_cmd
+ app_cmd,
]
return args
- #-----------------------
+
+ # -----------------------
# Required child methods
- #-----------------------
+ # -----------------------
@demarcate
def pre_processing(self):
- """Perform any pre-processing steps prior to profiling.
- """
+ """Perform any pre-processing steps prior to profiling."""
super().pre_processing()
if self.ready_to_profile:
self.pmc_perf_split()
@demarcate
def run_profiling(self, version, prog):
- """Run profiling.
- """
+ """Run profiling."""
if self.ready_to_profile:
if self.get_args().roof_only:
logging.info("[roofline] Generating pmc_perf.csv")
@@ -70,13 +75,11 @@ class rocprof_v2_profiler(OmniProfiler_Base):
@demarcate
def post_processing(self):
- """Perform any post-processing steps prior to profiling.
- """
+ """Perform any post-processing steps prior to profiling."""
super().post_processing()
if self.ready_to_profile:
- # Pass headers to join on
+ # Pass headers to join on
self.join_prof()
# Demangle and overwrite original KernelNames
kernel_name_shortener(self.get_args().path, self.get_args().kernel_verbose)
-
diff --git a/src/omniperf_profile/profiler_rocscope.py b/src/omniperf_profile/profiler_rocscope.py
index cc5a90a241..fc0121a5a9 100644
--- a/src/omniperf_profile/profiler_rocscope.py
+++ b/src/omniperf_profile/profiler_rocscope.py
@@ -26,26 +26,30 @@ import logging
from omniperf_profile.profiler_base import OmniProfiler_Base
from utils.utils import demarcate
-class rocscope_profiler(OmniProfiler_Base):
- def __init__(self,profiling_args,profiler_mode,soc):
- super().__init__(profiling_args,profiler_mode,soc)
- #-----------------------
+class rocscope_profiler(OmniProfiler_Base):
+ def __init__(self, profiling_args, profiler_mode, soc):
+ super().__init__(profiling_args, profiler_mode, soc)
+
+ # -----------------------
# Required child methods
- #-----------------------
+ # -----------------------
@demarcate
def pre_processing(self):
- """Perform any pre-processing steps prior to profiling.
- """
- self.__profiler="rocscope"
+ """Perform any pre-processing steps prior to profiling."""
+ self.__profiler = "rocscope"
logging.debug("[profiling] pre-processing using %s profiler" % self.__profiler)
+
@demarcate
def run_profiling(self, version, prog):
- """Run profiling.
- """
- logging.debug("[profiling] performing profiling using %s profiler" % self.__profiler)
+ """Run profiling."""
+ logging.debug(
+ "[profiling] performing profiling using %s profiler" % self.__profiler
+ )
+
@demarcate
def post_processing(self):
- """Perform any post-processing steps prior to profiling.
- """
- logging.debug("[profiling] performing post-processing using %s profiler" % self.__profiler)
+ """Perform any post-processing steps prior to profiling."""
+ logging.debug(
+ "[profiling] performing post-processing using %s profiler" % self.__profiler
+ )
diff --git a/src/omniperf_soc/soc_base.py b/src/omniperf_soc/soc_base.py
index 586068a1a6..a684998cc9 100644
--- a/src/omniperf_soc/soc_base.py
+++ b/src/omniperf_soc/soc_base.py
@@ -33,59 +33,74 @@ import numpy as np
from utils.utils import demarcate
from pathlib import Path
-class OmniSoC_Base():
- def __init__(self,args):
+
+class OmniSoC_Base:
+ def __init__(self, args):
self.__args = args
- self.__name = None # SoC name
+ self.__name = None # SoC name
self.__perfmon_dir = None
- self.__perfmon_config = {} # Per IP block max number of simulutaneous counters. GFX IP Blocks
- self.__soc_params = {} # SoC specifications
- self.__compatible_profilers = [] # Store profilers compatible with SoC
+ self.__perfmon_config = (
+ {}
+ ) # Per IP block max number of simulutaneous counters. GFX IP Blocks
+ self.__soc_params = {} # SoC specifications
+ self.__compatible_profilers = [] # Store profilers compatible with SoC
if self.__args.path == os.path.join(os.getcwd(), "workloads"):
- self.__workload_dir = os.path.join(self.__args.path, self.__args.name, self.__args.target)
+ self.__workload_dir = os.path.join(
+ self.__args.path, self.__args.name, self.__args.target
+ )
else:
self.__workload_dir = self.__args.path
-
+
def __hash__(self):
return hash(self.__name)
+
def __eq__(self, other):
if not isinstance(other, type(self)):
return NotImplemented
return self.__name == other.get_soc()
- def set_perfmon_dir(self, path:str):
+ def set_perfmon_dir(self, path: str):
self.__perfmon_dir = path
+
def set_perfmon_config(self, config: dict):
self.__perfmon_config = config
+
def set_soc_param(self, param: dict):
self.__soc_params = param
+
def get_workload_perfmon_dir(self):
return str(Path(self.__perfmon_dir).parent.absolute())
+
def get_soc_param(self):
return self.__soc_params
+
def set_soc_name(self, soc: str):
self.__name = soc
+
def get_soc_name(self):
return self.__name
+
def get_args(self):
return self.__args
+
def set_compatible_profilers(self, profiler_names: list):
self.__compatible_profilers = profiler_names
+
def get_compatible_profilers(self):
return self.__compatible_profilers
-
+
@demarcate
def get_profiler_options(self):
- """Fetch any SoC specific arguments required by the profiler
- """
+ """Fetch any SoC specific arguments required by the profiler"""
# assume no SoC specific options and return empty list by default
return []
-
+
@demarcate
def perfmon_filter(self, roofline_perfmon_only: bool):
- """Filter default performance counter set based on user arguments
- """
- if roofline_perfmon_only and os.path.isfile(os.path.join(self.get_args().path, "pmc_perf.csv")):
+ """Filter default performance counter set based on user arguments"""
+ if roofline_perfmon_only and os.path.isfile(
+ os.path.join(self.get_args().path, "pmc_perf.csv")
+ ):
return
workload_perfmon_dir = self.__workload_dir + "/perfmon"
@@ -99,7 +114,9 @@ class OmniSoC_Base():
if not roofline_perfmon_only:
ref_pmc_files_list = glob.glob(self.__perfmon_dir + "/" + "pmc_*perf*.txt")
- ref_pmc_files_list += glob.glob(self.__perfmon_dir + "/" + self.__name + "/pmc_*_perf*.txt")
+ ref_pmc_files_list += glob.glob(
+ self.__perfmon_dir + "/" + self.__name + "/pmc_*_perf*.txt"
+ )
# Perfmon list filtering
if self.__args.ipblocks != None:
@@ -124,38 +141,34 @@ class OmniSoC_Base():
ref_pmc_files_list = glob.glob(self.__perfmon_dir + "/" + "pmc_roof_perf.txt")
pmc_files_list = ref_pmc_files_list
-
# Coalesce and writeback workload specific perfmon
- pmc_list = perfmon_coalesce(pmc_files_list, self.__perfmon_config, self.__workload_dir)
+ pmc_list = perfmon_coalesce(
+ pmc_files_list, self.__perfmon_config, self.__workload_dir
+ )
perfmon_emit(pmc_list, self.__perfmon_config, self.__workload_dir)
- #----------------------------------------------------
+ # ----------------------------------------------------
# Required methods to be implemented by child classes
- #----------------------------------------------------
+ # ----------------------------------------------------
@abstractmethod
def profiling_setup(self):
- """Perform any SoC-specific setup prior to profiling.
- """
+ """Perform any SoC-specific setup prior to profiling."""
logging.debug("[profiling] perform SoC profiling setup for %s" % self.__name)
-
@abstractmethod
def post_profiling(self):
- """Perform any SoC-specific post profiling activities.
- """
+ """Perform any SoC-specific post profiling activities."""
logging.debug("[profiling] perform SoC post processing for %s" % self.__name)
@abstractmethod
def analysis_setup(self):
- """Perform any SoC-specific setup prior to analysis.
- """
+ """Perform any SoC-specific setup prior to analysis."""
logging.debug("[analysis] perform SoC analysis setup for %s" % self.__name)
-
+
@demarcate
def perfmon_coalesce(pmc_files_list, perfmon_config, workload_dir):
- """Sort and bucket all related performance counters to minimize required application passes
- """
+ """Sort and bucket all related performance counters to minimize required application passes"""
workload_perfmon_dir = workload_dir + "/perfmon"
# match pattern for pmc counters
@@ -216,9 +229,15 @@ def perfmon_coalesce(pmc_files_list, perfmon_config, workload_dir):
return pmc_list
+
@demarcate
def update_pmc_bucket(
- counters, save_file, perfmon_config, pmc_list=None, stext=None, workload_perfmon_dir=None
+ counters,
+ save_file,
+ perfmon_config,
+ pmc_list=None,
+ stext=None,
+ workload_perfmon_dir=None,
):
# Verify inputs.
# If save_file is True, we're being called internally, from perfmon_coalesce
@@ -303,6 +322,7 @@ def update_pmc_bucket(
pmc_list["TCC2"][str(ch)].sort()
return pmc_list
+
@demarcate
def perfmon_emit(pmc_list, perfmon_config, workload_dir=None):
# Calculate the minimum number of iteration to save the pmc counters
@@ -363,13 +383,13 @@ def perfmon_emit(pmc_list, perfmon_config, workload_dir=None):
for iter in range(niter):
# Prefix
line = "pmc: "
-
+
N = perfmon_config["TCC"]
# TCC per-channel counters
tcc_counters = []
for ch in range(perfmon_config["TCC_channels"]):
tcc_counters += pmc_list["TCC2"][str(ch)][tcc2_index * N : tcc2_index * N + N]
-
+
tcc2_index += 1
# TCC2 aggregated counters
@@ -387,4 +407,4 @@ def perfmon_emit(pmc_list, perfmon_config, workload_dir=None):
fd.write("kernel:\n")
fd.close()
else:
- return batches
\ No newline at end of file
+ return batches
diff --git a/src/omniperf_soc/soc_gfx906.py b/src/omniperf_soc/soc_gfx906.py
index 048397425d..d31d4e82bf 100644
--- a/src/omniperf_soc/soc_gfx906.py
+++ b/src/omniperf_soc/soc_gfx906.py
@@ -37,14 +37,22 @@ SOC_PARAM = {
"L2Banks": 16,
"LDSBanks": 32,
"Freq": 1725,
- "mclk": 1000
+ "mclk": 1000,
}
-class gfx906_soc (OmniSoC_Base):
- def __init__(self,args):
+
+class gfx906_soc(OmniSoC_Base):
+ def __init__(self, args):
super().__init__(args)
self.set_soc_name("gfx906")
- self.set_perfmon_dir(os.path.join(str(config.omniperf_home), "omniperf_soc", "profile_configs", self.get_soc_name()))
+ self.set_perfmon_dir(
+ os.path.join(
+ str(config.omniperf_home),
+ "omniperf_soc",
+ "profile_configs",
+ self.get_soc_name(),
+ )
+ )
self.set_compatible_profilers(["rocprofv1", "rocscope"])
# Per IP block max number of simultaneous counters. GFX IP Blocks
self.set_perfmon_config(
@@ -64,13 +72,12 @@ class gfx906_soc (OmniSoC_Base):
)
self.set_soc_param(SOC_PARAM)
- #-----------------------
+ # -----------------------
# Required child methods
- #-----------------------
+ # -----------------------
@demarcate
def profiling_setup(self):
- """Perform any SoC-specific setup prior to profiling.
- """
+ """Perform any SoC-specific setup prior to profiling."""
super().profiling_setup()
if self.get_args().roof_only:
error("%s does not support roofline analysis" % self.get_soc_name())
@@ -79,13 +86,10 @@ class gfx906_soc (OmniSoC_Base):
@demarcate
def post_profiling(self):
- """Perform any SoC-specific post profiling activities.
- """
+ """Perform any SoC-specific post profiling activities."""
super().post_profiling()
@demarcate
def analysis_setup(self):
- """Perform any SoC-specific setup prior to analysis.
- """
+ """Perform any SoC-specific setup prior to analysis."""
super().analysis_setup()
-
diff --git a/src/omniperf_soc/soc_gfx908.py b/src/omniperf_soc/soc_gfx908.py
index d7da55c76c..b80898fb66 100644
--- a/src/omniperf_soc/soc_gfx908.py
+++ b/src/omniperf_soc/soc_gfx908.py
@@ -37,14 +37,22 @@ SOC_PARAM = {
"L2Banks": 32,
"LDSBanks": 32,
"Freq": 1502,
- "mclk": 1200
+ "mclk": 1200,
}
-class gfx908_soc (OmniSoC_Base):
- def __init__(self,args):
+
+class gfx908_soc(OmniSoC_Base):
+ def __init__(self, args):
super().__init__(args)
self.set_soc_name("gfx908")
- self.set_perfmon_dir(os.path.join(str(config.omniperf_home), "omniperf_soc", "profile_configs", self.get_soc_name()))
+ self.set_perfmon_dir(
+ os.path.join(
+ str(config.omniperf_home),
+ "omniperf_soc",
+ "profile_configs",
+ self.get_soc_name(),
+ )
+ )
self.set_compatible_profilers(["rocprofv1", "rocscope"])
# Per IP block max number of simultaneous counters. GFX IP Blocks
self.set_perfmon_config(
@@ -69,13 +77,12 @@ class gfx908_soc (OmniSoC_Base):
# Mi100 requires a custom xml config
return ["-m", self.get_workload_perfmon_dir() + "/" + "metrics.xml"]
- #-----------------------
+ # -----------------------
# Required child methods
- #-----------------------
+ # -----------------------
@demarcate
def profiling_setup(self):
- """Perform any SoC-specific setup prior to profiling.
- """
+ """Perform any SoC-specific setup prior to profiling."""
super().profiling_setup()
if self.get_args().roof_only:
error("%s does not support roofline analysis" % self.get_soc_name())
@@ -84,12 +91,10 @@ class gfx908_soc (OmniSoC_Base):
@demarcate
def post_profiling(self):
- """Perform any SoC-specific post profiling activities.
- """
+ """Perform any SoC-specific post profiling activities."""
super().post_profiling()
@demarcate
def analysis_setup(self):
- """Perform any SoC-specific setup prior to analysis.
- """
- super().analysis_setup()
\ No newline at end of file
+ """Perform any SoC-specific setup prior to analysis."""
+ super().analysis_setup()
diff --git a/src/omniperf_soc/soc_gfx90a.py b/src/omniperf_soc/soc_gfx90a.py
index ea13d9e667..498fb613e6 100644
--- a/src/omniperf_soc/soc_gfx90a.py
+++ b/src/omniperf_soc/soc_gfx90a.py
@@ -39,17 +39,32 @@ SOC_PARAM = {
"L2Banks": 32,
"LDSBanks": 32,
"Freq": 1700,
- "mclk": 1600
+ "mclk": 1600,
}
-class gfx90a_soc (OmniSoC_Base):
- def __init__(self,args):
+
+class gfx90a_soc(OmniSoC_Base):
+ def __init__(self, args):
super().__init__(args)
self.set_soc_name("gfx90a")
- if hasattr(self.get_args(), 'roof_only') and self.get_args().roof_only:
- self.set_perfmon_dir(os.path.join(str(config.omniperf_home), "omniperf_soc", "profile_configs", "roofline"))
+ if hasattr(self.get_args(), "roof_only") and self.get_args().roof_only:
+ self.set_perfmon_dir(
+ os.path.join(
+ str(config.omniperf_home),
+ "omniperf_soc",
+ "profile_configs",
+ "roofline",
+ )
+ )
else:
- self.set_perfmon_dir(os.path.join(str(config.omniperf_home), "omniperf_soc", "profile_configs", self.get_soc_name()))
+ self.set_perfmon_dir(
+ os.path.join(
+ str(config.omniperf_home),
+ "omniperf_soc",
+ "profile_configs",
+ self.get_soc_name(),
+ )
+ )
self.set_compatible_profilers(["rocprofv1", "rocscope"])
# Per IP block max number of simultaneous counters. GFX IP Blocks
self.set_perfmon_config(
@@ -64,46 +79,40 @@ class gfx90a_soc (OmniSoC_Base):
"SPI": 2,
"GRBM": 2,
"GDS": 4,
- "TCC_channels": 32
+ "TCC_channels": 32,
}
)
self.set_soc_param(SOC_PARAM)
self.roofline_obj = Roofline(args)
- #-----------------------
+ # -----------------------
# Required child methods
- #-----------------------
+ # -----------------------
@demarcate
def profiling_setup(self):
- """Perform any SoC-specific setup prior to profiling.
- """
+ """Perform any SoC-specific setup prior to profiling."""
super().profiling_setup()
# Performance counter filtering
self.perfmon_filter(self.get_args().roof_only)
-
@demarcate
def post_profiling(self):
- """Perform any SoC-specific post profiling activities.
- """
+ """Perform any SoC-specific post profiling activities."""
super().post_profiling()
if not self.get_args().no_roof:
- logging.info("[roofline] Checking for roofline.csv in " + str(self.get_args().path))
+ logging.info(
+ "[roofline] Checking for roofline.csv in " + str(self.get_args().path)
+ )
if not os.path.isfile(os.path.join(self.get_args().path, "roofline.csv")):
mibench(self.get_args())
self.roofline_obj.post_processing()
else:
logging.info("[roofline] Skipping roofline")
-
@demarcate
def analysis_setup(self, roofline_parameters=None):
- """Perform any SoC-specific setup prior to analysis.
- """
+ """Perform any SoC-specific setup prior to analysis."""
super().analysis_setup()
# configure roofline for analysis
if roofline_parameters:
self.roofline_obj = Roofline(self.get_args(), roofline_parameters)
-
-
-
diff --git a/src/omniperf_soc/soc_gfx940.py b/src/omniperf_soc/soc_gfx940.py
index 504f14a523..38970a400f 100644
--- a/src/omniperf_soc/soc_gfx940.py
+++ b/src/omniperf_soc/soc_gfx940.py
@@ -39,18 +39,30 @@ SOC_PARAM = {
"L2Banks": 16,
"LDSBanks": 32,
"Freq": 1950,
- "mclk": 1300
+ "mclk": 1300,
}
-class gfx940_soc (OmniSoC_Base):
- def __init__(self,args):
+
+class gfx940_soc(OmniSoC_Base):
+ def __init__(self, args):
super().__init__(args)
self.set_soc_name("gfx940")
- if hasattr(self.get_args(), 'roof_only') and self.get_args().roof_only:
- self.set_perfmon_dir(os.path.join(str(config.omniperf_home), "omniperf_soc", "profile_configs", "roofline"))
+ if hasattr(self.get_args(), "roof_only") and self.get_args().roof_only:
+ self.set_perfmon_dir(
+ os.path.join(
+ str(config.omniperf_home),
+ "omniperf_soc",
+ "profile_configs",
+ "roofline",
+ )
+ )
else:
# NB: We're using generalized Mi300 perfmon configs
- self.set_perfmon_dir(os.path.join(str(config.omniperf_home), "omniperf_soc", "profile_configs", "gfx940"))
+ self.set_perfmon_dir(
+ os.path.join(
+ str(config.omniperf_home), "omniperf_soc", "profile_configs", "gfx940"
+ )
+ )
self.set_compatible_profilers(["rocprofv2"])
# Per IP block max number of simultaneous counters. GFX IP Blocks
self.set_perfmon_config(
@@ -65,28 +77,25 @@ class gfx940_soc (OmniSoC_Base):
"SPI": 2,
"GRBM": 2,
"GDS": 4,
- "TCC_channels": 32
+ "TCC_channels": 32,
}
)
self.set_soc_param(SOC_PARAM)
self.roofline_obj = Roofline(args)
- #-----------------------
+ # -----------------------
# Required child methods
- #-----------------------
+ # -----------------------
@demarcate
def profiling_setup(self):
- """Perform any SoC-specific setup prior to profiling.
- """
+ """Perform any SoC-specific setup prior to profiling."""
super().profiling_setup()
# Performance counter filtering
self.perfmon_filter(self.get_args().roof_only)
-
@demarcate
def post_profiling(self):
- """Perform any SoC-specific post profiling activities.
- """
+ """Perform any SoC-specific post profiling activities."""
super().post_profiling()
logging.info("[roofline] Roofline temporarily disabled in Mi300")
@@ -98,16 +107,11 @@ class gfx940_soc (OmniSoC_Base):
# else:
# logging.info("[roofline] Skipping roofline")
-
@demarcate
def analysis_setup(self, roofline_parameters=None):
- """Perform any SoC-specific setup prior to analysis.
- """
+ """Perform any SoC-specific setup prior to analysis."""
super().analysis_setup()
logging.info("[roofline] Roofline temporarily disabled in Mi300")
# configure roofline for analysis
# if roofline_parameters:
# self.roofline_obj = Roofline(self.get_args(), roofline_parameters)
-
-
-
diff --git a/src/omniperf_soc/soc_gfx941.py b/src/omniperf_soc/soc_gfx941.py
index 6b8865b820..f796a004d9 100644
--- a/src/omniperf_soc/soc_gfx941.py
+++ b/src/omniperf_soc/soc_gfx941.py
@@ -39,18 +39,30 @@ SOC_PARAM = {
"L2Banks": 16,
"LDSBanks": 32,
"Freq": 1950,
- "mclk": 1300
+ "mclk": 1300,
}
-class gfx941_soc (OmniSoC_Base):
- def __init__(self,args):
+
+class gfx941_soc(OmniSoC_Base):
+ def __init__(self, args):
super().__init__(args)
self.set_soc_name("gfx941")
- if hasattr(self.get_args(), 'roof_only') and self.get_args().roof_only:
- self.set_perfmon_dir(os.path.join(str(config.omniperf_home), "omniperf_soc", "profile_configs", "roofline"))
+ if hasattr(self.get_args(), "roof_only") and self.get_args().roof_only:
+ self.set_perfmon_dir(
+ os.path.join(
+ str(config.omniperf_home),
+ "omniperf_soc",
+ "profile_configs",
+ "roofline",
+ )
+ )
else:
# NB: We're using generalized Mi300 perfmon configs
- self.set_perfmon_dir(os.path.join(str(config.omniperf_home), "omniperf_soc", "profile_configs", "gfx940"))
+ self.set_perfmon_dir(
+ os.path.join(
+ str(config.omniperf_home), "omniperf_soc", "profile_configs", "gfx940"
+ )
+ )
self.set_compatible_profilers(["rocprofv2"])
# Per IP block max number of simultaneous counters. GFX IP Blocks
self.set_perfmon_config(
@@ -65,28 +77,25 @@ class gfx941_soc (OmniSoC_Base):
"SPI": 2,
"GRBM": 2,
"GDS": 4,
- "TCC_channels": 32
+ "TCC_channels": 32,
}
)
self.set_soc_param(SOC_PARAM)
self.roofline_obj = Roofline(args)
- #-----------------------
+ # -----------------------
# Required child methods
- #-----------------------
+ # -----------------------
@demarcate
def profiling_setup(self):
- """Perform any SoC-specific setup prior to profiling.
- """
+ """Perform any SoC-specific setup prior to profiling."""
super().profiling_setup()
# Performance counter filtering
self.perfmon_filter(self.get_args().roof_only)
-
@demarcate
def post_profiling(self):
- """Perform any SoC-specific post profiling activities.
- """
+ """Perform any SoC-specific post profiling activities."""
super().post_profiling()
logging.info("[roofline] Roofline temporarily disabled in Mi300")
@@ -98,16 +107,11 @@ class gfx941_soc (OmniSoC_Base):
# else:
# logging.info("[roofline] Skipping roofline")
-
@demarcate
def analysis_setup(self, roofline_parameters=None):
- """Perform any SoC-specific setup prior to analysis.
- """
+ """Perform any SoC-specific setup prior to analysis."""
super().analysis_setup()
logging.info("[roofline] Roofline temporarily disabled in Mi300")
# configure roofline for analysis
# if roofline_parameters:
# self.roofline_obj = Roofline(self.get_args(), roofline_parameters)
-
-
-
diff --git a/src/omniperf_soc/soc_gfx942.py b/src/omniperf_soc/soc_gfx942.py
index 064dd9792d..4135d337ce 100644
--- a/src/omniperf_soc/soc_gfx942.py
+++ b/src/omniperf_soc/soc_gfx942.py
@@ -39,18 +39,30 @@ SOC_PARAM = {
"L2Banks": 16,
"LDSBanks": 32,
"Freq": 1950,
- "mclk": 1300
+ "mclk": 1300,
}
-class gfx942_soc (OmniSoC_Base):
- def __init__(self,args):
+
+class gfx942_soc(OmniSoC_Base):
+ def __init__(self, args):
super().__init__(args)
self.set_soc_name("gfx942")
- if hasattr(self.get_args(), 'roof_only') and self.get_args().roof_only:
- self.set_perfmon_dir(os.path.join(str(config.omniperf_home), "omniperf_soc", "profile_configs", "roofline"))
+ if hasattr(self.get_args(), "roof_only") and self.get_args().roof_only:
+ self.set_perfmon_dir(
+ os.path.join(
+ str(config.omniperf_home),
+ "omniperf_soc",
+ "profile_configs",
+ "roofline",
+ )
+ )
else:
# NB: We're using generalized Mi300 perfmon configs
- self.set_perfmon_dir(os.path.join(str(config.omniperf_home), "omniperf_soc", "profile_configs", "gfx940"))
+ self.set_perfmon_dir(
+ os.path.join(
+ str(config.omniperf_home), "omniperf_soc", "profile_configs", "gfx940"
+ )
+ )
self.set_compatible_profilers(["rocprofv2"])
# Per IP block max number of simultaneous counters. GFX IP Blocks
self.set_perfmon_config(
@@ -65,28 +77,25 @@ class gfx942_soc (OmniSoC_Base):
"SPI": 2,
"GRBM": 2,
"GDS": 4,
- "TCC_channels": 32
+ "TCC_channels": 32,
}
)
self.set_soc_param(SOC_PARAM)
self.roofline_obj = Roofline(args)
- #-----------------------
+ # -----------------------
# Required child methods
- #-----------------------
+ # -----------------------
@demarcate
def profiling_setup(self):
- """Perform any SoC-specific setup prior to profiling.
- """
+ """Perform any SoC-specific setup prior to profiling."""
super().profiling_setup()
# Performance counter filtering
self.perfmon_filter(self.get_args().roof_only)
-
@demarcate
def post_profiling(self):
- """Perform any SoC-specific post profiling activities.
- """
+ """Perform any SoC-specific post profiling activities."""
super().post_profiling()
logging.info("[roofline] Roofline temporarily disabled in Mi300")
@@ -98,16 +107,11 @@ class gfx942_soc (OmniSoC_Base):
# else:
# logging.info("[roofline] Skipping roofline")
-
@demarcate
def analysis_setup(self, roofline_parameters=None):
- """Perform any SoC-specific setup prior to analysis.
- """
+ """Perform any SoC-specific setup prior to analysis."""
super().analysis_setup()
logging.info("[roofline] Roofline temporarily disabled in Mi300")
# configure roofline for analysis
# if roofline_parameters:
# self.roofline_obj = Roofline(self.get_args(), roofline_parameters)
-
-
-
diff --git a/src/roofline.py b/src/roofline.py
index 051bf51ed9..eebda645bf 100644
--- a/src/roofline.py
+++ b/src/roofline.py
@@ -36,69 +36,73 @@ import numpy as np
SYMBOLS = [0, 1, 2, 3, 4, 5, 13, 17, 18, 20]
+
class Roofline:
def __init__(self, args, run_parameters=None):
self.__args = args
- self.__run_parameters = run_parameters if run_parameters else {
- 'path_to_dir': self.__args.path,
- 'device_id': 0,
- 'sort_type': 'kernels',
- 'mem_level': 'ALL',
- 'include_kernel_names': False,
- 'is_standalone': False
- }
+ self.__run_parameters = (
+ run_parameters
+ if run_parameters
+ else {
+ "path_to_dir": self.__args.path,
+ "device_id": 0,
+ "sort_type": "kernels",
+ "mem_level": "ALL",
+ "include_kernel_names": False,
+ "is_standalone": False,
+ }
+ )
self.__ai_data = None
self.__ceiling_data = None
self.__figure = go.Figure()
- if not isinstance(self.__run_parameters['path_to_dir'], list):
+ if not isinstance(self.__run_parameters["path_to_dir"], list):
self.roof_setup()
# Set roofline run parameters from args
- if hasattr(self.__args, 'roof_only') and self.__args.roof_only == True:
- self.__run_parameters['is_standalone'] = True
- if hasattr(self.__args, 'kernel_names') and self.__args.kernel_names == True:
- self.__run_parameters['include_kernel_names'] = True
- if hasattr(self.__args, 'mem_level') and self.__args.mem_level != "ALL":
- self.__run_parameters['mem_level'] = self.__args.mem_level
- if hasattr(self.__args, 'sort') and self.__args.sort != "ALL":
- self.__run_parameters['sort_type'] = self.__args.sort
+ if hasattr(self.__args, "roof_only") and self.__args.roof_only == True:
+ self.__run_parameters["is_standalone"] = True
+ if hasattr(self.__args, "kernel_names") and self.__args.kernel_names == True:
+ self.__run_parameters["include_kernel_names"] = True
+ if hasattr(self.__args, "mem_level") and self.__args.mem_level != "ALL":
+ self.__run_parameters["mem_level"] = self.__args.mem_level
+ if hasattr(self.__args, "sort") and self.__args.sort != "ALL":
+ self.__run_parameters["sort_type"] = self.__args.sort
self.validate_parameters()
def validate_parameters(self):
- if self.__run_parameters['include_kernel_names'] and (not self.__run_parameters['is_standalone']):
+ if self.__run_parameters["include_kernel_names"] and (
+ not self.__run_parameters["is_standalone"]
+ ):
error("--roof-only is required for --kernel-names")
def roof_setup(self):
# set default workload path if not specified
- if self.__run_parameters['path_to_dir'] == os.path.join(os.getcwd(), 'workloads'):
- self.__run_parameters['path_to_dir'] = os.path.join(self.__run_parameters['path_to_dir'], self.__args.name, self.__args.target)
+ if self.__run_parameters["path_to_dir"] == os.path.join(os.getcwd(), "workloads"):
+ self.__run_parameters["path_to_dir"] = os.path.join(
+ self.__run_parameters["path_to_dir"], self.__args.name, self.__args.target
+ )
# create new directory for roofline if it doesn't exist
- if not os.path.isdir(self.__run_parameters['path_to_dir']):
- os.makedirs(self.__run_parameters['path_to_dir'])
+ if not os.path.isdir(self.__run_parameters["path_to_dir"]):
+ os.makedirs(self.__run_parameters["path_to_dir"])
@demarcate
def empirical_roofline(
self,
ret_df,
):
- """Generate a set of empirical roofline plots given a directory containing required profiling and benchmarking data
- """
+ """Generate a set of empirical roofline plots given a directory containing required profiling and benchmarking data"""
# Create arithmetic intensity data that will populate the roofline model
- logging.debug("[roofline] Path: %s" % self.__run_parameters['path_to_dir'])
- self.__ai_data = calc_ai(self.__run_parameters['sort_type'], ret_df)
-
+ logging.debug("[roofline] Path: %s" % self.__run_parameters["path_to_dir"])
+ self.__ai_data = calc_ai(self.__run_parameters["sort_type"], ret_df)
+
logging.debug("[roofline] AI at each mem level:")
for i in self.__ai_data:
logging.debug("%s -> %s" % (i, self.__ai_data[i]))
logging.debug("\n")
# Generate a roofline figure for each data type
- fp32_fig = self.generate_plot(
- dtype="FP32"
- )
- fp16_fig = self.generate_plot(
- dtype="FP16"
- )
+ fp32_fig = self.generate_plot(dtype="FP32")
+ fp16_fig = self.generate_plot(dtype="FP16")
ml_combo_fig = self.generate_plot(
dtype="I8",
fig=fp16_fig,
@@ -125,24 +129,36 @@ class Roofline:
self.__figure.update_xaxes(dtick=1)
# Output will be different depending on interaction type:
# Save PDFs if we're in "standalone roofline" mode, otherwise return HTML to be used in GUI output
- if self.__run_parameters['is_standalone']:
- dev_id = str(self.__run_parameters['device_id'])
+ if self.__run_parameters["is_standalone"]:
+ dev_id = str(self.__run_parameters["device_id"])
- fp32_fig.write_image(self.__run_parameters['path_to_dir'] + "/empirRoof_gpu-{}_fp32.pdf".format(dev_id))
+ fp32_fig.write_image(
+ self.__run_parameters["path_to_dir"]
+ + "/empirRoof_gpu-{}_fp32.pdf".format(dev_id)
+ )
ml_combo_fig.write_image(
- self.__run_parameters['path_to_dir'] + "/empirRoof_gpu-{}_int8_fp16.pdf".format(dev_id)
+ self.__run_parameters["path_to_dir"]
+ + "/empirRoof_gpu-{}_int8_fp16.pdf".format(dev_id)
)
# only save a legend if kernel_names option is toggled
- if self.__run_parameters['include_kernel_names']:
- self.__figure.write_image(self.__run_parameters['path_to_dir'] + "/kernelName_legend.pdf")
+ if self.__run_parameters["include_kernel_names"]:
+ self.__figure.write_image(
+ self.__run_parameters["path_to_dir"] + "/kernelName_legend.pdf"
+ )
time.sleep(1)
# Re-save to remove loading MathJax pop up
- fp32_fig.write_image(self.__run_parameters['path_to_dir'] + "/empirRoof_gpu-{}_fp32.pdf".format(dev_id))
- ml_combo_fig.write_image(
- self.__run_parameters['path_to_dir'] + "/empirRoof_gpu-{}_int8_fp16.pdf".format(dev_id)
+ fp32_fig.write_image(
+ self.__run_parameters["path_to_dir"]
+ + "/empirRoof_gpu-{}_fp32.pdf".format(dev_id)
)
- if self.__run_parameters['include_kernel_names']:
- self.__figure.write_image(self.__run_parameters['path_to_dir'] + "/kernelName_legend.pdf")
+ ml_combo_fig.write_image(
+ self.__run_parameters["path_to_dir"]
+ + "/empirRoof_gpu-{}_int8_fp16.pdf".format(dev_id)
+ )
+ if self.__run_parameters["include_kernel_names"]:
+ self.__figure.write_image(
+ self.__run_parameters["path_to_dir"] + "/kernelName_legend.pdf"
+ )
logging.info("[roofline] Empirical Roofline PDFs saved!")
else:
return html.Section(
@@ -173,17 +189,13 @@ class Roofline:
)
],
)
-
-
+
@demarcate
- def generate_plot(
- self, dtype, fig=None
- ) -> go.Figure():
- """Create graph object from ai_data (coordinate points) and ceiling_data (peak FLOP and BW) data.
- """
+ def generate_plot(self, dtype, fig=None) -> go.Figure():
+ """Create graph object from ai_data (coordinate points) and ceiling_data (peak FLOP and BW) data."""
if fig is None:
fig = go.Figure()
- plot_mode = "lines+text" if self.__run_parameters['is_standalone'] else "lines"
+ plot_mode = "lines+text" if self.__run_parameters["is_standalone"] else "lines"
self.__ceiling_data = constuct_roof(
roofline_parameters=self.__run_parameters,
dtype=dtype,
@@ -193,10 +205,10 @@ class Roofline:
#######################
# Plot ceilings
#######################
- if self.__run_parameters['mem_level'] == "ALL":
+ if self.__run_parameters["mem_level"] == "ALL":
cache_hierarchy = ["HBM", "L2", "L1", "LDS"]
else:
- cache_hierarchy = self.__run_parameters['mem_level']
+ cache_hierarchy = self.__run_parameters["mem_level"]
# Plot peak BW ceiling(s)
for cache_level in cache_hierarchy:
@@ -208,10 +220,14 @@ class Roofline:
mode=plot_mode,
hovertemplate="%{text}",
text=[
- "{} GB/s".format(to_int(self.__ceiling_data[cache_level.lower()][2])),
+ "{} GB/s".format(
+ to_int(self.__ceiling_data[cache_level.lower()][2])
+ ),
None
- if self.__run_parameters['is_standalone']
- else "{} GB/s".format(to_int(self.__ceiling_data[cache_level.lower()][2])),
+ if self.__run_parameters["is_standalone"]
+ else "{} GB/s".format(
+ to_int(self.__ceiling_data[cache_level.lower()][2])
+ ),
],
textposition="top right",
)
@@ -228,7 +244,7 @@ class Roofline:
hovertemplate="%{text}",
text=[
None
- if self.__run_parameters['is_standalone']
+ if self.__run_parameters["is_standalone"]
else "{} GFLOP/s".format(to_int(self.__ceiling_data["valu"][2])),
"{} GFLOP/s".format(to_int(self.__ceiling_data["valu"][2])),
],
@@ -250,7 +266,7 @@ class Roofline:
hovertemplate="%{text}",
text=[
None
- if self.__run_parameters['is_standalone']
+ if self.__run_parameters["is_standalone"]
else "{} GFLOP/s".format(to_int(self.__ceiling_data["mfma"][2])),
"{} GFLOP/s".format(to_int(self.__ceiling_data["mfma"][2])),
],
@@ -269,7 +285,9 @@ class Roofline:
name="ai_l1",
mode="markers",
marker={"color": "#00CC96"},
- marker_symbol=SYMBOLS if self.__run_parameters['include_kernel_names'] else None,
+ marker_symbol=SYMBOLS
+ if self.__run_parameters["include_kernel_names"]
+ else None,
)
)
fig.add_trace(
@@ -279,7 +297,9 @@ class Roofline:
name="ai_l2",
mode="markers",
marker={"color": "#EF553B"},
- marker_symbol=SYMBOLS if self.__run_parameters['include_kernel_names'] else None,
+ marker_symbol=SYMBOLS
+ if self.__run_parameters["include_kernel_names"]
+ else None,
)
)
fig.add_trace(
@@ -289,7 +309,9 @@ class Roofline:
name="ai_hbm",
mode="markers",
marker={"color": "#636EFA"},
- marker_symbol=SYMBOLS if self.__run_parameters['include_kernel_names'] else None,
+ marker_symbol=SYMBOLS
+ if self.__run_parameters["include_kernel_names"]
+ else None,
)
)
@@ -311,78 +333,78 @@ class Roofline:
from collections import OrderedDict
# Change vL1D to a interpretable str, if required
- if "vL1D" in self.__run_parameters['mem_level']:
- self.__run_parameters['mem_level'].remove("vL1D")
- self.__run_parameters['mem_level'].append("L1")
+ if "vL1D" in self.__run_parameters["mem_level"]:
+ self.__run_parameters["mem_level"].remove("vL1D")
+ self.__run_parameters["mem_level"].append("L1")
- app_path = os.path.join(self.__run_parameters['path_to_dir'], "pmc_perf.csv")
+ app_path = os.path.join(self.__run_parameters["path_to_dir"], "pmc_perf.csv")
roofline_exists = os.path.isfile(app_path)
if not roofline_exists:
logging.error("[roofline] Error: {} does not exist".format(app_path))
sys.exit(1)
t_df = OrderedDict()
t_df["pmc_perf"] = pd.read_csv(app_path)
- self.empirical_roofline(
- ret_df=t_df
- )
+ self.empirical_roofline(ret_df=t_df)
# Main methods
@abstractmethod
def pre_processing(self):
if self.__args.roof_only:
# check for sysinfo
- logging.info("[roofline] Checking for sysinfo.csv in " + str(self.__args.path))
+ logging.info(
+ "[roofline] Checking for sysinfo.csv in " + str(self.__args.path)
+ )
sysinfo_path = os.path.join(self.__args.path, "sysinfo.csv")
if not os.path.isfile(sysinfo_path):
logging.info("[roofline] sysinfo.csv not found. Generating...")
gen_sysinfo(
- workload_name=self.__args.name,
- workload_dir=self.__workload_dir,
- ip_blocks=self.__args.ipblocks,
- app_cmd=self.__args.remaining,
- skip_roof=self.__args.no_roof,
- roof_only=self.__args.roof_only
+ workload_name=self.__args.name,
+ workload_dir=self.__workload_dir,
+ ip_blocks=self.__args.ipblocks,
+ app_cmd=self.__args.remaining,
+ skip_roof=self.__args.no_roof,
+ roof_only=self.__args.roof_only,
)
@abstractmethod
def profile(self):
if self.__args.roof_only:
# check for roofline benchmark
- logging.info("[roofline] Checking for roofline.csv in " + str(self.__args.path))
+ logging.info(
+ "[roofline] Checking for roofline.csv in " + str(self.__args.path)
+ )
roof_path = os.path.join(self.__args.path, "roofline.csv")
if not os.path.isfile(roof_path):
mibench(self.__args)
# check for profiling data
- logging.info("[roofline] Checking for pmc_perf.csv in " + str(self.__args.path))
+ logging.info(
+ "[roofline] Checking for pmc_perf.csv in " + str(self.__args.path)
+ )
app_path = os.path.join(self.__args.path, "pmc_perf.csv")
if not os.path.isfile(app_path):
logging.info("[roofline] pmc_perf.csv not found. Generating...")
if not self.__args.remaining:
- error("An is required to run.\nomniperf profile -n test -- ")
- #TODO: Add an equivelent of characterize_app() to run profiling directly out of this module
-
+ error(
+ "An is required to run.\nomniperf profile -n test -- "
+ )
+ # TODO: Add an equivelent of characterize_app() to run profiling directly out of this module
+
elif self.__args.no_roof:
logging.info("[roofline] Skipping roofline.")
else:
mibench(self.__args)
- #NB: Currently the post_prossesing() method is the only one being used by omniperf,
- # we include pre_processing() and profile() methods for those who wish to borrow the roofline module
+ # NB: Currently the post_prossesing() method is the only one being used by omniperf,
+ # we include pre_processing() and profile() methods for those who wish to borrow the roofline module
@abstractmethod
def post_processing(self):
- if self.__run_parameters['is_standalone']:
+ if self.__run_parameters["is_standalone"]:
self.standalone_roofline()
-
def to_int(a):
if str(type(a)) == "":
return np.nan
else:
return int(a)
-
-
-
-
-
diff --git a/src/utils/db_connector.py b/src/utils/db_connector.py
index bf013164d8..e8b4e70ada 100644
--- a/src/utils/db_connector.py
+++ b/src/utils/db_connector.py
@@ -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.")
-
-
-
\ No newline at end of file
diff --git a/src/utils/file_io.py b/src/utils/file_io.py
index 1059bc433d..5c54874a6f 100644
--- a/src/utils/file_io.py
+++ b/src/utils/file_io.py
@@ -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)
\ No newline at end of file
+ sys.exit(1)
diff --git a/src/utils/gui.py b/src/utils/gui.py
index d3e2b11c63..bc1b3d8e96 100644
--- a/src/utils/gui.py
+++ b/src/utils/gui.py
@@ -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)
\ No newline at end of file
+ # print(d_t.columns)
diff --git a/src/utils/gui_components/memchart.py b/src/utils/gui_components/memchart.py
index e8f553169c..cdc655340a 100644
--- a/src/utils/gui_components/memchart.py
+++ b/src/utils/gui_components/memchart.py
@@ -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",
diff --git a/src/utils/kernel_name_shortener.py b/src/utils/kernel_name_shortener.py
index 9f07c35943..820330d1c2 100644
--- a/src/utils/kernel_name_shortener.py
+++ b/src/utils/kernel_name_shortener.py
@@ -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.")
\ No newline at end of file
+ logging.info("[profiling] Kernel_Name shortening complete.")
diff --git a/src/utils/mem_chart.py b/src/utils/mem_chart.py
index 686f45e25a..8a4dcf1f86 100644
--- a/src/utils/mem_chart.py
+++ b/src/utils/mem_chart.py
@@ -1039,4 +1039,4 @@ if __name__ == "__main__":
arch = ""
normal_unit = "per_kernel"
- print(plot_mem_chart(arch, normal_unit, metric_dict))
\ No newline at end of file
+ print(plot_mem_chart(arch, normal_unit, metric_dict))
diff --git a/src/utils/parser.py b/src/utils/parser.py
index 23f5024068..1654156580 100644
--- a/src/utils/parser.py
+++ b/src/utils/parser.py
@@ -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
-
-
diff --git a/src/utils/roofline_calc.py b/src/utils/roofline_calc.py
index a1cc8a9b0a..2c3cf44def 100644
--- a/src/utils/roofline_calc.py
+++ b/src/utils/roofline_calc.py
@@ -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]
diff --git a/src/utils/specs.py b/src/utils/specs.py
index 8e26f7fe25..f89c54726a 100644
--- a/src/utils/specs.py
+++ b/src/utils/specs.py
@@ -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,
diff --git a/src/utils/tty.py b/src/utils/tty.py
index 19b49a9821..4870ef7e60 100644
--- a/src/utils/tty.py
+++ b/src/utils/tty.py
@@ -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,
)
-
diff --git a/tests/test_profile_general.py b/tests/test_profile_general.py
index cb9aa1cd20..fc71c80128 100644
--- a/tests/test_profile_general.py
+++ b/tests/test_profile_general.py
@@ -358,7 +358,10 @@ def baseline_compare_metric(test_name, workload_dir, args=[]):
)
isValid = (
- (abs(absolute_diff) <= METRIC_THRESHOLDS[metric_idx]["absolute"])
+ (
+ abs(absolute_diff)
+ <= METRIC_THRESHOLDS[metric_idx]["absolute"]
+ )
if (threshold_type == "absolute")
else (
abs(relative_diff)