Reorganize the specs module to reduce duplicate code
Signed-off-by: colramos-amd <colramos@amd.com>
[ROCm/rocprofiler-compute commit: 3b1b8d7b5b]
Этот коммит содержится в:
коммит произвёл
Cole Ramos
родитель
f240822ea1
Коммит
5352eafde4
@@ -90,6 +90,7 @@ def omniarg_parser(parser, omniperf_home, supported_archs, omniperf_version):
|
||||
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.")
|
||||
|
||||
profile_group.add_argument(
|
||||
"-n",
|
||||
|
||||
@@ -135,7 +135,7 @@ class OmniAnalyze_Base:
|
||||
# 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"]
|
||||
arch = sys_info.iloc[0]["arch"]
|
||||
args = self.__args
|
||||
self.generate_configs(
|
||||
arch,
|
||||
@@ -155,10 +155,9 @@ class OmniAnalyze_Base:
|
||||
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"]
|
||||
arch = w.sys_info.iloc[0]["arch"]
|
||||
w.dfs = copy.deepcopy(self._arch_configs[arch].dfs)
|
||||
w.dfs_type = self._arch_configs[arch].dfs_type
|
||||
w.soc_spec = self.get_socs()[arch].get_soc_param()
|
||||
self._runs[d[0]] = w
|
||||
|
||||
return self._runs
|
||||
|
||||
@@ -70,17 +70,13 @@ class cli_analysis(OmniAnalyze_Base):
|
||||
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]["arch"]],
|
||||
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]["arch"]],
|
||||
self._output
|
||||
)
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
##############################################################################el
|
||||
|
||||
from omniperf_analyze.analysis_base import OmniAnalyze_Base
|
||||
from utils.utils import demarcate
|
||||
from utils.utils import demarcate, error
|
||||
from utils import file_io, parser
|
||||
from utils.gui import build_bar_chart, build_table_chart
|
||||
|
||||
@@ -163,12 +163,12 @@ class webui_analysis(OmniAnalyze_Base):
|
||||
# update roofline for visualization in GUI
|
||||
self.get_socs()[self.arch].analysis_setup(
|
||||
roofline_parameters={
|
||||
"path_to_dir": self.dest_dir,
|
||||
"device_id": 0,
|
||||
"sort_type": "kernels",
|
||||
"mem_level": "ALL",
|
||||
"include_kernel_names": False,
|
||||
"is_standalone": False,
|
||||
'workload_dir': self.dest_dir,
|
||||
'device_id': 0,
|
||||
'sort_type': 'kernels',
|
||||
'mem_level': 'ALL',
|
||||
'include_kernel_names': False,
|
||||
'is_standalone': False
|
||||
}
|
||||
)
|
||||
roof_obj = self.get_socs()[self.arch].roofline_obj
|
||||
@@ -284,12 +284,10 @@ class webui_analysis(OmniAnalyze_Base):
|
||||
# create the loaded kernel stats
|
||||
parser.load_kernel_top(self._runs[self.dest_dir], self.dest_dir)
|
||||
# set architecture
|
||||
self.arch = self._runs[self.dest_dir].sys_info.iloc[0]["gpu_soc"]
|
||||
|
||||
self.arch = self._runs[self.dest_dir].sys_info.iloc[0]['GPU']
|
||||
|
||||
else:
|
||||
self.error(
|
||||
"Multiple runs not yet supported in GUI. Retry without --gui flag."
|
||||
)
|
||||
error("Multiple runs not yet supported in GUI. Retry without --gui flag.")
|
||||
|
||||
@demarcate
|
||||
def run_analysis(self):
|
||||
@@ -308,6 +306,7 @@ class webui_analysis(OmniAnalyze_Base):
|
||||
input_filters,
|
||||
self._arch_configs[self.arch],
|
||||
)
|
||||
# Here I expect that self._runs[<path>].raw_pmc will no longer be populated
|
||||
if args.random_port:
|
||||
self.app.run_server(
|
||||
debug=False, host="0.0.0.0", port=random.randint(1024, 49151)
|
||||
|
||||
@@ -28,16 +28,8 @@ import sys
|
||||
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.specs import MachineSpecs
|
||||
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
|
||||
@@ -68,6 +60,7 @@ class Omniperf:
|
||||
}
|
||||
self.__options = {}
|
||||
self.__supported_archs = SUPPORTED_ARCHS
|
||||
self.__mspec: MachineSpecs = None # to be initalized in load_soc_specs()
|
||||
|
||||
self.setup_logging()
|
||||
self.set_version()
|
||||
@@ -163,33 +156,22 @@ class Omniperf:
|
||||
return
|
||||
|
||||
@demarcate
|
||||
def detect_soc(self, sys_info=pd.DataFrame()):
|
||||
"""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:
|
||||
mspec = get_machine_specs(0)
|
||||
arch = mspec.arch
|
||||
target = mspec.GPU
|
||||
else:
|
||||
arch = sys_info.iloc[0]["gpu_soc"]
|
||||
target = sys_info.iloc[0]["name"]
|
||||
def load_soc_specs(self, sysinfo=None):
|
||||
"""Load OmniSoC instance for Omniperf run
|
||||
"""
|
||||
if not sysinfo is None:
|
||||
self.__mspec = MachineSpecs(self.__args, sysinfo)
|
||||
|
||||
# instantiate underlying SoC support class
|
||||
# in case of analyze mode, __soc can accommodate multiple archs
|
||||
arch = self.__mspec.arch
|
||||
|
||||
# NB: This checker is a bit redundent. We already check this in specs module
|
||||
if arch not in self.__supported_archs.keys():
|
||||
error("%s is an unsupported SoC" % arch)
|
||||
else:
|
||||
self.__soc_name.add(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")
|
||||
self.__soc[arch] = soc_class(self.__args)
|
||||
|
||||
logging.info("SoC = %s" % self.__soc_name)
|
||||
return arch
|
||||
soc_module = importlib.import_module('omniperf_soc.soc_'+arch)
|
||||
soc_class = getattr(soc_module, arch+'_soc')
|
||||
self.__soc[arch] = soc_class(self.__args, self.__mspec)
|
||||
return
|
||||
|
||||
@demarcate
|
||||
def parse_args(self):
|
||||
@@ -207,7 +189,7 @@ class Omniperf:
|
||||
self.__args = parser.parse_args()
|
||||
|
||||
if self.__args.specs:
|
||||
print(get_machine_specs(0))
|
||||
print(MachineSpecs(self.__args))
|
||||
sys.exit(0)
|
||||
if self.__args.mode == None:
|
||||
parser.print_help(sys.stderr)
|
||||
@@ -218,47 +200,36 @@ class Omniperf:
|
||||
@demarcate
|
||||
def run_profiler(self):
|
||||
self.print_graphic()
|
||||
targ_arch = self.detect_soc()
|
||||
self.load_soc_specs()
|
||||
|
||||
# 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.__mspec.GPU)
|
||||
|
||||
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[self.__mspec.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[self.__mspec.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[self.__mspec.arch])
|
||||
else:
|
||||
logging.error("Unsupported profiler")
|
||||
sys.exit(1)
|
||||
|
||||
# -----------------------
|
||||
# run profiling workflow
|
||||
# -----------------------
|
||||
self.__soc[targ_arch].profiling_setup()
|
||||
#-----------------------
|
||||
self.__soc[self.__mspec.arch].profiling_setup()
|
||||
profiler.pre_processing()
|
||||
profiler.run_profiling(self.__version["ver"], config.prog)
|
||||
profiler.post_processing()
|
||||
self.__soc[targ_arch].post_profiling()
|
||||
self.__soc[self.__mspec.arch].post_profiling()
|
||||
|
||||
return
|
||||
|
||||
@@ -305,7 +276,7 @@ class Omniperf:
|
||||
# Load required SoC(s) from input
|
||||
for d in analyzer.get_args().path:
|
||||
sys_info = pd.read_csv(Path(d[0], "sysinfo.csv"))
|
||||
self.detect_soc(sys_info)
|
||||
self.load_soc_specs(sys_info)
|
||||
|
||||
analyzer.set_soc(self.__soc)
|
||||
analyzer.pre_processing()
|
||||
|
||||
@@ -312,7 +312,7 @@ class OmniProfiler_Base:
|
||||
# log basic info
|
||||
logging.info(str(prog) + " ver: " + str(version))
|
||||
logging.info("Path: " + str(os.path.abspath(self.__args.path)))
|
||||
logging.info("Target: " + str(self.__args.target))
|
||||
logging.info("Target: " + str(self._soc._mspec.GPU))
|
||||
logging.info("Command: " + str(self.__args.remaining))
|
||||
logging.info("Kernel Selection: " + str(self.__args.kernel))
|
||||
logging.info("Dispatch Selection: " + str(self.__args.dispatch))
|
||||
@@ -374,14 +374,10 @@ class OmniProfiler_Base:
|
||||
|
||||
if self.__profiler == "rocprofv1" or self.__profiler == "rocprofv2":
|
||||
run_prof(
|
||||
fname=fname,
|
||||
# workload_dir=self.get_args().path,
|
||||
# perfmon_dir=self.__perfmon_dir,
|
||||
# cmd=self.__args.remaining,
|
||||
# target=self.__args.target,
|
||||
fname=fname,
|
||||
profiler_options=options,
|
||||
target=self.__args.target,
|
||||
workload_dir=self.get_args().path,
|
||||
mspec=self._soc._mspec,
|
||||
)
|
||||
|
||||
elif self.__profiler == "rocscope":
|
||||
@@ -403,6 +399,7 @@ class OmniProfiler_Base:
|
||||
app_cmd=self.__args.remaining,
|
||||
skip_roof=self.__args.no_roof,
|
||||
roof_only=self.__args.roof_only,
|
||||
mspec=self._soc._mspec,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -33,53 +33,46 @@ import numpy as np
|
||||
from utils.utils import demarcate
|
||||
from pathlib import Path
|
||||
|
||||
from omniperf_base import SUPPORTED_ARCHS
|
||||
|
||||
class OmniSoC_Base:
|
||||
def __init__(self, args):
|
||||
class OmniSoC_Base():
|
||||
def __init__(self,args,mspec): # new info field will contain rocminfo or sysinfo to populate properties
|
||||
self.__args = args
|
||||
self.__name = None # SoC name
|
||||
self.__arch = None
|
||||
self._mspec = mspec
|
||||
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
|
||||
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
|
||||
)
|
||||
else:
|
||||
self.__workload_dir = self.__args.path
|
||||
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.populate_mspec()
|
||||
# In some cases (i.e. --specs) path will not be given
|
||||
if hasattr(self.__args, "path"):
|
||||
if self.__args.path == os.path.join(os.getcwd(), "workloads"):
|
||||
self.__workload_dir = os.path.join(self.__args.path, self.__args.name, self._mspec.GPU)
|
||||
else:
|
||||
self.__workload_dir = self.__args.path
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.__name)
|
||||
|
||||
return hash(self.__arch)
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, type(self)):
|
||||
return NotImplemented
|
||||
return self.__name == other.get_soc()
|
||||
return self.__arch == other.get_soc()
|
||||
|
||||
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 set_arch(self, arch: str):
|
||||
self.__arch = arch
|
||||
def get_arch(self):
|
||||
return self.__arch
|
||||
def get_args(self):
|
||||
return self.__args
|
||||
|
||||
@@ -95,6 +88,83 @@ class OmniSoC_Base:
|
||||
# assume no SoC specific options and return empty list by default
|
||||
return []
|
||||
|
||||
@demarcate
|
||||
def populate_mspec(self):
|
||||
from utils.specs import search, run
|
||||
|
||||
if not hasattr(self._mspec, "_rocminfo"):
|
||||
return
|
||||
|
||||
# load stats from rocminfo
|
||||
self._mspec.L1 = ""
|
||||
self._mspec.L2 = ""
|
||||
for idx2, linetext in enumerate(self._mspec._rocminfo):
|
||||
key = search(r"^\s*L1:\s+ ([a-zA-Z0-9]+)\s*", linetext)
|
||||
if key != None:
|
||||
self._mspec.L1 = key
|
||||
continue
|
||||
|
||||
key = search(r"^\s*L2:\s+ ([a-zA-Z0-9]+)\s*", linetext)
|
||||
if key != None:
|
||||
self._mspec.L2 = key
|
||||
continue
|
||||
|
||||
key = search(r"^\s*Max Clock Freq\. \(MHz\):\s+([0-9]+)", linetext)
|
||||
if key != None:
|
||||
self._mspec.max_sclk = key
|
||||
continue
|
||||
|
||||
key = search(r"^\s*Compute Unit:\s+ ([a-zA-Z0-9]+)\s*", linetext)
|
||||
if key != None:
|
||||
self._mspec.CU = key
|
||||
continue
|
||||
|
||||
key = search(r"^\s*SIMDs per CU:\s+ ([a-zA-Z0-9]+)\s*", linetext)
|
||||
if key != None:
|
||||
self._mspec.SIMD = key
|
||||
continue
|
||||
|
||||
key = search(r"^\s*Shader Engines:\s+ ([a-zA-Z0-9]+)\s*", linetext)
|
||||
if key != None:
|
||||
self._mspec.SE = key
|
||||
continue
|
||||
|
||||
key = search(r"^\s*Wavefront Size:\s+ ([a-zA-Z0-9]+)\s*", linetext)
|
||||
if key != None:
|
||||
self._mspec.wave_size = key
|
||||
continue
|
||||
|
||||
key = search(r"^\s*Workgroup Max Size:\s+ ([a-zA-Z0-9]+)\s*", linetext)
|
||||
if key != None:
|
||||
self._mspec.workgroup_max_size = key
|
||||
continue
|
||||
|
||||
key = search(r"^\s*Max Waves Per CU:\s+ ([a-zA-Z0-9]+)\s*", linetext)
|
||||
if key != None:
|
||||
self._mspec.max_waves_per_cu = key
|
||||
break
|
||||
|
||||
# we get the max mclk from rocm-smi --showmclkrange
|
||||
rocm_smi_mclk = run(["rocm-smi", "--showmclkrange"], exit_on_error=True)
|
||||
self._mspec.max_mclk = search(r'(\d+)Mhz\s*$', rocm_smi_mclk)
|
||||
|
||||
# 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)
|
||||
self._mspec.cur_sclk = self._mspec.max_sclk
|
||||
self._mspec.cur_mclk = self._mspec.max_mclk
|
||||
|
||||
self._mspec.compute_partition = ""
|
||||
self._mspec.memory_partition = ""
|
||||
|
||||
# specify gpu name for gfx942 hardware
|
||||
self._mspec.GPU = list(SUPPORTED_ARCHS[self._mspec.arch].keys())[0].upper()
|
||||
if self._mspec.GPU == "MI300":
|
||||
self._mspec.GPU = list(SUPPORTED_ARCHS[self._mspec.arch].values())[0][0]
|
||||
if (self._mspec.arch == "gfx942") and ("MI300A" in self._mspec._rocminfo):
|
||||
self._mspec.GPU = "MI300A_A1"
|
||||
if (self._mspec.arch == "gfx942") and ("MI300A" not in self._mspec._rocminfo):
|
||||
self._mspec.GPU = "MI300X_A1"
|
||||
|
||||
@demarcate
|
||||
def perfmon_filter(self, roofline_perfmon_only: bool):
|
||||
"""Filter default performance counter set based on user arguments"""
|
||||
@@ -114,9 +184,7 @@ 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.__arch + "/pmc_*_perf*.txt")
|
||||
|
||||
# Perfmon list filtering
|
||||
if self.__args.ipblocks != None:
|
||||
@@ -152,19 +220,22 @@ class OmniSoC_Base:
|
||||
# ----------------------------------------------------
|
||||
@abstractmethod
|
||||
def profiling_setup(self):
|
||||
"""Perform any SoC-specific setup prior to profiling."""
|
||||
logging.debug("[profiling] perform SoC profiling setup for %s" % self.__name)
|
||||
"""Perform any SoC-specific setup prior to profiling.
|
||||
"""
|
||||
logging.debug("[profiling] perform SoC profiling setup for %s" % self.__arch)
|
||||
|
||||
@abstractmethod
|
||||
def post_profiling(self):
|
||||
"""Perform any SoC-specific post profiling activities."""
|
||||
logging.debug("[profiling] perform SoC post processing for %s" % self.__name)
|
||||
"""Perform any SoC-specific post profiling activities.
|
||||
"""
|
||||
logging.debug("[profiling] perform SoC post processing for %s" % self.__arch)
|
||||
|
||||
@abstractmethod
|
||||
def analysis_setup(self):
|
||||
"""Perform any SoC-specific setup prior to analysis."""
|
||||
logging.debug("[analysis] perform SoC analysis setup for %s" % self.__name)
|
||||
|
||||
"""Perform any SoC-specific setup prior to analysis.
|
||||
"""
|
||||
logging.debug("[analysis] perform SoC analysis setup for %s" % self.__arch)
|
||||
|
||||
|
||||
@demarcate
|
||||
def perfmon_coalesce(pmc_files_list, perfmon_config, workload_dir):
|
||||
|
||||
@@ -27,32 +27,11 @@ import config
|
||||
from omniperf_soc.soc_base import OmniSoC_Base
|
||||
from utils.utils import demarcate, error
|
||||
|
||||
SOC_PARAM = {
|
||||
"numSE": 4,
|
||||
"numCU": 60,
|
||||
"numSIMD": 240,
|
||||
"numPipes": 4,
|
||||
"numWavesPerCU": 40,
|
||||
"numSQC": 15,
|
||||
"L2Banks": 16,
|
||||
"LDSBanks": 32,
|
||||
"Freq": 1725,
|
||||
"mclk": 1000,
|
||||
}
|
||||
|
||||
|
||||
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(),
|
||||
)
|
||||
)
|
||||
class gfx906_soc (OmniSoC_Base):
|
||||
def __init__(self,args,mspec):
|
||||
super().__init__(args,mspec)
|
||||
self.set_arch("gfx906")
|
||||
self.set_perfmon_dir(os.path.join(str(config.omniperf_home), "omniperf_soc", "profile_configs", self.get_arch()))
|
||||
self.set_compatible_profilers(["rocprofv1", "rocscope"])
|
||||
# Per IP block max number of simultaneous counters. GFX IP Blocks
|
||||
self.set_perfmon_config(
|
||||
@@ -70,7 +49,12 @@ class gfx906_soc(OmniSoC_Base):
|
||||
"TCC_channels": 16,
|
||||
}
|
||||
)
|
||||
self.set_soc_param(SOC_PARAM)
|
||||
|
||||
# Set arch specific specs
|
||||
self._mspec.L2Banks = 16
|
||||
self._mspec.LDSBanks = 32
|
||||
self._mspec.numSQC = 15
|
||||
self._mspec.numPipes = 4
|
||||
|
||||
# -----------------------
|
||||
# Required child methods
|
||||
@@ -80,7 +64,7 @@ class gfx906_soc(OmniSoC_Base):
|
||||
"""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())
|
||||
error("%s does not support roofline analysis" % self.get_arch())
|
||||
# Perfmon filtering
|
||||
self.perfmon_filter()
|
||||
|
||||
|
||||
@@ -27,32 +27,11 @@ import config
|
||||
from omniperf_soc.soc_base import OmniSoC_Base
|
||||
from utils.utils import demarcate, error
|
||||
|
||||
SOC_PARAM = {
|
||||
"numSE": 8,
|
||||
"numCU": 120,
|
||||
"numSIMD": 480,
|
||||
"numPipes": 4,
|
||||
"numWavesPerCU": 40,
|
||||
"numSQC": 30,
|
||||
"L2Banks": 32,
|
||||
"LDSBanks": 32,
|
||||
"Freq": 1502,
|
||||
"mclk": 1200,
|
||||
}
|
||||
|
||||
|
||||
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(),
|
||||
)
|
||||
)
|
||||
class gfx908_soc (OmniSoC_Base):
|
||||
def __init__(self,args,mspec):
|
||||
super().__init__(args,mspec)
|
||||
self.set_arch("gfx908")
|
||||
self.set_perfmon_dir(os.path.join(str(config.omniperf_home), "omniperf_soc", "profile_configs", self.get_arch()))
|
||||
self.set_compatible_profilers(["rocprofv1", "rocscope"])
|
||||
# Per IP block max number of simultaneous counters. GFX IP Blocks
|
||||
self.set_perfmon_config(
|
||||
@@ -70,7 +49,15 @@ class gfx908_soc(OmniSoC_Base):
|
||||
"TCC_channels": 32,
|
||||
}
|
||||
)
|
||||
self.set_soc_param(SOC_PARAM)
|
||||
|
||||
# Set arch specific specs
|
||||
self._mspec.L2Banks = 32
|
||||
self._mspec.LDSBanks = 32
|
||||
self._mspec.numSQC = 30
|
||||
self._mspec.numPipes = 4
|
||||
# --showmclkrange is broken in Mi100, hardcode freq
|
||||
self._info['max_mclk'] = 1200
|
||||
self._info['cur_mclk'] = 1200
|
||||
|
||||
@demarcate
|
||||
def get_profiler_options(self):
|
||||
@@ -85,7 +72,7 @@ class gfx908_soc(OmniSoC_Base):
|
||||
"""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())
|
||||
error("%s does not support roofline analysis" % self.get_arch())
|
||||
# Perfmon filtering
|
||||
self.perfmon_filter(self.get_args().roof_only)
|
||||
|
||||
|
||||
@@ -29,42 +29,14 @@ from utils.utils import demarcate, mibench
|
||||
from roofline import Roofline
|
||||
import logging
|
||||
|
||||
SOC_PARAM = {
|
||||
"numSE": 8,
|
||||
"numCU": 110,
|
||||
"numSIMD": 440,
|
||||
"numPipes": 4,
|
||||
"numWavesPerCU": 32,
|
||||
"numSQC": 56,
|
||||
"L2Banks": 32,
|
||||
"LDSBanks": 32,
|
||||
"Freq": 1700,
|
||||
"mclk": 1600,
|
||||
}
|
||||
|
||||
|
||||
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",
|
||||
)
|
||||
)
|
||||
class gfx90a_soc (OmniSoC_Base):
|
||||
def __init__(self,args,mspec):
|
||||
super().__init__(args,mspec)
|
||||
self.set_arch("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"))
|
||||
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_arch()))
|
||||
self.set_compatible_profilers(["rocprofv1", "rocscope"])
|
||||
# Per IP block max number of simultaneous counters. GFX IP Blocks
|
||||
self.set_perfmon_config(
|
||||
@@ -82,8 +54,13 @@ class gfx90a_soc(OmniSoC_Base):
|
||||
"TCC_channels": 32,
|
||||
}
|
||||
)
|
||||
self.set_soc_param(SOC_PARAM)
|
||||
self.roofline_obj = Roofline(args)
|
||||
self.roofline_obj = Roofline(args, self._mspec)
|
||||
|
||||
# Set arch specific specs
|
||||
self._mspec.L2Banks = 32
|
||||
self._mspec.LDSBanks = 32
|
||||
self._mspec.numSQC = 56
|
||||
self._mspec.numPipes = 4
|
||||
|
||||
# -----------------------
|
||||
# Required child methods
|
||||
@@ -104,7 +81,7 @@ class gfx90a_soc(OmniSoC_Base):
|
||||
"[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())
|
||||
mibench(self.get_args(), self._mspec)
|
||||
self.roofline_obj.post_processing()
|
||||
else:
|
||||
logging.info("[roofline] Skipping roofline")
|
||||
|
||||
@@ -29,33 +29,12 @@ from utils.utils import demarcate, mibench
|
||||
from roofline import Roofline
|
||||
import logging
|
||||
|
||||
SOC_PARAM = {
|
||||
"numSE": 8,
|
||||
"numCU": 38,
|
||||
"numSIMD": 4,
|
||||
"numPipes": 4,
|
||||
"numWavesPerCU": 32,
|
||||
"numSQC": 56,
|
||||
"L2Banks": 16,
|
||||
"LDSBanks": 32,
|
||||
"Freq": 1950,
|
||||
"mclk": 1300,
|
||||
}
|
||||
|
||||
|
||||
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",
|
||||
)
|
||||
)
|
||||
class gfx940_soc (OmniSoC_Base):
|
||||
def __init__(self,args,mspec):
|
||||
super().__init__(args,mspec)
|
||||
self.set_arch("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"))
|
||||
else:
|
||||
# NB: We're using generalized Mi300 perfmon configs
|
||||
self.set_perfmon_dir(
|
||||
@@ -80,8 +59,13 @@ class gfx940_soc(OmniSoC_Base):
|
||||
"TCC_channels": 32,
|
||||
}
|
||||
)
|
||||
self.set_soc_param(SOC_PARAM)
|
||||
self.roofline_obj = Roofline(args)
|
||||
self.roofline_obj = Roofline(args, self._mspec)
|
||||
|
||||
# Set arch specific specs
|
||||
self._mspec.L2Banks = 16
|
||||
self._mspec.LDSBanks = 32
|
||||
self._mspec.numSQC = 56
|
||||
self._mspec.numPipes = 4
|
||||
|
||||
# -----------------------
|
||||
# Required child methods
|
||||
|
||||
@@ -29,33 +29,12 @@ from utils.utils import demarcate, mibench
|
||||
from roofline import Roofline
|
||||
import logging
|
||||
|
||||
SOC_PARAM = {
|
||||
"numSE": 8,
|
||||
"numCU": 38,
|
||||
"numSIMD": 4,
|
||||
"numPipes": 4,
|
||||
"numWavesPerCU": 32,
|
||||
"numSQC": 56,
|
||||
"L2Banks": 16,
|
||||
"LDSBanks": 32,
|
||||
"Freq": 1950,
|
||||
"mclk": 1300,
|
||||
}
|
||||
|
||||
|
||||
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",
|
||||
)
|
||||
)
|
||||
class gfx941_soc (OmniSoC_Base):
|
||||
def __init__(self,args, mspec):
|
||||
super().__init__(args, mspec)
|
||||
self.set_arch("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"))
|
||||
else:
|
||||
# NB: We're using generalized Mi300 perfmon configs
|
||||
self.set_perfmon_dir(
|
||||
@@ -80,8 +59,13 @@ class gfx941_soc(OmniSoC_Base):
|
||||
"TCC_channels": 32,
|
||||
}
|
||||
)
|
||||
self.set_soc_param(SOC_PARAM)
|
||||
self.roofline_obj = Roofline(args)
|
||||
self.roofline_obj = Roofline(args, self._mspec)
|
||||
|
||||
# Set arch specific specs
|
||||
self._mspec.L2Banks = 16
|
||||
self._mspec.LDSBanks = 32
|
||||
self._mspec.numSQC = 56
|
||||
self._mspec.numPipes = 4
|
||||
|
||||
# -----------------------
|
||||
# Required child methods
|
||||
|
||||
@@ -29,33 +29,12 @@ from utils.utils import demarcate, mibench
|
||||
from roofline import Roofline
|
||||
import logging
|
||||
|
||||
SOC_PARAM = {
|
||||
"numSE": 8,
|
||||
"numCU": 38,
|
||||
"numSIMD": 4,
|
||||
"numPipes": 4,
|
||||
"numWavesPerCU": 32,
|
||||
"numSQC": 56,
|
||||
"L2Banks": 16,
|
||||
"LDSBanks": 32,
|
||||
"Freq": 1950,
|
||||
"mclk": 1300,
|
||||
}
|
||||
|
||||
|
||||
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",
|
||||
)
|
||||
)
|
||||
class gfx942_soc (OmniSoC_Base):
|
||||
def __init__(self,args,mspec):
|
||||
super().__init__(args,mspec)
|
||||
self.set_arch("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"))
|
||||
else:
|
||||
# NB: We're using generalized Mi300 perfmon configs
|
||||
self.set_perfmon_dir(
|
||||
@@ -80,8 +59,13 @@ class gfx942_soc(OmniSoC_Base):
|
||||
"TCC_channels": 32,
|
||||
}
|
||||
)
|
||||
self.set_soc_param(SOC_PARAM)
|
||||
self.roofline_obj = Roofline(args)
|
||||
self.roofline_obj = Roofline(args, self.__mspec)
|
||||
|
||||
# Set arch specific specs
|
||||
self._mspec.L2Banks = 16
|
||||
self._mspec.LDSBanks = 32
|
||||
self._mspec.numSQC = 56
|
||||
self._mspec.numPipes = 4
|
||||
|
||||
# -----------------------
|
||||
# Required child methods
|
||||
|
||||
@@ -38,34 +38,35 @@ SYMBOLS = [0, 1, 2, 3, 4, 5, 13, 17, 18, 20]
|
||||
|
||||
|
||||
class Roofline:
|
||||
def __init__(self, args, run_parameters=None):
|
||||
def __init__(self, args, mspec, 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.__mspec = mspec
|
||||
self.__run_parameters = run_parameters if run_parameters else {
|
||||
'workload_dir': None, # in some cases (i.e. --specs) path will not be given
|
||||
'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):
|
||||
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, 'path'):
|
||||
self.__run_parameters['workload_dir'] = self.__args.path
|
||||
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 (not isinstance(self.__run_parameters['workload_dir'], list)
|
||||
and self.__run_parameters['workload_dir'] != None):
|
||||
self.roof_setup()
|
||||
|
||||
self.validate_parameters()
|
||||
|
||||
@@ -77,13 +78,11 @@ class Roofline:
|
||||
|
||||
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['workload_dir'] == os.path.join(os.getcwd(), 'workloads'):
|
||||
self.__run_parameters['workload_dir'] = os.path.join(self.__run_parameters['workload_dir'], self.__args.name, self.__mspec.GPU)
|
||||
# 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['workload_dir']):
|
||||
os.makedirs(self.__run_parameters['workload_dir'])
|
||||
|
||||
@demarcate
|
||||
def empirical_roofline(
|
||||
@@ -92,9 +91,9 @@ class Roofline:
|
||||
):
|
||||
"""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['workload_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]))
|
||||
@@ -132,33 +131,21 @@ class Roofline:
|
||||
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['workload_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['workload_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['workload_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)
|
||||
)
|
||||
fp32_fig.write_image(self.__run_parameters['workload_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['workload_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"
|
||||
)
|
||||
if self.__run_parameters['include_kernel_names']:
|
||||
self.__figure.write_image(self.__run_parameters['workload_dir'] + "/kernelName_legend.pdf")
|
||||
logging.info("[roofline] Empirical Roofline PDFs saved!")
|
||||
else:
|
||||
return html.Section(
|
||||
@@ -345,7 +332,7 @@ class Roofline:
|
||||
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['workload_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))
|
||||
@@ -366,12 +353,13 @@ class Roofline:
|
||||
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,
|
||||
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,
|
||||
mspec=self.__mspec
|
||||
)
|
||||
|
||||
@abstractmethod
|
||||
@@ -383,7 +371,7 @@ class Roofline:
|
||||
)
|
||||
roof_path = os.path.join(self.__args.path, "roofline.csv")
|
||||
if not os.path.isfile(roof_path):
|
||||
mibench(self.__args)
|
||||
mibench(self.__args, self.__mspec)
|
||||
|
||||
# check for profiling data
|
||||
logging.info(
|
||||
@@ -401,7 +389,7 @@ class Roofline:
|
||||
elif self.__args.no_roof:
|
||||
logging.info("[roofline] Skipping roofline.")
|
||||
else:
|
||||
mibench(self.__args)
|
||||
mibench(self.__args, self.__mspec)
|
||||
|
||||
# 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
|
||||
|
||||
@@ -54,11 +54,7 @@ class DatabaseConnector:
|
||||
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
|
||||
)
|
||||
def prep_import(self):
|
||||
|
||||
# Extract SoC and workload name from sysinfo.csv
|
||||
sys_info = os.path.join(self.connection_info["workload"], "sysinfo.csv")
|
||||
|
||||
@@ -663,7 +663,7 @@ def build_metric_value_string(dfs, dfs_type, normal_unit):
|
||||
# print(tabulate(df, headers='keys', tablefmt='fancy_grid'))
|
||||
|
||||
|
||||
def eval_metric(dfs, dfs_type, sys_info, soc_spec, raw_pmc_df, debug):
|
||||
def eval_metric(dfs, dfs_type, sys_info, raw_pmc_df, debug):
|
||||
"""
|
||||
Execute the expr string for each metric in the df.
|
||||
"""
|
||||
@@ -679,25 +679,18 @@ def eval_metric(dfs, dfs_type, sys_info, soc_spec, raw_pmc_df, debug):
|
||||
print("WARNING: Dectected GRBM_GUI_ACTIVE == 0\nHaulting execution.")
|
||||
sys.exit(1)
|
||||
|
||||
# NB:
|
||||
# Following with Omniperf 0.2.0, we are using HW spec from sys_info instead.
|
||||
# The soc_spec is not in using right now, but can be used to do verification
|
||||
# against sys_info, forced theoretical evaluation, or supporting tool-chains
|
||||
# broken.
|
||||
ammolite__numSE = sys_info.numSE
|
||||
ammolite__numSE = sys_info.SE
|
||||
ammolite__numPipes = sys_info.numPipes
|
||||
ammolite__numCU = sys_info.numCU
|
||||
ammolite__numSIMD = sys_info.numSIMD
|
||||
ammolite__numWavesPerCU = sys_info.maxWavesPerCU # todo: check do we still need it
|
||||
ammolite__numCU = sys_info.CU
|
||||
ammolite__numSIMD = sys_info.SIMD
|
||||
ammolite__numWavesPerCU = sys_info.max_waves_per_cu # 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 = sys_info.LDSBanks
|
||||
ammolite__freq = sys_info.cur_sclk # todo: check do we still need it
|
||||
ammolite__mclk = sys_info.cur_mclk
|
||||
ammolite__sclk = sys_info.sclk
|
||||
ammolite__maxWavesPerCU = sys_info.maxWavesPerCU
|
||||
ammolite__sclk = sys_info.max_sclk
|
||||
ammolite__maxWavesPerCU = sys_info.max_waves_per_cu
|
||||
ammolite__hbmBW = sys_info.hbmBW
|
||||
ammolite__totalL2Banks = calc_builtin_var("$totalL2Banks", sys_info)
|
||||
|
||||
@@ -947,7 +940,6 @@ def load_table_data(workload, dir, is_gui, debug, verbose, skipKernelTop=False):
|
||||
workload.dfs,
|
||||
workload.dfs_type,
|
||||
workload.sys_info.iloc[0],
|
||||
workload.soc_spec,
|
||||
apply_filters(workload, dir, is_gui, debug),
|
||||
debug,
|
||||
)
|
||||
|
||||
@@ -474,7 +474,7 @@ def calc_ai(sort_type, ret_df):
|
||||
|
||||
|
||||
def constuct_roof(roofline_parameters, dtype):
|
||||
benchmark_results = os.path.join(roofline_parameters["path_to_dir"], "roofline.csv")
|
||||
benchmark_results = os.path.join(roofline_parameters["workload_dir"], "roofline.csv")
|
||||
# -----------------------------------------------------
|
||||
# Initialize roofline data dictionary from roofline.csv
|
||||
# -----------------------------------------------------
|
||||
|
||||
@@ -59,7 +59,6 @@ class ArchConfig:
|
||||
@dataclass
|
||||
class Workload:
|
||||
sys_info: pd.DataFrame = None
|
||||
soc_spec: dict = None # TODO: might move it to ArchConfig
|
||||
raw_pmc: pd.DataFrame = None
|
||||
dfs: Dict[int, pd.DataFrame] = field(default_factory=dict)
|
||||
dfs_type: Dict[int, str] = field(default_factory=dict)
|
||||
|
||||
@@ -31,46 +31,158 @@ import socket
|
||||
import subprocess
|
||||
import importlib
|
||||
import logging
|
||||
import pandas as pd
|
||||
|
||||
from datetime import datetime
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path as path
|
||||
from textwrap import dedent
|
||||
from utils.utils import error, get_hbm_stack_num
|
||||
|
||||
VERSION_LOC = [
|
||||
"version",
|
||||
"version-dev",
|
||||
"version-hip-libraries",
|
||||
"version-hiprt",
|
||||
"version-hiprt-devel",
|
||||
"version-hip-sdk",
|
||||
"version-libs",
|
||||
"version-utils",
|
||||
]
|
||||
|
||||
@dataclass
|
||||
class MachineSpecs:
|
||||
hostname: str
|
||||
CPU: str
|
||||
sbios: str
|
||||
kernel_version: str
|
||||
ram: str
|
||||
distro: str
|
||||
rocm_version: str
|
||||
GPU: str
|
||||
arch: str
|
||||
vbios: str
|
||||
L1: str
|
||||
L2: str
|
||||
CU: str
|
||||
SIMD: str
|
||||
SE: str
|
||||
wave_size: str
|
||||
workgroup_max_size: str
|
||||
max_sclk: str
|
||||
max_mclk: str
|
||||
cur_sclk: str
|
||||
cur_mclk: str
|
||||
max_waves_per_cu: str
|
||||
L2Banks: str
|
||||
totalL2Banks: str
|
||||
LDSBanks: str
|
||||
numSQC: str
|
||||
numPipes: str
|
||||
hbmBW: str
|
||||
compute_partition: str
|
||||
memory_partition: str
|
||||
def __init__(self, args, sysinfo=None):
|
||||
if not sysinfo is None:
|
||||
self.arch = sysinfo.iloc[0]["arch"]
|
||||
return
|
||||
# read timestamp info
|
||||
now = datetime.now()
|
||||
local_now = now.astimezone()
|
||||
local_tz = local_now.tzinfo
|
||||
local_tzname = local_tz.tzname(local_now)
|
||||
self.timestamp = now.strftime("%c") + " (" + local_tzname + ")"
|
||||
|
||||
# read rocminfo
|
||||
rocminfo_full = run(["rocminfo"])
|
||||
self._rocminfo = rocminfo_full.split("\n")
|
||||
|
||||
##########################################
|
||||
## A. Machine Specs
|
||||
##########################################
|
||||
cpuinfo = path("/proc/cpuinfo").read_text()
|
||||
meminfo = path("/proc/meminfo").read_text()
|
||||
version = path("/proc/version").read_text()
|
||||
os_release = path("/etc/os-release").read_text()
|
||||
|
||||
self.hostname: str = socket.gethostname()
|
||||
self.CPU: str = search(r"^model name\s*: (.*?)$", cpuinfo)
|
||||
self.sbios: str = (
|
||||
path("/sys/class/dmi/id/bios_vendor").read_text().strip()
|
||||
+ path("/sys/class/dmi/id/bios_version").read_text().strip()
|
||||
)
|
||||
self.kernel_version: str = search(r"version (\S*)", version)
|
||||
self.ram: str = search(r"MemTotal:\s*(\S*)", meminfo)
|
||||
self.distro: str = search(r'PRETTY_NAME="(.*?)"', os_release)
|
||||
if self.distro is None:
|
||||
self.distro = ""
|
||||
self.rocm_version: str = get_rocm_ver().strip()
|
||||
#FIXME: use device
|
||||
self.vbios: str = search(
|
||||
r"VBIOS version: (.*?)$", run(["rocm-smi", "-v"], exit_on_error=True)
|
||||
)
|
||||
self.compute_partition: str = search(
|
||||
r"Compute Partition:\s*(\w+)", run(["rocm-smi", "--showcomputepartition"])
|
||||
)
|
||||
if self.compute_partition is None:
|
||||
self.compute_partition = "NA"
|
||||
self.memory_partition: str = search(
|
||||
r"Memory Partition:\s*(\w+)", run(["rocm-smi", "--showmemorypartition"])
|
||||
)
|
||||
if self.memory_partition is None:
|
||||
self.memory_partition = "NA"
|
||||
|
||||
##########################################
|
||||
## B. SoC Specs
|
||||
##########################################
|
||||
self.arch: str = self.detect_arch()[0]
|
||||
self.L1: str = None
|
||||
self.L2: str = None
|
||||
self.CU: str = None
|
||||
self.SIMD: str = None
|
||||
self.SE: str = None
|
||||
self.wave_size: str = None
|
||||
self.workgroup_max_size: str = None
|
||||
self.max_sclk: str = None
|
||||
self.max_mclk: str = None
|
||||
self.cur_sclk: str = None
|
||||
self.cur_mclk: str = None
|
||||
self.max_waves_per_cu: str = None
|
||||
self.GPU: str = None
|
||||
self.L2Banks: str = None
|
||||
self.LDSBanks: str = None
|
||||
self.numSQC: str = None
|
||||
self.numPipes: str = None
|
||||
self.totalL2Banks: str = None
|
||||
self.hbmBW: str = None
|
||||
# Load above SoC specs via module import
|
||||
try:
|
||||
soc_module = importlib.import_module('omniperf_soc.soc_'+ self.arch)
|
||||
except ModuleNotFoundError as e:
|
||||
error("Arch %s marked as supported, but couldn't find class implementation %s." % (self.arch, e))
|
||||
soc_class = getattr(soc_module, self.arch+'_soc')
|
||||
self._rocminfo = self._rocminfo[self.detect_arch()[1] + 1 :] # update rocminfo for target section
|
||||
soc_obj = soc_class(args, self)
|
||||
# Update arch specific specs
|
||||
self.totalL2Banks: str = total_l2_banks(
|
||||
self.GPU, int(self.L2Banks), self.memory_partition
|
||||
)
|
||||
self.hbmBW: str = str(int(self.max_mclk) / 1000 * 32 * self.get_hbm_channels())
|
||||
|
||||
|
||||
def detect_arch(self):
|
||||
from omniperf_base import SUPPORTED_ARCHS
|
||||
|
||||
for idx1, linetext in enumerate(self._rocminfo):
|
||||
gpu_arch = search(r"^\s*Name\s*:\s+ ([a-zA-Z0-9]+)\s*$", linetext)
|
||||
if gpu_arch in SUPPORTED_ARCHS.keys():
|
||||
break
|
||||
if str(gpu_arch) in SUPPORTED_ARCHS.keys():
|
||||
gpu_arch = str(gpu_arch)
|
||||
break
|
||||
if not gpu_arch in SUPPORTED_ARCHS.keys():
|
||||
error("[profiling] Cannot find a supported arch in rocminfo")
|
||||
else:
|
||||
return (gpu_arch, idx1)
|
||||
|
||||
def get_hbm_channels(self):
|
||||
hbmchannels = int(self.totalL2Banks)
|
||||
if (
|
||||
self.GPU.lower() == "mi300a_a0"
|
||||
or self.GPU.lower() == "mi300a_a1"
|
||||
) and self.memory_partition.lower() == "nps1":
|
||||
# we have an extra 32 channels for the CCD
|
||||
hbmchannels += 32
|
||||
return hbmchannels
|
||||
|
||||
def get_class_members(self):
|
||||
all_populated = True
|
||||
data = {}
|
||||
# dataclass uses an OrderedDict for member variables, ensuring order consistency
|
||||
for attr_name in self.__dict__.keys():
|
||||
if not attr_name.startswith("_"):
|
||||
attr_value = getattr(self, attr_name)
|
||||
if attr_value is None:
|
||||
#TODO: use proper logging function when that's merged
|
||||
logging.warning(f"WARNING: Incomplete class definition for {self.arch}. Expecting populated {attr_name} but detected None.")
|
||||
all_populated = False
|
||||
data[attr_name] = attr_value
|
||||
|
||||
if not all_populated:
|
||||
error("Missing specs fields for %s" % self.arch)
|
||||
return pd.DataFrame(data, index=[0])
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return dedent(
|
||||
f"""\
|
||||
@@ -110,145 +222,27 @@ class MachineSpecs:
|
||||
)
|
||||
|
||||
|
||||
def gpuinfo():
|
||||
from omniperf_base import SUPPORTED_ARCHS
|
||||
|
||||
gpu_info = {
|
||||
"gpu_name": None,
|
||||
"gpu_arch": None,
|
||||
"L1": None,
|
||||
"L2": None,
|
||||
"max_sclk": None,
|
||||
"max_mclk": None,
|
||||
"num_CU": None,
|
||||
"num_SIMD": None,
|
||||
"numPipes": None,
|
||||
"num_SE": None,
|
||||
"wave_size": None,
|
||||
"grp_size": None,
|
||||
"max_waves_per_cu": None,
|
||||
"L2Banks": None,
|
||||
"LDSBanks": None,
|
||||
"numSQC": None,
|
||||
"compute_partition": None,
|
||||
"memory_partition": None,
|
||||
}
|
||||
|
||||
# Fixme: find better way to differentiate cards, GPU vs APU, etc.
|
||||
rocminfo_full = run(["rocminfo"])
|
||||
rocminfo = rocminfo_full.split("\n")
|
||||
|
||||
for idx1, linetext in enumerate(rocminfo):
|
||||
gpu_arch = search(r"^\s*Name\s*:\s+ ([a-zA-Z0-9]+)\s*$", linetext)
|
||||
if gpu_arch in SUPPORTED_ARCHS.keys():
|
||||
break
|
||||
if str(gpu_arch) in SUPPORTED_ARCHS.keys():
|
||||
gpu_arch = str(gpu_arch)
|
||||
break
|
||||
if not gpu_arch in SUPPORTED_ARCHS.keys():
|
||||
return gpu_info
|
||||
|
||||
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
|
||||
continue
|
||||
|
||||
key = search(r"^\s*L2:\s+ ([a-zA-Z0-9]+)\s*", linetext)
|
||||
if key != None:
|
||||
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
|
||||
continue
|
||||
|
||||
key = search(r"^\s*Compute Unit:\s+ ([a-zA-Z0-9]+)\s*", linetext)
|
||||
if key != None:
|
||||
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
|
||||
continue
|
||||
|
||||
key = search(r"^\s*Shader Engines:\s+ ([a-zA-Z0-9]+)\s*", linetext)
|
||||
if key != None:
|
||||
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
|
||||
continue
|
||||
|
||||
key = search(r"^\s*Workgroup Max Size:\s+ ([a-zA-Z0-9]+)\s*", linetext)
|
||||
if key != None:
|
||||
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
|
||||
break
|
||||
|
||||
try:
|
||||
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)
|
||||
)
|
||||
|
||||
# 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"])
|
||||
except KeyError as e:
|
||||
error(
|
||||
"Incomplete class definition for %s. Expected a field for %s in SOC_PARAM."
|
||||
% (gpu_arch, e)
|
||||
)
|
||||
|
||||
# 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)
|
||||
# check that we got the mclk from smi
|
||||
if gpu_info["max_mclk"] is None:
|
||||
if gpu_name == "MI100":
|
||||
# hardcoded due to rocm-smi limitation
|
||||
gpu_info["max_mclk"] = str(1200)
|
||||
else:
|
||||
error(
|
||||
"Could not obtain maximum mclk from rocm-smi for GPU: {}".format(gpu_info)
|
||||
def get_rocm_ver():
|
||||
rocm_found = False
|
||||
for itr in VERSION_LOC:
|
||||
_path = os.path.join(os.getenv("ROCM_PATH", "/opt/rocm"), ".info", itr)
|
||||
if os.path.exists(_path):
|
||||
rocm_ver = path(_path).read_text()
|
||||
rocm_found = True
|
||||
break
|
||||
if not rocm_found:
|
||||
# check if ROCM_VER is supplied externally
|
||||
ROCM_VER_USER = os.getenv("ROCM_VER")
|
||||
if ROCM_VER_USER is not None:
|
||||
logging.info(
|
||||
"Overriding missing ROCm version detection with ROCM_VER = %s"
|
||||
% ROCM_VER_USER
|
||||
)
|
||||
|
||||
# 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):
|
||||
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"] = ""
|
||||
|
||||
# verify all fields are filled
|
||||
for key, value in gpu_info.items():
|
||||
if value is None:
|
||||
logging.info("Warning: %s is missing from gpu_info dictionary." % key)
|
||||
|
||||
return gpu_info
|
||||
|
||||
rocm_ver = ROCM_VER_USER
|
||||
else:
|
||||
_rocm_path = os.getenv("ROCM_PATH", "/opt/rocm")
|
||||
error("Unable to detect a complete local ROCm installation.\nThe expected %s/.info/ versioning directory is missing. Please ensure you have valid ROCm installation." % _rocm_path)
|
||||
return rocm_ver
|
||||
|
||||
def run(cmd, exit_on_error=False):
|
||||
p = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
@@ -275,143 +269,20 @@ 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)
|
||||
return totalL2Banks
|
||||
|
||||
|
||||
def get_machine_specs(devicenum):
|
||||
cpuinfo = path("/proc/cpuinfo").read_text()
|
||||
meminfo = path("/proc/meminfo").read_text()
|
||||
version = path("/proc/version").read_text()
|
||||
os_release = path("/etc/os-release").read_text()
|
||||
|
||||
version_loc = [
|
||||
"version",
|
||||
"version-dev",
|
||||
"version-hip-libraries",
|
||||
"version-hiprt",
|
||||
"version-hiprt-devel",
|
||||
"version-hip-sdk",
|
||||
"version-libs",
|
||||
"version-utils",
|
||||
]
|
||||
|
||||
rocmFound = False
|
||||
for itr in version_loc:
|
||||
_path = os.path.join(os.getenv("ROCM_PATH", "/opt/rocm"), ".info", itr)
|
||||
if os.path.exists(_path):
|
||||
rocm_ver = path(_path).read_text()
|
||||
rocmFound = True
|
||||
break
|
||||
|
||||
if not rocmFound:
|
||||
# check if ROCM_VER is supplied externally
|
||||
ROCM_VER_USER = os.getenv("ROCM_VER")
|
||||
if ROCM_VER_USER is not None:
|
||||
print(
|
||||
"Overriding missing ROCm version detection with ROCM_VER = %s"
|
||||
% ROCM_VER_USER
|
||||
)
|
||||
rocm_ver = ROCM_VER_USER
|
||||
else:
|
||||
_rocm_path = os.getenv("ROCM_PATH", "/opt/rocm")
|
||||
print("Error: Unable to detect a complete local ROCm installation.")
|
||||
print(
|
||||
"\nThe expected %s/.info/ versioning directory is missing. Please"
|
||||
% _rocm_path
|
||||
)
|
||||
print("ensure you have valid ROCm installation.")
|
||||
sys.exit(1)
|
||||
|
||||
gpu_info = gpuinfo()
|
||||
|
||||
rocm_smi = run(["rocm-smi"], exit_on_error=True)
|
||||
|
||||
device = rf"^\s*{devicenum}(.*)"
|
||||
|
||||
hostname = socket.gethostname()
|
||||
sbios = (
|
||||
path("/sys/class/dmi/id/bios_vendor").read_text().strip()
|
||||
+ path("/sys/class/dmi/id/bios_version").read_text().strip()
|
||||
)
|
||||
CPU = search(r"^model name\s*: (.*?)$", cpuinfo)
|
||||
kernel_version = search(r"version (\S*)", version)
|
||||
ram = search(r"MemTotal:\s*(\S*)", meminfo)
|
||||
distro = search(r'PRETTY_NAME="(.*?)"', os_release)
|
||||
if distro is None:
|
||||
distro = ""
|
||||
|
||||
rocm_version = rocm_ver.strip()
|
||||
|
||||
# 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"]
|
||||
|
||||
# FIXME with device
|
||||
vbios = search(r"VBIOS version: (.*?)$", run(["rocm-smi", "-v"], exit_on_error=True))
|
||||
|
||||
compute_partition = search(
|
||||
r"Compute Partition:\s*(\w+)", run(["rocm-smi", "--showcomputepartition"])
|
||||
)
|
||||
if compute_partition == None:
|
||||
compute_partition = "NA"
|
||||
|
||||
memory_partition = search(
|
||||
r"Memory Partition:\s*(\w+)", run(["rocm-smi", "--showmemorypartition"])
|
||||
)
|
||||
if memory_partition == None:
|
||||
memory_partition = "NA"
|
||||
|
||||
totalL2Banks = total_l2_banks(
|
||||
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"
|
||||
) 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)
|
||||
totalL2Banks = str(totalL2Banks)
|
||||
|
||||
return MachineSpecs(
|
||||
hostname,
|
||||
CPU,
|
||||
sbios,
|
||||
kernel_version,
|
||||
ram,
|
||||
distro,
|
||||
rocm_version,
|
||||
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"],
|
||||
cur_sclk,
|
||||
cur_mclk,
|
||||
gpu_info["max_waves_per_cu"],
|
||||
gpu_info["L2Banks"],
|
||||
totalL2Banks,
|
||||
gpu_info["LDSBanks"],
|
||||
gpu_info["numSQC"],
|
||||
gpu_info["numPipes"],
|
||||
hbmBW,
|
||||
compute_partition,
|
||||
memory_partition,
|
||||
)
|
||||
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 str(totalL2Banks)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(get_machine_specs(0))
|
||||
print(MachineSpecs())
|
||||
|
||||
@@ -198,12 +198,10 @@ def capture_subprocess_output(subprocess_args, new_env=None):
|
||||
|
||||
return (success, output)
|
||||
|
||||
|
||||
def run_prof(fname, profiler_options, target, workload_dir):
|
||||
def run_prof(fname, profiler_options, workload_dir, mspec):
|
||||
|
||||
fbase = os.path.splitext(os.path.basename(fname))[0]
|
||||
m_specs = specs.get_machine_specs(0)
|
||||
|
||||
|
||||
logging.debug("pmc file: %s" % str(os.path.basename(fname)))
|
||||
|
||||
# standard rocprof options
|
||||
@@ -212,12 +210,7 @@ def run_prof(fname, profiler_options, target, workload_dir):
|
||||
|
||||
# set required env var for mi300
|
||||
new_env = None
|
||||
if (
|
||||
target.lower() == "mi300x_a0"
|
||||
or target.lower() == "mi300x_a1"
|
||||
or target.lower() == "mi300a_a0"
|
||||
or target.lower() == "mi300a_a1"
|
||||
) and (
|
||||
if (mspec.GPU.lower() == "mi300x_a0" or mspec.GPU.lower() == "mi300x_a1" or mspec.GPU.lower() == "mi300a_a0" or mspec.GPU.lower() == "mi300a_a1") and (
|
||||
os.path.basename(fname) == "pmc_perf_13.txt"
|
||||
or os.path.basename(fname) == "pmc_perf_14.txt"
|
||||
or os.path.basename(fname) == "pmc_perf_15.txt"
|
||||
@@ -239,8 +232,10 @@ def run_prof(fname, profiler_options, target, workload_dir):
|
||||
if new_env:
|
||||
# flatten tcc for applicable mi300 input
|
||||
f = path(workload_dir + "/out/pmc_1/results_" + fbase + ".csv")
|
||||
hbm_stack_num = get_hbm_stack_num(target, m_specs.memory_partition)
|
||||
df = flatten_tcc_info_across_hbm_stacks(f, hbm_stack_num, int(m_specs.L2Banks))
|
||||
hbm_stack_num = get_hbm_stack_num(mspec.GPU, mspec.memory_partition)
|
||||
df = flatten_tcc_info_across_hbm_stacks(
|
||||
f, hbm_stack_num, int(mspec.L2Banks)
|
||||
)
|
||||
df.to_csv(f, index=False)
|
||||
|
||||
if os.path.exists(workload_dir + "/out"):
|
||||
@@ -300,88 +295,27 @@ def replace_timestamps(workload_dir):
|
||||
)
|
||||
logging.warning(warning + "\n")
|
||||
|
||||
|
||||
def gen_sysinfo(workload_name, workload_dir, ip_blocks, app_cmd, skip_roof, roof_only):
|
||||
# Record system information
|
||||
mspec = specs.get_machine_specs(0)
|
||||
sysinfo = open(workload_dir + "/" + "sysinfo.csv", "w")
|
||||
|
||||
# write header
|
||||
header = "workload_name,"
|
||||
header += "command,"
|
||||
header += "host_name,host_cpu,sbios,host_distro,host_kernel,host_rocmver,date,"
|
||||
header += "gpu_soc,vbios,numSE,numCU,numSIMD,waveSize,maxWavesPerCU,maxWorkgroupSize,"
|
||||
header += "L1,L2,sclk,mclk,cur_sclk,cur_mclk,L2Banks,totalL2Banks,LDSBanks,name,numSQC,numPipes,"
|
||||
header += "hbmBW,compute_partition,memory_partition,"
|
||||
header += "ip_blocks\n"
|
||||
sysinfo.write(header)
|
||||
|
||||
# timestamp
|
||||
now = datetime.now()
|
||||
local_now = now.astimezone()
|
||||
local_tz = local_now.tzinfo
|
||||
local_tzname = local_tz.tzname(local_now)
|
||||
timestamp = now.strftime("%c") + " (" + local_tzname + ")"
|
||||
# host info
|
||||
param = [workload_name]
|
||||
param += ['"' + app_cmd + '"']
|
||||
param += [
|
||||
mspec.hostname,
|
||||
mspec.CPU,
|
||||
'"' + mspec.sbios + '"',
|
||||
mspec.distro,
|
||||
mspec.kernel_version,
|
||||
mspec.rocm_version,
|
||||
timestamp,
|
||||
]
|
||||
|
||||
# GPU info
|
||||
param += [
|
||||
mspec.arch,
|
||||
mspec.vbios,
|
||||
mspec.SE,
|
||||
mspec.CU,
|
||||
mspec.SIMD,
|
||||
mspec.wave_size,
|
||||
mspec.max_waves_per_cu,
|
||||
mspec.workgroup_max_size,
|
||||
]
|
||||
param += [
|
||||
mspec.L1,
|
||||
mspec.L2,
|
||||
mspec.max_sclk,
|
||||
mspec.max_mclk,
|
||||
mspec.cur_sclk,
|
||||
mspec.cur_mclk,
|
||||
mspec.L2Banks,
|
||||
mspec.totalL2Banks,
|
||||
mspec.LDSBanks,
|
||||
mspec.GPU,
|
||||
mspec.numSQC,
|
||||
mspec.numPipes,
|
||||
mspec.hbmBW,
|
||||
mspec.compute_partition,
|
||||
mspec.memory_partition,
|
||||
]
|
||||
|
||||
def gen_sysinfo(workload_name, workload_dir, ip_blocks, app_cmd, skip_roof, roof_only, mspec):
|
||||
df = mspec.get_class_members()
|
||||
|
||||
# Append workload information to machine specs
|
||||
df.insert(0, 'command', app_cmd)
|
||||
df.insert(0,'workload_name', workload_name)
|
||||
|
||||
blocks = []
|
||||
if mspec.arch == "gfx90a" and (not skip_roof):
|
||||
blocks.append("roofline")
|
||||
|
||||
# ip block info
|
||||
if ip_blocks == None:
|
||||
t = ["SQ", "LDS", "SQC", "TA", "TD", "TCP", "TCC", "SPI", "CPC", "CPF"]
|
||||
blocks += t
|
||||
else:
|
||||
blocks += ip_blocks
|
||||
param.append("|".join(blocks))
|
||||
if mspec.arch == "gfx90a" and (not skip_roof):
|
||||
blocks.append("roofline")
|
||||
df['ip_blocks'] = "|".join(blocks)
|
||||
|
||||
sysinfo.write(",".join(param))
|
||||
sysinfo.close()
|
||||
# Save csv
|
||||
df.to_csv(workload_dir + "/" + "sysinfo.csv", index=False)
|
||||
|
||||
|
||||
def detect_roofline():
|
||||
mspec = specs.get_machine_specs(0)
|
||||
def detect_roofline(mspec):
|
||||
rocm_ver = mspec.rocm_version[:1]
|
||||
|
||||
os_release = path("/etc/os-release").read_text()
|
||||
@@ -446,13 +380,13 @@ def run_rocscope(args, fname):
|
||||
logging.error(result.stderr.decode("ascii"))
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def mibench(args):
|
||||
"""Run roofline microbenchmark to generate peak BW and FLOP measurements."""
|
||||
def mibench(args, mspec):
|
||||
"""Run roofline microbenchmark to generate peak BW and FLOP measurements.
|
||||
"""
|
||||
logging.info("[roofline] No roofline data found. Generating...")
|
||||
distro_map = {"platform:el8": "rhel8", "15.3": "sle15sp3", "20.04": "ubuntu20_04"}
|
||||
|
||||
target_binary = detect_roofline()
|
||||
target_binary = detect_roofline(mspec)
|
||||
if target_binary["rocm_ver"] == "override":
|
||||
path_to_binary = target_binary["path"]
|
||||
else:
|
||||
@@ -462,7 +396,7 @@ def mibench(args):
|
||||
+ "-"
|
||||
+ distro_map[target_binary["distro"]]
|
||||
+ "-"
|
||||
+ args.target.lower()
|
||||
+ mspec.GPU.lower()
|
||||
+ "-rocm"
|
||||
+ target_binary["rocm_ver"]
|
||||
)
|
||||
|
||||
Ссылка в новой задаче
Block a user