Rehearse the MaxLPS Power Pilot With the SDK Simulator#
Use the DPS SDK Pilot profile to practice the MaxLPS power pilot without physical hardware. Deploy a local Kubernetes cluster, configure DPS, replay a power trace, and compare simulated GPU power across a three-rack baseline and a four-rack managed run.
This guide complements Run the MaxLPS Power Pilot, which remains the procedure for evaluating real systems. For the power-management model, refer to MaxLPS Power Management.
What the Rehearsal Measures#
The SDK runs DPS and Power Steering against simulated hardware. Use the following boundaries when interpreting results.
Evidence |
What You Can Learn |
|---|---|
DPS application telemetry |
Observe actual API health, topology state, resource-group membership, provisioned load, Redfish requests, and control-loop activity. |
Power Steering telemetry |
Observe actual controller scheduling, allocations, errors, and limit requests and confirmations against simulated endpoints. |
GPU and node power, utilization, and limits |
Observe values produced by the selected simulation model. |
The built-in nemotron-12b workload replays a power trace. It does not launch
an inference model. Job completion and simulated GPU utilization do not
measure tokens per second, time to first token, or request latency.
A completed rehearsal demonstrates the configuration workflow and control behavior. The comparison shows three racks with workload activity in the baseline and four under MaxLPS, against the same configured power envelope.
Step 1: Obtain and Deploy the Pilot Profile#
Download and extract the DPS SDK customer package from the NVIDIA NVOnline Portal. Run the commands in this guide from the extracted SDK directory.
Prepare your host before deployment:
Use Linux (Ubuntu or Debian) or macOS, with Task installed and a running Docker daemon accessible to your user.
Allow dependency downloads and access to the container and chart registries referenced by the package, including
nvcr.io. Resolve any image-pull or registry authentication errors before continuing.Allow the setup tasks to install tools and configure
/etc/hostswith elevated privileges. macOS setup uses Homebrew.Make local ports
80,443, and5001available for the cluster and registry. The workload helper also uses port18443for a temporary simulator connection.Install
curlandjqseparately if needed.task setupdoes not install these helper dependencies.Provide enough Docker memory, CPU, and disk for the monitoring stack, DPS, and simulator. The general SDK requirements in SDK Simulator User Guide are a starting point; a Pilot-specific minimum has not been established. Check for pending Pods, memory pressure, and restarts.
Install the SDK dependencies first:
task setup
Setup installs or checks Docker, kubectl, K3D, Helm, uv, and
the Docker-based dpsctl wrapper. On Linux, the wrapper is installed in
/usr/local/bin. On macOS, add its installation directory to your shell path
before deployment:
export PATH="$HOME/.local/bin:$PATH"
Confirm the tools and deploy the Pilot profile:
command -v task docker kubectl helm dpsctl curl jq
docker info
task deploy:pilot
task simulator:wait-for-dps-server
The deployment creates the dps-sdk K3D cluster and installs
DPS, Power Steering, a BMC simulator with a workload-model
sidecar, Prometheus, Grafana, and the web UI. It does not import the pilot
topology or run the paired workloads for you.
Configure the CLI endpoint and authenticate explicitly:
export DPSCTL_HOST=api.dps.sdk
export DPSCTL_PORT=80
export DPSCTL_INSECURE_TLS_SKIP_VERIFY=true
dpsctl login --username dps
Enter the local SDK password, dps. These connection settings apply to the
local SDK deployment. The packaged wrapper runs the CLI image through Docker
and maps SDK ingress hostnames inside the container.
Check the deployment and record the server version:
kubectl --context k3d-dps-sdk get pods -n dps
dpsctl server-version
dpsctl verify
Inspect reported status and diagnostics, including any status.ok field.
Confirm that the server, agent, authentication, database, simulator, and
monitoring components are available. Record the package version, CLI image
tag from scripts/dpsctl-wrapper.sh, and deployed component images with
your results.
The SDK does not deploy NVIDIA Base Command Manager, so its skipped
connectivity check is expected. Verification can also report a missing
dps-ui ingress because the SDK chart names it dps-sdk-ui. Check the actual
ingresses and open the UI to distinguish that naming mismatch from a failure.
Do not ignore API, authentication, database, or Pod readiness failures.
Use the following local services throughout the rehearsal.
Service |
Address |
Credentials |
|---|---|---|
DPS API |
|
|
DPS web UI |
|
|
Grafana |
|
|
Prometheus |
None |
If a service does not resolve, inspect the cluster ingresses and rerun the hostname configuration task:
kubectl --context k3d-dps-sdk get ingress -n dps
task deploy:etc:hosts
Step 2: Import and Activate the Pilot Topology#
The Pilot profile uses the following inventory and configured limits.
Item |
Configuration |
|---|---|
Simulated hardware |
Four GB300 racks, each with 18 compute nodes and 72 GPUs. |
Total inventory |
72 compute nodes and 288 GPUs. Names follow |
Baseline workload |
54 nodes and 216 GPUs across racks |
Managed workload |
All 72 nodes and 288 GPUs across racks |
Root domain |
|
Rack limits |
135,000 W each, represented by |
Static load |
7,416 W per rack, included in the topology budget. |
The four racks share a root envelope equal to three rack limits.
Validate, import, and activate the topology:
dpsctl topology validate sim/maxlps-pilot.json
dpsctl topology import sim/maxlps-pilot.json
dpsctl topology activate --topology maxlps-pilot
dpsctl topology list --active
Confirm that maxlps-pilot is active and that each operation reports success.
If import reports an existing topology, follow
Step 9: Retain Results and Clean Up before starting a new paired run.
Check the inventory and simulated node connectivity:
dpsctl topology list-entities
dpsctl check connection --topology maxlps-pilot
Resolve inaccessible nodes or simulator DNS errors before proceeding.
Step 3: Confirm Monitoring With the Topology Active#
Open Prometheus and check its scrape targets. Confirm that DPS, Power Steering, and the simulator are being scraped successfully. Then run the following expressions in the Prometheus query view to verify the data required for the comparison.
Confirm that the topology is present and active:
topology_service_active_status{topology_name="maxlps-pilot"}
Confirm that 72 distinct nodes have topology metadata:
count(count by (device_id) (device_total_power_watts{ device_type="ComputerSystem",topology_name="maxlps-pilot" }))
Confirm that 288 GPU power series are available:
count(max by (Hostname, gpu, UUID) (DCGM_FI_DEV_POWER_USAGE{ Hostname=~"gb300-nvl-00[1-4]-compute.*" }))
Confirm utilization samples for all four racks, including idle GPUs:
DCGM_FI_DEV_GPU_UTIL{Hostname=~"gb300-nvl-00[1-4]-compute.*"}
Confirm a root target of 405,000 W without a schedule or target override:
nvgrid_system_status_load_target_watts{feed_tag="PDU-Root"}
Allow several collection cycles after activation. The Pilot values configure a 5-second DPS scrape interval, a 10-second simulator scrape interval, and 5-second topology, grid, and node polling. Verify Power Steering’s actual scrape interval in Prometheus. Healthy scrape targets do not guarantee that every required metric or dashboard query is populated.
Use the DPS Server Health Dashboard for application diagnostics. The Datacenter and Resource Group dashboards are optional views for inventory, allocation, and membership checks. Refer to DPS Sample Dashboards for query and power-boundary details.
Step 4: Deactivate and Restore Simulator Defaults#
Remove DPS from the power-control path before the baseline:
dpsctl topology deactivate --topology maxlps-pilot
dpsctl topology list --active
dpsctl resource-group list --active
Confirm that maxlps-pilot is absent from the active topology list and no
resource group manages the pilot nodes. The simulator can retain power limits
written during activation. Deactivation alone does not establish an
unmanaged baseline.
Restart the Pilot simulator to restore its defaults:
kubectl --context k3d-dps-sdk rollout restart \
deploy/bmc-surrogate-simulator-pilot -n dps
kubectl --context k3d-dps-sdk rollout status \
deploy/bmc-surrogate-simulator-pilot -n dps --timeout=240s
After the simulator becomes ready, wait for fresh scrapes from the replacement Pod. Query the effective GPU limits in Prometheus:
DCGM_FI_DEV_POWER_MGMT_LIMIT{Hostname=~"gb300-nvl-00[1-4]-compute.*"}
The bundled GB300 simulator defaults to 1,400 W per GPU. Confirm that all 288 GPU limits report that value, rather than retained managed caps. Exclude old Pod series or wait for them to become stale before counting samples. Check GPU power, utilization, and DPS node metadata again with the expressions in Step 3: Confirm Monitoring With the Topology Active.
If limits remain capped, confirm that the topology is inactive and no other resource group or simulation is writing limits. Resolve that condition and repeat the reset before collecting a baseline. This reset is the simulator equivalent of restoring default GPU limits in the hardware procedure.
Step 5: Prepare Comparable Observation Windows#
Create a rehearsal record before starting the workloads. Retain the following information for both phases:
Package, CLI, server, controller, simulator, and dashboard versions.
Topology JSON, Pilot values, root and rack limits, and the
MaxLPSbundle.Trace name (
nemotron-12b),TIME_SCALE, job identifiers, and node sets.Collection and scrape intervals, workload start and end times, and selected observation windows in UTC.
Grafana datasource, topology, comparison offset, and active-GPU threshold.
Keep the trace, time scale, topology envelope, and collection settings consistent across both runs. The 54-node and 72-node replays exercise different simulated fleet sizes. They do not establish matched aggregate inference request demand.
The following commands use the task default, TIME_SCALE=1. A larger value
accelerates replay. At TIME_SCALE=1, each run takes about 30 minutes. At
TIME_SCALE=20, each run takes about 1 to 2 minutes. Choose a value that
leaves enough time to observe metrics and controller behavior, and use it
for both runs. The helper polls progress every 10 seconds and defaults to a
3-hour completion timeout. Record the baseline window during the run so you
can select a matching managed window.
Use the same measured power envelope in both phases: GPU draw across all 72 topology nodes, including idle GPUs in rack four during the baseline. CPU power and static rack loads are outside the dashboard’s GPU draw, although they consume part of the modeled topology budget.
Step 6: Run the Three-Rack Baseline#
Recheck that the topology is inactive, no pilot group is active, and simulator limits are restored. Record a UTC timestamp and start the baseline:
date -u '+%Y-%m-%dT%H:%M:%SZ'
task pilot:workload:baseline TIME_SCALE=1 JOB_ID=pilot-baseline
date -u '+%Y-%m-%dT%H:%M:%SZ'
The helper submits the trace to 54 nodes across racks 001 through 003 and waits
for completion. Expect confirmation that 54 nodes were accepted, progress
updates, and a completion message.
If submission fails, check simulator readiness, curl, jq, port 18443,
and the reported HTTP response. If progress times out, retain diagnostics
and inspect the workload and caps before repeating.
Each submission helper stops existing simulator jobs before starting its job. Run the phases sequentially, without another simulation in parallel. If metrics are absent or caps were retained, correct the issue and repeat the baseline before proceeding.
Step 7: Enable MaxLPS and Run the Managed Phase#
Reactivate the topology and inspect the server’s bundled policy:
dpsctl topology activate --topology maxlps-pilot
dpsctl topology list --active
dpsctl policy bundle list
dpsctl policy bundle get MaxLPS
Confirm successful activation, then create, populate, and activate the resource group:
dpsctl resource-group create --resource-group maxlps-pilot --external-id 1 \
--dpm-enable --prs-enabled --shared-gpu-enable --policy-bundle MaxLPS
dpsctl resource-group add --resource-group maxlps-pilot \
--entities "$(task pilot:nodes:72)"
dpsctl resource-group activate --resource-group maxlps-pilot \
--allow-reprovision --sync
dpsctl resource-group list --active
Inspect status and diagnostics from each command. Confirm the following fields for the active group before submitting the workload.
Field |
Expected Value |
|---|---|
|
|
|
|
|
|
|
All |
|
All 72 pilot compute nodes. |
Run the managed phase with the same time scale as the baseline:
date -u '+%Y-%m-%dT%H:%M:%SZ'
task pilot:workload:managed TIME_SCALE=1 JOB_ID=pilot-managed
date -u '+%Y-%m-%dT%H:%M:%SZ'
Confirm acceptance and completion for 72 nodes. Preserve the run output and group configuration with your timestamps.
Step 8: Compare the Results in Grafana#
After both runs, open DPS MaxP Window Comparison in Grafana. Comparison means the earlier baseline window. Current means the selected managed window, even after both runs have finished.
Configure the page with your recorded windows:
Select the provisioned Prometheus datasource under Metrics source.
Select maxlps-pilot under Datacenter / topology.
Set Grafana’s time picker to an absolute range covering the managed observation window. Use UTC to match your recorded timestamps.
Set Comparison window to the positive time difference between the managed and baseline window starts. The entire current range shifts backward by this offset. Verify that shifting the managed end by the same amount reaches the recorded baseline end.
Set Active GPU threshold to More than 5%. The count uses each GPU’s average utilization over the window. Any activity can include the simulated idle fourth rack because idle utilization is nonzero.
Confirm that both sets of summary cards, node power charts, and four named rack bars populate. Save the dashboard’s absolute URL and a screenshot.
The comparison offset is the difference between window starts. It is not
the baseline duration or the gap between runs. The dropdown defaults to one
day and accepts custom Prometheus durations, such as 2m or 125s.
The following example illustrates equal-duration windows separated by a 2-minute offset. Use your own timestamps and corresponding loaded trace portions; these example times do not identify an acceptance window.
Selection |
Example Value |
|---|---|
Baseline observation |
October 14, 9:04:30 p.m. to 9:05:30 p.m. UTC. |
Managed observation and Grafana absolute range |
October 14, 9:06:30 p.m. to 9:07:30 p.m. UTC. |
Comparison window |
|
Datacenter / topology |
|
Active GPU threshold |
More than 5% |
You can also supply the custom offset as var-baseline_offset in the saved
dashboard URL. For this example, retain the following query parameters,
alongside the absolute from and to parameters and datasource selection:
var-topology=maxlps-pilotvar-baseline_offset=2mvar-active_gpu_util_threshold=5
Interpret the Power Envelope#
Use the following definitions when reading the comparison.
Signal |
Meaning |
|---|---|
Power envelope |
Operating target from the Pilot’s single |
GPU draw and node power charts |
|
Active GPUs |
Count of GPUs whose window-average |
Mean power utilization |
Mean GPU draw divided by the root envelope. It is not a percentage of GPU maximum power or an applied GPU cap. |
Mean power headroom |
Root envelope minus mean GPU draw. CPU power and rack static loads still consume part of the modeled budget. |
Observed power change by rack |
Relative change in mean GPU draw from the baseline, displayed as a percentage. An initially idle rack can have a large relative increase. |
Power utilization change by rack |
Change in mean GPU draw divided by that rack’s 135 kW target, in percentage points. The panel displays a percent symbol. |
Active GPU change by rack |
Absolute count change. The fleet Active GPU change card instead shows a percentage. |
The peak utilization value sums individual GPU peak powers, which need not occur simultaneously. It is not an exact simultaneous fleet peak.
Check the Rehearsal Outcome#
Use the following observations together with successful workload completion and verified resource-group configuration.
Observation |
Expected Result in Loaded Windows |
|---|---|
Power envelope |
405 kW in both windows. In the inactive baseline, this is a reference target rather than evidence of enforcement. |
Active GPU counts |
Comparison active GPUs is 216, Current active GPUs is 288, and Active GPU change is approximately +33.3%. |
Rack activity |
Four named rack bars populate. Active GPU change by rack is zero for racks one through three and +72 for rack four. |
Simulated power behavior |
Rack four contributes loaded GPU draw in the managed window. The first three racks can draw less under managed caps. |
Exact power changes depend on trace phase, caps, and window selection. Do not require a particular reduction percentage.
Use the following checks for unexpected results.
Symptom |
Recovery |
|---|---|
Empty comparison cards |
Check the absolute range, offset, and availability of baseline telemetry. The default 1-day offset usually does not reach a run you just recorded. |
Empty current cards |
Check the managed window, datasource, topology, and the required metric series from Step 3. |
Equal active GPU counts |
Select More than 5%, inspect the loaded windows, and verify which node set received each workload. |
Missing rack bars or wrong topology |
Check topology selection, DPS node metadata, hostname matching, and the packaged dashboard version. |
Zero or unexpected envelope |
Check |
Power appears capped in the baseline |
Restore simulator defaults and repeat the baseline, then select a matching managed window. |
Step 9: Retain Results and Clean Up#
If desired, preserve the configuration and version record, workload output, active group status, membership, and both run timestamps. Retain the selected observation windows, computed offset, Grafana variables, saved absolute URL, and a screenshot or exported comparison. A dashboard view does not itself retain an evidence package.
Delete the resource group, then deactivate the topology:
dpsctl resource-group delete --resource-group maxlps-pilot
dpsctl topology deactivate --topology maxlps-pilot
dpsctl resource-group list --active
dpsctl topology list --active
Confirm success in the output and active lists. For another rehearsal, repeat the simulator reset in Step 4: Deactivate and Restore Simulator Defaults before collecting a new baseline. You can reuse the imported topology; skip its import step on a repeat run.
When you finish with the local environment, optionally remove the SDK cluster. This deletes its workloads and locally retained monitoring data:
task deploy:cluster:delete
Optional Follow-On: Move to the Hardware Pilot#
Use MaxLPS Power Pilot to plan the real-system evaluation and Run the MaxLPS Power Pilot to execute it.