Render Memory Chart from JSON description document - #962
Conversation
…ps, categories) Renders the compute memory chart from a relational JSON layout (blocks/arrows/metric refs) instead of hardcoded C++. Layout is read from the compute_workload.memory_chart_extdata DB blob with an embedded default fallback. Supports nested container blocks, per-item color categories, and metric refs by dotted id or name. Excludes local CMakePresets and sample .db changes. Co-authored-by: Cursor <cursoragent@cursor.com>
Extract the embedded default layout into rocprofvis_memory_chart_default_layout.h (kDefaultMemoryChartLayout) instead of a ~90-line inline blob in the renderer. Drop the display-name fallback: metrics now resolve only by their full dotted id 'category.table.entry'. Removes the m_ptr_by_name map and its population/lookups, and the schema's metricRef now regex-enforces the three-part id (no abbreviated ids or name aliases). Tighten comments in the renderer/header. No behavior change beyond the stricter metric-id rule. Co-authored-by: Cursor <cursoragent@cursor.com>
The schema, default layout, and example JSON are kept out of the PR (retained locally). The runtime default lives in rocprofvis_memory_chart_default_layout.h and real layouts come from the compute_workload.memory_chart_extdata blob. Co-authored-by: Cursor <cursoragent@cursor.com>
Pack skip-arrow highway lanes: horizontally disjoint arrows share a lane and shorter spans nest nearer the blocks than the spans enclosing them - fewer lanes, no crossings. Spread each block's bottom connectors symmetrically about its centre (longest spans centre-most) so vertical drops no longer stack. Draw all arrow lines first, then labels, with an opaque label background, so a later arrow's line is never painted over a label; widen lane pitch so labels clear the line above. Co-authored-by: Cursor <cursoragent@cursor.com>
|
memory_chart.schema.json |
Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # .agents/UI.md
- Remove the metric_source field: metric refs are full dotted ids (category.table.entry) that already encode their source, and a layout may span multiple categories/tables. FetchMemChartMetrics now fetches every category the layout references and UpdateMetrics indexes all of them (no single-category filter). - Start the layout version at 1 instead of 2 (default JSON, model default, and parser fallback). - Drop the unused id/by_id from MemChartMetricRef; refs are dotted-id strings only, so ParseMetricRef and MetricLabel are simplified. Co-authored-by: Cursor <cursoragent@cursor.com>
|
memory_chart.schema.json |
- Move the layout out of the hardcoded header into per-arch JSON files
(resources/memory_chart/{gfx950,gfx94x,default}.json + schema), embedded
at build time via cmake/embed_memory_chart_layouts.cmake.
- Select layout by workload gpu_arch: dev override -> DB memory_chart_extdata
blob -> arch-specific embedded -> default (legacy chart kept as default).
- Size each block from max(content, connectors, labels) and let the chart
grow vertically (uncapped) so fanned arrow labels no longer overlap.
Replace hardcoded pixel offsets, sizes, alphas, and gaps in the compute memory chart with named static constexpr constants at the top of the file, per CODING.md. No behavior change.
There was a problem hiding this comment.
Can you merge in latest main? Metrics for newer db versions are mapped incorrectly and there is a change that should address it.
A couple of issues from testing:
- Metric tooltips get cut off a few ticks above minimum font size.
- % metrics like hit rate and utilization now display without units where old version had them.
- Add an optional per-item `unit` to the layout (takes priority over the metric entry's unit) so the curated Memory Chart metrics (hit rate, utilization) show "%" again - those metrics carry no unit in the DB. Populated gfx950/gfx94x/default layouts + schema. - Fix description tooltips clipping near small font sizes: drop the window max-width constraint that fought the text-wrap position and let the tooltip auto-size to the wrapped text.
Remap all gfx950 metric ids to the current Memory Chart table (schema 2.2.0); Flat/Buffer/LDS read-write-atomic and xGMI BW now resolve instead of N/A.
drchen-amd
left a comment
There was a problem hiding this comment.
This seems to lack a "render friendly" memory chart model, and as a result there is a fair amount of redundant processing to make it render friendly every frame. For example:
-
ComputeMemoryChartView::MetricLabel- Returns a passed in overridden name if exists, otherwise metric name if metric exists. -
ComputeMemoryChartView::MetricValueText- Converts metric value to str, appends unit. -
Arrows and blocks searching for for which blocks they connect to.
There is a rocprofvis_memory_chart_model, but it is a collecting of helper functions and does not hold any data. This could be expanded to provide a "friendly" data representation. Rough idea being that it would store a bunch of these:
struct Metric
{
int category, table, entry
string name
string value
}
struct Block
{
int id,
string name,
vector<Metric> metrics
Imvec2 x,ypos
Imvec2 length,width
}
struct Arrow
{
int id,
int name,
Metric metric
Block* source
Block* target
}
Then your ComputeMemoryChartView would update subsections of this only when needed:
- On workload change, your entire layout changes, so you would create fresh Blocks and Arrows.
- On kernel change, you go through your Arrows and Blocks, and update only the metric related data.
The sizing and positioning updates need to remain in render, but everything else would be ready as is for render to consume.
Build the layout/index/strings on data changes instead of every frame:
- Move rocprofvis_memory_chart_model.{h,cpp} to model/compute/.
- Store the parsed MemChartLayout in WorkloadInfo (parsed once by the data
provider) instead of raw JSON; the view no longer re-parses.
- Add an id->block index (built on layout load) to replace the per-frame
FindBlock tree scans done for every arrow.
- Cache each item/arrow's resolved label/value; refresh only on layout load
and metric fetch, not per frame.
- Fetch metrics by individual (category, table) instead of whole categories.
…-json # Conflicts: # .agents/UI.md # src/view/src/compute/rocprofvis_compute_memory_chart.cpp
- default: drop no-longer-applicable vL1 and L2 latency metrics - gfx94x: split MALL, UMC, and HBM into their own columns - gfx950: add Data Fabric/MALL/UMC/HBM columns (matching gfx94x order), move xGMI/PCIe to a trailing column, and retarget L2 arrows to Data Fabric - view: give arrow-free column gaps a tighter width so unconnected columns sit close together; precompute the arrow-crossing set on layout load instead of every frame
|
Merging - but this should be addressed soon if real:
The one real gap bug. Skip arrows (column distance greater than 1) mark every intervening gap as arrow-bearing, but they are not drawn through those corridors — they go under the blocks on the highway, or up the left margin. A skip from L2 to HBM would re-open the MALL/UMC gaps this change is trying to close. default.json already has a skip (13 → 1); those gaps stay wide today only because adjacent arrows also cross them. |
Motivation
The compute kernel-details Memory Chart was a static, hardcoded diagram that couldn't adapt to different GPU architectures or traces. This makes it data-driven: the memory hierarchy is described as JSON stored per-workload in the trace database, so the chart reflects each workload and can evolve without code changes.
Technical Details
rocprofvis_memory_chart_model.{h,cpp}): a set of blocks (nodes) and arrows (edges) parsed from JSON. Blocks nest viachildren(container boxes); metrics are referenced by their full dotted idcategory.table.entry; a semanticcategorydrives accent colors. No coordinates in JSON — columns, block sizing, and arrow routing are computed at runtime.compute_workload.memory_chart_extdatacolumn, detected via PRAGMA and plumbed model → controller C ABI (kRPVControllerWorkloadMemoryChartLayout) → data provider → view, with an embedded default (rocprofvis_memory_chart_default_layout.h) as fallback.rocprofvis_compute_memory_chart.{cpp,h}): resolves the selected kernel's metric values and draws the chart. Skip-arrow routing packs "highway" lanes (horizontally disjoint arrows share a lane; shorter spans nest inside longer ones), spreads each block's bottom connectors symmetrically about its centre, and draws all lines before labels so no line is painted over a label..agents/AGENTS.md)