Last active
January 4, 2024 10:56
-
-
Save ayufan/37be5c0b8fd26113a8be to your computer and use it in GitHub Desktop.
KVM CPU pinning for Proxmox VE
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
set -eo pipefail | |
VMID=200 | |
cpu_tasks() { | |
expect <<EOF | sed -n 's/^.* CPU .*thread_id=\(.*\)$/\1/p' | tr -d '\r' || true | |
spawn qm monitor $VMID | |
expect ">" | |
send "info cpus\r" | |
expect ">" | |
EOF | |
} | |
VCPUS=($(cpu_tasks)) | |
VCPU_COUNT="${#VCPUS[@]}" | |
if [[ $VCPU_COUNT -eq 0 ]]; then | |
echo "* No VCPUS for VM$VMID" | |
exit 1 | |
fi | |
echo "* Detected ${#VCPUS[@]} assigned to VM$VMID..." | |
echo "* Resetting cpu shield..." | |
for CPU_INDEX in "${!VCPUS[@]}" | |
do | |
CPU_TASK="${VCPUS[$CPU_INDEX]}" | |
echo "* Assigning $CPU_INDEX to $CPU_TASK..." | |
taskset -pc "$CPU_INDEX" "$CPU_TASK" | |
done |
Is it giving a notable speed increased ? And was it only noticable in game .. ? thanks
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hacked up something based on this for PCs with 2 NUMA nodes. Hope this helps someone. I'm hoping it helps with the quite poor performance I'm getting in some games with GPU passthrough. I'll report back here if it does anything.
`root@ProxMox01:~# cat PinVM.sh
#!/bin/bash
set -eo pipefail
VMID=$1
OffSet=$2
cpu_tasks() {
expect <<EOF | sed -n 's/^.* CPU .thread_id=(.)$/\1/p' | tr -d '\r' || true
spawn qm monitor $VMID
expect ">"
send "info cpus\r"
expect ">"
EOF
}
VCPUs=($(cpu_tasks));
if ! [ ${VCPUs} ]; then
echo "* No VCPUS for VM$VMID";
exit 1;
fi
if ! (( ${2} % 2 )); then
NumaCPUs=($(lscpu | grep "NUMA node[0-9]" | awk '{print $4}' | head -n1 | sed 's/,/ /g'));
else
NumaCPUs=($(lscpu | grep "NUMA node[0-9]" | awk '{print $4}' | tail -n1 | sed 's/,/ /g'));
fi
echo -e "\nVCPU PIDs: ${VCPUs[@]}\n";
lscpu | grep "NUMA node. CPU"
echo -e "\nCores per Numa Boundary: ${#NumaCPUs[@]}";
echo "Number of VCPUs: ${#VCPUs[@]}";
echo "Defined Core offset: $2";
if [[$(( $ {#NumaCPUs[@]} + 1 )) < $(( $2 + $ {#VCPUs[@]} )) ]]; then
echo -e "\nOffset too great for number of CPU cores. Exiting\n";
exit 1;
fi;
VCPUCount="${#VCPUS[@]}";
VCPUCount=$(( ${VCPUCount} - 1 ));
if [[ $2 = 0 ]]; then
Index=0;
else
Index=$(( $2 - 1 ));
fi;
for VCPU in ${VCPUs[@]}; do$VCPU assigned to CORE: $ {NumaCPUs[$Index]}";
NumaCPU="${NumaCPUs[$CPUIndex]}";
echo "VCPU PID:
taskset -pc "${NumaCPUs[$Index]}" "${VCPU}" 2>&1 > /dev/null;
Index=$(( $Index + 1 ));
done`
Executed like:
./PinVM.sh
Sample output:
`root@ProxMox01:~# ./PinVM.sh 103 0
VCPU PIDs: 35681 35682 35683 35684 35685 35686 35687 35688 35689 35690 35691 35692
NUMA node0 CPU(s): 0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30
NUMA node1 CPU(s): 1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31
Cores per Numa Boundary: 16
Number of VCPUs: 12
Defined Core offset: 0
VCPU PID: 35681 assigned to CORE: 0
VCPU PID: 35682 assigned to CORE: 2
VCPU PID: 35683 assigned to CORE: 4
VCPU PID: 35684 assigned to CORE: 6
VCPU PID: 35685 assigned to CORE: 8
VCPU PID: 35686 assigned to CORE: 10
VCPU PID: 35687 assigned to CORE: 12
VCPU PID: 35688 assigned to CORE: 14
VCPU PID: 35689 assigned to CORE: 16
VCPU PID: 35690 assigned to CORE: 18
VCPU PID: 35691 assigned to CORE: 20
VCPU PID: 35692 assigned to CORE: 22`
And if you try to set too large an offset you get an error:
`root@ProxMox01:~# ./PinVM.sh 103 7
VCPU PIDs: 35681 35682 35683 35684 35685 35686 35687 35688 35689 35690 35691 35692
NUMA node0 CPU(s): 0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30
NUMA node1 CPU(s): 1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31
Cores per Numa Boundary: 16
Number of VCPUs: 12
Defined Core offset: 7
Offset too great for number of CPU cores. Exiting`