Power Reservation Steering (PRS)
Overview
Power Reservation Steering (PRS) is an advanced dynamic power management feature in DPS that automatically redistributes power across compute nodes based on real-time telemetry data. PRS optimizes power allocation within a power domain by monitoring GPU utilization and dynamically adjusting power limits to maximize workload performance while staying within overall power budgets.
Unlike static power policies that set fixed power limits, PRS continuously analyzes workload behavior and steers unused power from idle or underutilized GPUs to those that need more power, enabling more efficient use of datacenter power capacity.
Key Concepts
Dynamic Power Redistribution
PRS operates in a continuous loop that:
- Collects Telemetry - Gathers real-time power usage and GPU utilization data from all nodes in the domain
- Analyzes Workload - Identifies GPUs that are underutilizing their allocated power
- Calculates Recommendations - Determines optimal power distribution based on actual demand
- Applies Changes - Dynamically adjusts GPU power limits through DPS
Budget and Idle-Power Semantics
PRS works within an aggregate power budget. The budget is an upper bound, not an exact draw target, and PRS does not try to make every node consume the same amount of power. Nodes can receive different GPU limits as their observed demand changes.
Idle and underutilized GPUs still retain the minimum power defined by their device specification. DPS 0.8.x does not expose a separate workload-idle threshold that can be tuned per node, resource group, or topology. This is different from a device specification’s idlePolicy: idlePolicy is a fallback policy used when no explicit topology policy is assigned, not the telemetry threshold PRS uses to classify current workload demand.
Integration with Resource Groups
PRS integrates seamlessly with DPS’s resource group system. When a resource group is activated with PRS enabled:
- The resource group’s nodes are added to the PRS domain
- PRS begins monitoring and optimizing power for those nodes
- When the resource group is deactivated, nodes return to their topology defaults
Configuration Methods
PRS can be configured at multiple levels, providing flexibility for different deployment scenarios.
1. Helm Chart Configuration
Enable PRS deployment and connection when installing DPS via Helm:
# Enable PRS deployment
prs:
enabled: true
image:
repository: nvcr.io/nvidia/prs
tag: 1.0.12-prs-0.1.1.10-dpsapi
config:
configServerPort: 8880
jobSchedServerPort: 8881
# Chart default; tune from measured BMC latency.
loopIntervalSeconds: 10
rpcTimeoutSeconds: 10
windowSize: 3
# Connect DPS-Server to PRS
dps:
prs:
enabled: true
headroomPercent: -30.0
# hostPort defaults to internal PRS service if not specified
hostPort: ""Both enable switches are required. prs.enabled deploys the PRS service,
while dps.prs.enabled connects DPS-Server to that service and supplies the
startup headroom value.
loopIntervalSeconds: 10 is the chart default, not a fixed recommendation for
every deployment. Set the interval from measured BMC latency so PRS does not
iterate faster than the BMC telemetry and power-control paths can respond.
Follow the MaxLPS pilot BMC latency measurement procedure
and its BMC latency tuning instructions
before choosing the production value.
PRS Configuration Parameters
| Parameter | Description | Default |
|---|---|---|
prs.enabled |
Deploy the PRS service | false |
prs.config.loopIntervalSeconds |
Interval between PRS optimization cycles; tune from measured BMC latency by following the MaxLPS pilot procedure | 10 |
prs.config.rpcTimeoutSeconds |
Timeout for RPC calls to DPS | 10 |
prs.config.windowSize |
Number of samples for averaging power metrics | 3 |
dps.prs.enabled |
Enable PRS integration in DPS-Server | false |
dps.prs.headroomPercent |
Deployment-wide percentage applied to the GPU budget sent to PRS (-50 through 100); negative values are generally recommended and -30 is the tested starting point |
-30.0 |
dps.prs.hostPort |
PRS service endpoint (auto-configured if empty) | "" |
How Headroom Is Calculated
Headroom is global to the DPS deployment. It is not independently configurable per node, resource group, or topology. For each node in an active PRS-enabled resource group, DPS calculates:
gpuPool = max(0, nodePolicyCap - reservedCPU - reservedMemory)
nodeBudget = gpuPool * (1 + headroomPercent / 100) + nonGPUStatic
domainBudget = sum(nodeBudget for every node in the resource group)nodePolicyCap is the node-level limit from the effective policy, with the
node hardware maximum as the fallback when no node limit is present.
reservedCPU and reservedMemory come from the policy when present and use
the hardware-minimum fallback otherwise. DPS calculates
nonGPUStatic = max(0, nodeHardwareMinimum - gpuCount * gpuMinimum), so the
GPU minimum is not counted twice. Adding nonGPUStatic after the multiplier
means headroom scales only the GPU pool, not the chassis baseline.
The valid range is -50 through 100:
- A negative value reduces the GPU pool sent to PRS and causes more aggressive capping. Negative headroom is generally recommended.
0sends the unscaled GPU pool.- A positive value gives PRS more redistribution slack.
Negative headroom is important to PRS responsiveness because it keeps the
domain under an active aggregate constraint. When workload demand moves between
GPUs, PRS must actively steer the constrained budget instead of absorbing the
change in unallocated slack. The -30 setting has been tested and is the
recommended starting point for DPS 0.8.x. Zero and positive values are valid,
but the additional slack can make steering less responsive; use them only after
validating power compliance and workload performance. Headroom controls the
strength of this budget pressure, while loopIntervalSeconds separately
controls how often PRS reacts.
For example, if nodePolicyCap is 12,000 W, the CPU and memory reservations
are 1,000 W and 500 W, and nonGPUStatic is 400 W, then gpuPool is
10,500 W. At -30, that node contributes 10,500 * 0.70 + 400 = 7,750 W
to the domain budget. Four identical nodes contribute 31,000 W.
Headroom changes only the aggregate domain power_budget; it does not scale
each GPU’s power_max, which remains the hardware TGP sent to PRS. It is also
separate from topology PowerDomain.OverProvisioningPercentage. PRS headroom
changes the runtime GPU budget sent to PRS, while topology overprovisioning
changes how much capacity DPS can provision above a PowerDomain operating
limit.
The domain budget is an aggregate upper bound; it is not a target that every
node must draw and it does not guarantee equal node power. DPS still validates
PRS recommendations against the effective resource-group policy, shared-GPU
budget, PowerDomain, and NvGrid constraints. Headroom does not override those
limits, and an infeasible budget or recommendation can be rejected.
Startup Defaults and the Helm Zero Limitation
The DPS 0.8.x Helm chart defaults dps.prs.headroomPercent to -30. The
DPS-Server binary itself defaults --prs-headroom-percent (and
PRS_HEADROOM_PERCENT) to 0 when it is run directly without the chart.
In the 0.8.x chart, setting the Helm value to the numeric value 0 still
renders PRS_HEADROOM_PERCENT=-30.0 because the template treats numeric zero
as empty. To use zero headroom, deploy DPS and then set the runtime value:
dpsctl settings update --set prs_headroom_percent=0The runtime value is persisted. It takes precedence over Helm or direct-binary startup values on subsequent DPS-Server restarts. To return to another value, update the runtime setting explicitly; changing only the Helm value does not replace a value already persisted in the database.
Headroom Tuning
Use negative headroom for normal PRS operation. For an initial MaxLPS pilot,
start with the tested chart default of -30. If the workload has unacceptable
performance, repeat the same workload at -15. Keep the resource-group policy,
topology, workload, load-generator mode, controlled input, and measurement
window unchanged so the result can be attributed to headroom. Use the same
target-QPS schedule for an open-loop test or the same configured concurrency
for a closed-loop test. The topology’s PowerDomain.OperatingLimit defines the
pilot constraint, the resource-group policy sets the starting requested
allocation inside that constraint, and PRS headroom scales the GPU budget sent
to PRS. Change only one control at a time.
2. Global Config API
Read or update the global PRS enable and headroom settings using the Global Configuration API:
Get Current Configuration
# gRPC request
grpcurl -plaintext localhost:50051 nvidia.dcpower.v1.ConfigurationManagementService/GetConfigurationResponse:
{
"status": { "ok": true, "diagMsg": "Success" },
"settings": {
"prs_enabled": "true",
"prs_headroom_percent": "-30",
"metrics_interval_seconds": "30"
}
}Update PRS Setting
# Enable PRS
grpcurl -plaintext -d '{"settings": {"prs_enabled": "true"}}' \
localhost:50051 nvidia.dcpower.v1.ConfigurationManagementService/UpsertConfiguration
# Disable PRS
grpcurl -plaintext -d '{"settings": {"prs_enabled": "false"}}' \
localhost:50051 nvidia.dcpower.v1.ConfigurationManagementService/UpsertConfiguration
# Change global PRS headroom
grpcurl -plaintext -d '{"settings": {"prs_headroom_percent": "-15"}}' \
localhost:50051 nvidia.dcpower.v1.ConfigurationManagementService/UpsertConfiguration3. dpsctl Command Line
Manage PRS settings using the dpsctl command-line tool:
List Current Settings
dpsctl settings listOutput:
{
"settings": {
"metrics_interval_seconds": "30",
"prs_enabled": "false",
"prs_headroom_percent": "-30"
},
"status": {
"diag_msg": "Success",
"ok": true
}
}Enable PRS Globally
dpsctl settings update --set prs_enabled=trueDisable PRS Globally
dpsctl settings update --set prs_enabled=falseChange PRS Headroom
dpsctl settings update --set prs_headroom_percent=-15Use dpsctl settings list to read the persisted value that DPS is currently
using. Do not infer the effective value from the Helm values file alone.
4. User Interface (UI)
The DPS web interface provides a visual way to manage PRS:
- Navigate to Settings in the DPS UI
- Locate the Dynamic Power Integrations section
- Find the Power Reservation Steering (PRS) card
- Toggle the switch to enable or disable PRS
- Enter a value from
-50through100in PRS Headroom (%) - Click Save to apply both settings
The UI displays PRS with descriptive tags:
workload-agnostic- Works with any workload typetopology- Applies across the entire topologyresource-group- Integrates with resource group management
The headroom field is disabled while the global PRS switch is off. Values
saved from the UI use the same persistent runtime setting as the API and
dpsctl.
Applying, Verifying, and Rolling Back a Runtime Change
A runtime headroom update does not require a DPS-Server restart. When the
effective value changes, DPS persists the value, updates its PRS client, and
asynchronously recomputes and re-upserts every active PRS-enabled
resource-group domain. The API or dpsctl command can therefore return before
all domain upserts finish. A write of the existing value is a no-op and does
not produce a new re-upsert or configuration-change log message.
After changing the value:
-
Confirm the persisted effective setting:
dpsctl settings list -
Confirm that the DPS-Server observed the change and initiated the re-upsert:
kubectl logs -n dps -l app=dps-server -c dps-server --since=5m \ | grep "PRS config changed, re-triggering PRS upsert" -
Confirm the intended resource groups are active and have PRS enabled:
dpsctl resource-group list
Record the previous value before tuning. Roll back by writing that value through the same runtime path, for example:
dpsctl settings update --set prs_headroom_percent=-30Then repeat the verification steps. Rollback is also asynchronous and remains persisted across restarts.
5. Resource Group Configuration
Control PRS behavior on a per-resource-group basis:
Create Resource Group with PRS Disabled
dpsctl resource-group create \
--resource-group "static-training" \
--external-id 12345 \
--policy "Node-High" \
--dpm-enable=false \
--prs-enabled=falseCreate Resource Group with PRS Enabled (Default)
# PRS is enabled by default when creating resource groups
dpsctl resource-group create \
--resource-group "dynamic-inference" \
--external-id 12346 \
--policy "Node-Med" \
--dpm-enable \
--shared-gpu-enablePRS vs Dynamic Power Management (DPM)
DPS supports two complementary dynamic power features:
| Feature | PRS | DPM |
|---|---|---|
| Scope | Cross-node optimization within domain | Per-resource-group policy management |
| Mechanism | Telemetry-based power steering | Policy-based power allocation |
| Control | Global setting + per-resource-group | Per-resource-group flag |
| Use Case | Maximize utilization of power budget | Flexible policy application |
Both can be used together:
- DPM enabled allows DPS to dynamically adjust policies
- PRS enabled allows automatic power redistribution based on telemetry
# Full dynamic power management
dpsctl resource-group create \
--resource-group "full-dynamic" \
--external-id 12347 \
--policy "Node-High" \
--dpm-enable=true \
--prs-enabled=true
# Static policy only (no dynamic adjustment)
dpsctl resource-group create \
--resource-group "strict-policy" \
--external-id 12348 \
--policy "Node-Med" \
--dpm-enable=false \
--prs-enabled=falseArchitecture
PRS Service Components
PRS runs as a separate service in the dps namespace with the following components:
- Configuration Server (port 8880) - Manages PRS configuration and domain definitions
- Controller Loop - Continuously monitors and optimizes power distribution
Data Flow
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ DPS-Server │────▶│ PRS Service │────▶│ DPS-Server │
│ (Telemetry) │ │ (Optimization) │ │ (Apply Limits) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
▼ ▼ ▼
GPU Metrics Power Budget GPU Power Limits
Collection Calculation ApplicationBest Practices
When to Enable PRS
- Heterogeneous workloads - When GPUs in a domain run different workload types
- Variable utilization - When GPU utilization fluctuates over time
- Power-constrained environments - When maximizing work within a fixed power budget is critical
- Large-scale deployments - When manual power tuning is impractical
When to Disable PRS
- Consistent workloads - When all GPUs run identical, steady-state workloads
- Fixed-cap requirements - When a workload must keep a fixed policy cap without dynamic redistribution
- Debugging scenarios - When isolating power-related issues
- Short jobs - When job duration is shorter than PRS optimization cycles
Configuration Recommendations
- Start with defaults - PRS default settings work well for most deployments
- Monitor before tuning - Observe PRS behavior before adjusting parameters
- Use per-resource-group control - Disable PRS for specific workloads that need strict power limits
- Coordinate with policies - Ensure power policies provide reasonable bounds for PRS optimization
Troubleshooting
Headroom Value Is Rejected
prs_headroom_percent must be a finite number from -50 through 100.
Values outside that range are rejected by the runtime API and dpsctl.
Effective Headroom Does Not Match Helm
Run dpsctl settings list. A previously saved API, dpsctl, or UI value is
persisted and takes precedence over the Helm startup value. Update the runtime
setting explicitly to change it. If Helm numeric zero rendered as -30 on
DPS 0.8.x, use the documented runtime prs_headroom_percent=0 workaround.
Headroom Changed but PRS Behavior Did Not
Confirm that the PRS service is deployed, the effective global prs_enabled
setting is true, and the active resource group has PRS enabled. When the
effective headroom value changes, the domain re-upsert is asynchronous, so
also inspect the DPS-Server log for completion or failure after the
configuration-change message. A no-op write of the current value does not
produce a new message or re-upsert. A strongly negative value can make the
computed domain budget lower than PRS’s node and GPU minimums; correct the
policy or increase headroom if PRS rejects that configuration. A positive
value still cannot bypass policy, shared-GPU, PowerDomain, or NvGrid
enforcement.
PRS Not Redistributing Power
-
Check PRS is enabled globally:
dpsctl settings list -
Verify PRS service is running:
kubectl get pods -n dps -l app=prs -
Check resource group PRS setting:
dpsctl resource-group list
PRS Service Connection Issues
-
Verify DPS-Server can reach PRS:
kubectl logs -n dps statefulset/dps-server | grep -i prs -
Check PRS configuration:
kubectl get configmap -n dps dps-prs-config -o yaml
Further Reading
- Power Policies - Define static power limits
- Resource Groups - Manage workload power allocations
- Workload Power Profiles Settings - GPU-specific power optimization
- Topologies - Datacenter infrastructure modeling