Add chip specs (#681)

* Add perfmon config spec, enhance memory partition info.

* Add gfx950 perfmon config.

* Add High Freq variants in gfx942.

* Add backup detection methods for gpu model.

* Improve get_num_xcds logic by adding detection of 1to1 arch-to-compute_partition logic.

* Add default compute partition settings spx:8 for when gpu_model=None.

* Update gpu spec tests.

* Add backup compute partition detection.

---------

Signed-off-by: xuchen-amd <xuchen@amd.com>
This commit is contained in:
xuchen-amd
2025-05-29 16:35:34 -04:00
committed by GitHub
parent 45296ceb46
commit f0fad19e8b
13 changed files with 527 additions and 177 deletions
+62 -1
View File
@@ -186,12 +186,73 @@ class OmniSoC_Base:
self._mspec.gpu_model = mi_gpu_specs.get_gpu_model(
self._mspec.gpu_arch, self._mspec.gpu_chip_id
)
if not self._mspec.gpu_model:
self._mspec.gpu_model = self.detect_gpu_model(self._mspec.gpu_arch)
self._mspec.num_xcd = str(
mi_gpu_specs.get_num_xcds(
self._mspec.gpu_model, self._mspec.compute_partition
self._mspec.gpu_arch, self._mspec.gpu_model, self._mspec.compute_partition
)
)
@demarcate
def detect_gpu_model(self, gpu_arch):
"""
Detects the GPU model using various identifiers from 'amd-smi static'.
Falls back through multiple methods if the primary method fails.
"""
from utils.specs import run, search
# TODO: use amd-smi python api when available
amd_smi_static = run(["amd-smi", "static", "--gpu=0"], exit_on_error=True)
# Purposely search for patterns without variants suffix to try and match a known GPU model.
detection_methods = [
{
"name": "Market Name",
"pattern": r"MARKET_NAME:\s*.*(mi|MI\d*[a-zA-Z]*)",
},
{
"name": "VBIOS Name",
"pattern": r"NAME:\s*.*(mi|MI\d*[a-zA-Z]*)",
},
{"name": "Product Name", "pattern": r"PRODUCT_NAME:\s*.*(mi|MI\d*[a-zA-Z]*)"},
]
gpu_model = None
for method in detection_methods:
console_log(f"Determining GPU model using {method['name']}.")
gpu_model = search(method["pattern"], amd_smi_static)
if gpu_model:
break
if not gpu_model:
console_warning("Unable to determine the GPU model.")
return
gpu_model = self._adjust_mi300_model(gpu_model.lower(), gpu_arch.lower())
if gpu_model.lower() not in mi_gpu_specs.get_num_xcds_dict().keys():
console_warning(f"Unknown GPU model detected: '{gpu_model}'.")
return
return gpu_model.upper()
def _adjust_mi300_model(self, gpu_model, gpu_arch):
"""
Applies specific adjustments for MI300 series GPU models based on architecture.
"""
if gpu_model in ["mi300a", "mi300x"]:
if gpu_arch in ["gfx940", "gfx941"]:
gpu_model += "_a0"
elif gpu_arch == "gfx942":
gpu_model += "_a1"
return gpu_model
@demarcate
def detect_counters(self):
"""
+2 -17
View File
@@ -22,11 +22,9 @@
# SOFTWARE.
##############################################################################el
from pathlib import Path
import config
from rocprof_compute_soc.soc_base import OmniSoC_Base
from utils.logger import console_error, demarcate
from utils.mi_gpu_spec import mi_gpu_specs
class gfx906_soc(OmniSoC_Base):
@@ -35,20 +33,7 @@ class gfx906_soc(OmniSoC_Base):
self.set_arch("gfx906")
self.set_compatible_profilers(["rocprofv1", "rocscope"])
# Per IP block max number of simultaneous counters. GFX IP Blocks
self.set_perfmon_config(
{
"SQ": 8,
"TA": 2,
"TD": 2,
"TCP": 4,
"TCC": 4,
"CPC": 2,
"CPF": 2,
"SPI": 2,
"GRBM": 2,
"GDS": 4,
}
)
self.set_perfmon_config({mi_gpu_specs.get_perfmon_config("gfx906")})
# Set arch specific specs
self._mspec._l2_banks = 16
+2 -14
View File
@@ -27,6 +27,7 @@ from pathlib import Path
import config
from rocprof_compute_soc.soc_base import OmniSoC_Base
from utils.logger import console_error, demarcate
from utils.mi_gpu_spec import mi_gpu_specs
class gfx908_soc(OmniSoC_Base):
@@ -37,20 +38,7 @@ class gfx908_soc(OmniSoC_Base):
["rocprofv1", "rocscope", "rocprofv3", "rocprofiler-sdk"]
)
# Per IP block max number of simultaneous counters. GFX IP Blocks
self.set_perfmon_config(
{
"SQ": 8,
"TA": 2,
"TD": 2,
"TCP": 4,
"TCC": 4,
"CPC": 2,
"CPF": 2,
"SPI": 2,
"GRBM": 2,
"GDS": 4,
}
)
self.set_perfmon_config(mi_gpu_specs.get_perfmon_config("gfx908"))
# Set arch specific specs
self._mspec._l2_banks = 32
+2 -14
View File
@@ -28,6 +28,7 @@ import config
from rocprof_compute_soc.soc_base import OmniSoC_Base
from roofline import Roofline
from utils.logger import console_log, console_warning, demarcate
from utils.mi_gpu_spec import mi_gpu_specs
from utils.utils import mibench
@@ -50,20 +51,7 @@ class gfx90a_soc(OmniSoC_Base):
["rocprofv1", "rocscope", "rocprofv2", "rocprofv3", "rocprofiler-sdk"]
)
# Per IP block max number of simultaneous counters. GFX IP Blocks
self.set_perfmon_config(
{
"SQ": 8,
"TA": 2,
"TD": 2,
"TCP": 4,
"TCC": 4,
"CPC": 2,
"CPF": 2,
"SPI": 2,
"GRBM": 2,
"GDS": 4,
}
)
self.set_perfmon_config(mi_gpu_specs.get_perfmon_config("gfx90a"))
# Create roofline object if mode is provided; skip for --specs
if hasattr(self.get_args(), "mode") and self.get_args().mode:
self.roofline_obj = Roofline(args, self._mspec)
+2 -14
View File
@@ -28,6 +28,7 @@ import config
from rocprof_compute_soc.soc_base import OmniSoC_Base
from roofline import Roofline
from utils.logger import console_error, console_log, console_warning, demarcate
from utils.mi_gpu_spec import mi_gpu_specs
from utils.utils import mibench
@@ -50,20 +51,7 @@ class gfx940_soc(OmniSoC_Base):
["rocprofv1", "rocprofv2", "rocprofv3", "rocprofiler-sdk"]
)
# Per IP block max number of simultaneous counters. GFX IP Blocks
self.set_perfmon_config(
{
"SQ": 8,
"TA": 2,
"TD": 2,
"TCP": 4,
"TCC": 4,
"CPC": 2,
"CPF": 2,
"SPI": 2,
"GRBM": 2,
"GDS": 4,
}
)
self.set_perfmon_config(mi_gpu_specs.get_perfmon_config("gfx940"))
# Create roofline object if mode is provided; skip for --specs
if hasattr(self.get_args(), "mode") and self.get_args().mode:
self.roofline_obj = Roofline(args, self._mspec)
+2 -14
View File
@@ -28,6 +28,7 @@ import config
from rocprof_compute_soc.soc_base import OmniSoC_Base
from roofline import Roofline
from utils.logger import console_error, console_log, console_warning, demarcate
from utils.mi_gpu_spec import mi_gpu_specs
from utils.utils import mibench
@@ -50,20 +51,7 @@ class gfx941_soc(OmniSoC_Base):
["rocprofv1", "rocprofv2", "rocprofv3", "rocprofiler-sdk"]
)
# Per IP block max number of simultaneous counters. GFX IP Blocks
self.set_perfmon_config(
{
"SQ": 8,
"TA": 2,
"TD": 2,
"TCP": 4,
"TCC": 4,
"CPC": 2,
"CPF": 2,
"SPI": 2,
"GRBM": 2,
"GDS": 4,
}
)
self.set_perfmon_config(mi_gpu_specs.get_perfmon_config("gfx941"))
# Create roofline object if mode is provided; skip for --specs
if hasattr(self.get_args(), "mode") and self.get_args().mode:
self.roofline_obj = Roofline(args, self._mspec)
+2 -14
View File
@@ -28,6 +28,7 @@ import config
from rocprof_compute_soc.soc_base import OmniSoC_Base
from roofline import Roofline
from utils.logger import console_error, console_log, console_warning, demarcate
from utils.mi_gpu_spec import mi_gpu_specs
from utils.utils import mibench
@@ -50,20 +51,7 @@ class gfx942_soc(OmniSoC_Base):
["rocprofv1", "rocprofv2", "rocprofv3", "rocprofiler-sdk"]
)
# Per IP block max number of simultaneous counters. GFX IP Blocks
self.set_perfmon_config(
{
"SQ": 8,
"TA": 2,
"TD": 2,
"TCP": 4,
"TCC": 4,
"CPC": 2,
"CPF": 2,
"SPI": 2,
"GRBM": 2,
"GDS": 4,
}
)
self.set_perfmon_config(mi_gpu_specs.get_perfmon_config("gfx942"))
# Create roofline object if mode is provided; skip for --specs
if hasattr(self.get_args(), "mode") and self.get_args().mode:
self.roofline_obj = Roofline(args, self._mspec)
+4 -17
View File
@@ -27,8 +27,9 @@ from pathlib import Path
import config
from rocprof_compute_soc.soc_base import OmniSoC_Base
from roofline import Roofline
from utils.logger import demarcate
from utils.utils import console_error, console_log, console_warning, mibench
from utils.logger import console_error, console_log, console_warning, demarcate
from utils.mi_gpu_spec import mi_gpu_specs
from utils.utils import mibench
class gfx950_soc(OmniSoC_Base):
@@ -48,21 +49,7 @@ class gfx950_soc(OmniSoC_Base):
)
self.set_compatible_profilers(["rocprofv3", "rocprofiler-sdk"])
# Per IP block max number of simultaneous counters. GFX IP Blocks
self.set_perfmon_config(
{
"SQ": 8,
"TA": 2,
"TD": 2,
"TCP": 4,
"TCC": 4,
"CPC": 2,
"CPF": 2,
"SPI": 2,
"GRBM": 2,
"GDS": 4,
"TCC_channels": 16,
}
)
self.set_perfmon_config(mi_gpu_specs.get_perfmon_config("gfx950"))
# Create roofline object if mode is provided; skip for --specs
if hasattr(self.get_args(), "mode") and self.get_args().mode:
self.roofline_obj = Roofline(args, self._mspec)
+150 -33
View File
@@ -1,10 +1,10 @@
import os
from dataclasses import dataclass, field
from dataclasses import dataclass
from typing import Any, Dict
import yaml
from utils.logger import console_debug, console_error, console_log, console_warning
from utils.logger import console_debug, console_error, console_warning
# Constants for MI series
# NOTE: Currently supports MI50, MI100, MI200, MI300
@@ -32,10 +32,15 @@ MI_CONSTANS = {
class MIGPUSpecs:
_instance = None
_gpu_series_dict = {} # key: gpu arch
_gpu_series_dict = {} # key: gpu_arch
_gpu_model_dict = {} # key: gpu_arch
_num_xcds_dict = {} # key: gpu model
_chip_id_dict = {} # key: chip id (int)
_num_xcds_dict = {} # key: gpu_model
_chip_id_dict = {} # key: chip_id (int)
_perfmon_config = {} # key: gpu_arch
_gpu_arch_to_compute_partition_dict = (
{}
) # key: gpu_arch, used for gpu archs containing only one gpu model and thus one compute partition
_initialized = False
@@ -88,9 +93,14 @@ class MIGPUSpecs:
MI GPUs
|-- series
|-- architecture (list)
|-- perfmon_config
|-- gpu model
|-- chip_ids
| -- physical
| -- virtual
|-- partition_mode
| -- compute partition mode
| -- memory partition mode
"""
current_dir = os.path.dirname(__file__)
@@ -105,6 +115,7 @@ class MIGPUSpecs:
for archs in series["gpu_archs"]:
curr_gpu_arch = archs["gpu_arch"]
cls._gpu_series_dict[curr_gpu_arch] = curr_gpu_series
cls._perfmon_config[curr_gpu_arch] = archs["perfmon_config"]
cls._gpu_model_dict[curr_gpu_arch] = []
for models in archs["models"]:
curr_gpu_model = models["gpu_model"]
@@ -119,6 +130,28 @@ class MIGPUSpecs:
if "chip_ids" in models and "virtual" in models["chip_ids"]:
cls._chip_id_dict[models["chip_ids"]["virtual"]] = curr_gpu_model
# detect gpu arch to compute partition relationships
cls._populate_gpu_arch_to_compute_partition_dict()
@classmethod
def _populate_gpu_arch_to_compute_partition_dict(cls):
"""
This creates a mapping of gpu_arch -> compute_partition for architectures
where there's only one model (and therefore one partition configuration).
"""
for gpu_arch, gpu_models in cls._gpu_model_dict.items():
if len(gpu_models) == 1:
single_model = gpu_models[0]
compute_partition = cls._num_xcds_dict.get(single_model)
if compute_partition is not None:
cls._gpu_arch_to_compute_partition_dict[gpu_arch] = compute_partition
console_debug(
"[populate_single_arch_partition_dict] Single model arch found: "
"%s -> %s (partition: %s)"
% (gpu_arch, single_model, compute_partition)
)
@classmethod
def get_gpu_series_dict(cls):
if not cls._gpu_series_dict:
@@ -146,6 +179,19 @@ class MIGPUSpecs:
console_warning(f"No matching gpu series found for gpu arch: {gpu_arch_}")
return None
@classmethod
def get_perfmon_config(cls, gpu_arch_):
# Check that gpu_model_dict is populated first
if not cls._perfmon_config:
console_error(
"gpu_model_dict not yet populated. Did you run parse_mi_gpu_spec()?"
)
return None
gpu_arch_lower = gpu_arch_.lower()
return cls._perfmon_config.get(gpu_arch_lower, None)
@classmethod
def get_gpu_model(cls, gpu_arch_, chip_id_):
# Check that gpu_model_dict is populated first
@@ -180,38 +226,99 @@ class MIGPUSpecs:
return gpu_model.upper()
@classmethod
def get_num_xcds(cls, gpu_model_, compute_partition_):
# Only gpu in and above mi 300 series have more than one XCDs
if gpu_model_.lower() in ("mi50", "mi60", "mi100", "mi210", "mi250", "mi250x"):
def set_default_gpu_settings(self, gpu_arch, gpu_model, compute_partition):
"""
Set default GPU settings when model is unknown or cannot be determined.
NOTE: This is a fallback to gfx942 settings - consider making this architecture-specific.
"""
DEFAULT_COMPUTE_PARTITION = "SPX"
DEFAULT_NUM_XCD = 8
console_warning(
f"Unable to determine xcd count from:\n\t"
f"GPU arch: '{gpu_arch}', model: '{gpu_model}', partition: '{compute_partition}'"
)
console_warning(
f"Applying default gfx942 settings:\n"
f"\t- Compute partition: {DEFAULT_COMPUTE_PARTITION}\n"
f"\t- Number of XCDs: {DEFAULT_NUM_XCD}"
)
return DEFAULT_NUM_XCD
@classmethod
def get_num_xcds(
cls, gpu_arch: str = None, gpu_model: str = None, compute_partition: str = None
):
"""
Retrieve the number of XCDs based on GPU architecture, model, and compute partition.
Priority order:
1. Legacy GPU check (returns 1 XCD for older architectures/models)
2. Architecture-based lookup (preferred)
3. Model + partition-based lookup (fallback)
4. Default settings (last resort)
"""
# Constants for legacy GPUs that don't support compute partitions
LEGACY_ARCHS = {"gfx906", "gfx908", "gfx90a"}
LEGACY_MODELS = {"mi50", "mi60", "mi100", "mi210", "mi250", "mi250x"}
# Normalize inputs to lowercase for consistent comparison
gpu_arch_norm = gpu_arch.lower().strip() if gpu_arch else ""
gpu_model_norm = gpu_model.lower().strip() if gpu_model else ""
partition_norm = compute_partition.lower().strip() if compute_partition else ""
# 1. Return 1 XCDs for archs/models not supporting compute partition
# NOTE: gpu arch is enough to verify this logic, gpu model is used as a backup.
if gpu_arch_norm in LEGACY_ARCHS or gpu_model_norm in LEGACY_MODELS:
return 1
if not cls._num_xcds_dict:
console_error(
"mi300_num_xcds_dict not yet populated, did you run parse_mi_gpu_spec()?"
)
return None
# 2. Try architecture-based lookup first (preferred method)
if gpu_arch_norm and hasattr(cls, "_gpu_arch_to_compute_partition_dict"):
arch_dict = cls._gpu_arch_to_compute_partition_dict
if gpu_arch_norm in arch_dict:
num_xcds = arch_dict[gpu_arch_norm]
if num_xcds is not None:
return num_xcds
else:
console_warning(
f"No compute partition data found for architecture '{gpu_arch.upper()}'"
)
gpu_model_lower = gpu_model_.lower()
partition_lower = compute_partition_.lower()
# 3. Fall back to model + partition-based lookup
if gpu_model_norm:
# Validate XCD dictionary is populated
if not hasattr(cls, "_num_xcds_dict") or not cls._num_xcds_dict:
console_error(
"mi300_num_xcds_dict not populated. Did you run parse_mi_gpu_spec()?"
)
elif gpu_model_norm not in cls._num_xcds_dict:
console_warning(
f"Unknown gpu model provided for num xcds lookup: {gpu_model}."
)
else:
model_dict = cls._num_xcds_dict[gpu_model_norm]
if gpu_model_lower not in cls._num_xcds_dict:
return None
if not partition_norm:
console_warning(
"No compute partition provided for model-based lookup"
)
elif partition_norm not in model_dict:
console_warning(
f"Unknown compute partition '{compute_partition}' for model '{gpu_model}'"
)
else:
num_xcds = model_dict[partition_norm]
if num_xcds is not None:
return num_xcds
else:
console_warning(
f"Unknown compute partition found for {compute_partition} / {gpu_model}"
)
else:
console_warning("No gpu model provided for num xcds lookup.")
model_dict = cls._num_xcds_dict[gpu_model_lower]
if partition_lower not in model_dict:
console_log(f"Unknown compute partition: {compute_partition_}")
return None
num_xcds = model_dict[partition_lower]
if not num_xcds:
console_warning(
"Unknown compute partition found for %s / %s",
compute_partition_,
gpu_model_,
)
return None
return num_xcds
# 4. Last resort: use default settings
return cls.set_default_gpu_settings(gpu_arch, gpu_model, compute_partition)
@classmethod
def get_chip_id_dict(cls):
@@ -220,7 +327,17 @@ class MIGPUSpecs:
else:
console_error()
@classmethod
def get_num_xcds_dict(cls):
if cls._num_xcds_dict:
return cls._num_xcds_dict
else:
console_error()
@classmethod
def get_gpu_arch_to_compute_partition_dict(cls):
return cls._gpu_arch_to_compute_partition_dict
# pre-initialize the instance when module loads
mi_gpu_specs = MIGPUSpecs()
+223 -16
View File
@@ -9,8 +9,11 @@
# MI GPUs
# |-- series: the specific MI series; mi50, mi100, mi200, mi300
# |-- architecture: currently, only mi300 gpus hold different architectures
# |-- perfmon_config
# |-- gpu model
# |-- chip_ids: chip id is specific to the environment the gpu is being used on
# | -- physical
# | -- virtual
# |-- partition_mode
# | -- compute partition mode
# | -- memory partition mode
@@ -21,6 +24,17 @@ mi_gpu_spec:
- gpu_series: mi50
gpu_archs:
- gpu_arch: gfx906
perfmon_config:
SQ: 8
TA: 2
TD: 2
TCP: 4
TCC: 4
CPC: 2
CPF: 2
SPI: 2
GRBM: 2
GDS: 4
models:
- gpu_model: mi50
- gpu_model: mi60
@@ -28,6 +42,17 @@ mi_gpu_spec:
- gpu_series: mi100
gpu_archs:
- gpu_arch: gfx908
perfmon_config:
SQ: 8
TA: 2
TD: 2
TCP: 4
TCC: 4
CPC: 2
CPF: 2
SPI: 2
GRBM: 2
GDS: 4
models:
- gpu_model: mi100
chip_ids:
@@ -36,6 +61,17 @@ mi_gpu_spec:
- gpu_series: mi200
gpu_archs:
- gpu_arch: gfx90a
perfmon_config:
SQ: 8
TA: 2
TD: 2
TCP: 4
TCC: 4
CPC: 2
CPF: 2
SPI: 2
GRBM: 2
GDS: 4
models:
- gpu_model: mi210
chip_ids:
@@ -46,12 +82,21 @@ mi_gpu_spec:
- gpu_model: mi250x
chip_ids:
physical: 29704
- gpu_model: mi250
- gpu_model: mi250x
- gpu_series: mi300
gpu_archs:
- gpu_arch: gfx940
perfmon_config:
SQ: 8
TA: 2
TD: 2
TCP: 4
TCC: 4
CPC: 2
CPF: 2
SPI: 2
GRBM: 2
GDS: 4
models:
- gpu_model: mi300a_a0
partition_mode:
@@ -59,11 +104,29 @@ mi_gpu_spec:
num_xcds:
spx: 6
tpx: 2
cpx: 1
memory_partition_mode:
nps4: [tpx]
nps1: [spx, tpx]
nps4:
tpx: 3
nps1:
spx: 1
tpx: 3
chip_ids:
physical: null
virtual: null
- gpu_arch: gfx941
perfmon_config:
SQ: 8
TA: 2
TD: 2
TCP: 4
TCC: 4
CPC: 2
CPF: 2
SPI: 2
GRBM: 2
GDS: 4
models:
- gpu_model: mi300x_a0
partition_mode:
@@ -74,10 +137,31 @@ mi_gpu_spec:
qpx: 2
cpx: 1
memory_partition_mode:
nps4: [qpx, cpx]
nps1: [spx, qpx, cpx]
nps4:
qpx: 4
cpx: 8
nps2:
dpx: 2
nps1:
spx: 1
qpx: 4
cpx: 8
chip_ids:
physical: null
virtual: null
- gpu_arch: gfx942
perfmon_config:
SQ: 8
TA: 2
TD: 2
TCP: 4
TCC: 4
CPC: 2
CPF: 2
SPI: 2
GRBM: 2
GDS: 4
models:
- gpu_model: mi300a_a1
partition_mode:
@@ -85,9 +169,14 @@ mi_gpu_spec:
num_xcds:
spx: 6
tpx: 2
cpx: 1
memory_partition_mode:
nps4: [tpx]
nps1: [spx, tpx]
nps4:
tpx: 3
nps1:
spx: 1
tpx: 3
cpx: 8
chip_ids:
physical: 29856
virtual: 29876
@@ -101,12 +190,41 @@ mi_gpu_spec:
qpx: 2
cpx: 1
memory_partition_mode:
nps4: [qpx, cpx]
nps1: [spx, qpx, cpx]
nps4:
qpx: 4
cpx: 8
nps2:
dpx: 2
nps1:
spx: 1
qpx: 4
cpx: 8
chip_ids:
physical: 29857
virtual: 29877
- gpu_model: mi300xhf
partition_mode:
compute_partition_mode:
num_xcds:
spx: 8
dpx: 4
qpx: 2
cpx: 1
memory_partition_mode:
nps4:
qpx: 4
cpx: 8
nps2:
dpx: 2
nps1:
spx: 1
qpx: 4
cpx: 8
chip_ids:
physical: 29865
virtual: 29885
- gpu_model: mi308x
partition_mode:
compute_partition_mode:
@@ -115,12 +233,34 @@ mi_gpu_spec:
dpx: 2
cpx: 1
memory_partition_mode:
nps4: [cpx]
nps1: [spx, dpx, cpx]
nps4:
cpx: 8
nps1:
spx: 1
qpx: 4
cpx: 8
chip_ids:
physical: 29858
virtual: 29878
- gpu_model: mi308xhf
partition_mode:
compute_partition_mode:
num_xcds:
spx: 4
dpx: 2
cpx: 1
memory_partition_mode:
nps4:
cpx: 8
nps1:
spx: 1
qpx: 4
cpx: 8
chip_ids:
physical: 29864
virtual: 29884
- gpu_model: mi325x
partition_mode:
compute_partition_mode:
@@ -130,8 +270,15 @@ mi_gpu_spec:
qpx: 2
cpx: 1
memory_partition_mode:
nps4: [qpx, cpx]
nps1: [spx, qpx, cpx]
nps4:
qpx: 4
cpx: 8
nps2:
dpx: 2
nps1:
spx: 1
qpx: 4
cpx: 8
chip_ids:
physical: 29861
virtual: 29881
@@ -139,6 +286,18 @@ mi_gpu_spec:
- gpu_series: mi350
gpu_archs:
- gpu_arch: gfx950
perfmon_config:
SQ: 8
TA: 2
TD: 2
TCP: 4
TCC: 4
CPC: 2
CPF: 2
SPI: 2
GRBM: 2
GDS: 4
TCC_channels: 16
models:
- gpu_model: mi350
partition_mode:
@@ -149,7 +308,55 @@ mi_gpu_spec:
qpx: 2
cpx: 1
memory_partition_mode:
nps1: [spx, dpx, qpx, cpx]
nps4: [qpx, cpx]
nps4:
qpx: 4
cpx: 8
nps2:
dpx: 2
nps1:
spx: 1
qpx: 4
cpx: 8
chip_ids:
physical: 30112
virutal: 30128
- gpu_model: mi355
partition_mode:
compute_partition_mode:
num_xcds:
spx: 8
dpx: 4
qpx: 2
cpx: 1
memory_partition_mode:
nps4:
qpx: 4
cpx: 8
nps2:
dpx: 2
nps1:
spx: 1
qpx: 4
cpx: 8
chip_ids:
physical: 30115
virtual: 30131
- gpu_model: mi358
partition_mode:
compute_partition_mode:
num_xcds:
spx: 8
dpx: 4
qpx: 2
cpx: 1
memory_partition_mode:
nps4:
qpx: 4
cpx: 8
nps1:
spx: 1
qpx: 4
cpx: 8
chip_ids:
physical: 30114
virtual: 30130
+42 -16
View File
@@ -38,13 +38,7 @@ from pathlib import Path as path
import pandas as pd
import config
from utils.logger import (
console_debug,
console_error,
console_log,
console_warning,
demarcate,
)
from utils.logger import console_debug, console_error, console_log, console_warning
from utils.mi_gpu_spec import mi_gpu_specs
from utils.tty import get_table_string
from utils.utils import get_version
@@ -158,15 +152,40 @@ def generate_machine_specs(args, sysinfo: dict = None):
rocm_version = get_rocm_ver().strip()
# FIXME: use device
amd_smi_output = run(["amd-smi", "static"], exit_on_error=True)
vbios_pattern = r"PART_NUMBER:\s*(\S+)"
compute_partition_pattern = r"COMPUTE_PARTITION:\s*(\S+)"
accelerator_partition_pattern = r"ACCELERATOR_PARTITION:\s*(\S+)"
memory_partition_pattern = r"MEMORY_PARTITION:\s*(\S+)"
vbios = search(vbios_pattern, run(["amd-smi", "static"], exit_on_error=True))
compute_partition = search(compute_partition_pattern, run(["amd-smi", "static"]))
rocm_smi_compute_partition_output = run(
["rocm-smi", "--showcomputepartition"], exit_on_error=True
)
rocm_smi_compute_partition_pattern = r"Compute Partition:\s*(\S+)"
vbios = search(vbios_pattern, amd_smi_output)
# 1. get compute partition from amd-smi
compute_partition = search(compute_partition_pattern, amd_smi_output)
console_debug(f"amd-smi compute partition: {compute_partition}")
# 2. get compute partition from rocm-smi
if compute_partition is None:
compute_partition = "NA"
memory_partition = search(memory_partition_pattern, run(["amd-smi", "static"]))
compute_partition = search(
rocm_smi_compute_partition_pattern, rocm_smi_compute_partition_output
)
console_debug(f"rocm-smi compute partition: {compute_partition}")
# 3. get compute partition from amd-smi using keyword accelerator
if compute_partition is None:
compute_partition = search(accelerator_partition_pattern, amd_smi_output)
console_debug(f"amd-smi accelerator partition: {compute_partition}")
# 4. apply default compute partition
if compute_partition is None:
console_warning(
f"Can not detect compute/accelerator partition from amd-smi and rocm-smi."
)
console_warning(f"Applying default compute partition: SPX")
compute_partition = "SPX"
memory_partition = search(memory_partition_pattern, amd_smi_output)
if memory_partition is None:
memory_partition = "NA"
@@ -216,8 +235,12 @@ def generate_machine_specs(args, sysinfo: dict = None):
soc_class = getattr(soc_module, specs.gpu_arch + "_soc")
soc_obj = soc_class(args, specs)
# Update arch specific specs
specs.gpu_model = mi_gpu_specs.get_gpu_model(specs.gpu_arch, specs.gpu_chip_id)
specs.num_xcd = mi_gpu_specs.get_num_xcds(
specs.gpu_arch, specs.gpu_model, specs.compute_partition
)
specs.total_l2_chan: str = total_l2_banks(
specs.gpu_model, int(specs._l2_banks), specs.compute_partition
specs.gpu_arch, specs.gpu_model, specs._l2_banks, specs.compute_partition
)
specs.num_hbm_channels: str = str(specs.get_hbm_channels())
return specs
@@ -673,10 +696,13 @@ def total_sqc(archname, numCUs, numSEs):
return int(sq_per_se) * int(numSEs)
def total_l2_banks(archname, L2Banks, compute_partition):
xcds = mi_gpu_specs.get_num_xcds(archname, compute_partition)
totalL2Banks = L2Banks * xcds
return totalL2Banks
def total_l2_banks(gpu_arch, gpu_model, L2Banks, compute_partition):
xcd_count = mi_gpu_specs.get_num_xcds(gpu_arch, gpu_model, compute_partition)
# TODO: MachineSpecs and OmniSoC mspec should converge...
if L2Banks is not None and xcd_count is not None:
return int(L2Banks) * int(xcd_count)
return None
if __name__ == "__main__":
+3 -1
View File
@@ -756,7 +756,9 @@ def run_prof(
if new_env and not using_v3() and not using_v1():
# flatten tcc for applicable mi300 input
f = path(workload_dir + "/out/pmc_1/results_" + fbase + ".csv")
xcds = mi_gpu_specs.get_num_xcds(mspec.gpu_model, mspec.compute_partition)
xcds = mi_gpu_specs.get_num_xcds(
mspec.gpu_arch, mspec.gpu_model, mspec.compute_partition
)
df = flatten_tcc_info_across_xcds(f, xcds, int(mspec._l2_banks))
df.to_csv(f, index=False)
+31 -6
View File
@@ -22,6 +22,10 @@ GFX942_CHIP_IDS_TO_NUM_XCDS = {
"29878": {"spx": 4, "dpx": 2, "cpx": 1},
"29861": {"spx": 8, "dpx": 4, "qpx": 2, "cpx": 1},
"29881": {"spx": 8, "dpx": 4, "qpx": 2, "cpx": 1},
"29864": {"spx": 4, "dpx": 2, "cpx": 1},
"29884": {"spx": 4, "dpx": 2, "cpx": 1},
"29865": {"spx": 8, "dpx": 4, "qpx": 2, "cpx": 1},
"29885": {"spx": 8, "dpx": 4, "qpx": 2, "cpx": 1},
}
# helper to strip ANSI color codes if your app uses them
@@ -91,17 +95,37 @@ def get_num_xcds():
if str(chip_id) in GFX942_CHIP_IDS_TO_NUM_XCDS.keys():
num_xcds = GFX942_CHIP_IDS_TO_NUM_XCDS[str(chip_id)]
if num_xcds is None:
return
return num_xcds
def get_gpu_arch():
rocminfo = str(
# decode with utf-8 to account for rocm-smi changes in latest rocm
subprocess.run(
["rocminfo"], stdout=subprocess.PIPE, stderr=subprocess.PIPE
).stdout.decode("utf-8")
)
rocminfo = rocminfo.split("\n")
soc_regex = re.compile(r"^\s*Name\s*:\s+ ([a-zA-Z0-9]+)\s*$", re.MULTILINE)
devices = list(filter(soc_regex.match, rocminfo))
gpu_arch = devices[0].split()[1]
return gpu_arch
@pytest.mark.num_xcds_spec_class
def test_num_xcds_spec_class(monkeypatch):
num_xcds = get_num_xcds()
# 1. Check if gfx942 soc
if not num_xcds:
gpu_arch = get_gpu_arch()
if gpu_arch is None or gpu_arch.lower() != "gfx942":
pytest.skip("Skipping num xcds test for non-gfx942 socs.")
num_xcds = get_num_xcds()
# 2. load machine specs
machine_spec = generate_machine_specs(None)
@@ -114,12 +138,13 @@ def test_num_xcds_spec_class(monkeypatch):
@pytest.mark.num_xcds_cli_output
def test_num_xcds_cli_output():
num_xcds = get_num_xcds()
# 1. Check if gfx942 soc
if not num_xcds:
gpu_arch = get_gpu_arch()
if gpu_arch is None or gpu_arch.lower() != "gfx942":
pytest.skip("Skipping num xcds test for non-gfx942 socs.")
num_xcds = get_num_xcds()
# 2. Run rocprof-compute -s and grab rocprof-compute num_xcd
proc = subprocess.run(
["rocprof-compute", "-s"],