Update ui to show DGX spark gpu usage correctly
This commit is contained in:
1 parent
60ca869b38
commit
5aa3d0c9a8
3 files changed
+34
-4
No files matched your search
@@ -61,7 +61,7 @@ export default function GPUWidget({ gpu }: GPUWidgetProps) {
|
||||
</div>
|
||||
<div className="flex items-center space-x-2 mb-1 mt-3">
|
||||
<HardDrive className="w-4 h-4 text-blue-600 dark:text-blue-400" />
|
||||
<p className="text-xs text-gray-400">Memory</p>
|
||||
<p className="text-xs text-gray-400">{gpu.memory.shared ? 'Shared Memory' : 'Memory'}</p>
|
||||
<span className="text-xs text-gray-300 ml-auto">
|
||||
{((gpu.memory.used / gpu.memory.total) * 100).toFixed(1)}%
|
||||
</span>
|
||||
|
||||
@@ -35,6 +35,13 @@ const NV_BATCH_FLUSH_MS = 100;
|
||||
// Temperature refresh is decoupled from the tick (see refreshCpuTemp)
|
||||
const CPU_TEMP_REFRESH_MS = 5000;
|
||||
|
||||
// Power limits for GPUs whose driver reports none (nvidia-smi gives [N/A]).
|
||||
// GB10 (DGX Spark) is a unified SoC with no settable GPU limit; 140 W is
|
||||
// NVIDIA's rated TDP for the GB10 superchip.
|
||||
const KNOWN_POWER_LIMITS_W: Record<string, number> = {
|
||||
'NVIDIA GB10': 140,
|
||||
};
|
||||
|
||||
function parseGpuLine(line: string): GpuInfo | null {
|
||||
const [
|
||||
index,
|
||||
@@ -69,7 +76,7 @@ function parseGpuLine(line: string): GpuInfo | null {
|
||||
},
|
||||
power: {
|
||||
draw: parseFloat(powerDraw),
|
||||
limit: parseFloat(powerLimit),
|
||||
limit: isNaN(parseFloat(powerLimit)) ? (KNOWN_POWER_LIMITS_W[name] ?? NaN) : parseFloat(powerLimit),
|
||||
},
|
||||
clocks: {
|
||||
graphics: parseInt(clockGraphics),
|
||||
@@ -81,6 +88,23 @@ function parseGpuLine(line: string): GpuInfo | null {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Unified-memory GPUs (GB10 / DGX Spark) have no dedicated VRAM, so
|
||||
* nvidia-smi reports memory as [N/A]. Report the system RAM pool they share
|
||||
* instead, like the Mac path does for Apple silicon.
|
||||
*/
|
||||
function withSharedMemory(gpu: GPUApiResponse, cpu: CpuInfo | null): GPUApiResponse {
|
||||
if (!cpu || !gpu.gpus.some(g => isNaN(g.memory.total))) return gpu;
|
||||
const total = Math.round(cpu.totalMemory);
|
||||
const free = Math.round(cpu.availableMemory);
|
||||
return {
|
||||
...gpu,
|
||||
gpus: gpu.gpus.map(g =>
|
||||
isNaN(g.memory.total) ? { ...g, memory: { total, free, used: total - free, shared: true } } : g,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
// Serialized once per tick and shared, so N subscribers don't stringify N times
|
||||
type Subscriber = (sample: MonitorSample, serialized: string) => void;
|
||||
|
||||
@@ -138,7 +162,7 @@ class SystemMonitor {
|
||||
return {
|
||||
t: Date.now(),
|
||||
cpu: this.latestCpu,
|
||||
gpu: this.latestGpu,
|
||||
gpu: withSharedMemory(this.latestGpu, this.latestCpu),
|
||||
history: [...this.history],
|
||||
};
|
||||
}
|
||||
@@ -175,7 +199,11 @@ class SystemMonitor {
|
||||
console.error('Monitor: GPU sample failed:', error);
|
||||
}
|
||||
|
||||
const sample: MonitorSample = { t, cpu: this.latestCpu, gpu: this.latestGpu };
|
||||
const sample: MonitorSample = {
|
||||
t,
|
||||
cpu: this.latestCpu,
|
||||
gpu: withSharedMemory(this.latestGpu, this.latestCpu),
|
||||
};
|
||||
this.history.push(historyPointFromSample(sample));
|
||||
if (this.history.length > MONITOR_HISTORY_LENGTH) {
|
||||
this.history.splice(0, this.history.length - MONITOR_HISTORY_LENGTH);
|
||||
|
||||
@@ -11,6 +11,8 @@ export interface GpuMemory {
|
||||
total: number;
|
||||
free: number;
|
||||
used: number;
|
||||
// unified memory (e.g. GB10): figures are the system RAM pool the GPU shares
|
||||
shared?: boolean;
|
||||
}
|
||||
|
||||
export interface GpuPower {
|
||||
|
||||
Reference in new issue
Block a user