0ab214d1c8
Add GPU monitoring support for AMD and Intel GPUs on Windows using D3DKMT (DirectX) and PDH performance counters. - Add PDH-based GPU utilization via \GPU Engine(*)\Utilization Percentage counter, summing all engine types per adapter (3D, Compute, Copy, Video). - Add D3DKMT bindings for adapter enumeration, memory segments, and adapter perf data. - Use PDH as primary utilization source (works on all vendors), with D3DKMT RunningTime as fallback for systems without PDH counters. - Prefer nvidia-smi when available, fall back to D3DKMT + PDH for AMD/Intel. - Backend priority: nvidia-smi -> D3DKMT + PDH -> ErrNoGpuTool. Verified on AMD 7900XTX GPU with llama.cpp Vulkan & ROCm backend: GPU utilization correctly shows ~99% during inference, ~0-2% when idle. --- LLM disclosure: GLM 5.1 & Kimi K2.6 have been used extensively during exploration and coding to the point that the LLM's wrote over 3/4 of the code, and I have done additional verification myself. As such, it should be considered experimental. Additional verification is needed. I have tested it on my 7900XTX system with Windows 11, and it works correctly, but as I only have this one rig, I cannot verify it everywhere.
54 lines
1.4 KiB
Go
54 lines
1.4 KiB
Go
//go:build windows
|
|
|
|
package perf
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestParsePdhLuid_Valid(t *testing.T) {
|
|
name := `pid_25312_luid_0x00000000_0x000148BF_phys_0_eng_2_engtype_Compute`
|
|
got, ok := parsePdhLuid(name)
|
|
assert.True(t, ok)
|
|
assert.Equal(t, uint32(0x000148BF), got.LowPart)
|
|
assert.Equal(t, int32(0x00000000), got.HighPart)
|
|
}
|
|
|
|
func TestParsePdhLuid_ValidNvidia(t *testing.T) {
|
|
name := `pid_1388_luid_0x00000000_0x00011372_phys_0_eng_8_engtype_Compute_1`
|
|
got, ok := parsePdhLuid(name)
|
|
assert.True(t, ok)
|
|
assert.Equal(t, uint32(0x00011372), got.LowPart)
|
|
assert.Equal(t, int32(0x00000000), got.HighPart)
|
|
}
|
|
|
|
func TestParsePdhLuid_NonZeroHighPart(t *testing.T) {
|
|
name := `pid_1234_luid_0x00000001_0x0000C85A_phys_0_eng_5_engtype_Copy`
|
|
got, ok := parsePdhLuid(name)
|
|
assert.True(t, ok)
|
|
assert.Equal(t, uint32(0x0000C85A), got.LowPart)
|
|
assert.Equal(t, int32(0x00000001), got.HighPart)
|
|
}
|
|
|
|
func TestParsePdhLuid_InvalidNoLuid(t *testing.T) {
|
|
_, ok := parsePdhLuid("invalid_string_without_luid")
|
|
assert.False(t, ok)
|
|
}
|
|
|
|
func TestParsePdhLuid_InvalidEmpty(t *testing.T) {
|
|
_, ok := parsePdhLuid("")
|
|
assert.False(t, ok)
|
|
}
|
|
|
|
func TestParsePdhLuid_InvalidHex(t *testing.T) {
|
|
_, ok := parsePdhLuid("pid_1234_luid_0xZZZZ_0xGGGG_phys_0")
|
|
assert.False(t, ok)
|
|
}
|
|
|
|
func TestParsePdhLuid_ShortAfterLuid(t *testing.T) {
|
|
_, ok := parsePdhLuid("pid_1234_luid_0x00000000")
|
|
assert.False(t, ok)
|
|
}
|