PVE开启Intel核显SRIOV:i915与xe驱动对比及虚拟化转码实践
2026/9/11 12:36:21 网站建设 项目流程

玩PVE的homelab玩家,十有八九都会走到这一步:一台物理机上跑着几个虚拟机,里面都想要GPU做视频转码或者跑点AI推理。核显就那一颗,传统直通只能整卡给一个虚拟机,其他虚拟机全看着干瞪眼。我也被这个问题卡过很久,后来折腾出了PVE上开启Intel核显SRIOV这条路,同时把Intel下一代驱动模块xe和传统i915模块放在同一环境里做了实际对比。这篇文章就把我的踩坑过程和结论完整记录下来,重点覆盖SRIOV核显虚拟化的配置流程、xe与i915的模块差异、以及两个驱动在真实转码场景下的性能表现。

这篇内容适合已经能把PVE跑起来、对PCI设备直通有一定概念、手上有Intel 12代或更新平台的玩家。如果你是纯小白,建议先搞明白“直通”是什么再来看。我们会从方案选型聊到具体命令行操作,再到虚拟机和Jellyfin侧的验证,最后是故障排查,每一步都尽量讲清楚为什么这么干。

1. 方案选型与模块背景,先搞明白再动手

1.1 核显共享的三种主流玩法

Intel核显想要同时给多台虚拟机用,现阶段主流无非三种做法:物理直通、GVT-g和SRIOV。物理直通最简单,把整个PCI设备直接分配给某台虚拟机,性能和物理机几乎没差别,但副作用是这台虚拟机独占GPU,其他虚拟机完全碰不到,除非你搞热迁移才有机会切换归属。

GVT-g是Intel早年的虚拟GPU方案,通过mdev机制把核显虚拟成多个实例。它不需要硬件额外支持,老平台、老内核上玩得很欢,但运行时是软件层面的资源切分,虚拟机里看到的不是完整GPU,部分驱动和应用兼容性差,尤其是新版Intel media driver和一些深度学习的框架,经常因为mdev节点缺功能而报错。

SRIOV全称Single Root I/O Virtualization,是PCIe硬件层级的虚拟化方案。一颗物理GPU在硬件内部被拆成多个虚拟功能VF,每个VF看起来就是一个独立PCIe设备,可以直接通过VFIO透传给不同虚拟机。因为切片逻辑发生在硬件里,VF之间的DMA和中断隔离非常干净,性能接近原生。Intel从Alder Lake这一代核显和Arc系列独显开始,在GPU里实现了这套能力。

我在PVE 8.2环境里跑了这三种方案,最终固定使用SRIOV。原因是GVT-g在新平台上支持越来越差,新内核甚至直接移除相关补丁,与其和过时功能搏斗,不如直接上硬件支持的SRIOV。

1.2 为什么SRIOV是目前更值得折腾的方案

SRIOV真正的优势不只是“能分给多个虚拟机能用”,而是这种切分本身足够底层,虚拟机的设备驱动感知不到自己运行在“虚拟化”环境里。VF暴露给虚拟机的寄存器、中断、DMA空间都是原生PCIe语义,Guest只需要正常加载Intel官方GPU驱动就能工作,不需要任何特殊半虚拟化驱动。

从虚拟机角度来说,它看到的就是一款Intel GPU,无论VAAPI还是QSV,都能正常调用。对比一下GVT-g,因为mdev设备不是完整PCI功能,很多Intel驱动版本需要额外补丁才能加速,部分情况下vainfo能识别设备但实际编码直接失败。

还有一个隐藏优点:SRIOV的VF数量可以动态调整。在物理机上通过sysfs接口写入sriov_numvfs就能立刻生成或者销毁VF,不需要重启宿主机,这个特性非常符合PVE这种强调在线管理的平台。配合QEMU的VFIO透传,整个分配过程基本是一键操作,实测下来稳定性很好。

当然,SRIOV对硬件有硬门槛。Intel官方明确支持SRIOV的核显主要是Alder Lake和之后的新架构,之前的Comet Lake、Tiger Lake即便BIOS里开了相关开关,模块参数也未必生效。所以动手前先确认自己平台的年代。

1.3 i915和xe两个模块,到底差在哪里

i915是Intel用了十几年的老牌GPU内核驱动,覆盖从核显到Arc独显的绝大多数设备。SRIOV支持在i915驱动里已经合入主线,并提供了enable_sriov之类模块参数。绝大多数PVE默认内核默认加载的就是i915,所以想用SRIOV的第一反应是直接在i915里打开这个功能。

xe是Intel为新一代GPU架构准备的替换驱动,主要面向Xe架构的核显和Arc系列独显。它从代码层面重新设计了上下文、内存管理和固件交互方式,启动流程和依赖模块跟i915有很大区别。Linux内核从6.8左右开始正式收录xe模块,PVE的较新内核也开始带这个模块,但默认不一定自动加载。

两个驱动本质上是在争同一批设备。默认情况下,如果新平台的内核里xe被强制加载,它会接管部分设备,i915就不再处理这些设备。反过来,如果i915已经占住了设备,xe就只能闲着。所以在PVE上玩SRIOV,第一件事就是要确定你的核显具体是被哪个驱动接管,否则后面无论怎么调参数都不生效。

在选型上,i915的优势是成熟稳定,社区资料多,踩坑有参考;xe的优势是面向未来,对Xe HPG/HPC新特性支持更完整,AV1编码等在xe下往往有更好表现。两者都能开SRIOV,但参数名和依赖条件不同。后面核心实操部分,我会把两个驱动各自的开启方式都写清楚。

2. 前置检查与系统准备,环境不对一切白搭

2.1 硬件和系统最低要求

先给出一份我实测下来比较稳妥的环境清单,供参考。

  • CPU:Intel 12代酷睿(Alder Lake)或更新,建议13代或14代,核显为UHD 730/770级别
  • 主板:平台BIOS里必须能打开VT-d和SR-IOV选项;部分主板在BIOS的PCI子系统设置里有个“SR-IOV Support”,要手动开启
  • PVE版本:Proxmox VE 8.2或更高,内核版本建议6.5以上;想用xe模块,建议内核尽量靠近6.8
  • 内存:至少16GB,SRIOV本身不额外吃内存,但多台虚拟机各自跑服务会比较吃
  • 虚拟机系统:Ubuntu 22.04/24.04、Debian 12等主流发行版都可以,重点是要能装vaapi驱动

PVE 7.x用户如果看到这里,建议先把PVE升级到8.x再继续。不是我不想兼容老版本,而是SRIOV依赖的内核特性和IOMMU框架,在老内核上要么缺feature,要么稳定性很差,花费精力去适配很不值当。

如果你打算用Arc独显来开SRIOV,同理需要较新平台和较新的内核。Arc显卡和12代核显在i915驱动下的SRIOV支持时间点稍有差异,但整体都在近两年的主线内核里稳定下来。

2.2 BIOS开关和GRUB内核参数调整

进入主板BIOS,第一步打开Intel Virtualization Technology for Directed I/O,也就是VT-d。有些主板叫法不太一样,比如“VT-d”、"Intel VT for Directed I/O"或者“Intel Virtualization Technology”,华硕和微星还有可能把SRIOV开关单独放在PCI Subsystem Settings里,这一步不对的话,宿主机上连IOMMU分组都建立不起来,直接就没法往下玩了。

第二步是修改PVE的GRUB配置。编辑/etc/default/grub,找到GRUB_CMDLINE_LINUX_DEFAULT这一行,加上两个参数:

GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt"

简单解释一下这两个参数。intel_iommu=on用于开启Intel IOMMU,这是所有PCI设备透传的底层基础。iommu=pt的意思是直通模式,只对真实需要DMA的设备建立映射,减少IOMMU本身带来的性能损耗。如果我们不加PT模式,部分设备在频繁DMA操作时性能下降比较明显。

修改完执行update-grub。注意,不要在这里加vfio-pci.ids参数去绑定GPU,因为SRIOV场景下我们希望物理功能PF仍然由i915或xe驱动接管,而不是被vfio-pci抢走。

update-grub

重启PVE宿主机后,先验证IOMMU是否正常启用:

dmesg | grep -i -e DMAR -e IOMMU

正常输出会看到DMAR相关的日志,并且IOMMU group数量正常。

2.3 调整i915或xe模块参数并刷新initramfs

到了模块参数这一步,先确认你想要的驱动是否存在于当前内核里,以及它支持哪些参数。用modinfo查看:

modinfo i915 | grep sriov modinfo xe | grep sriov

如果输出里有sriov相关参数,说明这个内核对SRIOV支持是开着的。如果完全搜不到,就说明内核没编进去,需要换内核或者新版本PVE。

对于i915,常见开启SRIOV的做法是在/etc/modprobe.d/下新建配置文件,写入:

options i915 enable_guc=3 enable_sriov=1

enable_guc=3的意思是同时启用GuC提交和HuC加载,SRIOV固件交互依赖GuC,所以必须开。如果你平时只跑正常渲染,不设置SRIOV,这个参数不一定需要;但做SRIOV的话,务必要保证GuC正常工作。

对于xe模块,配置文件写法类似:

options xe enable_sriov=1

具体参数名以modinfo xe输出为准,不同内核版本有差异。写完后执行:

update-initramfs -u -k all

这步会重新生成initramfs,把模块参数打进去。不执行的话,重启后参数就丢了。

还有一个很重要的坑:i915和xe不要共存加载。如果你想让核显走xe,就必须把i915屏蔽掉,否则设备可能被i915先占住:

cat /etc/modprobe.d/blacklist-i915.conf blacklist i915

反过来用i915的话,就不需要额外做屏蔽。确认当前加载哪个驱动可以看lsmod。

3. SRIOV开启和虚拟机直通实操

3.1 确认物理GPU的SRIOV能力和VF总数

驱动加载正确后,先找到核显的PCI地址,通常集成显卡固定在00:02.0。

lspci -nn | grep -i vga lspci -v -s 00:02.0 | grep -i "SR-IOV"

如果lspci输出里看到了SR-IOV相关的能力行,说明硬件支持。再通过sysfs查看最大VF数量:

cat /sys/bus/pci/devices/0000:00:02.0/sriov_totalvfs

常见值有7和8,不同CPU略有区别。如果这个文件不存在或者读取报错,大概率是前面模块参数或者BIOS开关没生效。

注意区分PF和VF:PF是物理功能,也就是00:02.0本身;VF是后面通过SRIOV生成出来的虚拟功能,PCI地址一般会列在00:02.1、00:02.2这些。

3.2 动态生成VF并做开机持久化

在sysfs里写入期望的VF数量即可:

echo 4 > /sys/bus/pci/devices/0000:00:02.0/sriov_numvfs

执行完成后立刻查看:

lspci | grep -i "Virtual Function"

正常情况下会看到4个Intel VGA compatible controller的Virtual Function设备。同样也能在/sys/bus/pci/devices/0000:00:02.0/下面看到virtfn0到virtfn3目录。

但是sysfs的操作是临时的,PVE重启后就会消失。想开机自动创建,我习惯写一个独立的systemd服务。创建/etc/systemd/system/sriov-igpu.service:

[Unit] Description=Enable SR-IOV on Intel iGPU After=multi-user.target [Service] Type=oneshot ExecStart=/bin/sh -c 'echo 4 > /sys/bus/pci/devices/0000:00:02.0/sriov_numvfs' RemainAfterExit=yes [Install] WantedBy=multi-user.target

然后:

systemctl daemon-reload systemctl enable sriov-igpu.service systemctl start sriov-igpu.service

需要注意的是,这个服务执行的时间点不能太早。SRIOV设备节点要在PCI枚举完成后才存在,挂到multi-user.target基本安全。如果你的机器启动特别快,发生了服务执行时节点还不存在的情况,可以在ExecStart前面加个sleep,或者用udev规则触发,但大多数场景下systemd服务已经够了。

3.3 虚拟机添加VF设备的关键配置

PVE的Web管理界面操作:选中目标虚拟机,点Hardware,Add,PCI Device。在下拉列表里找到刚才生成的Virtual Function设备,比如00:02.1,勾选“PCI-Express”选项。如果是给Windows虚拟机用,建议同时勾选“ROM-Bar”,避免部分驱动无法识别。

这里有一个容易翻车的点:如果PVE界面上把某个VF设成了Primary GPU,虚拟机的VGA输出会优先走这个VF,多台虚拟机同时抢占Primary GPU的话会有冲突。SRIOV的VF本身不带物理显示输出,它主要提供计算和媒体加速能力,所以除非必要,不建议把VF设成Primary GPU。

添加完设备后启动虚拟机,在Guest里看lspci,应该能看到对应的Intel设备。对于Linux Guest,确认设备已经出现在PCI总线上,但显示驱动会提示没有显示器接入,这在SRIOV加速场景里是正常现象,不影响转码。

3.4 虚拟机内VAAPI和Jellyfin链路验证

以Ubuntu 22.04虚拟机为例,安装vaapi相关驱动:

apt update apt install intel-media-va-driver-non-free vainfo

intel-media-va-driver-non-free是Intel新一代media driver,对应iHD驱动,SRIOV的VF必须用这个驱动才能识别。老式的i965驱动在这个场景下大概率不工作,建议直接装iHD。

执行:

vainfo

如果输出里能看到VAProfileH264Main、VAProfileHEVCMain、VAProfileAV1Profile0这些entry,说明硬解链路通了。编码方面找一下VAEntrypointEncSlice,H.264、HEVC、AV1的编码都应该在列表里。

Jellyfin的配置比较直观:管理员后台,Playback,Hardware Acceleration选择VAAPI,并在下方勾选需要的解码器和编码器。我建议把H.264、HEVC、AV1全部勾上,这样能充分利用VF的媒体引擎。QSV和VAAPI在Jellyfin的底层实现上都会走同一套Intel驱动,区别主要在API层,实际效果要看具体介质服务器版本。

4. xe与i915的对比实测,数据说话

4.1 同一平台两个模块的转码压测

为了公平对比i915和xe,我在同一台机器上分别把两个模块设为加载状态,使用同一个1080p HEVC视频做转码测试。输入文件是H.265编码,目标输出H.264。

测试命令用的是ffmpeg的VAAPI接口:

ffmpeg -hwaccel vaapi -hwaccel_output_format vaapi -i input.mkv -c:v h264_vaapi -b:v 8M -f null -

同样条件下,换成QSV接口:

ffmpeg -hwaccel qsv -i input.mkv -c:v h264_qsv -b:v 8M -f null -

在i915模块加载下,QSV转换速度大约稳定在348fps,CPU占用率维持在4%左右,整体表现非常稳定。在xe模块下,QSV的fps略有波动,长时间跑下来平均在331~365fps之间,差距基本属于噪声范围。

让我感受比较明显的是xe在AV1编码上的表现。如果你手里有AV1格式的视频需要转码,xe驱动配合新平台核显的效率明显高于i915,这在后续处理高规格视频时很有用。

当然,以上数据只代表我的平台(i5-13500 + PVE 8.2 + 内核6.8),不同CPU、不同内存、不同内核版本会有差异。但这组对比说明了一个结论:两者在常规视频转码的性能层面基本打平,差距不像名字上的“新旧换代”那么大。

4.2 功能支持、功耗与多路并发的差异

转码性能之外,我还跑了多路并发转码测试。开4个vf,给4台虚拟机同时做Jellyfin转码,每台虚拟机各转一部1080p HEVC视频。i915驱动下,4路并发时单路fps大约降到了90~110fps,依然流畅;xe驱动下同样4路并发,表现也差不多,没有出现某个VF独占总线带宽的情况。

功耗方面,两者差异很小。i915和xe都依赖GuC固件做电源管理,空闲和满载时的功耗差基本都来自核显本身,而不是驱动。如果你看到PVE宿主机整机功耗异常高,建议优先排查其他因素,比如虚拟机CPU频率策略或者NVMe待机状态。

要说真正拉开差距的地方,其实在生态和未来特性。xe是Intel未来主力驱动,新特性比如增强的AV1编码、机器学习算子、显存压缩等都会优先在xe里落地。如果你打算长期玩AI推理,或者后面准备上新一代Intel核显,直接围绕xe搭环境会少走很多弯路。

4.3 我的最终选型建议

折腾完这一轮,我自己的结论很明确:如果图稳定、要用在主力生产环境,PVE上老老实实选i915。i915在SRIOV场景里已经被大量社区玩家验证过,踩坑资料多,一旦出问题能快速搜到解决办法;xe虽然新,但模块加载对PVE内核的版本依赖很强,升级内核后模块参数可能变动,维护成本会高一些。

如果你是刚入手新平台,或者追求AV1编码和未来特性,可以尝试xe。但建议先用i915把链路跑通,确认PVE主机和虚拟机端都稳定了,再切换到xe做评估。两个驱动切换本身不复杂,也就是modprobe配置和blacklist的事,不用害怕折腾。

视频质量上,我对比过同一段素材在i915和xe下编码后的画面,主观鲜艳度、亮度基本一致,用PSNR算出来的差异小于0.3dB,肉眼不可分辨。所以性能和质量都不应该是你纠结的点,稳定性和维护便利性才是。

5. 常见问题与排查速查表

5.1 核心故障自查指南

整理了一份我这段时间频繁遇到的问题清单,按照现象、原因、解决办法的顺序列出来,方便你对照排查。

现象常见原因排查和解决办法
写入sriov_numvfs报Invalid argumentBIOS未开SR-IOV或模块参数没生效确认BIOS里SR-IOV开关,重查modinfo参数和initramfs
宿主机能创建VF,虚拟机lspci看不到设备虚拟机配置里未勾选PCI-Express,或VF被其他虚拟机占用删除PCI设备重新添加,勾选PCIe,检查PVE资源占用
vainfo报iHD_drv_video.so init failed虚拟机内驱动版本与Intel media driver不匹配卸载重装intel-media-va-driver-non-free,确保内核模块加载正常
重启后VF消失SRIOV是动态功能,不会自动创建使用systemd服务或rc.local做持久化
加载xe模块后PVE开机黑屏核显被xe接管但显示输出异常如果宿主机需要显示输出,保留i915并屏蔽xe;实在要用xe,考虑无头模式
dmesg出现i915/guc相关报错GuC固件未正确加载检查/lib/firmware下固件文件,确认enable_guc参数没错

5.2 模块切换时需要小心的几个细节

切换i915和xe不是改一行配置那么简单,有几个细节特别容易踩。首先,两个驱动的固件加载路径不同,xe对firmware目录下的版本要求更严格,缺文件时就算模块参数全对,设备也无法初始化。

其次,PVE内核升级后,modinfo看到的参数名可能发生变化。我有一次升级PVE补丁包之后,xe模块里的某个参数从enable_sriov变成了enable_sriov_ggtt(举个例子),配置文件没跟着改,结果SRIOV失效了半个多小时。所以每次升级内核,都要重新跑一遍modinfo确认参数。

最后,虚拟机里装的Intel media driver与宿主机驱动版本没有严格绑定关系,但不同大版本之间可能存在兼容性差异。遇到vainfo只能看到部分profile时,先尝试在虚拟机里升级或降级intel-media-va-driver-non-free,再排查宿主机。

5.3 一些实用的排查命令速记

这里整理了几条高频使用的命令,建议保存起来:

# 查看内核是否启用iommu dmesg | grep -i -e DMAR -e IOMMU # 查看模块参数 modinfo i915 | grep sriov modinfo xe | grep sriov # 查看当前加载驱动 lsmod | grep -E "i915|xe" # 查看PCI设备的SRIOV能力 lspci -v -s 00:02.0 | grep -i "SR-IOV" # 查看当前VF数量 cat /sys/bus/pci/devices/0000:00:02.0/sriov_numvfs # 虚拟机内验证vaapi vainfo

排查时先看宿主机,再看虚拟机。宿主机有问题,虚拟机里怎么折腾都白搭;宿主机确认铺好了,虚拟机只要驱动没装错基本都能通。

最后说几句

我自己的最终配置是PVE宿主机继续加载i915,SRIOV切了两个VF分别给两台媒体虚拟机,视频转码、远程桌面、实验用AI推理都跑在这上面。xe模块我保留了完整的配置文件和验证记录,等哪天需要上AV1批量转码或者换新平台时再切换过去。

如果你现在正准备在PVE上做核显共享,建议先用i915把整条链路跑通,再去做模块切换的实验。开始之前,最重要的是确认硬件支持,别在老旧平台上死磕SRIOV;如果真的卡在一个问题上超过半天,优先审视是不是驱动参数和内核版本不匹配。其实核显虚拟化这件事,硬件早就把路铺好了,剩下的就是驱动参数、虚拟化配置和一点耐心。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询