Power Consumption when GPU idle with Passthrough

Nafr1

New Member
Jan 10, 2024
5
0
1
Hello,

Currently I have 2 headless machines that I use as homelab machines. 1 machine is running proxmox with around 4 VMs and 5 LXC. The 2nd machine is a windows machine with a GPU RTX 3060 that I use for occasional game streaming (using steamlink). Most of the time that gaming machine is off, I only turn it on few hours a week....

Now I was thinking to get rid of the 2nd (gaming machine) and instead install my RTX 3060 on 1st machine (i.e running Proxmox) and do a gpu passthrough to a Windows 11 VM for gaming.

My question is, since that windows VM will only be used few hours a week, does the gpu (RTX 3060) that is passthrough to the VM, will still consume the power even when the VM is off/suspended?

Based on your experiences, would you guys suggest to leave the gaming machine baremetal (current setup)... or does it make sense to have a gaming VM?

Your input would be appreciated.

Thanks
 
Just a quick comment, concerning the power-consumption, but intentionally not fully tackling your "1 all-in-one machine vs. 2 dedicated machines" thought:
For pass-through to work, you usually completely unload all the relevant drivers from the host OS (Proxmox here). Which means, that this virtualization host will not really touch the graphics card.
As a result, the power-consumption with the "gaming VM" in off-state, will be higher than it could be, as no driver will send the GPU into its lowest power states.
So, if you plan to use the "all-in-one" approach, then consider, that the gaming VM should ideally always be running, for the GPU to be handled by a matching driver.
 
  • Like
Reactions: leesteken
Just a quick comment, concerning the power-consumption, but intentionally not fully tackling your "1 all-in-one machine vs. 2 dedicated machines" thought:
For pass-through to work, you usually completely unload all the relevant drivers from the host OS (Proxmox here). Which means, that this virtualization host will not really touch the graphics card.
As a result, the power-consumption with the "gaming VM" in off-state, will be higher than it could be, as no driver will send the GPU into its lowest power states.
So, if you plan to use the "all-in-one" approach, then consider, that the gaming VM should ideally always be running, for the GPU to be handled by a matching driver.

Thanks very much for your response... is there any way (running a script or something when that gaming VM is suspended, that script would completley shut down the GPU).... Ideally,, I would like to set the GPU to almost no or minimum power use when the VM is Off... That GPU is only going to be used in that gaming VM and outside of it, I would like to keep it off to save Power bill...
 
Thanks very much for your response... is there any way (running a script or something when that gaming VM is suspended, that script would completley shut down the GPU).... Ideally,, I would like to set the GPU to almost no or minimum power use when the VM is Off... That GPU is only going to be used in that gaming VM and outside of it, I would like to keep it off to save Power bill...
You can use a hookscript ( https://pve.proxmox.com/pve-docs/pve-admin-guide.html#_hookscripts ) to start another VM with a driver for the GPU or unbind the GPU from vfio-pci and load the Linux driver for the GPU. There are examples in other threads about this on the forum.
 
# **Proxmox Multi-GPU NVIDIA VFIO Setup (P400 + GTX 1060)**

I’ve been running a home server setup where my GTX 1060 was dedicated to a windows gaming/streaming VM, while my P400 served another VM for different workloads. One of the challenges I quickly ran into was the **power consumption** of having both GPUs always powered, even when idle. The GTX 1060, in particular, tends to draw a noticeable amount of power when sitting idle in a VM passthrough scenario, and the P400, while less hungry, still added to the total.

After experimenting with GPU passthrough management and driver unbinding techniques, I managed to **significantly reduce idle power draw**, saving roughly **40 watts**. This improvement not only helps reduce electricity costs but also lessens heat output and wear on the hardware — which is important for a system that runs 24/7.

The struggle was balancing **VM accessibility** with **host control**, making sure I could still assign the GPUs to VMs when needed without leaving them permanently consuming power on the host.
**Important:** Both GPUs **must be present on the host during driver installation** so that the NVIDIA persistence daemon can manage both devices properly.

---


## **Step 0 — Preparation**

1. Update system and install build tools:


```bash
apt update && apt full-upgrade -y
apt install build-essential dkms pve-headers pkg-config
```

2. Check kernel and headers:


```bash
uname -r
dpkg -l | grep pve-headers
```

- Ensure headers match the running kernel (e.g., `6.14.11-2-pve`).


3. Blacklist conflicting modules in /etc/modprobe.d/blacklist.conf:


blacklist nouveau
blacklist radeon
#blacklist nvidia
Update initramfs and reboot:
update-initramfs -u
reboot
---

## **Step 1 — Prepare GPUs for Driver Installation**

1. List all NVIDIA GPUs:

lspci -nn | grep -i nvidia

- Example output:

02:00.0 Quadro P400
02:00.1 P400 Audio
65:00.0 GTX 1060
65:00.1 GTX 1060 Audio

2. **Important:** Both P400 and GTX 1060 **must be visible to the host** when installing the NVIDIA driver. This ensures the NVIDIA persistence daemon can manage both GPUs, allowing idle power management and avoiding errors during passthrough.

3. Temporarily unbind the GPU you want to dedicate to VFIO (GTX 1060) **only for driver installation**, so the driver can see it:
For my gtx 1060
echo 0000:65:00.0 > /sys/bus/pci/devices/0000:65:00.0/driver/unbind
echo 0000:65:00.1 > /sys/bus/pci/devices/0000:65:00.1/driver/unbind
echo "" > /sys/bus/pci/devices/0000:65:00.0/driver_override
echo "" > /sys/bus/pci/devices/0000:65:00.1/driver_override
- For my Quadro P400

echo 0000:02:00.0 > /sys/bus/pci/devices/0000:02:00.0/driver/unbind
echo 0000:02:00.1 > /sys/bus/pci/devices/0000:02:00.1/driver/unbind
echo "" > /sys/bus/pci/devices/0000:02:00.0/driver_override
echo "" > /sys/bus/pci/devices/0000:02:00.1/driver_override
- After installation, both GPUs should be visible to the host again under ```nvidia-smi```
---

## **Step 2 — Install NVIDIA Driver**

1. Make installer executable (this can be downloaded from Nvidia page):

chmod +x NVIDIA-Linux-x86_64-*.run
2. Run installer:

./NVIDIA-Linux-x86_64-*.run
- **Important:** Make sure both GPUs are visible on the host **during installation**. This ensures the NVIDIA persistence daemon can initialize both devices.

- Choose **No** for module signing if Secure Boot is disabled.

- Ignore X or 32-bit warnings; they are not needed for headless VFIO setups.

- Confirm installation of `nvidia-persistenced` if prompted.
---

## **Step 3 — Verify Driver Installation**
nvidia-smi
lsmod | grep nvidia
- Both P400 and GTX 1060 should appear.
1758495106026.png
- Persistence mode for both GPUs can now be managed via the NVIDIA persistence daemon.

- If one GPU is missing, **persistence mode will not work correctly** for that device, potentially causing errors during passthrough or idle power issues.

## **Step 4 — Enable NVIDIA Persistence Daemon**

Create the systemd service:
cat <<EOF > /etc/systemd/system/nvidia-persistenced.service
[Unit]
Description=NVIDIA Persistence Daemon
After=network.target

[Service]
Type=forking
ExecStart=/usr/bin/nvidia-persistenced --user root --no-persistence-mode
ExecStop=/usr/bin/nvidia-persistenced --terminate
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF
Reload systemd and enable:
systemctl daemon-reload
systemctl enable nvidia-persistenced
systemctl start nvidia-persistenced
systemctl status nvidia-persistenced
- **Both GPUs must be visible to the host** at this point for the daemon to manage persistence mode correctly.

## **Step 5 — Return GTX 1060 to VFIO for Passthrough**
echo vfio-pci > /sys/bus/pci/devices/0000:65:00.0/driver_override
echo vfio-pci > /sys/bus/pci/devices/0000:65:00.1/driver_override
echo 0000:65:00.0 > /sys/bus/pci/drivers_probe
echo 0000:65:00.1 > /sys/bus/pci/drivers_probe
- VM 311 will now use GTX 1060.

- Host keeps control of P400 for persistence and idle management.


---

## **Step 6 — Hook Scripts for Automatic Passthrough**
I have created two files with:
```bash
nano /var/lib/vz/snippets/gtx1060.sh
nano /var/lib/vz/snippets/p400.sh
```

### **GTX 1060 → VM 311**
#!/usr/bin/env bash
# GTX 1060 GPU passthrough hook for VM 311

GPU_VGA="0000:65:00.0" # Replace with your GPU PCI ID
GPU_AUDIO="0000:65:00.1" # Replace with HDMI/audio PCI ID

if [ "$2" == "pre-start" ]; then
# Disable persistence mode to allow unbinding
nvidia-smi -i "$GPU_VGA" --persistence-mode=0

# Unbind GPU and audio from NVIDIA driver
echo "$GPU_VGA" > /sys/bus/pci/devices/$GPU_VGA/driver/unbind
echo "$GPU_AUDIO" > /sys/bus/pci/devices/$GPU_AUDIO/driver/unbind

# Override driver to vfio-pci
echo vfio-pci > /sys/bus/pci/devices/$GPU_VGA/driver_override
echo vfio-pci > /sys/bus/pci/devices/$GPU_AUDIO/driver_override

# Bind GPU and audio to vfio-pci for VM passthrough
echo "$GPU_VGA" > /sys/bus/pci/drivers/vfio-pci/bind
echo "$GPU_AUDIO" > /sys/bus/pci/drivers/vfio-pci/bind

elif [ "$2" == "post-stop" ]; then
# Unbind GPU and audio from vfio-pci
echo "$GPU_VGA" > /sys/bus/pci/devices/$GPU_VGA/driver/unbind
echo "$GPU_AUDIO" > /sys/bus/pci/devices/$GPU_AUDIO/driver/unbind

# Rebind to NVIDIA driver
echo nvidia > /sys/bus/pci/devices/$GPU_VGA/driver_override
echo "$GPU_VGA" > /sys/bus/pci/drivers/nvidia/bind

# Re-enable persistence mode for host use
nvidia-smi -i "$GPU_VGA" --persistence-mode=1
fi

exit 0

### **P400 → VM 306
#!/usr/bin/env bash
# GTX 1060 GPU passthrough hook for VM 311

GPU_VGA="0000:02:00.0" # Replace with your GPU PCI ID
GPU_AUDIO="0000:02:00.1" # Replace with HDMI/audio PCI ID

if [ "$2" == "pre-start" ]; then
# Disable persistence mode to allow unbinding
nvidia-smi -i "$GPU_VGA" --persistence-mode=0

# Unbind GPU and audio from NVIDIA driver
echo "$GPU_VGA" > /sys/bus/pci/devices/$GPU_VGA/driver/unbind
echo "$GPU_AUDIO" > /sys/bus/pci/devices/$GPU_AUDIO/driver/unbind

# Override driver to vfio-pci
echo vfio-pci > /sys/bus/pci/devices/$GPU_VGA/driver_override
echo vfio-pci > /sys/bus/pci/devices/$GPU_AUDIO/driver_override

# Bind GPU and audio to vfio-pci for VM passthrough
echo "$GPU_VGA" > /sys/bus/pci/drivers/vfio-pci/bind
echo "$GPU_AUDIO" > /sys/bus/pci/drivers/vfio-pci/bind

elif [ "$2" == "post-stop" ]; then
# Unbind GPU and audio from vfio-pci
echo "$GPU_VGA" > /sys/bus/pci/devices/$GPU_VGA/driver/unbind
echo "$GPU_AUDIO" > /sys/bus/pci/devices/$GPU_AUDIO/driver/unbind

# Rebind to NVIDIA driver
echo nvidia > /sys/bus/pci/devices/$GPU_VGA/driver_override
echo "$GPU_VGA" > /sys/bus/pci/drivers/nvidia/bind

# Re-enable persistence mode for host use
nvidia-smi -i "$GPU_VGA" --persistence-mode=1
fi

exit 0
**Then make it executable:**

```bash
chmod +x /var/lib/vz/snippets/gtx1060.sh
chmod +x /var/lib/vz/snippets/p400.sh
```

VM configs:

```ini
# VM 311
hookscript: local:snippets/gtx1060.sh

# VM 306
hookscript: local:snippets/p400.sh
```

---

## **Step 7 — Test Setup**

1. Reboot host for a clean state.

2. Start VM 311 → GTX 1060 is assigned to VM.

3. Stop VM 311 → GTX 1060 returns to host.

4. Start VM 312 → P400 is assigned to VM.

5. Stop VM 312 → P400 returns to host.


Verify:
1758495274539.png
```bash
nvidia-smi # Host GPU should be idle when not used by VMs
systemctl status nvidia-persistenced
```

---

✅ **Result**

- Both GPUs managed by host initially.

- Each GPU assigned to its own VM when running.

- NVIDIA persistence daemon ensures low idle power and proper GPU initialization.

- Host always regains control after VM shutdown.

- Future driver updates can be applied safely with temporary unbind/bind.


I think this approach is pretty elegant compared to putting the GPU in another low-power VM. The Linux driver from NVIDIA is kind of frustrating—it won’t allow the GPU to enter P8 state for power saving—but fortunately, there is still a small workaround for this problem.
 
Last edited:
  • Like
Reactions: Onslow