Power#
This chapter describes the Windows power modes to use for gaming and AI workloads, and how to query the power state of the system and the GPU at run time. The following sections cover the battery mode recommendations, the Win32 and NVML queries to use, the NVML power state definitions, and the recommendations to follow when an application runs on battery.
Battery Mode Recommendations for Gaming and AI Workloads#
Performance Mode: Recommended for gaming and highest AI inference throughput.
Balanced Mode: Acceptable for gaming and AI workloads while preserving battery life.
Power Efficiency Mode: Not recommended for gaming, suitable for AI background tasks.
Framerate Cap: A framerate cap of 30 fps is recommended to conserve battery life.
Querying Battery Mode (System-Level)#
Use the Win32 API to query battery mode through GetSystemPowerStatus.
#include <windows.h>
#include <stdio.h>
int main(void)
{
SYSTEM_POWER_STATUS sps;
if (GetSystemPowerStatus(&sps))
{
if (sps.ACLineStatus == 1)
{
printf("On AC power\n");
}
else if (sps.ACLineStatus == 0)
{
printf("On battery (DC)\n");
}
else
{
printf("Power status unknown\n");
}
return 0;
}
else
{
fprintf(stderr, "GetSystemPowerStatus failed\n");
return 1;
}
}
Querying GPU Power State (Fine-Tuning)#
Use the NVIDIA Management Library (NVML) to query GPU power state.
#include <nvml.h>
int main()
{
nvmlInit();
nvmlDevice_t device;
nvmlDeviceGetHandleByIndex(0, &device);
unsigned int powerState;
nvmlDeviceGetPowerState(device, &powerState);
printf("Power State: P%u\n", powerState); // P0 - P12
nvmlShutdown();
return 0;
}
Power State Definitions from NVML (GPU Power State)#
P0: Fully active (AC power, best performance)
P4: Balanced mode
P8: Battery mode
Developer Recommendations#
Query system-level power state using Win32 API.
Use the NVML for the GPU-specific power state.
Let the scheduler choose between efficiency and performance cores based on battery mode, unless manually overridden.
To provide the best experience on battery:
Build your application for the native ARM64 platform if possible. Running x86 or x86_64 code on ARM64 incurs emulation overhead and performance penalties.
Use profiling tools to find hotspots in your application and optimize them. Inefficient code keeps the CPU awake for longer than necessary and degrades battery life.
Ensure your code uses vector ISAs (NEON, SVE) where appropriate. Vector instructions generally perform more work per Joule.
When parallelizing with solutions like OpenMP, choose a scheduling strategy that considers hybrid architectures, such as
dynamicorguided. Consider increasing batch sizes to mitigate synchronization overhead.When dealing with memory locality issues, consider that RTX Spark does not have the same amount of L3 cache in its CPU clusters.
If your process does not require high responsiveness, consider lowering its QoS using
SetProcessInformationandPROCESS_POWER_THROTTLING_STATEAPIs. There are analogous APIs that apply to threads.For .NET Framework applications, use the Prefer Native ARM64 option to avoid double-JITting. See How to run .NET Framework apps natively on Arm64 devices.