首发于aii in one

切换模式

写文章

登录/注册

all in one服务器折腾一，消费级N卡解锁GPU虚拟化功能

日明月

来自专栏 · aii in one

70 人赞同了该文章

all in one玩家有没有遇到一个问题：在虚拟机平台上安装了操作系统，他们有的需要显卡来加速图形化界面才能获得流畅的体验，有的需要显卡来提供各种计算加速支持，比如常见编码解码，通用计算等等。虚拟化平台所提供的虚拟显卡并不能很好的完成这些任务，为满足需求只能将显卡直通给虚拟机。但是显卡有限不可能每个虚拟机都能分配到物理显卡，就算显卡充足主板所提供的PCI-E接口也不足以安装那么多张的显卡。

最好的解决办法就是显卡虚拟化 ，将一张显卡拆分成多张虚拟显卡直通给虚拟机，让虚拟机可以共享物理显卡上的资源。目前显卡虚拟化只要有4个选择，nVidia GRID方案，AMD SR-IOV方案 ，Intel gvt-g，微软 GPU-PV 。

NVidia和AMD的需要专门的显卡才能开启显卡虚拟化，INTEL 在6代酷睿到9代都能使用，微软 GPU-PV仅限于较新的window10版本，WDDM 2.5以上，虚拟机系统只能是较新本的Windows10或以上。

github上有一个名为“vgpu-unlock ”的项目，这是一个用于解锁消费级显卡虚拟化功能的linux补丁，到今天已经它已经支持了大部分家用显卡。nvidia的专业卡和消费卡向来都是使用同一种核心的，通过VBIOS和驱动来区分。vgpu-unlock的作用就是通过欺骗驱动使驱动认为消费卡是专业卡，从而开启显卡虚拟化功能。

目前vgpu-unlock项目只支持linux平台，因此这次教程选择的虚拟化平台是大家熟悉的proxmox ve 。

这是我的all in one配置

CPU：I5-4590
主板：华擎Z87极限玩家4
内存：4X4GB DDR3
显卡：GTX1050
虚拟化平台：proxmox ve 7.02

首先安装好proxmox ve 7.02。由于proxmox ve7.02 使用 了5.13 内核，无法使用 vgpu-unlock补丁解锁。所有我们要手动降级到5.11内核

1，降级内核

增加一个源

echo 'deb http://download.proxmox.com/debian/pve bullseye pve-no-subscription' | tee -a /etc/apt/sources.list

下载一个内核，我选择的是5.11.22-7

apt install pve-headers-5.11.22-7-pve

更改内核启动顺序，启动我们指定的内核

nano /etc/default/grub

对应项目进行如下修改，我这里使用nano编辑器。

GRUB_DEFAULT="Advanced options for Proxmox VE GNU/Linux>Proxmox VE GNU/Linux, with
Linux 5.11.22-7-pve

更新grub并重启

update-grub
reboot

重启后检查内核版本

uname -r

输出下列信息就表示内核更换成功

5.11.22-7-pve

2,安装相关依赖和下载相关插件

安装相关依赖

apt update && apt upgrade -y

apt install -y git build-essential pve-headers-`uname -r` dkms jq unzip python3 python3-pip

pip3 install frida

下载vgpu_unlock并赋予权限

git clone https://github.com/DualCoder/vgpu_unlockchmod -R +x vgpu_unlock

chmod -R +x vgpu_unlock

下载5.1内核专用的vgpu-unlock补丁并赋予权限

git clone https://github.com/rupansh/vgpu_unlock_5.12

chmod -R +x vgpu_unlock_5.12

下载vgpu_unlock-rs

git clonehttps://github.com/mbilker/vgpu_unlock-rs.git

ps：所有插件都下载到/root目录下

3.开启IOMMU

nano /etc/default/grub

对于Intel处理器这一行更改为

GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt"

对于使用amd处理器这一行更改为

GRUB_CMDLINE_LINUX_DEFAULT="quiet amd_iommu=on iommu=pt"

保存并更新grub

update-grub

在引导中加载vfio模块

nano /etc/modules

插入下面这四行代码并保存退出

vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd

输入下面4条命令

echo "options vfio_iommu_type1 allow_unsafe_interrupts=1" > /etc/modprobe.d/iommu_unsafe_interrupts.conf

echo "options kvm ignore_msrs=1" > /etc/modprobe.d/kvm.conf

echo "blacklist nouveau" >> /etc/modprobe.d/blacklist.conf

update-initramfs -u

重启

reboot

重启完成后验证iommu是否开启

dmesg | grep -e DMAR -e IOMMU

如果输出下列内容代表输出成功

[ 0.008580] ACPI: DMAR 0x00000000BC150C80 0000B8 (v01 INTEL HSW 00000001 INTL 00000001)
[ 0.008597] ACPI: Reserving DMAR table memory at [mem 0xbc150c80-0xbc150d37]
[ 0.036762] DMAR: IOMMU enabled

4.安装和修改nvidia驱动，激活消费级显卡vgpu功能

下载nvidia宿主机驱动

wgethttp://www1.deskpool.com:9000/software/NVIDIA-Linux-x86_64-460.32.04-vgpu-kvm.run

赋予权限并解压驱动

chmod +x NVIDIA-Linux-x86_64-460.32.04-vgpu-kvm.run

./NVIDIA-Linux-x86_64-460.32.04-vgpu-kvm.run -x

下载应用补丁

wget https://raw.githubusercontent.com/rupansh/vgpu_unlock_5.12/master/twelve.patch

wget https://raw.githubusercontent.com/wvthoog/nvidia_vgpu_proxmox_7/main/nv-caps.patch

wget https://raw.githubusercontent.com/wvthoog/nvidia_vgpu_proxmox_7/main/nv-frontend.patch

wget https://raw.githubusercontent.com/wvthoog/nvidia_vgpu_proxmox_7/main/nvidia-vgpu-vfio.patch

cd NVIDIA-Linux-x86_64-460.32.04-vgpu-kvm

patch -p0 < ../twelve.patch

patch -p0 < ../nv-caps.patch

patch -p0 < ../nv-frontend.patch

patch -p0 < ../nvidia-vgpu-vfio.patch

安装驱动

chmod +x nvidia-installer

./nvidia-installer --dkms

修改驱动文件

nano /lib/systemd/system/nvidia-vgpud.service

更改为下列内容，这里vgpu_unlock_5.12的下载路径为/root，如果是其他路径的根据实际修改下列内容

ExecStart=/root/vgpu_unlock_5.12/vgpu_unlock /usr/bin/nvidia-vgpud

修改下一个文件

nano /lib/systemd/system/nvidia-vgpu-mgr.service

更改为下列内容

ExecStart=/root/vgpu_unlock_5.12/vgpu_unlock /usr/bin/nvidia-vgpu-mgr

重新加载服务守护进程

systemctl daemon-reload

修改文件

nano /usr/src/nvidia-460.32.04/nvidia/os-interface.c

在#include “nv-time.h”下插入下面这一行

#include "/root/vgpu_unlock_5.12/vgpu_unlock_hooks.c"

修改文件

nano /usr/src/nvidia-460.32.04/nvidia/nvidia.Kbuild

在文件底部添加下面这一行

ldflags-y += -T /root/vgpu_unlock_5.12/kern.ld

要想解锁成功后重启能在日志看的“vGPU unlock patch applied.”的提示

nano /root/vgpu_unlock_5.12/vgpu_unlock_hooks.c

找到下面的内容，将“#if 0”改为“#if 1”保存退出

/* Debug logs can be enabled here. To enable it, change 0 to 1. */
#if 1
#define LOG(...) printk(__VA_ARGS__)

移除原来的 Nvidia dkms 模块

dkms remove -m nvidia -v 460.32.04 --all

重建模块

dkms install -m nvidia -v 460.32.04

5.配置RS版的解锁补丁，RS版本的解锁补丁比较稳定

cd ~
curl --proto '=https' --tlsv1.2 -sSf https://rsproxy.cn/rustup-init.sh | sh
source $HOME/.cargo/env
cd vgpu_unlock-rs
cargo build --release

新建两个配置文件

mkdir -p /etc/systemd/system/nvidia-vgpud.service.d
mkdir -p /etc/systemd/system/nvidia-vgpu-mgr.service.d

编辑nvidia-vgpud.service.d 文件

nano /etc/systemd/system/nvidia-vgpud.service.d/vgpu_unlock.conf

对nvidia-vgpud.service.d 文件写入下面的内容并保存

[Service]
Environment=LD_PRELOAD=/root/vgpu_unlock-rs/target/release/libvgpu_unlock_rs.so

编辑nvidia-vgpu-mgr.service.d文件

nano /etc/systemd/system/nvidia-vgpu-mgr.service.d/vgpu_unlock.conf

对nvidia-vgpu-mgr.service.d文件写入下面的内容并保存

[Service]
Environment=LD_PRELOAD=/root/vgpu_unlock-rs/target/release/libvgpu_unlock_rs.so

完成后重启

reboot

重启完成后输入命令出现下图的输出则证明VGPU开启成功

mdevctl types

6.VGPU类型

nvidia的显卡虚拟化是通过显存来划分的，最小的划分单位是1GB显存。因此只有大于等于2G显存的显卡才能使用VGPU虚拟化。比如我的GTX1050是2GB显存就最多划分2个VGPU，每个VGPU分到1GB的显存。GTX1060 6G显存就可以划分为6个1G显存的VGPU，或是3个2G显存的VGPU，或是2个3G显存的VGPU 。

root@pveliocl:~# mdevctl types
0000:01:00.0
nvidia-156
Available instances: 0
Device API: vfio-pci
Name: GRID P40-2B
Description: num_heads=4, frl_config=45, framebuffer=2048M, max_resolution=5120x2880, max_instance=12
nvidia-215
Available instances: 0
Device API: vfio-pci
Name: GRID P40-2B4
Description: num_heads=4, frl_config=45, framebuffer=2048M, max_resolution=5120x2880, max_instance=12
nvidia-241
Available instances: 0
Device API: vfio-pci
Name: GRID P40-1B4
Description: num_heads=4, frl_config=45, framebuffer=1024M, max_resolution=5120x2880, max_instance=24
nvidia-283
Available instances: 0
Device API: vfio-pci
Name: GRID P40-4C
Description: num_heads=1, frl_config=60, framebuffer=4096M, max_resolution=4096x2160, max_instance=6

上面是执行“mdevctl types”命令后的输出

“0000:01:00.0”这是显卡的物理地址，每个人的都可能不一样，我的是“0000:01:00.0”

“nvidia-156”这是VGPU的类型名

“Name: GRID P40-2B”这是名为“nvidia-156”VGPU类型的在虚拟机中显示的显卡名字

“Name: GRID P40-2B”中2B中的2代表显存容量，此类型的VGPU显存为2G

“Name: GRID P40-2B”中最后一个字母是VGPU的显卡功能标识

B：代表=Virtual Desktops(vPC)，针对普通虚拟电脑，没有 cuda，没有专业卡支持
Q：代表Virtual Workstations(vWS)，最完善的版本，什么功能都有
C:代表AI/Machine Learning/Training(vCS or vWS)
A:代表Virtual Applications(vApps)
C和A普通用户用不到，就不去深究了

7.VGPU创建

首先我们需要生成几组UUID，下面为大家准备了8组UUID。

f090c00f-338b-47b4-a419-700101cd70c5
cee34c0a-6144-4f3e-8bdb-51538a98ba80
692c4c12-0def-4aa8-87b4-732fd5ef43ea
bc4b8513-43f0-49d2-81b1-a4aa9fe35826
e46b8864-0271-41ce-86b4-d5df5579d332
6fb3f4a0-a17d-43e5-b4fd-1a52acc3e382
24642876-0a6b-4c50-a199-8bdeef5da6f1
e2736865-12c3-446d-9ec4-42d799a7dbed

选择合适自己的VGPU类型，我要创建两个全功的VGPU,因为我的卡是GTX1050只有2G显存，所以我的VGPU名字为“GRID P40-1Q ”，对应的类型名为“nvidia-46”

注意：一张显卡同时只能使用一种GPU类型，以gtx 1060 6g为例子。要么使用1+1+1+1+1+1的6vgpu类型，要么使用2+2+2的3vgpu类型，要么使用3+3的2vgpu类型。1+1+4的类型是无法使用的

输入命令开始创建VGPU，命令格式“mdevctl start -u [UUID] -p 设备 ID --type [UUID]”

例子如下，物理地址要根据自己的实际情况修改，不可以照抄，GPU类型根据自己的需求选择

mdevctl start -u f090c00f-338b-47b4-a419-700101cd70c5 -p 0000:01:00.0 --type
nvidia-46
mdevctl start -u cee34c0a-6144-4f3e-8bdb-51538a98ba80 -p 0000:01:00.0 --type nvidia-46

这样就创建了一个VGPU，之后可以根据自己的显存大小和VGPU类型，使用新的UUID号在创建一个VGPU。

输入下面命令，命令格式“mdevctl define --auto --uuid [UUID]”，例如

//这个UUID要和上面创建的VGP UUUDI相同，有几个VGPU就执行几条命令
mdevctl define --auto --uuid f090c00f-338b-47b4-a419-700101cd70c5
mdevctl define --auto --uuid cee34c0a-6144-4f3e-8bdb-51538a98ba80

这样VGPU就创建好了

8.VGPU直通

需要记住VMID等会直通VGPU的时候需要用到，为了实现直通主板芯片组需要选择Q35,bios选择OVMF(uefI)，其他就没有什么特殊设置了。

编辑虚拟机配置文件，根据自己的VMID修改，比如我的VMID是100 命令如下

nano /etc/pve/qemu-server/100.conf

在最前面插入一行 ，注意“f090c00f-338b-47b4-a419-700101cd70c5”是UUID，最后的“100”是VMID。根据自己的实际情况修改，然后保存退出。

args: -device 'vfio-pci,sysfsdev=/sys/bus/mdev/devices/f090c00f-338b-47b4-a419-700101cd70c5' -uuid 00000000-0000-0000-0000-000000000100

现在VGPU已经直通给了虚拟机
接下来就是安装操作系统，开启远程访问，在之后才安装客户机的显卡驱动。注意客户机只能安装GRID驱动，要先开启远程访问之后在安装驱动，因为安装显卡驱动以后proxmox ve控制台就不好操作了。

当然RDP远程访问没有办法利用好GPU，大家可以使用Parsec串流工具进行远程，这样能很好的利用VGPU的性能。

9.性能演示

VM1

系统：windows 10
VCPU：4核心4线程
内存：4gb
VGPU：gtx1050 1g （模拟为P40-1Q）

vm2

系统：Ubuntu20.04
VCPU：4核心4线程
内存：4gb
VGPU：gtx1050 1g（模拟为P40-1Q）

首先是GPUZ的信息，可以看到显卡被插件模拟成了特斯拉P40显卡，显存为1G，CUDA单元为640.支持CUDA，DX OPENCL

接下来是喜闻乐见的娱乐大师跑分，场景21帧左右，显卡总分13w。物理gtx1050的鲁大师跑分在14.8w，性能有所损失，可能是显存容量变小的原因。

接下来是视频编解码的测试，估计这个也是大家最关心的内容。直接说结论吧！编码解码器都没有问题可以正常工作，毕竟Parsec是编码成HEVC后串流给客户机的。通过任务管理器可以看到Parsec已经调用了显卡的编码器，显卡的编码器也有负载。通过DXVA也可以看到VGPU支持的编解码器和GTX1050一样。但是potplayer能识别的显卡，但是播放HEVC 10bit 4k视频特别卡，而物理gtx1050就能流畅播放。jellyfin可以识别到显卡解码器，但是无法硬解，而物理gtx1050可以流畅解码。目前正在寻找解决的办法。

第二个系统ubuntu也直通了vgpu，并可以识别到vgpu。不过ubuntu安装nvidia驱动特别麻烦，搞了一个多星期。首先要关闭UEFI安全启动。然后显卡驱动安装到

installing dkms kernel module:
Building module(This may take a moment): 5%

这个时候其实是要你设置内核的密码(8位以上数字+字母)，但是NVIDIA驱动安装程序没有给显示出来，你就需要自己盲打，而且密码要输入两次，即输入一次密码然后回车，再输入一次密码，然后回车，如果无效就多等一会儿然后输入密码+回车。

另外虚拟机使用的GRID驱动是需要授权的，否则只能用20分钟。

发布于 2022-04-07 12:53

虚拟化

虚拟机

​ 赞同 70​ ​ 24 条评论

​ 分享

​ 喜欢​ 收藏​ 申请转载

​

写下你的评论...

24 条评论

默认

最新

董李茂

“其他就没有什么特殊设置了”

2022-05-14

​ 回复​ 2

日明月

作者

没有

2022-05-16

​ 回复​ 喜欢

Kinging Wang

你好,我只能同时开启一台虚拟机,第二台开启会报错,请问应该怎么解决?kvm: -device vfio-pci,sysfsdev=/sys/bus/mdev/devices/cee34c0a-6144-4f3e-8bdb-51538a98ba80: vfio cee34c0a-6144-4f3e-8bdb-51538a98ba80: error getting device from group 310: Input/output error
Verify all devices in group 310 are bound to vfio-<bus> or pci-stub and not already in use
TASK ERROR: start failed: QEMU exited with code 1

2023-09-20

​ 回复​ 喜欢

小孟

创建好了，如何在docker容器中使用啊

2023-05-30

​ 回复​ 喜欢

知乎用户9VQOxN

这个需要向英伟达买license吗？

2023-05-07

​ 回复​ 喜欢

Mins

楼主，ubuntu怎么才能装上驱动啊，安全模式也关掉了，有时候装上了，nvidia-smi也没用。

2022-11-09

​ 回复​ 喜欢

心如止水

请问楼主，jellyfin使用vgpu硬解是否找到了解决方案？我的1660s开启vgpu直通给truenas，jellyfin容器里面使用nvidia-smi检查，所有信息显示正常，但是也无法硬解。

2022-11-02

​ 回复​ 喜欢

紫夜

心如止水

我P4 给win10分配的4q的vgpu Jellyfin 都限制在60fps……从1g到4g我都试了，授权也是docker直接给的90天，你的4k转1080多少fps？我这还不如核显，直通整卡就没问题

2023-02-06

​ 回复​ 喜欢

eq2q

日明月

1660s一般是6g显存，层主应该会分配大于等于2G显存吧，

2023-01-06

​ 回复​ 喜欢

查看全部 9 条回复​

业余厨

有办法在开启vgpu的情况下实现显示器输出吗

2022-07-29

​ 回复​ 喜欢

eq2q

有办法，用usb转hdmi的

2023-01-05

​ 回复​ 喜欢

可分离变量

您好，请问虚机中的vgpu使用的驱动分别是？还有就是win10中VGPU使用不是需要授权吗？您如何解决的

2022-07-26

​ 回复​ 喜欢

日明月

作者

GRID驱动，有一个脚本可以延续使用时间到24小时_vGPU_LicenseBypass。linux使用下面命令延续至24小时。
$echo'optionsnvidia
NVreg_RegistryDwords="UnlicensedUnrestrictedStateTimeout=0x5A0;Unlicensed
Restricted1StateTimeout=0x5A0"'|sudotee/etc/modprobe.d/nvidia.conf
$sudoupdate-initramfs-u
$sudoreboot
1
2
3

2022-07-26

​ 回复​ 2

Mins

日明月

如果跑着程序，使用这个脚本，到重新加载驱动的时候会报错。

2022-11-18

​ 回复​ 喜欢

展开其他 3 条回复​

写下你的评论...

关于作者

日明月

回答
120

文章
4

关注者
95

​ 关注​ 发私信

推荐阅读

QEMU/KVM 虚拟机显卡透传 (vfio-pci)

穷人小水滴发表于计算机入门

centos 7 笔记本 Intel nvidia 双显卡 安装nvidia驱动并成功安装cuda

奥古斯宏

将双系统塞入A4主机：OSX-KVM 显卡直通教程

Luv Letter

PVE核显虚拟化，一起All In One！！！

前言最近也是玩上All In Boom了哈哈，VMware已经不太能满足我目前的使用场景，特别是VM17一言难尽的显卡，所以打算逐步从VM Workstation转到PVE。期间也是遇到了不少问题。网上大部分都是直…

有梦想的年轮哦

想来知乎工作？请发送邮件到 [email-masked]

登录即可查看 超5亿 专业优质内容
超 5 千万创作者的优质提问、专业回答、深度文章和精彩视频尽在知乎。
立即登录/注册

下载

投屏

高速下载