diff --git a/agent/gpu.go b/agent/gpu.go index b5ace45a..d1b7b422 100644 --- a/agent/gpu.go +++ b/agent/gpu.go @@ -361,12 +361,16 @@ func (gm *GPUManager) calculateGPUAverage(id string, gpu *system.GPUData, cacheK // If no new data arrived if deltaCount == 0 { - // If GPU appears suspended (instantaneous values are 0), return zero values - // Otherwise return last known average for temporary collection gaps - if gpu.Temperature == 0 && gpu.MemoryUsed == 0 { + // Only discrete GPUs report temp/memory, so treat all-zero as suspended (return zeros). + // Engine-based (Intel) GPUs don't, so carry the last average forward across sample gaps. + if gpu.Engines == nil && gpu.Temperature == 0 && gpu.MemoryUsed == 0 { return system.GPUData{Name: gpu.Name} } - return gm.lastAvgData[id] // zero value if not found + lastAvg := gm.lastAvgData[id] // zero value if not found + if lastAvg.Name == "" { + lastAvg.Name = gpu.Name + } + return lastAvg } // Calculate new average diff --git a/agent/gpu_test.go b/agent/gpu_test.go index 075228c3..1ac6e018 100644 --- a/agent/gpu_test.go +++ b/agent/gpu_test.go @@ -566,6 +566,42 @@ func TestGetCurrentData(t *testing.T) { assert.EqualValues(t, 2, gm.GpuDataMap["0"].Count, "Count should still be 2") }) + t.Run("carries Intel GPU average forward between samples", func(t *testing.T) { + // Intel GPUs report no temp/memory, so between-sample gaps (delta 0) must + // reuse the last average instead of returning zeros and blanking the chart. + gm := &GPUManager{ + GpuDataMap: map[string]*system.GPUData{ + "0": { + Name: "GPU", + Usage: 0, // derived from engines for Intel + Power: 200, // averages to 100 over 2 counts + PowerPkg: 60, // averages to 30 over 2 counts + Count: 2, + Engines: map[string]float64{ + "Render/3D": 80, // averages to 40 + "Video": 20, // averages to 10 + }, + }, + }, + } + + cacheKey := uint16(1000) // realtime cache key + + // First collection - computes and stores averages + result1 := gm.GetCurrentData(cacheKey) + assert.InDelta(t, 100.0, result1["0"].Power, 0.01) + assert.InDelta(t, 30.0, result1["0"].PowerPkg, 0.01) + assert.InDelta(t, 40.0, result1["0"].Engines["Render/3D"], 0.01) + + // Second collection with no new sample (count unchanged, temp/mem still 0). + // Must carry the last average forward rather than blanking to zero. + result2 := gm.GetCurrentData(cacheKey) + assert.Equal(t, "GPU", result2["0"].Name, "Name should be preserved") + assert.InDelta(t, 100.0, result2["0"].Power, 0.01, "Should reuse last average power, not 0") + assert.InDelta(t, 30.0, result2["0"].PowerPkg, 0.01, "Should reuse last average package power, not 0") + assert.InDelta(t, 40.0, result2["0"].Engines["Render/3D"], 0.01, "Should reuse last average engine usage") + }) + t.Run("tracks separate averages per cache key", func(t *testing.T) { gm := &GPUManager{ GpuDataMap: map[string]*system.GPUData{