Skip to content

docs: sync GPU power monitoring design doc with collector logic - #2498

Open
iacker wants to merge 2 commits into
sustainable-computing-io:mainfrom
iacker:docs/2497-sync-gpu-idle-power
Open

docs: sync GPU power monitoring design doc with collector logic#2498
iacker wants to merge 2 commits into
sustainable-computing-io:mainfrom
iacker:docs/2497-sync-gpu-idle-power

Conversation

@iacker

@iacker iacker commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

What

Syncs the GPU power monitoring design doc (docs/developer/design/architecture/gpu-power-monitoring.md) with the current implementation in internal/device/gpu/nvidia/collector.go. Two sections had drifted from the code.

Why

I noticed this while reading the GPU collector, in the context of #2430 and #2497. The doc describes behaviour that no longer matches the code.

Idle Power Detection

The doc showed minObservedPower updated on every reading, and idle power resolved as a plain minimum lookup. getDevicePowerStatsLocked now does three things differently.

  • It only updates the baseline when the GPU is truly idle. A Kepler start under load no longer sets a false baseline.
  • It resolves idle power by precedence: configured SetIdlePower(), then observed idle, then a conservative zero.
  • It clamps active power at zero, so negative active power is never reported.

MIG Mode

The doc still said per-instance attribution was not implemented, and showed the partitioned case skipped with continue. The collector attributes MIG power per instance via attributePartitioned, based on DCGM activity. attributePartitionedFallback distributes equally when DCGM is unavailable.

Change

Rewrites both sections to match the real control flow. Documentation only, no code changes.

@github-actions github-actions Bot added the docs Documentation changes label Jul 12, 2026
@iacker
iacker force-pushed the docs/2497-sync-gpu-idle-power branch from aa3aae8 to 96b6a84 Compare July 12, 2026 19:01
@iacker iacker changed the title docs: sync GPU idle power detection with actual collector logic docs: sync GPU power monitoring design doc with collector logic Jul 12, 2026
```go
if totalPower < c.minObservedPower[uuid] {
c.minObservedPower[uuid] = totalPower
// Only update the observed baseline when the GPU is truly idle

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this something planned to introduce in the upcoming PR?
I have found that it is not duplicated from the current implementation:

// Check if the GPU is truly idle (no compute processes running)
procs, err := dev.GetComputeRunningProcesses()
if err != nil {
// Non-fatal: log and skip idle detection for this reading
c.logger.Debug("GetComputeRunningProcesses failed, skipping idle detection",
"device", deviceIndex, "error", err)
} else if len(procs) == 0 {
// GPU is truly idle — update minimum observed power
if min, exists := c.minObservedPower[uuid]; !exists || totalPower < min {
c.minObservedPower[uuid] = totalPower
c.logger.Debug("updated idle power baseline",
"device", deviceIndex, "uuid", uuid, "idlePower", totalPower)
}
c.idleObserved[uuid] = true
}
// Determine idle power:

@sunya-ch sunya-ch left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the PR!

I have confirmed the following sync pointers.

c.logger.Debug("MIG attribution failed",

var idlePower float64

However, there is one point left where I cannot find the match source.

@iacker

iacker commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review @sunya-ch. On the MIG section, per-instance attribution is in the current implementation, it just sits further down than L234-250, which is the idle-detection path. The MIG logic the doc describes is in attributePartitioned:

So it is describing what is there today, not something planned.

@sunya-ch

sunya-ch commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

@iacker Actually, I want to point to the section Idle Power Detection.

I cannot find the source of the following code snippet that you place there. It seems to be a similar thing that L234-L250 does for checking if the GPU is truly idle but the code is different.

// Only update the observed baseline when the GPU is truly idle
// (no compute processes running).
procs, err := dev.GetComputeRunningProcesses()
if err == nil && len(procs) == 0 {
    if min, exists := c.minObservedPower[uuid]; !exists || totalPower < min {
        c.minObservedPower[uuid] = totalPower
    }
    c.idleObserved[uuid] = true
}

@iacker

iacker commented Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

Good catch, you are right. That snippet was a paraphrase and had drifted from the real code. It collapsed the error path into err == nil && len(procs) == 0, which hides the non-fatal GetComputeRunningProcesses() failure branch that getDevicePowerStatsLocked actually has.

Fixed in e4bbbad. Both Go blocks in Idle Power Detection now match collector.go verbatim. The idle check keeps the real if err != nil { log & skip } else if len(procs) == 0 { ... } shape, so the doc no longer implies errors are treated as "not idle". The precedence switch is copied as-is, without the editorial comments that were not in the source.

@iacker
iacker force-pushed the docs/2497-sync-gpu-idle-power branch from e4bbbad to ceeb957 Compare July 18, 2026 15:19
@sunya-ch
sunya-ch force-pushed the docs/2497-sync-gpu-idle-power branch from ceeb957 to b8aa1a3 Compare July 21, 2026 07:11
@sunya-ch

Copy link
Copy Markdown
Collaborator

@iacker I rebased the branch but it turns me to co-author.
Could you please rebase the branch locally and force push here instead?

@iacker
iacker force-pushed the docs/2497-sync-gpu-idle-power branch 3 times, most recently from b2a30e6 to 8d41c0a Compare August 6, 2026 19:22
@iacker

iacker commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

Both points addressed.

Snippet source: replaced the paraphrase with the verbatim block from getDevicePowerStatsLocked, the idle check plus the idlePower precedence switch and the activePower < 0 clamp. Added a [collector-idle] permalink to those lines so the doc stays traceable to the source. It matches L234-L247 exactly now.

Rebase: done locally, no co-author trailer left, DCO green.

iacker added 2 commits August 14, 2026 00:55
Two sections of the GPU power monitoring design doc had drifted from the
implementation in internal/device/gpu/nvidia/collector.go:

Idle Power Detection:
- the doc showed minObservedPower updated unconditionally; the collector
  now only updates the baseline when the GPU is truly idle (no compute
  processes running), avoiding a false baseline when Kepler starts under
  load;
- documents the idle-power precedence (user-configured SetIdlePower > 0,
  then observed idle, then a conservative 0 fallback) and the clamp that
  prevents negative active power.

MIG Mode:
- the doc claimed per-instance power attribution was 'not yet implemented'
  and skipped; the collector now attributes MIG power per instance via
  attributePartitioned (DCGM activity based), with an equal-distribution
  fallback when DCGM is unavailable.

Documentation-only, no code changes.

Signed-off-by: iacker <iacker@users.noreply.github.com>
Match the two Go snippets in the Idle Power Detection section to the actual
getDevicePowerStatsLocked implementation, including the non-fatal
GetComputeRunningProcesses error branch that was previously collapsed. Add a
source permalink to collector.go so readers can locate the code.

Signed-off-by: iacker <iacker@users.noreply.github.com>
@iacker
iacker force-pushed the docs/2497-sync-gpu-idle-power branch from 8d41c0a to df87633 Compare August 13, 2026 22:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Documentation changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants