Skip to content

NVIDIA datacenter telemetry: GPM compute breakdown, health counters, NVLink/C2C interconnect - #1

Open
rocker-zhang wants to merge 9 commits into
masterfrom
feat-nvlink
Open

NVIDIA datacenter telemetry: GPM compute breakdown, health counters, NVLink/C2C interconnect#1
rocker-zhang wants to merge 9 commits into
masterfrom
feat-nvlink

Conversation

@rocker-zhang

@rocker-zhang rocker-zhang commented Jun 29, 2026

Copy link
Copy Markdown
Owner

Summary

Adds a richer NVIDIA datacenter telemetry layer to the GPU Detail panel and a few
layout refinements. Validated on real hardware (A100 8-GPU, B300, GB200/Grace) across
both x86-64 and aarch64 builds. Default full-backend cmake build is green.

This stack is grouped into themes for an eventual upstream split; opening it here on the
fork first so it can be reviewed end-to-end before anything is proposed upstream.

What's in here (8 commits, on top of master @ 3d4a953)

Foundation

  • c6f83a8 NVLink/GPM/health metrics + a merged GPU Detail panel
  • 5758990 derive NVLink peak speed from link version on Blackwell
  • 382cc60 cap plot height for few-GPU layouts when processes are shown

Compute breakdown (GPM)

  • ab99c43 per-pipe GPM compute breakdown with a tensor MMA-class label
    (SM / occupancy / DRAM-BW + HMMA/IMMA/DFMA pipe activity). GPM capability is decided
    by the actual nvmlGpmSampleGet return rather than isSupportedDevice, which is
    unreliable on some Blackwell SKUs. The tensor label names the MMA class only (no
    precision-width claim) because GPM exposes no FP8/FP4 bucket.

Health

  • e793331 HBM / memory temperature and health-counter plumbing
    (ECC SBE/DBE, remap pending/failure, NVLink error counters, PCIe replay, mem temp)

Interconnect

  • 7c75ac7 NVLink active-link roll-up in the GPU Detail panel (active/total, NVSwitch detect)
  • f59c8f8 NVLink-C2C fabric surfacing (Grace coherent fabric capacity)

Cleanup

  • 10c6ea9 trim speculative fields, render uncorrectable-remap, clarify C2C

Testing

  • A100 8-GPU: NVLink Rx/Tx throughput within ~1% of nvidia-smi, peak resolves correctly;
    health counters read real values (incl. a non-zero NVLink error count on one GPU).
  • B300: GPM SM/Tensor match dcgmi to three decimals; FP8 GEMM observed in the HMMA bucket
    (kernel verified via profiler), confirming the MMA-class label is honest.
  • GB200 (aarch64 Grace): builds, runs, GPM works; C2C fabric surfaced.
  • Graceful degradation verified on a non-GPM SKU (panel shows N/A, no crash, no regression).

Notes

  • Health panel, the merged-panel layout, and the optional GDR/GDS build flag are intended
    to stay fork-only; the compute / interconnect pieces are the upstream-candidate parts.

Summary by CodeRabbit

  • New Features

    • Added an optional GPU Detail panel with richer live metrics, including interconnect activity, compute utilization/activity, and health indicators.
    • Added new plots for interconnect Rx/Tx rates plus SM and tensor activity utilization.
    • Added an experimental option to enable a host-global GPUDirect RDMA/Storage (GDR/GDS) panel readout.
    • Added configuration to show or hide the GPU Detail panel.
  • Bug Fixes

    • Improved window layout sizing and resizing for process and chart regions.
    • Enhanced snapshot JSON with interconnect Rx/Tx rate fields (when available).

- NVLink aggregate throughput (Rx/Tx + %-of-peak) via the NVML field-value
  API, as an opt-in plot series and an absolute-rate panel column.
- SM and Tensor-core activity via NVML GPM, opt-in and gated so it only
  samples the shared perfmon counters while actually displayed.
- GPU reliability signals: clock-throttle reasons, ECC SBE/DBE, row-remap
  pending/failure, NVLink errors, PCIe replay; summarised as a per-GPU
  status glyph plus detail fields.
- Merge the interconnect/health/compute panels into one width-adaptive
  per-GPU "GPU Detail" table; categories with no data collapse out.
- Size the process region to its content so an empty list no longer
  leaves a large blank gap above the panel.
- Experimental host-global GDR/GDS summary behind -DNVTOP_GDR (off by default).
NVML stopped exposing NVLINK_SPEED_MBPS_COMMON (field 90) on Blackwell, so
the per-link peak used to compute NVLink utilisation could not be read and the
utilisation percentage disappeared on those GPUs. When the field is
unavailable, fall back to mapping the NVLink version (nvmlDeviceGetNvLinkVersion)
to the per-link speed: version 7 (NVLink 5) is 53.125 GB/s/link, matching
nvidia-smi. Unknown versions leave the peak unset so only absolute Rx/Tx is
shown, never a wrong percentage.

Verified on GB200 and B300: utilisation matches nvidia-smi throughput within
measurement error (20% vs 20.2% ground truth under peer-copy traffic); the
existing field-90 path on A100/Hopper is unchanged.
With only a few GPUs the per-GPU charts stretched to fill the whole screen,
making each chart much taller than it is in an 8-GPU layout. When there are
processes to display, cap the plot area to roughly half the height an 8-GPU
layout would use (about 13 rows per stacked row of charts) and give the freed
rows to the process list. An idle box keeps the full-height charts so it never
shows an empty band below them. 8/16-GPU layouts already fit under the budget
and are unaffected.

Verified on GB200/B300 (4 GPUs): charts shrink from full to about half when
processes appear and restore when they exit; A100 (8 GPUs) chart heights are
unchanged.
Sample the per-pipe NVML GPM metrics alongside the existing aggregate
SM/tensor/occupancy/DRAM-BW, in the same nvmlGpmMetricsGet diff: the
tensor MMA classes (HMMA float / IMMA int / DFMA fp64) and the CUDA-core
pipes (FP16/FP32/FP64/INT). Tag the GPU Detail tensor field with the
dominant tensor class so an INT8-quantised inference workload reads
distinctly from FP training/inference.

GPM exposes no FP8/FP4 metric and no QMMA/OMMA counter, so float width is
not separable: on B300 a real FP8 GEMM (nvjet qqtst kernel, QMMA-class at
the SASS level) still lands in the GPM HMMA/ANY_TENSOR bucket at full
util, so it is observable but indistinguishable from FP16/BF16. HMMA is
therefore labelled "FP" (never a specific width that would mislead).
Verified on a B300 SXM6 node: BF16/FP8 -> "FP", INT8 -> "INT8".
Add the HBM/memory junction temperature (NVML field NVML_FI_DEV_MEMORY_TEMP)
to the GPU Detail health cluster, coloured by absolute risk band — it is the
HBM3 thermal limiter, distinct from the die temperature already shown and a
leading indicator of the thermal throttle it precedes.

Also plumb, for the upcoming detail drill-down, three health counters read in
the same field-value batch: correctable/uncorrectable row-remap counts
(fields 142/143, RMA proximity beyond the pending/failure flags) and the
perf-policy violation times (power/thermal/total seconds held below
application clocks — the non-deprecated replacement for the CUDA-13
deprecated nvmlDeviceGetViolationStatus). Note total-app-clocks also counts
benign idle downclocking, so only the power/thermal limiters are surfaced.

Field semantics verified on a B300 SXM6 node: MEMORY_TEMP returns degrees C
distinct from the die sensor; perf-policy fields return nanoseconds.
Enumerate each device's NVLinks via nvmlDeviceGetNvLinkState and roll up how
many are still active. A single link dropping out is invisible in the summed
Rx/Tx throughput already shown, yet it halves that GPU's share of collective
bandwidth — so the panel now prints "NVLink active/total" next to the
aggregate, in red when active < total, to localise a degraded fabric before a
collective run stalls on it.

The roll-up is two scalar counts (no per-link array), so it fits the existing
single-row layout; a full per-link throughput/error drill-down is left for a
later expandable detail view. Verified on a B300 SXM6 node (18/18 links active,
NVLink 5), matching nvmlDeviceGetNvLinkState enumeration.
Two interconnect-visibility additions to the GPU Detail panel:

- C2C: on Grace systems (GH200/GB200) the coherent CPU<->GPU NVLink-C2C
  fabric carries several times the host bandwidth of the PCIe link nvtop
  already shows, yet was invisible. Read the C2C link count/status/max-BW
  fields and show the aggregate capacity ("C2C 224GB/s"), red when a link
  is inactive. NOT_SUPPORTED on non-Grace boards, where the block collapses.

- NVSwitch: probe the NVLink remote device type and tag the link roll-up
  with "sw" when the links terminate on an NVSwitch, distinguishing a
  switched DGX/NVL72 fabric from direct GPU-to-GPU wiring.

Verified across two real nodes: a B300 SXM6 x86 node ("NVLink 18/18 sw",
no C2C) and a GB200 Grace node ("NVLink 18/18 sw" + "C2C 224GB/s",
5 links x 44712 MB/s).
Address a pre-push review of the GPU Detail additions: drop fields that were
extracted but rendered nowhere rather than carry speculative scope.

- Remove the FP16/FP32/FP64/INTEGER CUDA-core GPM pipes (and the four GPM
  metric slots they sampled): the tensor MMA-class label only needs
  HMMA/IMMA/DFMA, so numMetrics drops 11 -> 7.
- Remove the perf-policy throttle-second counters and the correctable
  row-remap count: these were boot-cumulative and need rate-differencing to
  display meaningfully, deferred rather than stored unused.
- Keep the uncorrectable row-remap count and now render it: a nonzero value
  (spent remap budget, RMA proximity) appends "<n>u" in yellow to the Rmp
  field, shown only when nonzero so a healthy row stays unchanged.
- Label C2C as "<n>GB/s cap" to mark it max capacity, not live throughput,
  distinguishing it from the adjacent live NVLink Rx/Tx.

Re-verified on B300 (compute "FP", NVLink 18/18 sw, HBM 46c) and GB200
(C2C 224GB/s cap). Build clean; struct/valid-enum still 1:1.
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 74622ed0-6347-4786-9608-8067d69a048f

📥 Commits

Reviewing files that changed from the base of the PR and between 10c6ea9 and 488553e.

📒 Files selected for processing (2)
  • src/interface.c
  • src/interface_layout_selection.c
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/interface_layout_selection.c
  • src/interface.c

📝 Walkthrough

Walkthrough

Adds a GPU Detail bottom panel with NVLink, C2C, SM/Tensor, and health metrics, plus optional host RDMA/GDS readout. The NVIDIA backend now collects the required telemetry, layouts reserve space for the panel, config persists the option, and plots/snapshots expose the new values.

Changes

GPU Detail Panel and Telemetry

Layer / File(s) Summary
Data contracts and build flags
CMakeLists.txt, src/CMakeLists.txt, include/nvtop/extract_gpuinfo_common.h, include/nvtop/interface_common.h, include/nvtop/interface_internal_common.h, include/nvtop/interface_layout_selection.h, include/nvtop/interface_options.h, src/extract_gpuinfo.c
Adds the NVTOP_GDR build option and compile definition, new shared telemetry fields and validity bits, new plot identifiers, GPU Detail window state, layout signature updates, the GPU Detail option flag, and the compute-activity gate.
NVIDIA backend telemetry collection
src/extract_gpuinfo_nvidia.c
Adds NVML field-value and GPM helpers, per-GPU rate and sample state, symbol loading and shutdown cleanup, NVLink max speed derivation, and dynamic collection for NVLink, C2C, throttle, ECC, remap, PCIe, memory temperature, and SM/Tensor activity.
Bottom panel layout sizing
src/interface_layout_selection.c
Extends layout computation with process-count-aware sizing, bottom-strip reservation, plot budgeting, and bottom-panel placement.
GpuDetailPanel config persistence
src/interface_options.c
Adds the GpuDetailPanel setting, defaults it on, loads it from config, and writes it back.
Interface windows, plots, detail panel, and snapshot output
src/interface.c, src/interface_setup_win.c
Allocates and tears down the GPU Detail window, adds NVLink/SM/Tensor plot series and labels, renders the detailed GPU panel including optional host RDMA/GDS data, gates compute-activity collection from visible state, and adds NVLink rates to snapshot JSON.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Poem

🐇 A panel blooms with glow and pace,
NVLink hops in a tidy space.
SM and Tensor twirl and spin,
GDR and GDS now chime within,
Hop-hop—my whiskers cheer the trace!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main additions: GPM compute breakdowns, health counters, and NVLink/C2C interconnect telemetry.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat-nvlink

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/interface_layout_selection.c`:
- Around line 251-252: The bottom panel visibility check in the interface layout
selection logic is too strict and prevents showing the panel on exact-fit
terminals. Update the conditional in the layout-sizing flow around
rows_for_bottom_panel handling so that the bottom panel is kept when rows
exactly equals min_rows_for_header + rows_for_bottom_panel + 1, while still
preserving the existing fallback behavior for smaller terminals. Use the rows,
min_rows_for_header, and rows_for_bottom_panel comparison in this branch to
adjust the threshold accordingly.
- Around line 292-295: The plot-to-process height reallocation in the layout
logic is using proc_count alone, which can still reserve space for an empty
process pane when no process fields are displayed. Update the condition around
the plot_budget adjustment in interface_layout_selection.c to also require
process_field_displayed_count(process_displayed) > 0, so rows are only shifted
from plots when the process pane can actually render content.

In `@src/interface_options.c`:
- Line 132: The default initialization of show_gpu_detail_panel in
interface_options.c is unintentionally enabling downstream
gpuinfo_collect_compute_activity for fresh/default configs. Update the interface
options setup so the merged GPU detail panel is not enabled by default, or
separate the panel-visibility flag from SM/Tensor sampling in the initialization
path. Keep the change localized to the options initialization logic that sets
show_gpu_detail_panel and any related defaults used by
gpuinfo_collect_compute_activity.

In `@src/interface.c`:
- Around line 2234-2322: The health cluster in interface.c can still overflow
the right border because the counter fields printed in the GPU health block are
unbounded. Update the health rendering logic around the health cluster block to
check available width before each numeric `wprintw`, especially for ECC,
remapped counts, NVLink errors, PCIe replay, and HBM temperature, or
pre-truncate those values to fit. Use the existing `getcurx(win)`/`maxx` guard
pattern in the same rendering section so the output stays within the reserved
health area.
- Around line 2354-2362: The GPM sampling gate in interface.c is too broad
because gpuinfo_collect_compute_activity is tied only to show_gpu_detail_panel,
which can stay true even when the bottom panel is hidden. Update this logic so
the actual detail window state is checked before enabling sampling, and keep the
existing plot scan using gpu_specific_opts and
plot_isset_draw_info(plot_sm_util/plot_tensor_util) to allow sampling only when
SM/Tensor data is really being shown.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c2c8a4e7-cb9a-472b-86b1-c88e2fe8620a

📥 Commits

Reviewing files that changed from the base of the PR and between 3d4a953 and 10c6ea9.

📒 Files selected for processing (13)
  • CMakeLists.txt
  • include/nvtop/extract_gpuinfo_common.h
  • include/nvtop/interface_common.h
  • include/nvtop/interface_internal_common.h
  • include/nvtop/interface_layout_selection.h
  • include/nvtop/interface_options.h
  • src/CMakeLists.txt
  • src/extract_gpuinfo.c
  • src/extract_gpuinfo_nvidia.c
  • src/interface.c
  • src/interface_layout_selection.c
  • src/interface_options.c
  • src/interface_setup_win.c

Comment thread src/interface_layout_selection.c
Comment thread src/interface_layout_selection.c
Comment thread src/interface_options.c
Comment thread src/interface.c
Comment thread src/interface.c
- width-guard each health counter (ECC/remap/NVLink/PCIe/HBM) against the
  right border so an unexpectedly large value can't wrap past the panel edge;
  the existing entry check only reserves the common-case width
- only arm GPM sampling when the detail-panel window is actually rendered
  (gpu_detail_win != NULL), not merely when the option is set, so a
  layout-suppressed panel no longer perturbs the shared perfmon counters
- skip the plot-shrink rebalance when no process columns are displayed, so
  rows aren't shifted into a blank process pane
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant