Every GPU-selection picker (Load/SAT, Burn, Benchmark) now renders the
card serial: "GPU N — <model> · <mem> MiB · sn: <serial>". The serial is
monospace and the digits that differ across the listed GPUs (common
prefix/suffix stripped) are emphasised so operators can tell cards apart.
Row markup was duplicated across three pages (and twice within
page_validate.go). Consolidated into a single module,
internal/webui/gpu_picker.go: beeGpuPicker.render({...}) builds every row;
gpuPickerCSS/gpuPickerJS are injected once by layoutHead/renderPage. Pages
keep their own selection-note text and multi-GPU toggles but no longer
hand-build <label> markup.
ListNvidiaGPUs() adds the serial via nvidia-smi --query-gpu=...,serial;
N/A is normalised to empty. Serial flows to the client unchanged through
the existing /api/gpu/nvidia JSON response.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AudE3Q2nd9kxxVuxPKcTho
128 lines
5.3 KiB
Markdown
128 lines
5.3 KiB
Markdown
# GPU Model Name Propagation
|
|
|
|
How GPU model names are detected, stored, and displayed throughout the project.
|
|
|
|
---
|
|
|
|
## Detection Sources
|
|
|
|
There are **two separate pipelines** for GPU model names — they use different structs and don't share state.
|
|
|
|
### Pipeline A — Live / SAT (nvidia-smi query at runtime)
|
|
|
|
**File:** `audit/internal/platform/sat.go`
|
|
|
|
- `ListNvidiaGPUs()` → `NvidiaGPU.Name` (field: `name`, from `nvidia-smi --query-gpu=index,name,...`)
|
|
- `ListNvidiaGPUStatuses()` → `NvidiaGPUStatus.Name`
|
|
- Used by: GPU selection UI, live metrics labels, burn/stress test logic
|
|
|
|
### Pipeline B — Benchmark results
|
|
|
|
**File:** `audit/internal/platform/benchmark.go`, line 124
|
|
|
|
- `queryBenchmarkGPUInfo(selected)` → `benchmarkGPUInfo.Name`
|
|
- Stored in `BenchmarkGPUResult.Name` (`json:"name,omitempty"`)
|
|
- Used by: benchmark history table, benchmark report
|
|
|
|
### Pipeline C — Hardware audit JSON (PCIe schema)
|
|
|
|
**File:** `audit/internal/schema/hardware.go`
|
|
|
|
- `HardwarePCIeDevice.Model *string` (field name is **Model**, not Name)
|
|
- For AMD GPUs: populated by `audit/internal/collector/amdgpu.go` from `info.Product`
|
|
- For NVIDIA GPUs: **NOT populated** by `audit/internal/collector/nvidia.go` — the NVIDIA enricher sets telemetry/status but skips the Model field
|
|
- Used by: hardware summary page (`hwDescribeGPU` in `pages.go:487`)
|
|
|
|
---
|
|
|
|
## Key Inconsistency: NVIDIA PCIe Model is Never Set
|
|
|
|
`audit/internal/collector/nvidia.go` — `enrichPCIeWithNVIDIAData()` enriches NVIDIA PCIe devices with telemetry and status but does **not** populate `HardwarePCIeDevice.Model`.
|
|
|
|
This means:
|
|
- Hardware summary page shows "Unknown GPU" for all NVIDIA devices (falls back at `pages.go:486`)
|
|
- AMD GPUs do have their model populated
|
|
|
|
The fix would be: copy `gpu.Name` from the SAT pipeline into `dev.Model` inside `enrichPCIeWithNVIDIAData`.
|
|
|
|
---
|
|
|
|
## Benchmark History "Unknown GPU" Issue
|
|
|
|
**Symptom:** Benchmark history table shows "GPU #N — Unknown GPU" columns instead of real GPU model names.
|
|
|
|
**Root cause:** `BenchmarkGPUResult.Name` has tag `json:"name,omitempty"`. If `queryBenchmarkGPUInfo()` fails (warns at `benchmark.go:126`) or returns empty names, the Name field is never set and is omitted from JSON. Loaded results have empty Name → falls back to "Unknown GPU" at `pages.go:2226, 2237`.
|
|
|
|
This happens for:
|
|
- Older result files saved before the `Name` field was added
|
|
- Runs where nvidia-smi query failed before the benchmark started
|
|
|
|
---
|
|
|
|
## Fallback Strings — Current State
|
|
|
|
| Location | File | Fallback string |
|
|
|---|---|---|
|
|
| Hardware summary (PCIe) | `pages.go:486` | `"Unknown GPU"` |
|
|
| Benchmark report summary | `benchmark_report.go:43` | `"Unknown GPU"` |
|
|
| Benchmark report scorecard | `benchmark_report.go:93` | `"Unknown"` ← inconsistent |
|
|
| Benchmark report detail | `benchmark_report.go:122` | `"Unknown GPU"` |
|
|
| Benchmark history per-GPU col | `pages.go:2226` | `"Unknown GPU"` |
|
|
| Benchmark history parallel col | `pages.go:2237` | `"Unknown GPU"` |
|
|
| SAT status file write | `sat.go:922` | `"unknown"` ← lowercase, inconsistent |
|
|
| GPU selection API | `api.go:163` | `"GPU N"` (no "Unknown") |
|
|
|
|
**Rule:** all UI fallbacks should use `"Unknown GPU"`. The two outliers are `benchmark_report.go:93` (`"Unknown"`) and `sat.go:922` (`"unknown"`).
|
|
|
|
---
|
|
|
|
## GPU Selection UI
|
|
|
|
**File:** `audit/internal/webui/pages.go`
|
|
|
|
- Source: `GET /api/gpus` → `api.go` → `ListNvidiaGPUs()` → live nvidia-smi
|
|
- Render: `'GPU N — <model> · <mem> MiB · sn: <serial>'`
|
|
(serial from `nvidia-smi --query-gpu=...,serial`; omitted when N/A)
|
|
- **Single source:** `audit/internal/webui/gpu_picker.go` — `beeGpuPicker.render({...})` builds every
|
|
row. All three pages (Load/SAT, Burn, Benchmark) call it from their `*RenderGPUList` wrapper;
|
|
`gpuPickerCSS`/`gpuPickerJS` are injected once by `layoutHead`/`renderPage`.
|
|
- Serial is rendered monospace; the digits that differ across the listed GPUs (common
|
|
prefix/suffix stripped) are bolded in accent colour.
|
|
- Fallback: `gpu.name || 'GPU ' + idx` (JS, line ~1432)
|
|
|
|
This always shows the correct model because it queries nvidia-smi live. It is **not** connected to benchmark result data.
|
|
|
|
---
|
|
|
|
## Data Flow Summary
|
|
|
|
```
|
|
nvidia-smi (live)
|
|
└─ ListNvidiaGPUs() → NvidiaGPU.Name
|
|
├─ GPU selection UI (always correct)
|
|
├─ Live metrics labels (charts_svg.go)
|
|
└─ SAT/burn status file (sat.go)
|
|
|
|
nvidia-smi (at benchmark start)
|
|
└─ queryBenchmarkGPUInfo() → benchmarkGPUInfo.Name
|
|
└─ BenchmarkGPUResult.Name (json:"name,omitempty")
|
|
├─ Benchmark report
|
|
└─ Benchmark history table columns
|
|
|
|
nvidia-smi / lspci (audit collection)
|
|
└─ HardwarePCIeDevice.Model (NVIDIA: NOT populated; AMD: populated)
|
|
└─ Hardware summary page hwDescribeGPU()
|
|
```
|
|
|
|
---
|
|
|
|
## Fixed Issues
|
|
|
|
All previously open items are resolved:
|
|
|
|
1. **NVIDIA PCIe Model** — `enrichPCIeWithNVIDIAData()` sets `dev.Model = &v` (`nvidia.go:78`).
|
|
2. **Fallback consistency** — `sat.go` and `benchmark_report.go` both use `"Unknown GPU"`.
|
|
3. **`tops_per_sm_per_ghz`** — computed in `benchmark.go` and stored in `BenchmarkGPUScore.TOPSPerSMPerGHz`.
|
|
4. **`MultiprocessorCount`, `PowerLimitW`, `DefaultPowerLimitW`** — present in `benchmark_types.go`.
|
|
5. **Old benchmark JSONs** — no fix possible for already-saved results with missing names (display-only issue).
|