agentleFS
ROCmROCm/rocprofiler-systems-skills/skills/verify-pmc-metrics/SKILL.md

verify-pmc-metrics

Skill5 starsChanged 18 days agoMITView on GitHub

Mock-based rigorous PMC metric validation — tests sentinel filtering, value ranges, and architecture-specific behavior across Perfetto and RocPD

  • Deletes or force-pushes

The file

We split this skill into the rules it gives an agent

7 rules. About 0 are common, 4 are distinctive, and 3 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈4

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 3

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Run ALL 6 test matrix entries (2 architectures x 3 formats).

    line 12
  2. Distinctive:

    Use rocprof-sys MCP tools for Perfetto traces, sqlite3 for RocPD databases.

    line 14
  3. Very specific:

    Verify mock support: ldd bin/rocprof-sys-run | grep yaml (yaml-cpp must be linked)

    line 134
  4. Very specific:

    Verify transpose workload exists

    line 136
  5. Very specific:

    Run 6 profiling sessions. Use /tmp/pmc-validate-<run-id>/ output paths.

    line 140
  6. Distinctive:

    Verify that all configured metrics appear in output with expected value ranges.

    line 230
  7. Distinctive:

    Verify that metrics NOT configured in the mock do NOT appear in output.

    line 313

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Mock-Based PMC Validation

Deterministic validation of AMD SMI Performance Monitoring Counter (PMC) metrics using the mock system (AMD_SMI_MOCK_CONFIG). Tests sentinel filtering, expected value ranges, positive presence of configured metrics, and negative absence of unsupported metrics across all output formats.

<IMPORTANT> - Execute all profiling and validation automatically — do NOT ask for user confirmation. - Run ALL 6 test matrix entries (2 architectures x 3 formats). - Sentinel detection is THE critical check — a single leaked sentinel is a FAIL. - Use rocprof-sys MCP tools for Perfetto traces, sqlite3 for RocPD databases. - Mock configs are in the worktree at `~/worktree/rocm-systems/amd-smi-mocks/`. </IMPORTANT>

Sentinel Value Reference

GPU firmware returns these values for unsupported/unavailable metrics. They must NEVER appear in output.

TypeHexDecimalFloat (Perfetto)Where Used
uint16_t0xFFFF6553565535.0Temperature, activity %, power, voltage, clocks, PCIe width/speed, VCN/JPEG arrays
uint32_t0xFFFFFFFF42949672954294967295.0Various 32-bit fields
uint64_t0xFFFFFFFFFFFFFFFF184467440737095516151.8446744073709552e+19PCIe bandwidth, XGMI data, memory

Perfetto stores counter values as doubles, so UINT64_MAX appears as 1.8446744073709552e+19. Both exact and float representations must be checked.

Known Sentinel Filtering Pipeline

Metricdevice.hppperfetto_policy.hppperfetto_processor.cpprocpd_processor.cpp
VCN/JPEG (uint16)Support check onlyFilteredFilteredNOT filtered
XGMI (uint64)Zeroed via populate_if_supported()N/ADouble-checkedFiltered
PCIe (uint16/64)Zeroed via populate_if_supported()N/ARelies on zero checkNOT filtered
NIC RDMAN/AN/ANo filteringNo filtering

Known leakage risks:

  1. RocPD VCN/JPEG array values (no explicit sentinel filter)
  2. RocPD PCIe values (relies on device.hpp zeroing only)
  3. NIC metrics in all outputs (no sentinel filtering anywhere)

Mock Configurations

Two architectures test complementary metric subsets. Located in ~/worktree/rocm-systems/amd-smi-mocks/.

MI300X (mock_mi300x.yaml)

Data-center GPU with per-XCP metrics, HBM, and NIC.

CategoryWhat's ConfiguredExpected RangeNotes
Temperaturehotspot only[55, 75]No temperature_edge (sentineled)
HBM Temperature4 active / 4 total[40, 60]Array: active entries have values, rest sentineled
Powercurrent_socket_power[300, 500]Watts
GFX Busygfx_activity[80, 100]%
UMC Busyumc_activity[0, 10]%
MM BusyNOT configuredN/AShould be absent (sentineled)
VCN Busyper-XCP, 4 active engines[0, 10]Per-XCP format, NOT device-level VCN Activity
JPEG Busyper-XCP, 32 active engines[0, 10]Per-XCP format, NOT device-level JPEG Activity
PCIe WidthFixed 1616Lanes
PCIe SpeedFixed 3200032000MT/s
XGMINOT configuredN/AShould be absent (sentineled)
SDMA2 processesvariesCumulative byte counters
Memoryvram_usedvariesDerived from vram_used / vram_total
VoltagesNOT configuredN/AShould be absent (sentineled)
FanNOT configuredN/AShould be absent (sentineled)
NIC RDMA6 stats configured[0, 1000000]RX/TX bytes, packets, CNP

Navi 48 (mock_navi48.yaml)

Consumer GPU with device-level metrics, no XCP, no NIC.

CategoryWhat's ConfiguredExpected RangeNotes
Temperatureedge, hotspot, mem[35, 75]Has temperature_edge
HBM TemperatureNOT configuredN/AShould be absent (sentineled)
Powercurrent_socket_power[20, 30]Watts
GFX Busygfx_activity[0, 10]%
UMC Busyumc_activity[0, 5]%
MM Busymm_activity[0, 10]% (present, unlike MI300X)
VCN Activitydevice-level, 1 active / 4 total[0, 10]Device-level, NOT per-XCP
JPEG ActivityNOT configuredN/AShould be absent (sentineled)
PCIe WidthFixed 1616Lanes
PCIe SpeedFixed 25002500MT/s
XGMINOT configuredN/AShould be absent
SDMA1 processvariesCumulative byte counters
Memoryvram_usedvariesDerived
Voltagesgfx, soc, mem configured[700, 1200]mV
Fanrpm and max configured[800, 1200]RPM
NICNo NIC devicesN/ANo NIC tracks should appear

Output Formats

#FormatEnvironment Variables
1Perfetto StandardROCPROFSYS_TRACE=1
2Perfetto LegacyROCPROFSYS_TRACE=1 ROCPROFSYS_TRACE_LEGACY=true
3RocPDROCPROFSYS_USE_ROCPD=1

Perfetto Track Name Differences

FormatGPU PatternNIC Pattern
StandardGPU [N] <Metric> (S)NIC [N] <Metric> (S)
LegacyGPU <Metric> [N] (S)NIC <device_name> <Metric> [N] (S)

Legacy also uses abbreviated forms: Pkts vs Packets.

Test Matrix

Run IDConfigFormatExtra Env
mi300-perfettomock_mi300x.yamlPerfetto StandardROCPROFSYS_SAMPLING_AINICS="all"
mi300-legacymock_mi300x.yamlPerfetto LegacyROCPROFSYS_SAMPLING_AINICS="all"
mi300-rocpdmock_mi300x.yamlRocPDROCPROFSYS_SAMPLING_AINICS="all"
navi-perfettomock_navi48.yamlPerfetto Standard—
navi-legacymock_navi48.yamlPerfetto Legacy—
navi-rocpdmock_navi48.yamlRocPD—

Common env for ALL runs:

  • AMD_SMI_MOCK_CONFIG=<path-to-yaml>
  • ROCPROFSYS_AMD_SMI_METRICS="all"

Workload: ./transpose (mock generates all metric values regardless of workload type).

Execution

Phase 1: Setup

  1. Auto-discover build directory (build/debug, build/release, or build/)
  2. cd into build dir, source share/rocprofiler-systems/setup-env.sh
  3. Verify mock support: ldd bin/rocprof-sys-run | grep yaml (yaml-cpp must be linked)
  4. Locate mock configs: ~/worktree/rocm-systems/amd-smi-mocks/mock_mi300x.yaml and mock_navi48.yaml
  5. Verify transpose workload exists

Phase 2: Execute Test Matrix

Run 6 profiling sessions. Use /tmp/pmc-validate-<run-id>/ output paths.

source share/rocprofiler-systems/setup-env.sh

# MI300X — Perfetto Standard
AMD_SMI_MOCK_CONFIG=~/worktree/rocm-systems/amd-smi-mocks/mock_mi300x.yaml \
ROCPROFSYS_OUTPUT_PATH=/tmp/pmc-validate-mi300-perfetto \
ROCPROFSYS_TRACE=1 \
ROCPROFSYS_AMD_SMI_METRICS="all" \
ROCPROFSYS_SAMPLING_AINICS="all" \
bin/rocprof-sys-run -- ./transpose

# MI300X — Perfetto Legacy
AMD_SMI_MOCK_CONFIG=~/worktree/rocm-systems/amd-smi-mocks/mock_mi300x.yaml \
ROCPROFSYS_OUTPUT_PATH=/tmp/pmc-validate-mi300-legacy \
ROCPROFSYS_TRACE=1 \
ROCPROFSYS_TRACE_LEGACY=true \
ROCPROFSYS_AMD_SMI_METRICS="all" \
ROCPROFSYS_SAMPLING_AINICS="all" \
bin/rocprof-sys-run -- ./transpose

# MI300X — RocPD
AMD_SMI_MOCK_CONFIG=~/worktree/rocm-systems/amd-smi-mocks/mock_mi300x.yaml \
ROCPROFSYS_OUTPUT_PATH=/tmp/pmc-validate-mi300-rocpd \
ROCPROFSYS_USE_ROCPD=1 \
ROCPROFSYS_AMD_SMI_METRICS="all" \
ROCPROFSYS_SAMPLING_AINICS="all" \
bin/rocprof-sys-run -- ./transpose

# Navi 48 — Perfetto Standard
AMD_SMI_MOCK_CONFIG=~/worktree/rocm-systems/amd-smi-mocks/mock_navi48.yaml \
ROCPROFSYS_OUTPUT_PATH=/tmp/pmc-validate-navi-perfetto \
ROCPROFSYS_TRACE=1 \
ROCPROFSYS_AMD_SMI_METRICS="all" \
bin/rocprof-sys-run -- ./transpose

# Navi 48 — Perfetto Legacy
AMD_SMI_MOCK_CONFIG=~/worktree/rocm-systems/amd-smi-mocks/mock_navi48.yaml \
ROCPROFSYS_OUTPUT_PATH=/tmp/pmc-validate-navi-legacy \
ROCPROFSYS_TRACE=1 \
ROCPROFSYS_TRACE_LEGACY=true \
ROCPROFSYS_AMD_SMI_METRICS="all" \
bin/rocprof-sys-run -- ./transpose

# Navi 48 — RocPD
AMD_SMI_MOCK_CONFIG=~/worktree/rocm-systems/amd-smi-mocks/mock_navi48.yaml \
ROCPROFSYS_OUTPUT_PATH=/tmp/pmc-validate-navi-rocpd \
ROCPROFSYS_USE_ROCPD=1 \
ROCPROFSYS_AMD_SMI_METRICS="all" \
bin/rocprof-sys-run -- ./transpose

Phase 3: Sentinel Detection (CRITICAL)

This is the most important validation phase. A single leaked sentinel value is a FAIL.

Perfetto Traces (Standard and Legacy)

Load each trace with MCP tools, then run:

-- SENTINEL CHECK: Find ANY sentinel value in PMC counters
SELECT t.name, c.value, c.ts
FROM counter c JOIN counter_track t ON c.track_id = t.id
WHERE t.name LIKE '%(S)%'
  AND (c.value = 65535
    OR c.value = 4294967295
    OR c.value = 18446744073709551615
    OR c.value = 1.8446744073709552e+19
    OR c.value >= 1.844e+19)
LIMIT 20;
-- Expected: 0 rows. ANY result is a FAIL.

RocPD Databases

sqlite3 <db-file> "
SELECT p.name, e.value
FROM rocpd_pmc_event e JOIN rocpd_info_pmc p ON e.pmc_id = p.id
WHERE e.value IN (65535, 4294967295, 18446744073709551615)
   OR e.value > 1e18
LIMIT 20;
"
# Expected: 0 rows. ANY result is a FAIL.

Phase 4: Positive Validation (Configured Metrics Present)

Verify that all configured metrics appear in output with expected value ranges.

Perfetto SQL

-- ALL PMC TRACKS: Get every metric with stats
SELECT t.name,
       COUNT(*) as samples,
       MIN(c.value) as min_val,
       MAX(c.value) as max_val,
       ROUND(AVG(c.value), 2) as avg_val
FROM counter c JOIN counter_track t ON c.track_id = t.id
WHERE t.name LIKE '%(S)%'
GROUP BY t.name
ORDER BY t.name;

RocPD SQL

sqlite3 <db-file> "
SELECT p.name, COUNT(*) as samples,
       MIN(e.value) as min_val, MAX(e.value) as max_val,
       ROUND(AVG(e.value), 2) as avg_val
FROM rocpd_pmc_event e JOIN rocpd_info_pmc p ON e.pmc_id = p.id
GROUP BY p.name ORDER BY p.name;
"

MI300X Expected Metrics

MetricPerfetto Standard TrackExpected RangeNotes
Temperature (hotspot)GPU [0] Temperature (S)[55, 75]Celsius
PowerGPU [0] Current Power (S)[300, 500]Watts
GFX BusyGPU [0] GFX Busy (S)[80, 100]%
UMC BusyGPU [0] UMC Busy (S)[0, 10]%
Memory UsageGPU [0] Memory Usage (S)>0MB, derived from vram
VCN BusyGPU [0] VCN Busy ... (S)[0, 10]Per-XCP, 4 active engines
JPEG BusyGPU [0] JPEG Busy ... (S)[0, 10]Per-XCP, 32 active engines
PCIe WidthGPU [0] PCIe Link Width (S)16Fixed
PCIe SpeedGPU [0] PCIe Link Speed (S)32000Fixed MT/s
SDMA UsageGPU [0] SDMA Usage (S)>=0Derived from cumulative counters
NIC RX BytesNIC [0] RX RDMA Bytes (S)[0, 1000000]
NIC TX BytesNIC [0] TX RDMA Bytes (S)[0, 1000000]
NIC RX PacketsNIC [0] RX RDMA Packets (S)[0, 1000000]
NIC TX PacketsNIC [0] TX RDMA Packets (S)[0, 1000000]
NIC RX CNPNIC [0] RX CNP Packets (S)[0, 1000000]
NIC TX CNPNIC [0] TX CNP Packets (S)[0, 1000000]

Navi 48 Expected Metrics

MetricPerfetto Standard TrackExpected RangeNotes
Temperature (edge)GPU [0] Temperature (S)[35, 55]Has edge temp
PowerGPU [0] Current Power (S)[20, 30]Watts
GFX BusyGPU [0] GFX Busy (S)[0, 10]%
UMC BusyGPU [0] UMC Busy (S)[0, 5]%
MM BusyGPU [0] MM Busy (S)[0, 10]% (absent on MI300X)
VCN ActivityGPU [0] VCN Activity ... (S)[0, 10]Device-level, 1 active
Memory UsageGPU [0] Memory Usage (S)>0MB
PCIe WidthGPU [0] PCIe Link Width (S)16Fixed
PCIe SpeedGPU [0] PCIe Link Speed (S)2500Fixed MT/s
SDMA UsageGPU [0] SDMA Usage (S)>=01 process

Range Validation SQL

For each metric with a known range, verify no values fall outside:

-- Example: MI300 power should be [300, 500]
SELECT t.name, c.value
FROM counter c JOIN counter_track t ON c.track_id = t.id
WHERE t.name LIKE '%Current Power%' AND t.name LIKE '%(S)%'
  AND (c.value < 300 OR c.value > 500)
LIMIT 10;
-- Expected: 0 rows

Repeat for each metric with known range bounds from the mock config.

Phase 5: Negative Validation (Unsupported Metrics Absent)

Verify that metrics NOT configured in the mock do NOT appear in output.

MI300X Should NOT Have

Absent MetricPerfetto PatternRocPD Pattern
Temperature Edge%Temperature Edge% or %temperature_edge%device_temp_edge
MM Busy%MM Busy% or %mm_activity%device_busy_mm
VCN Activity (device-level)%VCN Activity%device_vcn_activity
JPEG Activity (device-level)%JPEG Activity%device_jpeg_activity
XGMI%XGMI%device_xgmi%
Voltage%Voltage%device_voltage%
Fan%Fan%device_fan%

Navi 48 Should NOT Have

Absent MetricPerfetto PatternRocPD Pattern
HBM Temperature%HBM Temp%device_temp_hbm%
VCN Busy (per-XCP)%VCN Busy%N/A
JPEG Busy (per-XCP)%JPEG Busy%N/A
JPEG Activity%JPEG Activity%device_jpeg_activity%
XGMI%XGMI%device_xgmi%
NIC%NIC%nic_%

Perfetto Negative Check SQL

-- MI300X: Verify absent metrics
SELECT t.name FROM counter_track t
WHERE t.name LIKE '%(S)%'
  AND (t.name LIKE '%Temperature Edge%'
    OR t.name LIKE '%MM Busy%'
    OR t.name LIKE '%VCN Activity%'
    OR t.name LIKE '%JPEG Activity%'
    OR t.name LIKE '%XGMI%'
    OR t.name LIKE '%Voltage%'
    OR t.name LIKE '%Fan%');
-- Expected: 0 rows

-- Navi 48: Verify absent metrics
SELECT t.name FROM counter_track t
WHERE t.name LIKE '%(S)%'
  AND (t.name LIKE '%HBM Temp%'
    OR t.name LIKE '%VCN Busy%'
    OR t.name LIKE '%JPEG Busy%'
    OR t.name LIKE '%JPEG Activity%'
    OR t.name LIKE '%XGMI%'
    OR t.name LIKE '%NIC%');
-- Expected: 0 rows

RocPD Negative Check

# MI300X
sqlite3 <db-file> "
SELECT DISTINCT p.name FROM rocpd_info_pmc p
WHERE p.name IN ('device_busy_mm', 'device_temp_edge')
   OR p.name LIKE 'device_vcn_activity%'
   OR p.name LIKE 'device_jpeg_activity%'
   OR p.name LIKE 'device_xgmi%'
   OR p.name LIKE 'device_voltage%'
   OR p.name LIKE 'device_fan%';
"
# Expected: 0 rows

# Navi 48
sqlite3 <db-file> "
SELECT DISTINCT p.name FROM rocpd_info_pmc p
WHERE p.name LIKE 'device_temp_hbm%'
   OR p.name LIKE 'device_jpeg_activity%'
   OR p.name LIKE 'device_xgmi%'
   OR p.name LIKE 'nic_%';
"
# Expected: 0 rows

Phase 6: Cross-Format Consistency

For each architecture, verify that the same set of metrics appears across all 3 formats (accounting for naming differences):

-- Compare metric counts between Standard and Legacy Perfetto
-- Both should have the same number of unique PMC track names
SELECT COUNT(DISTINCT t.name) FROM counter_track t WHERE t.name LIKE '%(S)%';

For RocPD, compare the set of distinct rocpd_info_pmc.name values against Perfetto track names.

Discrepancies between formats indicate a bug in one of the output processors.

Phase 7: Cleanup

rm -rf /tmp/pmc-validate-mi300-perfetto /tmp/pmc-validate-mi300-legacy /tmp/pmc-validate-mi300-rocpd
rm -rf /tmp/pmc-validate-navi-perfetto /tmp/pmc-validate-navi-legacy /tmp/pmc-validate-navi-rocpd

Report Format

# PMC Validation Report (Mock-Based)

**Date**: YYYY-MM-DD
**Build**: <build_dir>
**Branch**: <branch>

## Sentinel Check Results

| Config | Format | Sentinel Values Found | Status |
|--------|--------|--------------------|--------|
| MI300X | Perfetto | 0 | PASS |
| MI300X | Legacy | 0 | PASS |
| MI300X | RocPD | 0 | PASS |
| Navi 48 | Perfetto | 0 | PASS |
| Navi 48 | Legacy | 0 | PASS |
| Navi 48 | RocPD | 0 | PASS |

## Positive Validation (Configured Metrics)

| Config | Metric | Perfetto | Legacy | RocPD | Range OK |
|--------|--------|----------|--------|-------|----------|
| MI300X | Power | PASS (N, [300-500]) | PASS | PASS | YES |
| MI300X | Temperature | PASS (N, [55-75]) | PASS | PASS | YES |
| ... | ... | ... | ... | ... | ... |
| Navi 48 | Power | PASS (N, [20-30]) | PASS | PASS | YES |
| ... | ... | ... | ... | ... | ... |

## Negative Validation (Unsupported Metrics)

| Config | Metric Should Be Absent | Perfetto | Legacy | RocPD |
|--------|------------------------|----------|--------|-------|
| MI300X | temperature_edge | PASS (absent) | PASS | PASS |
| MI300X | MM Busy | PASS (absent) | PASS | PASS |
| MI300X | XGMI | PASS (absent) | PASS | PASS |
| Navi 48 | HBM Temperature | PASS (absent) | PASS | PASS |
| Navi 48 | JPEG Activity | PASS (absent) | PASS | PASS |
| Navi 48 | NIC | PASS (absent) | PASS | PASS |
| ... | ... | ... | ... | ... |

## Cross-Format Consistency

| Config | Perfetto Metrics | Legacy Metrics | RocPD Metrics | Match |
|--------|-----------------|----------------|---------------|-------|
| MI300X | N | N | N | YES |
| Navi 48 | N | N | N | YES |

## Issues Found
[List with severity: CRITICAL / HIGH / MEDIUM / LOW]

## Conclusion
[Overall assessment]

Save report to: planning/pmc-validation-report.md in the project worktree.

Common Issues & Known Limitations

IssueDescriptionImpact
Perfetto double precisionUINT64_MAX stored as 1.8446744073709552e+19Must check >= 1.844e+19 in addition to exact values
Legacy timingShort workloads (<0.5s) may get 0-1 samples in Legacy formatUse transpose which runs ~2.4s
SDMA cumulativeSDMA values are cumulative byte counters, not instantaneous ratesDelta calculation needed for rate validation
Mock workload independenceMock generates values regardless of workload typeVCN/JPEG don't need decode binaries
yaml-cpp dependencyMock requires yaml-cpp linked into the buildCheck with ldd before running
Invalid timestamps (Legacy)First sample may have invalid timestamp, dropped with warningReduces sample count by 1-2

Integration

OutcomeNext Step
Sentinel foundplanning-bugfix — plan fix for the leaking pipeline stage
Missing configured metricplanning-bugfix — investigate why metric isn't reaching output
Unsupported metric presentplanning-bugfix — sentinel filtering gap
All checks passgit-prepare-pull-request to submit

This skill is also agent-level knowledge for the orchestrator's Tester agent.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.