Re-implementing HBM stack / XCD info for incoming product sku

Co-authored-by: Nicholas Curtis <nicholas.curtis@amd.com>
Signed-off-by: coleramos425 <colramos@amd.com>
This commit is contained in:
coleramos425
2024-06-03 17:04:32 +00:00
committed by Cole Ramos
parent 7c06b4d2ae
commit 295b344646
2 changed files with 70 additions and 88 deletions
+25 -53
View File
@@ -37,7 +37,7 @@ from math import ceil
from dataclasses import dataclass, field, fields
from pathlib import Path as path
from utils.utils import (
get_hbm_stack_num,
total_xcds,
get_version,
console_error,
console_warning,
@@ -184,7 +184,7 @@ def generate_machine_specs(args, sysinfo: dict = None):
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.gpu_model, int(specs._l2_banks), specs.compute_partition
)
specs.hbm_bw: str = str(int(specs.max_mclk) / 1000 * 32 * specs.get_hbm_channels())
return specs
@@ -480,7 +480,7 @@ class MachineSpecs:
"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",
"unit": "GB/s",
},
)
num_xcd: str = field(
@@ -489,17 +489,26 @@ class MachineSpecs:
"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",
"unit": "XCDs",
},
)
def get_hbm_channels(self):
hbmchannels = int(self.total_l2_chan)
if (
self.gpu_model.lower() == "mi300a_a0" or self.gpu_model.lower() == "mi300a_a1"
) and self.memory_partition.lower() == "nps1":
# we have an extra 32 channels for the CCD
hbmchannels += 32
# check MI300 has a valid compute partition
mi300a_archs = ["mi300a_a0", "mi300a_a1"]
mi300x_archs = ["mi300x_a0", "mi300x_a1"]
mi308x_archs = ["mi308x"]
if self.gpu_model.lower() in mi300a_archs + mi300x_archs + mi308x_archs:
hbmchannels = 128
if self.memory_partition.lower() == "nps2":
hbmchannels /= 2
elif self.memory_partition.lower() == "nps4":
hbmchannels /= 4
elif self.memory_partition.lower() == "nps8":
hbmchannels /= 8
return int(hbmchannels)
else:
hbmchannels = int(self.total_l2_chan)
return hbmchannels
def get_class_members(self):
@@ -618,17 +627,6 @@ def search(pattern, string):
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)
return str(totalL2Banks)
def total_sqc(archname, numCUs, numSEs):
cu_per_se = float(numCUs) / float(numSEs)
sq_per_se = cu_per_se / 2
@@ -638,38 +636,12 @@ def total_sqc(archname, numCUs, numSEs):
return int(sq_per_se) * int(numSEs)
def total_xcds(archname, compute_partition):
# check MI300 has a valid compute partition
mi300a_archs = ["mi300a_a0", "mi300a_a1"]
mi300x_archs = ["mi300x_a0", "mi300x_a1"]
if archname.lower() in mi300a_archs + mi300x_archs and compute_partition == "NA":
console_error("Invalid compute partition found for {}".format(archname))
if archname.lower() not in mi300a_archs + mi300x_archs:
return 1
# from the whitepaper
# https://www.amd.com/content/dam/amd/en/documents/instinct-tech-docs/white-papers/amd-cdna-3-white-paper.pdf
if compute_partition.lower() == "spx":
if archname.lower() in mi300a_archs:
return 6
if archname.lower() in mi300x_archs:
return 8
if compute_partition.lower() == "tpx":
if archname.lower() in mi300a_archs:
return 2
if compute_partition.lower() == "dpx":
if archname.lower() in mi300x_archs:
return 4
if compute_partition.lower() == "qpx":
if archname.lower() in mi300x_archs:
return 2
if compute_partition.lower() == "cpx":
if archname.lower() in mi300x_archs:
return 2
console_error(
"Unknown compute partition / arch found for {} / {}".format(
compute_partition, archname
)
)
def total_l2_banks(archname, L2Banks, compute_partition):
# Fixme: support all supported partitioning mode
# Fixme: "name" is a bad name!
totalL2Banks = L2Banks
xcds = total_xcds(archname, compute_partition)
return L2Banks * xcds
if __name__ == "__main__":
+45 -35
View File
@@ -285,8 +285,8 @@ def run_prof(fname, profiler_options, workload_dir, mspec, loglevel):
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(mspec.gpu_model, mspec.memory_partition)
df = flatten_tcc_info_across_hbm_stacks(f, hbm_stack_num, int(mspec._l2_banks))
xcds = total_xcds(mspec.gpu_model, mspec.compute_partition)
df = flatten_tcc_info_across_xcds(f, xcds, int(mspec._l2_banks))
df.to_csv(f, index=False)
if os.path.exists(workload_dir + "/out"):
@@ -492,9 +492,9 @@ def mibench(args, mspec):
)
def flatten_tcc_info_across_hbm_stacks(file, stack_num, tcc_channel_per_stack):
def flatten_tcc_info_across_xcds(file, xcds, tcc_channel_per_xcd):
"""
Flatten TCC per channel counters across all HBM stacks in used.
Flatten TCC per channel counters across all XCDs in partition.
NB: This func highly depends on the default behavior of rocprofv2 on MI300,
which might be broken anytime in the future!
"""
@@ -513,22 +513,22 @@ def flatten_tcc_info_across_hbm_stacks(file, stack_num, tcc_channel_per_stack):
cols = non_tcc_cols_orig
tcc_cols_in_group = {}
for i in range(0, stack_num):
for i in range(0, xcds):
tcc_cols_in_group[i] = []
for col in tcc_cols_orig:
for i in range(0, stack_num):
for i in range(0, xcds):
# filter the channel index only
p = re.compile(r"\[(\d+)\]")
# pick up the 1st element only
r = (
lambda match: "["
+ str(int(match.group(1)) + i * tcc_channel_per_stack)
+ str(int(match.group(1)) + i * tcc_channel_per_xcd)
+ "]"
)
tcc_cols_in_group[i].append(re.sub(pattern=p, repl=r, string=col))
for i in range(0, stack_num):
for i in range(0, xcds):
# print(tcc_cols_in_group[i])
cols += tcc_cols_in_group[i]
# print(cols)
@@ -537,7 +537,7 @@ def flatten_tcc_info_across_hbm_stacks(file, stack_num, tcc_channel_per_stack):
### Rearrange data with extended column names
# print(len(df_orig.index))
for idx in range(0, len(df_orig.index), stack_num):
for idx in range(0, len(df_orig.index), xcds):
# assume the front none TCC columns are the same for all XCCs
df_non_tcc = df_orig.iloc[idx].filter(regex=r"^(?!.*TCC).*$")
# display(df_non_tcc)
@@ -545,7 +545,7 @@ def flatten_tcc_info_across_hbm_stacks(file, stack_num, tcc_channel_per_stack):
# extract all tcc from one dispatch
# NB: assuming default contiguous order might not be safe!
df_tcc_all = df_orig.iloc[idx : (idx + stack_num)].filter(regex="TCC")
df_tcc_all = df_orig.iloc[idx : (idx + xcds)].filter(regex="TCC")
# display(df_tcc_all)
for idx, row in df_tcc_all.iterrows():
@@ -557,36 +557,46 @@ def flatten_tcc_info_across_hbm_stacks(file, stack_num, tcc_channel_per_stack):
return df
def get_hbm_stack_num(gpu_name, memory_partition):
"""
Get total HBM stack numbers based on memory partition for MI300.
"""
# TODO:
# - better err log
if gpu_name.lower() == "mi300a_a0" or gpu_name.lower() == "mi300a_a1":
if memory_partition.lower() == "nps1":
def total_xcds(archname, compute_partition):
# check MI300 has a valid compute partition
mi300a_archs = ["mi300a_a0", "mi300a_a1"]
mi300x_archs = ["mi300x_a0", "mi300x_a1"]
mi308x_archs = ["mi308x"]
if archname.lower() in mi300a_archs + mi300x_archs + mi308x_archs and compute_partition == "NA":
console_error("Invalid compute partition found for {}".format(archname))
if archname.lower() not in mi300a_archs + mi300x_archs + mi308x_archs:
return 1
# from the whitepaper
# https://www.amd.com/content/dam/amd/en/documents/instinct-tech-docs/white-papers/amd-cdna-3-white-paper.pdf
if compute_partition.lower() == "spx":
if archname.lower() in mi300a_archs:
return 6
elif memory_partition.lower() == "nps4":
return 2
elif memory_partition.lower() == "nps8":
return 1
else:
console_error("Invalid MI300A memory partition mode!")
elif gpu_name.lower() == "mi300x_a0" or gpu_name.lower() == "mi300x_a1":
if memory_partition.lower() == "nps1":
if archname.lower() in mi300x_archs:
return 8
elif memory_partition.lower() == "nps2":
if archname.lower() in mi308x_archs:
return 4
elif memory_partition.lower() == "nps4":
if compute_partition.lower() == "tpx":
if archname.lower() in mi300a_archs:
return 2
elif memory_partition.lower() == "nps8":
if compute_partition.lower() == "dpx":
if archname.lower() in mi300x_archs:
return 4
if archname.lower() in mi308x_archs:
return 2
if compute_partition.lower() == "qpx":
if archname.lower() in mi300x_archs:
return 2
if compute_partition.lower() == "cpx":
if archname.lower() in mi300x_archs:
return 2
if archname.lower() in mi308x_archs:
return 1
else:
console_error("Invalid MI300X memory partition mode!")
else:
# Fixme: add proper numbers for other archs
return -1
# TODO implement other archs here as needed
console_error(
"Unknown compute partition / arch found for {} / {}".format(
compute_partition, archname
)
)
def get_submodules(package_name):