Re-implement machine-specs to contain documentation, units, etc. Print using tabulate
Signed-off-by: Nicholas Curtis <nicurtis@amd.com>
此提交包含在:
+4
-3
@@ -28,7 +28,7 @@ import sys
|
||||
import os
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
from utils.specs import MachineSpecs
|
||||
from utils.specs import generate_machine_specs
|
||||
from utils.utils import demarcate, trace_logger, get_version, get_version_display, detect_rocprof, error, get_submodules
|
||||
from argparser import omniarg_parser
|
||||
import config
|
||||
@@ -160,7 +160,7 @@ class Omniperf:
|
||||
def load_soc_specs(self, sysinfo:dict=None):
|
||||
"""Load OmniSoC instance for Omniperf run
|
||||
"""
|
||||
self.__mspec = MachineSpecs(self.__args, sysinfo)
|
||||
self.__mspec = generate_machine_specs(self.__args, sysinfo)
|
||||
if self.__args.specs:
|
||||
print(self.__mspec)
|
||||
sys.exit(0)
|
||||
@@ -193,7 +193,7 @@ class Omniperf:
|
||||
|
||||
if self.__args.mode == None:
|
||||
if self.__args.specs:
|
||||
print(MachineSpecs(self.__args))
|
||||
print(generate_machine_specs(self.__args))
|
||||
sys.exit(0)
|
||||
parser.print_help(sys.stderr)
|
||||
error("Omniperf requires a valid mode.")
|
||||
@@ -280,6 +280,7 @@ class Omniperf:
|
||||
for d in analyzer.get_args().path:
|
||||
sys_info = pd.read_csv(Path(d[0], "sysinfo.csv"))
|
||||
sys_info = sys_info.to_dict('list')
|
||||
sys_info = {key: value[0] for key, value in sys_info.items()}
|
||||
self.load_soc_specs(sys_info)
|
||||
|
||||
analyzer.set_soc(self.__soc)
|
||||
|
||||
@@ -92,7 +92,7 @@ class OmniSoC_Base():
|
||||
def populate_mspec(self):
|
||||
from utils.specs import search, run, total_sqc, total_xcds
|
||||
|
||||
if not hasattr(self._mspec, "_rocminfo"):
|
||||
if not hasattr(self._mspec, "_rocminfo") or self._mspec._rocminfo is None:
|
||||
return
|
||||
|
||||
# load stats from rocminfo
|
||||
|
||||
+301
-170
@@ -36,10 +36,11 @@ import pandas as pd
|
||||
|
||||
from datetime import datetime
|
||||
from math import ceil
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import dataclass, field, asdict, fields
|
||||
from pathlib import Path as path
|
||||
from textwrap import dedent
|
||||
from utils.utils import error, get_hbm_stack_num, get_version
|
||||
from utils.tty import get_table_string
|
||||
|
||||
VERSION_LOC = [
|
||||
"version",
|
||||
@@ -52,129 +53,264 @@ VERSION_LOC = [
|
||||
"version-utils",
|
||||
]
|
||||
|
||||
@dataclass
|
||||
def detect_arch(_rocminfo):
|
||||
from omniperf_base import SUPPORTED_ARCHS
|
||||
|
||||
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():
|
||||
error("[profiling] Cannot find a supported arch in rocminfo")
|
||||
else:
|
||||
return (gpu_arch, idx1)
|
||||
|
||||
def generate_machine_specs(args, sysinfo:dict=None):
|
||||
if not sysinfo is None:
|
||||
sysinfo_ver = str(sysinfo['version'])
|
||||
version = get_version(config.omniperf_home)['version']
|
||||
if sysinfo_ver != version[:version.find(".")]:
|
||||
logging.warning("WARNING: Detected mismatch in sysinfo versioning. You may need to reprofile to update data.")
|
||||
return MachineSpecs(**sysinfo)
|
||||
# read timestamp info
|
||||
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 + ")"
|
||||
hostname = socket.gethostname()
|
||||
|
||||
# set specs version
|
||||
vData = get_version(config.omniperf_home)
|
||||
version = vData["version"]
|
||||
# NB: Just taking major as specs version. May want to make this more specific in the future
|
||||
specs_version = version[:version.find(".")] # version will always follow 'major.minor.patch' format
|
||||
|
||||
##########################################
|
||||
## 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()
|
||||
cpu_model = search(r"^model name\s*: (.*?)$", cpuinfo)
|
||||
sbios = path("/sys/class/dmi/id/bios_vendor").read_text().strip() + \
|
||||
path("/sys/class/dmi/id/bios_version").read_text().strip()
|
||||
linux_kernel_version = search(r"version (\S*)", version)
|
||||
amd_gpu_kernel_version = "" #TODO: Extract amdgpu kernel version
|
||||
cpu_memory = search(r"MemTotal:\s*(\S*)", meminfo)
|
||||
gpu_memory = "" #TODO: Extract gpu memory
|
||||
linux_distro = search(r'PRETTY_NAME="(.*?)"', os_release)
|
||||
if linux_distro is None:
|
||||
linux_distro = ""
|
||||
rocm_version = get_rocm_ver().strip()
|
||||
#FIXME: use 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 is None:
|
||||
compute_partition = "NA"
|
||||
memory_partition = search(
|
||||
r"Memory Partition:\s*(\w+)", run(["rocm-smi", "--showmemorypartition"]))
|
||||
if memory_partition is None:
|
||||
memory_partition = "NA"
|
||||
|
||||
##########################################
|
||||
## B. SoC Specs
|
||||
##########################################
|
||||
# read rocminfo
|
||||
rocminfo_full = run(["rocminfo"])
|
||||
_rocminfo = rocminfo_full.split("\n")
|
||||
gpu_arch, idx = detect_arch(_rocminfo)
|
||||
_rocminfo = _rocminfo[idx + 1 :] # update rocminfo for target section
|
||||
specs = MachineSpecs(version=specs_version,
|
||||
timestamp=timestamp,
|
||||
_rocminfo=_rocminfo,
|
||||
hostname=hostname,
|
||||
cpu_model=cpu_model,
|
||||
sbios=sbios,
|
||||
linux_kernel_version=linux_kernel_version,
|
||||
amd_gpu_kernel_version=amd_gpu_kernel_version,
|
||||
cpu_memory=cpu_memory,
|
||||
gpu_memory=gpu_memory,
|
||||
linux_distro=linux_distro,
|
||||
rocm_version=rocm_version,
|
||||
vbios=vbios,
|
||||
compute_partition=compute_partition,
|
||||
memory_partition=memory_partition,
|
||||
gpu_arch=gpu_arch)
|
||||
# Load above SoC specs via module import
|
||||
try:
|
||||
soc_module = importlib.import_module('omniperf_soc.soc_'+ specs.gpu_arch)
|
||||
except ModuleNotFoundError as e:
|
||||
error("Arch %s marked as supported, but couldn't find class implementation %s." % (specs.gpu_arch, e))
|
||||
soc_class = getattr(soc_module, specs.gpu_arch+'_soc')
|
||||
soc_obj = soc_class(args, specs)
|
||||
# Update arch specific specs
|
||||
specs.total_l2_chan: str = total_l2_banks(
|
||||
specs.gpu_model, int(specs._l2_banks), specs.memory_partition
|
||||
)
|
||||
specs.hbm_bw: str = str(int(specs.max_mclk) / 1000 * 32 * specs.get_hbm_channels())
|
||||
return specs
|
||||
|
||||
@dataclass(kw_only=True)
|
||||
class MachineSpecs:
|
||||
def __init__(self, args, sysinfo:dict=None):
|
||||
if not sysinfo is None:
|
||||
sysinfo_ver = str(sysinfo['specs_version'][0])
|
||||
version = get_version(config.omniperf_home)['version']
|
||||
if sysinfo_ver != version[:version.find(".")]:
|
||||
logging.warning("WARNING: Detected mismatch in sysinfo versioning. You may need to reprofile to update data.")
|
||||
for key, value in sysinfo.items():
|
||||
setattr(self, key, value[0])
|
||||
return
|
||||
# set specs version
|
||||
vData = get_version(config.omniperf_home)
|
||||
version = vData["version"]
|
||||
# NB: Just taking major as specs version. May want to make this more specific in the future
|
||||
self.specs_version = version[:version.find(".")] # version will alway follow 'major.minor.patch' format
|
||||
##########################################
|
||||
## A. Workload / Spec info
|
||||
##########################################
|
||||
|
||||
# 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 + ")"
|
||||
# these three fields are special in that they're not included
|
||||
# when you use (e.g.,) --specs to view the machinespecs, but they
|
||||
# _are_ included in profiling/analysis, so we mark them as 'optional'
|
||||
# in the metadata to avoid erroring out on missing fields on
|
||||
# serialization
|
||||
workload_name: str = field(default=None, metadata={
|
||||
'doc': 'The name of the workload data was collected for.',
|
||||
'name': 'Workload Name',
|
||||
'optional': True})
|
||||
command: str = field(default=None, metadata={
|
||||
'doc': 'The command the workload was executed with.',
|
||||
'name': 'Command',
|
||||
'optional': True})
|
||||
ip_blocks: str = field(default=None, metadata={
|
||||
'doc': 'The hardware blocks profiling information was collected for.',
|
||||
'name': 'IP Blocks',
|
||||
'optional': True
|
||||
})
|
||||
timestamp: str = field(default=None, metadata={
|
||||
'doc': 'The time (in local system time) when data was collected',
|
||||
'name': 'Timestamp'})
|
||||
version: str = field(default=None, metadata={
|
||||
'doc': 'The version of the machine specification file format.',
|
||||
'name': 'MachineSpecs Version'})
|
||||
timestamp: str = field(default=None, metadata={
|
||||
'doc': 'The time (in local system time) when data was collected',
|
||||
'name': 'Timestamp'})
|
||||
_rocminfo: list = field(default=None)
|
||||
##########################################
|
||||
## A. Machine Specs
|
||||
##########################################
|
||||
hostname: str = field(default=None, metadata={'doc': 'The hostname of the machine.',
|
||||
'name': 'Hostname'})
|
||||
cpu_model: str = field(default=None, metadata={'doc': 'The model name of the CPU used.',
|
||||
'name': 'CPU Model'})
|
||||
sbios: str = field(default=None, metadata={'doc': 'The system management bios version and vendor.',
|
||||
'name': "SBIOS"})
|
||||
linux_distro: str = field(default=None, metadata={'doc': 'The Linux distribution installed on the machine.',
|
||||
'name': 'Linux Distribution'})
|
||||
linux_kernel_version: str = field(default=None,
|
||||
metadata={'doc': 'The Linux kernel version running on the machine.',
|
||||
'name': 'Linux Kernel Version'})
|
||||
amd_gpu_kernel_version: str = field(default=None, metadata={
|
||||
'doc': '[RESERVED] The version of the AMDGPU driver installed on the machine. Unimplemented.',
|
||||
'name': "AMD GPU Kernel Version"})
|
||||
cpu_memory: str = field(default=None, metadata={
|
||||
'doc': 'The total amount of memory available to the CPU.', 'unit': 'KB',
|
||||
'name': 'CPU Memory'})
|
||||
gpu_memory: str = field(default=None, metadata={
|
||||
'doc': '[RESERVED] The total amount of memory available to accelerators/GPUs in the system. Unimplemented.',
|
||||
'unit': 'KB',
|
||||
'name': 'GPU Memory'})
|
||||
rocm_version: str = field(default=None,
|
||||
metadata={'doc': 'The ROCm version used during data-collection.',
|
||||
'name': "ROCm Version"})
|
||||
vbios: str = field(default=None,
|
||||
metadata={'doc': 'The version of the accelerators/GPUs video bios in the system.',
|
||||
'name': 'VBIOS'})
|
||||
compute_partition: str = field(default=None,
|
||||
metadata={'doc': 'The compute partitioning mode active on the accelerators/GPUs in the system (MI300 only).',
|
||||
'name': 'Compute Partition'})
|
||||
memory_partition: str = field(default=None,
|
||||
metadata={'doc': 'The memory partitioning mode active on the accelerators/GPUs in the system (MI300 only).',
|
||||
'name': 'Memory Partition'})
|
||||
|
||||
# read rocminfo
|
||||
rocminfo_full = run(["rocminfo"])
|
||||
self._rocminfo = rocminfo_full.split("\n")
|
||||
##########################################
|
||||
## B. SoC Specs
|
||||
##########################################
|
||||
gpu_model: str = field(
|
||||
default=None,
|
||||
metadata={
|
||||
'doc': 'The product name of the accelerators/GPUs in the system.',
|
||||
'name': 'GPU Model'})
|
||||
gpu_arch: str = field(
|
||||
default=None,
|
||||
metadata={
|
||||
'doc': 'The architecture name of the accelerators/GPUs in the system,\n'
|
||||
'as used by (e.g.,) the AMDGPU backed of LLVM.',
|
||||
'name': 'GPU Arch'})
|
||||
gpu_l1: str = field(default=None, metadata={'doc':
|
||||
"The size of the vL1D cache (per compute-unit) on the accelerators/GPUs in the system in KiB",
|
||||
'name': 'GPU L1'})
|
||||
gpu_l2: str = field(default=None, metadata={'doc':
|
||||
"The size of the vL1D cache (per compute-unit) on the accelerators/GPUs in the system in KiB",
|
||||
'name': 'GPU L2'})
|
||||
cu_per_gpu: str = field(default=None, metadata={'doc':
|
||||
"The total number of compute units per accelerator/GPU in the system. On systems with configurable\n"
|
||||
"partitioning, (e.g., MI300) this is the total number of compute units in a partition.",
|
||||
'name': 'CU per GPU'})
|
||||
simd_per_cu: str = field(default=None, metadata={'doc':
|
||||
"The number of SIMD processors in a compute unit for the accelerators/GPUs in the system.",
|
||||
'name': 'SIMD per CU'})
|
||||
se_per_gpu: str = field(default=None, metadata={'doc':
|
||||
'The number of shader engines on the accelerators/GPUs in the system. On systems with configurable\n'
|
||||
'partitioning, (e.g., MI300) this is the total number of shader engines in a partition.',
|
||||
'name': 'SE per GPU'})
|
||||
wave_size: str = field(default=None, metadata={'doc':
|
||||
'The number work-items in a wavefront on the accelerators/GPUs in the system.',
|
||||
'name': 'Wave Size'})
|
||||
workgroup_max_size: str = field(default=None, metadata={'doc':
|
||||
'The maximum number of work-items in a workgroup on the accelerators/GPUs in the system.',
|
||||
'name': 'Workgroup Max Size'})
|
||||
max_waves_per_cu: str = field(default=None, metadata={'doc':
|
||||
'The maximum number of wavefronts that can be resident on a compute unit on the\n'
|
||||
'accelerators/GPUs in the system',
|
||||
'name': 'Max Waves per CU'})
|
||||
max_sclk: str = field(default=None, metadata={'doc':
|
||||
'The maximum engine (compute-unit) clock rate of the accelerators/GPUs in the system.',
|
||||
'name': 'Max SCLK',
|
||||
'unit': 'MHz'})
|
||||
max_mclk: str = field(default=None, metadata={'doc':
|
||||
'The maximum memory clock rate of the accelerators/GPUs in the system.',
|
||||
'name': 'Max MCLK',
|
||||
'unit': 'MHz'})
|
||||
cur_sclk: str = field(default=None, metadata={'doc':
|
||||
'[RESERVED] The current engine (compute unit) clock rate of the accelerators/GPUs in the system. Unused.',
|
||||
'name': 'Max SCLK',
|
||||
'unit': 'MHz'})
|
||||
cur_mclk: str = field(default=None, metadata={'doc':
|
||||
'[RESERVED] The current memory clock rate of the accelerators/GPUs in the system. Unused.',
|
||||
'name': 'Max MCLK',
|
||||
'unit': 'MHz'})
|
||||
_l2_banks: str = None # NB: This only used in flatten_tcc_info_across_hbm_stacks()
|
||||
total_l2_chan: str = field(default=None, metadata={
|
||||
'doc': 'The maximum number of L2 cache channels on the accelerators/GPUs in the system. On systems with\n'
|
||||
'configurable partitioning, (e.g., MI300) this is the total number of L2 cache channels in a partition.',
|
||||
'name': 'Total L2 Channels'})
|
||||
lds_banks_per_cu: str = field(default=None, metadata={'doc':
|
||||
'The number of banks in the LDS for a compute unit on the accelerators/GPUs in the system.',
|
||||
'name': 'LDS Banks per CU'})
|
||||
sqc_per_gpu: str = field(default=None, metadata={
|
||||
'doc': 'The number of L1I/sL1D caches on the accelerators/GPUs in the system. On systems with\n'
|
||||
'configurable partitioning, (e.g., MI300) this is the total number of L1I/sL1D caches in a partition.',
|
||||
'name': 'SQC per GPU'})
|
||||
pipes_per_gpu: str = field(default=None, metadata={
|
||||
'doc': 'The number of scheduler-pipes on the accelerators/GPUs in the system.',
|
||||
'name': 'Pipes per GPU'})
|
||||
hbm_bw: str = field(default=None, metadata={
|
||||
'doc': 'The peak theoretical HBM bandwidth for the accelerators/GPUs in the system. On systems with\n'
|
||||
'configurable partitioning, (e.g., MI300) this is the peak theoretical HBM bandwidth for a partition.',
|
||||
'name': 'HBM BW',
|
||||
'unit': 'MB/s'})
|
||||
num_xcd: str = field(default=None, metadata={
|
||||
'doc': 'The total number of accelerator complex dies in a compute partition on the accelerators/GPUs in the\n'
|
||||
'system. For accelerators without partitioning (i.e., pre-MI300), this is considered to be one.',
|
||||
'name': 'Num XCDs',
|
||||
'unit': 'MB/s'})
|
||||
|
||||
##########################################
|
||||
## 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_model: 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.linux_kernel_version: str = search(r"version (\S*)", version)
|
||||
self.amd_gpu_kernel_version: str = None
|
||||
if self.amd_gpu_kernel_version is None: #TODO: Extract amdgpu kernel version
|
||||
self.amd_gpu_kernel_version = ""
|
||||
self.cpu_memory: str = search(r"MemTotal:\s*(\S*)", meminfo)
|
||||
self.gpu_memory: str = None #TODO: Extract total gpu memory
|
||||
if self.gpu_memory is None:
|
||||
self.gpu_memory = ""
|
||||
self.linux_distro: str = search(r'PRETTY_NAME="(.*?)"', os_release)
|
||||
if self.linux_distro is None:
|
||||
self.linux_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.gpu_arch: str = self.detect_arch()[0]
|
||||
self.gpu_l1: str = None
|
||||
self.gpu_l2: str = None
|
||||
self.cu_per_gpu: str = None
|
||||
self.simd_per_cu: str = None
|
||||
self.se_per_gpu: 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_model: str = None
|
||||
self._l2_banks: str = None #NB: This only used in flatten_tcc_info_across_hbm_stacks()
|
||||
self.lds_banks_per_cu: str = None
|
||||
self.sqc_per_gpu: str = None
|
||||
self.pipes_per_gpu: str = None
|
||||
self.total_l2_chan: str = None
|
||||
self.hbm_bw: str = None
|
||||
self.num_xcd: str = None
|
||||
# Load above SoC specs via module import
|
||||
try:
|
||||
soc_module = importlib.import_module('omniperf_soc.soc_'+ self.gpu_arch)
|
||||
except ModuleNotFoundError as e:
|
||||
error("Arch %s marked as supported, but couldn't find class implementation %s." % (self.gpu_arch, e))
|
||||
soc_class = getattr(soc_module, self.gpu_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.total_l2_chan: str = total_l2_banks(
|
||||
self.gpu_model, int(self._l2_banks), self.memory_partition
|
||||
)
|
||||
self.hbm_bw: 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.total_l2_chan)
|
||||
if (
|
||||
@@ -189,60 +325,55 @@ class MachineSpecs:
|
||||
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.gpu_arch}. Expecting populated {attr_name} but detected None.")
|
||||
all_populated = False
|
||||
data[attr_name] = attr_value
|
||||
for field in fields(self):
|
||||
name = field.name
|
||||
if not name.startswith("_"):
|
||||
value = getattr(self, name)
|
||||
if value is None:
|
||||
# check if we've marked it optional
|
||||
if field.metadata and 'optional' in field.metadata and field.metadata['optional']:
|
||||
pass
|
||||
else:
|
||||
#TODO: use proper logging function when that's merged
|
||||
logging.warning(
|
||||
f"WARNING: Incomplete class definition for {self.gpu_arch}. "
|
||||
f"Expecting populated {name} but detected None.")
|
||||
all_populated = False
|
||||
data[name] = value
|
||||
|
||||
if not all_populated:
|
||||
error("Missing specs fields for %s" % self.gpu_arch)
|
||||
return pd.DataFrame(data, index=[0])
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return dedent(
|
||||
f"""\
|
||||
Specs version: v{self.specs_version}
|
||||
Host info:
|
||||
Hostname: {self.hostname}
|
||||
CPU Model: {self.cpu_model}
|
||||
sbios: {self.sbios}
|
||||
CPU Memory: {self.cpu_memory}
|
||||
GPU Memory: {self.gpu_memory}
|
||||
Linux Distro: {self.linux_distro}
|
||||
Linux Kernel Version: {self.linux_kernel_version}
|
||||
AMD GPU Kernel Version: {self.amd_gpu_kernel_version}
|
||||
ROCm Version: {self.rocm_version}
|
||||
Device info:
|
||||
GPU Model: {self.gpu_model}
|
||||
GPU Arch: {self.gpu_arch}
|
||||
vbios: {self.vbios}
|
||||
GPU L1: {self.gpu_l1} KB
|
||||
GPU L2: {self.gpu_l2} KB
|
||||
Max SCLK: {self.max_sclk} MHz
|
||||
Max MCLK: {self.max_mclk} MHz
|
||||
Cur SCLK: {self.cur_sclk} MHz
|
||||
Cur MCLK: {self.cur_mclk} MHz
|
||||
CU per GPU: {self.cu_per_gpu}
|
||||
SIMD per CU: {self.simd_per_cu}
|
||||
SE per GPU: {self.se_per_gpu}
|
||||
Wave Size: {self.wave_size}
|
||||
Workgroup Max Size: {self.workgroup_max_size}
|
||||
Max Waves per CU: {self.max_waves_per_cu}
|
||||
Total L2 Channels: {self.total_l2_chan}
|
||||
LDS Banks per CU: {self.lds_banks_per_cu}
|
||||
SQC per GPU: {self.sqc_per_gpu}
|
||||
Pipes per GPU: {self.pipes_per_gpu}
|
||||
HBM BW: {self.hbm_bw} MB/s
|
||||
Compute Partition: {self.compute_partition}
|
||||
Memory Partition: {self.memory_partition}
|
||||
Num XCDs: {self.num_xcd}
|
||||
"""
|
||||
)
|
||||
def __repr__(self):
|
||||
data = []
|
||||
for field in fields(self):
|
||||
name = field.name
|
||||
if not name.startswith("_"):
|
||||
_data = {}
|
||||
value = getattr(self, name)
|
||||
if field.metadata:
|
||||
if 'name' in field.metadata:
|
||||
name = field.metadata['name']
|
||||
if 'unit' in field.metadata:
|
||||
_data['Unit'] = field.metadata['unit']
|
||||
if 'doc' in field.metadata:
|
||||
_data['Description'] = field.metadata['doc']
|
||||
_data['Spec'] = name
|
||||
_data['Value'] = value
|
||||
data.append(_data)
|
||||
df = pd.DataFrame(data)
|
||||
columns = ['Spec', 'Value']
|
||||
if 'Description' in df.columns:
|
||||
columns += ['Description']
|
||||
if 'Unit' in df.columns:
|
||||
columns += ['Unit']
|
||||
df = df[columns]
|
||||
df = df.fillna('')
|
||||
return (
|
||||
"Machine Specifications: describing the state of the machine that Omniperf data was collected on." +
|
||||
"\n" +
|
||||
get_table_string(df, transpose=False, decimal=2))
|
||||
|
||||
|
||||
def get_rocm_ver():
|
||||
@@ -350,4 +481,4 @@ def total_xcds(archname, compute_partition):
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(MachineSpecs())
|
||||
print(generate_machine_specs())
|
||||
|
||||
+11
-12
@@ -50,6 +50,13 @@ def string_multiple_lines(source, width, max_rows):
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def get_table_string(df, transpose=False, decimal=2):
|
||||
return tabulate(df.transpose() if transpose else df,
|
||||
headers="keys",
|
||||
tablefmt="fancy_grid",
|
||||
floatfmt="." + str(decimal) + "f")
|
||||
|
||||
|
||||
def show_all(args, runs, archConfigs, output):
|
||||
"""
|
||||
Show all panels with their data in plain text mode.
|
||||
@@ -214,19 +221,11 @@ def show_all(args, runs, archConfigs, output):
|
||||
# df when load it, because we need those items in column.
|
||||
# For metric_table, we only need to show the data in column
|
||||
# fash for now.
|
||||
transpose = (type != "raw_csv_table"
|
||||
and "columnwise" in table_config
|
||||
and table_config["columnwise"] == True)
|
||||
ss += (
|
||||
tabulate(
|
||||
(
|
||||
df.transpose()
|
||||
if type != "raw_csv_table"
|
||||
and "columnwise" in table_config
|
||||
and table_config["columnwise"] == True
|
||||
else df
|
||||
),
|
||||
headers="keys",
|
||||
tablefmt="fancy_grid",
|
||||
floatfmt="." + str(args.decimal) + "f",
|
||||
)
|
||||
get_table_string(df, transpose=transpose, decimal=args.decimal)
|
||||
+ "\n"
|
||||
)
|
||||
|
||||
|
||||
+2
-2
@@ -299,8 +299,8 @@ def gen_sysinfo(workload_name, workload_dir, ip_blocks, app_cmd, skip_roof, roof
|
||||
df = mspec.get_class_members()
|
||||
|
||||
# Append workload information to machine specs
|
||||
df.insert(0, 'command', app_cmd)
|
||||
df.insert(0,'workload_name', workload_name)
|
||||
df['command'] = app_cmd
|
||||
df['workload_name'] = workload_name
|
||||
|
||||
blocks = []
|
||||
if ip_blocks == None:
|
||||
|
||||
新增問題並參考
封鎖使用者