Files
TheRock/rocm-systems/projects/rocprofiler-compute/tests/test_mem_chart.py
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

721 lines
24 KiB
Python

# Copyright (c) Advanced Micro Devices, Inc.
# SPDX-License-Identifier: MIT
"""
Unit tests for memory-chart renderers.
Covers:
- mem_chart_gfx11.py - RDNA3.5 (Rich-based) memory architecture visualization
- mem_chart_gfx9.py - CDNA (plotille-based) memory architecture visualization
"""
import re
import common
import pytest
from utils import mem_chart_gfx9, mem_chart_gfx11
DEFAULT_TITLE = "3. Memory Chart (Normalization: per_kernel)"
# =============================================================================
# Tests for format_bw_human_readable function (gfx11)
# =============================================================================
class TestFormatBwHumanReadable:
"""Tests for format_bw_human_readable - converts Bytes/s to human-readable."""
def test_terabytes_per_second(self):
"""Test TB/s formatting for values >= 1e12."""
# 1 TB/s
result = mem_chart_gfx11.format_bw_human_readable(1e12, "Bytes/s", 1)
assert result == "1.0 TB/s"
# 2.5 TB/s
result = mem_chart_gfx11.format_bw_human_readable(2.5e12, "Bytes/s", 1)
assert result == "2.5 TB/s"
# Large value with higher precision
result = mem_chart_gfx11.format_bw_human_readable(1.234e12, "Bytes/s", 2)
assert result == "1.23 TB/s"
def test_gigabytes_per_second(self):
"""Test GB/s formatting for values >= 1e9 and < 1e12."""
# 1 GB/s
result = mem_chart_gfx11.format_bw_human_readable(1e9, "Bytes/s", 1)
assert result == "1.0 GB/s"
# 100 GB/s (typical HBM bandwidth)
result = mem_chart_gfx11.format_bw_human_readable(100e9, "Bytes/s", 1)
assert result == "100.0 GB/s"
# 512.5 GB/s
result = mem_chart_gfx11.format_bw_human_readable(512.5e9, "Bytes/s", 1)
assert result == "512.5 GB/s"
def test_megabytes_per_second(self):
"""Test MB/s formatting for values >= 1e6 and < 1e9."""
# 1 MB/s
result = mem_chart_gfx11.format_bw_human_readable(1e6, "Bytes/s", 1)
assert result == "1.0 MB/s"
# 500 MB/s
result = mem_chart_gfx11.format_bw_human_readable(500e6, "Bytes/s", 1)
assert result == "500.0 MB/s"
def test_kilobytes_per_second(self):
"""Test KB/s formatting for values >= 1e3 and < 1e6."""
# 1 KB/s
result = mem_chart_gfx11.format_bw_human_readable(1e3, "Bytes/s", 1)
assert result == "1.0 KB/s"
# 512 KB/s
result = mem_chart_gfx11.format_bw_human_readable(512e3, "Bytes/s", 1)
assert result == "512.0 KB/s"
def test_bytes_per_second(self):
"""Test B/s formatting for values < 1e3."""
# 500 B/s
result = mem_chart_gfx11.format_bw_human_readable(500, "Bytes/s", 1)
assert result == "500.0 B/s"
# 0 B/s
result = mem_chart_gfx11.format_bw_human_readable(0, "Bytes/s", 1)
assert result == "0.0 B/s"
def test_legacy_gbps_unit_conversion(self):
"""Test conversion from legacy GB/s unit to human-readable."""
# Input is 100 GB/s, should convert to Bytes/s first then format
result = mem_chart_gfx11.format_bw_human_readable(100, "GB/s", 1)
assert result == "100.0 GB/s"
# 1500 GB/s -> 1.5 TB/s
result = mem_chart_gfx11.format_bw_human_readable(1500, "GB/s", 1)
assert result == "1.5 TB/s"
def test_none_value(self):
"""Test handling of None values."""
result = mem_chart_gfx11.format_bw_human_readable(None, "Bytes/s", 1)
assert result == "N/A"
def test_invalid_string_value(self):
"""Test handling of non-numeric string values."""
result = mem_chart_gfx11.format_bw_human_readable("invalid", "Bytes/s", 1)
assert result == "N/A"
def test_precision_parameter(self):
"""Test different precision values."""
value = 123.456789e9 # 123.456789 GB/s
assert (
mem_chart_gfx11.format_bw_human_readable(value, "Bytes/s", 0) == "123 GB/s"
)
assert (
mem_chart_gfx11.format_bw_human_readable(value, "Bytes/s", 1)
== "123.5 GB/s"
)
assert (
mem_chart_gfx11.format_bw_human_readable(value, "Bytes/s", 2)
== "123.46 GB/s"
)
assert (
mem_chart_gfx11.format_bw_human_readable(value, "Bytes/s", 3)
== "123.457 GB/s"
)
# =============================================================================
# Tests for format_value function (gfx11)
# =============================================================================
class TestFormatValue:
"""Tests for format_value - general value formatting."""
def test_percentage_formatting(self):
"""Test percentage formatting."""
result = mem_chart_gfx11.format_value(85.5, "%", 1)
assert result == "85.5%"
result = mem_chart_gfx11.format_value(100, "%", 0)
assert result == "100%"
def test_bytes_per_second_unit(self):
"""Test Bytes/s formatting routes to human-readable."""
result = mem_chart_gfx11.format_value(100e9, "Bytes/s", 1)
assert "GB/s" in result
def test_gbps_unit(self):
"""Test GB/s formatting routes to human-readable."""
result = mem_chart_gfx11.format_value(100, "GB/s", 1)
assert "GB/s" in result
def test_none_value(self):
"""Test handling of None values."""
result = mem_chart_gfx11.format_value(None, "%", 1)
assert result == "N/A"
def test_string_value_conversion(self):
"""Test conversion of string values to float."""
result = mem_chart_gfx11.format_value("50.5", "%", 1)
assert result == "50.5%"
def test_invalid_string_value(self):
"""Test handling of non-convertible string values."""
result = mem_chart_gfx11.format_value("invalid", "%", 1)
assert result == "invalid"
# =============================================================================
# Tests for format_sci function (gfx11)
# =============================================================================
class TestFormatSci:
"""Tests for format_sci - scientific notation formatting."""
def test_small_numbers_no_scientific(self):
"""Test that small numbers are displayed as integers."""
assert mem_chart_gfx11.format_sci(100) == "100"
assert mem_chart_gfx11.format_sci(999) == "999"
def test_large_numbers_scientific(self):
"""Test that large numbers are displayed in scientific notation."""
result = mem_chart_gfx11.format_sci(1000000)
assert "e" in result.lower()
result = mem_chart_gfx11.format_sci(12345678, 2)
assert "e" in result.lower()
def test_none_value(self):
"""Test handling of None values."""
result = mem_chart_gfx11.format_sci(None)
assert result == "N/A"
def test_invalid_value(self):
"""Test handling of invalid values."""
result = mem_chart_gfx11.format_sci("invalid")
assert result == "N/A"
def test_negative_numbers(self):
"""Test negative number handling."""
result = mem_chart_gfx11.format_sci(-500)
assert result == "-500"
result = mem_chart_gfx11.format_sci(-1000000)
assert "e" in result.lower()
# =============================================================================
# Tests for bar function (gfx11)
# =============================================================================
class TestBar:
"""Tests for bar - progress bar visualization."""
def test_full_bar(self):
"""Test 100% progress bar."""
result = mem_chart_gfx11.bar(100, 10)
assert "█" * 10 in result
assert "░" not in result
def test_empty_bar(self):
"""Test 0% progress bar."""
result = mem_chart_gfx11.bar(0, 10)
assert "░" * 10 in result
assert "█" not in result
def test_partial_bar(self):
"""Test 50% progress bar."""
result = mem_chart_gfx11.bar(50, 10)
assert "█" * 5 in result
assert "░" * 5 in result
def test_none_value(self):
"""Test None value returns empty bar."""
result = mem_chart_gfx11.bar(None, 10)
assert "░" * 10 in result
def test_invalid_value(self):
"""Test invalid value returns empty bar."""
result = mem_chart_gfx11.bar("invalid", 10)
assert "░" * 10 in result
def test_over_100_clamped(self):
"""Test values over 100% are clamped."""
result = mem_chart_gfx11.bar(150, 10)
assert "█" * 10 in result
def test_negative_clamped(self):
"""Test negative values are clamped to 0."""
result = mem_chart_gfx11.bar(-50, 10)
assert "░" * 10 in result
# =============================================================================
# Tests for metric_line function (gfx11)
# =============================================================================
class TestMetricLine:
"""Tests for metric_line - formatted metric display."""
def test_basic_metric(self):
"""Test basic metric line formatting."""
result = mem_chart_gfx11.metric_line("Util", 75.5, "%", "green")
assert "Util" in result
assert "75.5%" in result
assert "green" in result
def test_with_none_value(self):
"""Test metric line with None value."""
result = mem_chart_gfx11.metric_line("BW", None, "GB/s", "cyan")
assert "BW" in result
assert "N/A" in result
# =============================================================================
# Tests for get_sample_metrics function (gfx11)
# =============================================================================
class TestGetSampleMetrics:
"""Tests for get_sample_metrics - returns sample test data."""
def test_returns_dict(self):
"""Test that sample metrics returns a dictionary."""
metrics = mem_chart_gfx11.get_sample_metrics()
assert isinstance(metrics, dict)
def test_contains_key_metrics(self):
"""Test that sample metrics contains expected keys."""
metrics = mem_chart_gfx11.get_sample_metrics()
# Check for key bandwidth metrics
assert "TCP-GL1 Read Bandwidth" in metrics
assert "GL1-GL2 Read Bandwidth" in metrics
assert "GL2 Cache Read BW" in metrics
assert "DRAM Read Bandwidth" in metrics
# Check for utilization metrics
assert "GL1 Cache Utilization" in metrics
assert "GL2 Cache Utilization" in metrics
# Check for hit rate metrics
assert "GL0 Cache Hit Rate (TCP Cache)" in metrics
assert "GL1 Cache Hit Rate" in metrics
assert "GL2 Cache Hit Rate" in metrics
def test_bandwidth_values_in_bytes_per_second(self):
"""Test that bandwidth values are in Bytes/s format."""
metrics = mem_chart_gfx11.get_sample_metrics()
# TCP-GL1 Read Bandwidth should be 96 GB/s = 96e9 Bytes/s
assert metrics["TCP-GL1 Read Bandwidth"] == 96e9
# DRAM Read Bandwidth should be 100 GB/s = 100e9 Bytes/s
assert metrics["DRAM Read Bandwidth"] == 100e9
def test_returns_copy(self):
"""Test that sample metrics returns a copy (not the original)."""
metrics1 = mem_chart_gfx11.get_sample_metrics()
metrics2 = mem_chart_gfx11.get_sample_metrics()
# Modify metrics1 and verify metrics2 is not affected
metrics1["TCP-GL1 Read Bandwidth"] = 0
assert metrics2["TCP-GL1 Read Bandwidth"] == 96e9
# =============================================================================
# Tests for plot_mem_chart function (gfx11)
# =============================================================================
class TestPlotMemChartGfx11:
"""Tests for gfx11 plot_mem_chart - main chart generation."""
def test_returns_string(self):
"""Test that plot_mem_chart returns a string."""
metrics = mem_chart_gfx11.get_sample_metrics()
result = mem_chart_gfx11.plot_mem_chart(metrics, chart_title=DEFAULT_TITLE)
clean = common.strip_ansi(result)
assert isinstance(result, str)
assert len(result) > 0
assert "3. Memory Chart" in clean
assert "Normalization: per_kernel" in clean
assert "GPU" in clean and "System Memory" in clean
def test_contains_complete_rdna35_architecture(self):
"""RDNA3.5 output contains every rendered memory component."""
metrics = mem_chart_gfx11.get_sample_metrics()
output = common.strip_ansi(
mem_chart_gfx11.plot_mem_chart(metrics, chart_title=DEFAULT_TITLE)
)
expected_components = (
"Kernel",
"LDS",
"GL0 (TCP Cache)",
"SQC",
"GL1 Cache",
"GL2 Cache",
"GCEA",
"DRAM",
)
for component in expected_components:
assert component in output, f"Missing RDNA3.5 component: {component}"
def test_gfx115x_contains_heading_scope_and_directional_connectors(self):
"""RDNA3.5 output exposes chart scope and connector directions."""
metrics = mem_chart_gfx11.get_sample_metrics()
output = common.strip_ansi(
mem_chart_gfx11.plot_mem_chart(metrics, chart_title=DEFAULT_TITLE)
)
assert DEFAULT_TITLE in output
assert "GPU" in output
assert "System Memory" in output
assert "Read BW" in output
assert "Write BW" in output
assert "Atomic" in output
assert re.search(r"<(?!-+>)-{3,}", output)
assert re.search(r"(?<![<-])-{3,}>", output)
assert re.search(r"<-{3,}>", output)
def test_contains_bandwidth_values(self):
"""Test that output contains formatted bandwidth values."""
metrics = mem_chart_gfx11.get_sample_metrics()
result = mem_chart_gfx11.plot_mem_chart(metrics, chart_title=DEFAULT_TITLE)
# Should contain GB/s units since sample data uses GB/s range
assert "GB/s" in result
def test_normalize_mem_chart_metrics_flat_ordered(self):
"""Metrics are flattened to panel YAML order; extras dropped; missing None."""
raw = {"GL0 Cache Hit Rate (TCP Cache)": 1.0, "noise_key": 99}
norm = mem_chart_gfx11.normalize_mem_chart_metrics(raw)
assert list(norm.keys()) == list(mem_chart_gfx11.MEM_CHART_PANEL_METRIC_KEYS)
assert norm["GL0 Cache Hit Rate (TCP Cache)"] == 1.0
assert "noise_key" not in norm
assert norm["ICache Requests"] is None
def test_empty_metrics(self):
"""Test with empty metrics dictionary."""
result = mem_chart_gfx11.plot_mem_chart({}, chart_title=DEFAULT_TITLE)
# Should still produce output (with N/A values)
assert isinstance(result, str)
assert len(result) > 0
def test_partial_metrics(self):
"""Test with partial metrics (some missing)."""
partial_metrics = {
"TCP-GL1 Read Bandwidth": 50e9,
"GL1 Cache Utilization": 65.0,
# Missing many other metrics
}
result = mem_chart_gfx11.plot_mem_chart(
partial_metrics, chart_title=DEFAULT_TITLE
)
assert isinstance(result, str)
assert len(result) > 0
def test_extreme_bandwidth_values(self):
"""Test with extreme bandwidth values."""
extreme_metrics = {
"DRAM Read Bandwidth": 10e12, # 10 TB/s
"DRAM Write Bandwidth": 5e12, # 5 TB/s
}
result = mem_chart_gfx11.plot_mem_chart(
extreme_metrics, chart_title=DEFAULT_TITLE
)
assert "TB/s" in result
def test_zero_bandwidth_values(self):
"""Test with zero bandwidth values."""
zero_metrics = {
"DRAM Read Bandwidth": 0,
"DRAM Write Bandwidth": 0,
}
result = mem_chart_gfx11.plot_mem_chart(zero_metrics, chart_title=DEFAULT_TITLE)
assert "B/s" in result # Zero formats as "0.0 B/s"
# =============================================================================
# Tests for DEFAULT_SAMPLE_METRICS constant (gfx11)
# =============================================================================
class TestDefaultSampleMetrics:
"""Tests for DEFAULT_SAMPLE_METRICS constant."""
def test_keys_match_mem_chart_panel_yaml(self):
"""Keys match gfx1151 Memory Chart YAML (MEM_CHART_PANEL_METRIC_KEYS)."""
assert set(mem_chart_gfx11.DEFAULT_SAMPLE_METRICS) == set(
mem_chart_gfx11.MEM_CHART_PANEL_METRIC_KEYS
)
assert len(mem_chart_gfx11.DEFAULT_SAMPLE_METRICS) == len(
mem_chart_gfx11.MEM_CHART_PANEL_METRIC_KEYS
)
def test_all_bandwidth_values_positive(self):
"""Test that all bandwidth values are positive."""
for key, value in mem_chart_gfx11.DEFAULT_SAMPLE_METRICS.items():
if "Bandwidth" in key:
assert value >= 0, f"{key} should be non-negative"
def test_all_rate_values_in_range(self):
"""Test that rate/percentage values are in valid range."""
for key, value in mem_chart_gfx11.DEFAULT_SAMPLE_METRICS.items():
if "Rate" in key or "Utilization" in key:
assert 0 <= value <= 100, f"{key} should be between 0 and 100"
def test_has_all_memory_hierarchy_levels(self):
"""Test that all memory hierarchy levels are represented."""
metrics = mem_chart_gfx11.DEFAULT_SAMPLE_METRICS
# GL0 (TCP)
assert any("TCP" in k for k in metrics.keys())
# LDS
assert any("LDS" in k for k in metrics.keys())
# GL1 Cache
assert any("GL1" in k for k in metrics.keys())
# GL2 Cache
assert any("GL2" in k for k in metrics.keys())
# DRAM
assert any("DRAM" in k for k in metrics.keys())
# =============================================================================
# Integration Tests (gfx11)
# =============================================================================
class TestIntegrationGfx11:
"""Integration tests for complete gfx11 workflows."""
def test_full_workflow_with_sample_data(self):
"""Test complete workflow with sample data."""
# Get sample metrics
metrics = mem_chart_gfx11.get_sample_metrics()
# Generate chart
chart = mem_chart_gfx11.plot_mem_chart(
metrics,
chart_title="3. Memory Chart (Normalization: per_dispatch)",
)
# Verify chart contains expected elements
assert isinstance(chart, str)
assert len(chart) > 100 # Should be substantial output
assert "Kernel" in chart
assert "Legend" in chart
def test_bandwidth_unit_consistency(self):
"""Test that bandwidth units are consistently formatted."""
# Create metrics with known bandwidth values
metrics = {
"TCP-GL1 Read Bandwidth": 100e9, # 100 GB/s
"TCP-GL1 Write Bandwidth": 50e9, # 50 GB/s
"GL1-GL2 Read Bandwidth": 75e9, # 75 GB/s
"GL1-GL2 Write Bandwidth": 25e9, # 25 GB/s
"DRAM Read Bandwidth": 200e9, # 200 GB/s
"DRAM Write Bandwidth": 100e9, # 100 GB/s
}
chart = mem_chart_gfx11.plot_mem_chart(metrics, chart_title=DEFAULT_TITLE)
# All values should show in GB/s since they're in that range
assert chart.count("GB/s") >= 6
def test_mixed_bandwidth_scales(self):
"""Test chart with mixed bandwidth scales."""
metrics = {
"DRAM Read Bandwidth": 1.5e12, # 1.5 TB/s
"GL2 Cache Read BW": 500e9, # 500 GB/s
"GL1-GL2 Read Bandwidth": 100e6, # 100 MB/s
"TCP-GL1 Read Bandwidth": 50e3, # 50 KB/s
}
chart = mem_chart_gfx11.plot_mem_chart(metrics, chart_title=DEFAULT_TITLE)
# Should contain multiple unit types
assert "TB/s" in chart
assert "GB/s" in chart
# =============================================================================
# Tests for plot_mem_chart function (gfx9)
# =============================================================================
GFX9_SAMPLE_METRICS = {
"Wavefront Occupancy": 1,
"Wave Life": 2,
"SALU": 3,
"SMEM": 4,
"VALU": 5,
"Matrix Ops": 6,
"VMEM": 7,
"LDS": 8,
"GWS": 9,
"BR": 10,
"Active CUs": 11,
"Num CUs": 12,
"VGPR": 13,
"SGPR": 14,
"LDS Allocation": 15,
"Scratch Allocation": 16,
"Wavefronts": 17,
"Workgroups": 18,
"LDS Req": 19,
"LDS Util": 20,
"LDS Latency": 21,
"VL1 Rd": 22,
"VL1 Wr": 23,
"VL1 Atomic": 24,
"VL1 Hit": 25,
"VL1 Lat": 26,
"VL1 Coalesce": 27,
"VL1 Stall": 28,
"sL1D Rd": 29,
"sL1D Hit": 30,
"sL1D Lat": 31,
"IL1 Fetch": 32,
"IL1 Hit": 33,
"IL1 Lat": 34,
"VL1_L2 Rd": 36,
"VL1_L2 Wr": 37,
"VL1_L2 Atomic": 38,
"sL1D_L2 Rd": 39,
"sL1D_L2 Wr": 40,
"sL1D_L2 Atomic": 41,
"IL1_L2 Rd": 42,
"L2 Hit": 43,
"L2 Rd": 44,
"L2 Wr": 45,
"L2 Atomic": 46,
"L2 Rd Lat": 47,
"L2 Wr Lat": 48,
"Fabric_L2 Rd": 49,
"Fabric_L2 Wr": 50,
"Fabric_L2 Atomic": 51,
"Fabric Rd Lat": 52,
"Fabric Wr Lat": 53,
"Fabric Atomic Lat": 54,
"HBM Rd": 55,
"HBM Wr": 56,
}
class TestPlotMemChartGfx9:
"""Tests for gfx9 plot_mem_chart - CDNA memory chart generation."""
def test_returns_non_empty_string(self):
"""Full sample metrics produce a non-empty chart string."""
result = mem_chart_gfx9.plot_mem_chart(
dict(GFX9_SAMPLE_METRICS), chart_title=DEFAULT_TITLE
)
assert isinstance(result, str)
assert len(result) > 0
def test_empty_metrics(self):
"""Empty metric dict still produces a non-empty chart (N/A placeholders)."""
result = mem_chart_gfx9.plot_mem_chart({}, chart_title=DEFAULT_TITLE)
assert isinstance(result, str)
assert len(result) > 0
def test_partial_metrics(self):
"""Partial metric dict still produces a non-empty chart."""
partial = {
"Wavefront Occupancy": 4,
"L2 Hit": 75,
"HBM Rd": 100,
}
result = mem_chart_gfx9.plot_mem_chart(partial, chart_title=DEFAULT_TITLE)
assert isinstance(result, str)
assert len(result) > 0
def test_contains_complete_cdna_architecture(self):
"""CDNA output contains every component enabled by the renderer."""
output = common.strip_ansi(
mem_chart_gfx9.plot_mem_chart(
dict(GFX9_SAMPLE_METRICS),
chart_title=DEFAULT_TITLE,
)
)
expected_components = (
"Instr Buff",
"Instr Dispatch",
"Exec",
"LDS",
"Vector L1 Cache",
"Scalar L1D Cache",
"Instr L1 Cache",
"L2 Cache",
"xGMI/PCIe",
"Fabric",
"HBM",
)
for component in expected_components:
assert component in output, f"Missing CDNA component: {component}"
assert re.search(r"(?<!x)GMI(?!/PCIe)", output)
def test_gfx9_heading_outside_chart_and_directional_connectors(self):
"""CDNA output prints the heading once outside the chart, with connectors."""
output = common.strip_ansi(
mem_chart_gfx9.plot_mem_chart(
dict(GFX9_SAMPLE_METRICS),
chart_title=DEFAULT_TITLE,
)
)
output_lines = output.splitlines()
assert output_lines[0] == DEFAULT_TITLE
assert "3. Memory Chart" not in "\n".join(output_lines[1:])
assert "Instr Buff" in output_lines[4]
assert output.count("(Normalization: per_kernel)") == 1
for connector_label in ("Req", "Fetch", "Rd", "Wr", "Atomic"):
assert connector_label in output
assert re.search(r"<(?!-+>)-{3,}", output)
assert re.search(r"(?<![<-])-{3,}>", output)
assert re.search(r"<-{3,}>", output)
@pytest.mark.parametrize(
("renderer", "metrics"),
[
pytest.param(
mem_chart_gfx11.plot_mem_chart,
mem_chart_gfx11.get_sample_metrics(),
id="gfx115x",
),
pytest.param(
mem_chart_gfx9.plot_mem_chart,
dict(GFX9_SAMPLE_METRICS),
id="gfx9",
),
],
)
def test_chart_title_appears_as_first_line(renderer, metrics):
"""Both renderers print the caller's chart_title as the first line."""
chart_title = "7. Memory Chart (Normalization: per_kernel)"
output = common.strip_ansi(renderer(metrics, chart_title=chart_title))
assert output.strip().splitlines()[0] == chart_title
assert "3. Memory Chart" not in output