mirror of
https://github.com/lone-cloud/gerbil
synced 2026-06-03 19:54:44 -07:00
windows vram display in about, better rocm display on windows, amd/nvidia driver display
This commit is contained in:
parent
61b730c3f7
commit
c2287b1d5c
5 changed files with 173 additions and 44 deletions
|
|
@ -108,13 +108,14 @@ const checkVramWarnings = async (backend: string): Promise<Warning[]> => {
|
|||
|
||||
if (gpuMemoryInfo) {
|
||||
const lowVramThreshold = 8;
|
||||
const lowVramGpus = gpuMemoryInfo.filter(
|
||||
(gpu) =>
|
||||
typeof gpu.totalMemoryGB === 'number' &&
|
||||
gpu.totalMemoryGB < lowVramThreshold
|
||||
const validGpus = gpuMemoryInfo.filter(
|
||||
(gpu) => typeof gpu.totalMemoryGB === 'number'
|
||||
);
|
||||
const lowVramGpus = validGpus.filter(
|
||||
(gpu) => gpu.totalMemoryGB! < lowVramThreshold
|
||||
);
|
||||
|
||||
if (lowVramGpus.length > 0) {
|
||||
if (validGpus.length > 0 && lowVramGpus.length === validGpus.length) {
|
||||
const memoryDetails = lowVramGpus
|
||||
.map((gpu) => `${gpu.totalMemoryGB!.toFixed(1)}GB`)
|
||||
.join(', ');
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ export async function detectCPU() {
|
|||
const devices: string[] = [];
|
||||
if (cpu.brand) {
|
||||
devices.push(
|
||||
`${formatDeviceName(cpu.brand)} (${cpu.physicalCores} cores, ${cpu.speed} GHz)`
|
||||
`${formatDeviceName(cpu.brand)} (${cpu.cores} cores) @ ${cpu.speed} GHz`
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -125,17 +125,12 @@ export async function detectGPUCapabilities() {
|
|||
|
||||
async function detectCUDA() {
|
||||
try {
|
||||
const { stdout } = await execa(
|
||||
'nvidia-smi',
|
||||
['--query-gpu=name,driver_version', '--format=csv,noheader,nounits'],
|
||||
{
|
||||
timeout: 5000,
|
||||
reject: false,
|
||||
}
|
||||
);
|
||||
const { stdout } = await execa('nvidia-smi', [], {
|
||||
timeout: 5000,
|
||||
reject: false,
|
||||
});
|
||||
|
||||
if (stdout.trim()) {
|
||||
// Check for error messages that indicate nvidia-smi failed
|
||||
const errorPatterns = [
|
||||
'NVIDIA-SMI has failed',
|
||||
'No devices found',
|
||||
|
|
@ -152,24 +147,39 @@ async function detectCUDA() {
|
|||
return { supported: false, devices: [] } as const;
|
||||
}
|
||||
|
||||
const lines = stdout.trim().split('\n');
|
||||
const devices: string[] = [];
|
||||
let version: string | undefined;
|
||||
let cudaVersion: string | undefined;
|
||||
let driverVersion: string | undefined;
|
||||
|
||||
for (const line of lines) {
|
||||
const parts = line.split(',');
|
||||
const rawName = parts[0]?.trim() || 'Unknown NVIDIA GPU';
|
||||
devices.push(formatDeviceName(rawName));
|
||||
const cudaMatch = stdout.match(/CUDA Version:\s*(\d+\.\d+)/);
|
||||
if (cudaMatch) {
|
||||
cudaVersion = cudaMatch[1];
|
||||
}
|
||||
|
||||
if (!version && parts[1]?.trim()) {
|
||||
version = parts[1].trim();
|
||||
const driverMatch = stdout.match(
|
||||
/Driver Version:\s*(\d+\.\d+(?:\.\d+)?)/
|
||||
);
|
||||
if (driverMatch) {
|
||||
driverVersion = driverMatch[1];
|
||||
}
|
||||
|
||||
const gpuNameMatch = stdout.match(/\|\s+\d+\s+([^|]+)\s+On\s+\|/g);
|
||||
if (gpuNameMatch) {
|
||||
for (const match of gpuNameMatch) {
|
||||
const name = match
|
||||
.replace(/\|\s+\d+\s+([^|]+)\s+On\s+\|/, '$1')
|
||||
.trim();
|
||||
if (name) {
|
||||
devices.push(formatDeviceName(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
supported: devices.length > 0,
|
||||
supported: devices.length > 0 || !!cudaVersion,
|
||||
devices,
|
||||
version,
|
||||
version: cudaVersion,
|
||||
driverVersion,
|
||||
} as const;
|
||||
}
|
||||
|
||||
|
|
@ -245,27 +255,69 @@ export async function detectROCm() {
|
|||
}
|
||||
|
||||
let version: string | undefined;
|
||||
try {
|
||||
const { stdout: amdSmiOutput } = await execa('amd-smi', {
|
||||
timeout: 3000,
|
||||
reject: false,
|
||||
});
|
||||
|
||||
if (amdSmiOutput.trim()) {
|
||||
const match =
|
||||
amdSmiOutput.match(/ROCm version:\s*(\d+\.\d+\.\d+)/i) ||
|
||||
amdSmiOutput.match(/version\s*(\d+\.\d+\.\d+)/i) ||
|
||||
amdSmiOutput.match(/(\d+\.\d+\.\d+)/);
|
||||
if (match) {
|
||||
version = match[1];
|
||||
if (platform === 'linux' || platform === 'darwin') {
|
||||
try {
|
||||
const { stdout: amdSmiOutput } = await execa('amd-smi', {
|
||||
timeout: 3000,
|
||||
reject: false,
|
||||
});
|
||||
|
||||
if (amdSmiOutput.trim()) {
|
||||
const match =
|
||||
amdSmiOutput.match(/ROCm version:\s*(\d+\.\d+\.\d+)/i) ||
|
||||
amdSmiOutput.match(/version\s*(\d+\.\d+\.\d+)/i) ||
|
||||
amdSmiOutput.match(/(\d+\.\d+\.\d+)/);
|
||||
if (match) {
|
||||
version = match[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {}
|
||||
} catch {}
|
||||
} else {
|
||||
try {
|
||||
const { stdout: hipccOutput } = await execa('hipcc', ['--version'], {
|
||||
timeout: 3000,
|
||||
reject: false,
|
||||
});
|
||||
|
||||
if (hipccOutput.trim()) {
|
||||
const hipVersionMatch = hipccOutput.match(
|
||||
/HIP version:\s*(\d+\.\d+(?:\.\d+)?)/i
|
||||
);
|
||||
if (hipVersionMatch) {
|
||||
version = hipVersionMatch[1];
|
||||
}
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
|
||||
let driverVersion: string | undefined;
|
||||
|
||||
if (platform === 'win32') {
|
||||
try {
|
||||
const { stdout: driverOutput } = await execa(
|
||||
'powershell',
|
||||
[
|
||||
'-Command',
|
||||
`Get-CimInstance -ClassName Win32_VideoController | Where-Object { $_.Name -like '*AMD*' -or $_.Name -like '*Radeon*' } | Select-Object -First 1 -ExpandProperty DriverVersion`,
|
||||
],
|
||||
{
|
||||
timeout: 3000,
|
||||
reject: false,
|
||||
}
|
||||
);
|
||||
|
||||
if (driverOutput.trim()) {
|
||||
driverVersion = driverOutput.trim();
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
|
||||
return {
|
||||
supported: devices.length > 0,
|
||||
devices,
|
||||
version,
|
||||
driverVersion,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -422,7 +474,7 @@ export async function detectGPUMemory() {
|
|||
}
|
||||
|
||||
const result = await safeExecute(async () => {
|
||||
const gpuData = await getGPUData();
|
||||
const gpuData = await getGPUData(true);
|
||||
const memoryInfo: GPUMemoryInfo[] = [];
|
||||
|
||||
for (const gpu of gpuData) {
|
||||
|
|
|
|||
2
src/types/hardware.d.ts
vendored
2
src/types/hardware.d.ts
vendored
|
|
@ -19,11 +19,13 @@ export interface GPUCapabilities {
|
|||
readonly supported: boolean;
|
||||
readonly devices: readonly string[];
|
||||
readonly version?: string;
|
||||
readonly driverVersion?: string;
|
||||
};
|
||||
rocm: {
|
||||
readonly supported: boolean;
|
||||
readonly devices: readonly string[];
|
||||
readonly version?: string;
|
||||
readonly driverVersion?: string;
|
||||
};
|
||||
vulkan: {
|
||||
readonly supported: boolean;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { readFile, readdir } from 'fs/promises';
|
||||
import { join } from 'path';
|
||||
import { platform } from 'process';
|
||||
import { execa } from 'execa';
|
||||
|
||||
interface CachedGPUInfo {
|
||||
devicePath: string;
|
||||
|
|
@ -19,9 +20,11 @@ let linuxGpuCache: CachedGPUInfo[] | null = null;
|
|||
|
||||
let linuxCachePromise: Promise<CachedGPUInfo[]> | null = null;
|
||||
|
||||
export async function getGPUData() {
|
||||
export async function getGPUData(forNonMetrics = false) {
|
||||
if (platform === 'linux') {
|
||||
return getLinuxGPUData();
|
||||
} else if (platform === 'win32' && forNonMetrics) {
|
||||
return getWindowsGPUData();
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
|
|
@ -143,3 +146,58 @@ async function getLinuxGPUData() {
|
|||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
async function getWindowsGPUData() {
|
||||
try {
|
||||
const { stdout } = await execa(
|
||||
'powershell',
|
||||
[
|
||||
'-Command',
|
||||
`$activeGpus = Get-CimInstance -ClassName Win32_VideoController | Where-Object { $_.Status -eq 'OK' } | Select-Object -ExpandProperty Name;
|
||||
$gpuKeys = Get-ChildItem 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Class\\{4d36e968-e325-11ce-bfc1-08002be10318}' | Where-Object { $_.PSChildName -match '^\\d{4}$' };
|
||||
foreach($key in $gpuKeys) {
|
||||
$props = Get-ItemProperty $key.PSPath -ErrorAction SilentlyContinue;
|
||||
if($props.DriverDesc -and $props.'HardwareInformation.qwMemorySize' -and $activeGpus -contains $props.DriverDesc) {
|
||||
$vramBytes = $props.'HardwareInformation.qwMemorySize';
|
||||
$vramGB = [math]::Round($vramBytes/1GB, 2);
|
||||
if($vramGB -gt 0.5) {
|
||||
Write-Output "$($props.DriverDesc)|$vramGB";
|
||||
}
|
||||
}
|
||||
}`,
|
||||
],
|
||||
{
|
||||
timeout: 10000,
|
||||
reject: false,
|
||||
}
|
||||
);
|
||||
|
||||
if (!stdout.trim()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const gpus: GPUData[] = [];
|
||||
const lines = stdout.trim().split('\n');
|
||||
const seenVram = new Set<number>();
|
||||
|
||||
for (const line of lines) {
|
||||
const parts = line.trim().split('|');
|
||||
if (parts.length === 2) {
|
||||
const vramGB = parseFloat(parts[1]);
|
||||
if (vramGB > 0 && !seenVram.has(vramGB)) {
|
||||
seenVram.add(vramGB);
|
||||
gpus.push({
|
||||
usage: 0,
|
||||
memoryUsed: 0,
|
||||
memoryTotal: vramGB,
|
||||
temperature: undefined,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return gpus;
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,9 +32,11 @@ export const createSoftwareItems = (versionInfo: SystemVersionInfo) => [
|
|||
{ label: 'Electron', value: versionInfo.electronVersion },
|
||||
{
|
||||
label: 'Node.js',
|
||||
value: versionInfo.nodeJsSystemVersion
|
||||
? `${versionInfo.nodeVersion} (System: ${versionInfo.nodeJsSystemVersion})`
|
||||
: versionInfo.nodeVersion,
|
||||
value:
|
||||
versionInfo.nodeJsSystemVersion &&
|
||||
versionInfo.nodeJsSystemVersion !== versionInfo.nodeVersion
|
||||
? `${versionInfo.nodeVersion} (system: ${versionInfo.nodeJsSystemVersion})`
|
||||
: versionInfo.nodeVersion,
|
||||
},
|
||||
{ label: 'Chromium', value: versionInfo.chromeVersion },
|
||||
{ label: 'V8', value: versionInfo.v8Version },
|
||||
|
|
@ -67,6 +69,13 @@ export const createDriverItems = (hardwareInfo: HardwareInfo) => {
|
|||
? `v${gpuCapabilities.cuda.version}`
|
||||
: 'Available',
|
||||
});
|
||||
|
||||
if (gpuCapabilities.cuda.driverVersion) {
|
||||
items.push({
|
||||
label: 'NVIDIA Driver',
|
||||
value: `v${gpuCapabilities.cuda.driverVersion}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (gpuCapabilities.rocm.supported) {
|
||||
|
|
@ -76,6 +85,13 @@ export const createDriverItems = (hardwareInfo: HardwareInfo) => {
|
|||
? `v${gpuCapabilities.rocm.version}`
|
||||
: 'Available',
|
||||
});
|
||||
|
||||
if (gpuCapabilities.rocm.driverVersion) {
|
||||
items.push({
|
||||
label: 'AMD Driver',
|
||||
value: `v${gpuCapabilities.rocm.driverVersion}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (gpuCapabilities.vulkan.supported) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue