麒麟系统帧率只有 7 FPS —— X11 未使用 NVIDIA 驱动
-
环境:银河麒麟国防版 / X11 会话 / NVIDIA RTX 3060 Ti (8G) / 驱动 595.91.07 / TESP Linux 打包版(Vulkan RHI)
-
现象:主界面(登录页)帧率仅 7.74 FPS(129 ms/帧),全系统性卡顿
-
结论:X Server 没有加载 NVIDIA 的 X 驱动,OpenGL 栈回退到 llvmpipe 软件光栅器。Vulkan 渲染虽然在独显上,但每帧画面要回拷到 CPU 软件显示栈才能上屏,成为瓶颈。
-
状态:已修复,主界面卡顿消失
一、现象与初始数据
stat unit 输出:
| 指标 | 值 |
|---|---|
| FPS | 7.74 |
| Frame | 129.03 ms |
| Game | 2.72 ms |
| Draw | 3.65 ms |
| RHIT | 3.31 ms |
| GPU Time | (空白) |
| DynRes | Unsupported |
| Draws / Prims | 38 / 836 |
关键矛盾:CPU 三条线程(Game / Draw / RHIT)加起来不到 10 ms,但整帧 129 ms。约 120 ms 不在任何一条被统计的线程里。
二、排查过程
1. 排除 GPU 侧(全部否定)
nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total,pstate,clocks.sm,clocks.max.sm,power.draw,power.limit,temperature.gpu,pcie.link.gen.current,pcie.link.width.current --format=csv -l 1
结果:22%, 1484MiB/8192MiB, P8, 210MHz/2100MHz, 15W/200W, 44℃, gen1, x8
sudo nvidia-smi -q -d PERFORMANCE | grep -A15 "Clocks Event Reasons"
结果:Idle : Active,其余(SW Power Cap / HW Slowdown / Thermal / Sync Boost / Display Clock)全部 Not Active。
即:驱动自己认定 GPU 是空闲的,没有任何限频原因。
强制锁频验证:
sudo nvidia-smi -pm 1 sudo nvidia-smi -lgc 1500,2100
重启程序后帧率毫无变化,仍是 7 FPS → 频率变量彻底排除。
由此排除:算力不足、频率未拉升、功耗墙、温度墙、显存不足、PCIe 带宽(Gen1 是 P8 待机态的正常表现,x8 对游戏影响 <2%)。
2. 定位到"呈现阻塞"
关键机制:UE 在统计 Draw / RHIT 时会主动扣除等待时间(RenderThreadIdle / RHIThreadIdle)。 因此渲染线程卡在 vkAcquireNextImageKHR / vkQueuePresentKHR 上的 100 ms 会被从 Draw 中减掉,只计入 Frame。
"CPU 三线程闲 + GPU 报 Idle + Frame 129 ms" —— 这是 Present 阻塞的典型特征。
量级换算:4K 一帧 3840×2160×4B ≈ 33 MB,129 ms → 约 257 MB/s。这不是显卡在工作,是 CPU 在搬内存。
3. 参照程序对比(关键分叉)
glxgears -info # 全屏约 410 FPS(后续证实是 llvmpipe 在跑) vkcube # 小窗流畅,拉大窗口明显卡顿
vkcube 的开销随窗口像素面积增长 —— 说明每帧存在按像素收费的全屏拷贝,而非零拷贝翻页(page flip)。
⚠️ 踩坑:vkcube 的帧数参数是
--c(双横杠),写成-c会直接打印 Usage 后退出(real 0m0.001s)。该版本也没有--width/--height选项,窗口大小只能手动拖。
4. 定位根因
glxinfo -B | grep -E "OpenGL renderer|OpenGL vendor"
OpenGL vendor string: VMware, Inc. OpenGL renderer string: llvmpipe (LLVM 11.0.0, 128 bits)
xrandr --listproviders
Providers: number : 1 Provider 0: id: 0x47 cap: 0x0 crtcs: 4 outputs: 4 associated providers: 0 name: modesetting
llvmpipe = Mesa 纯 CPU 软件光栅器(VMware, Inc. 是 Mesa 软件驱动的厂商字符串,与虚拟机无关)。 Provider 只有一个 modesetting(通用 KMS 驱动),不是 NVIDIA-0,且 cap: 0x0 连 PRIME 卸载能力都没有。
排除项(均已确认正常,非本次原因):
cat /sys/module/nvidia_drm/parameters/modeset # Y echo $XDG_SESSION_TYPE # x11(非 Wayland/XWayland)
三、根因与完整因果链
X Server 用通用 modesetting 驱动绑定了显示设备,而不是 nvidia_drv.so。
-
nvidia-drm.modeset=1使 NVIDIA 注册了一个 DRM 设备(4 个输出) -
X 用
modesetting驱动绑上它,而非 NVIDIA 的 X 驱动 -
Mesa 在该设备上找不到可用 GL 驱动 → 回退 llvmpipe 软件渲染
-
TESP 是 Vulkan,Vulkan ICD 绕过 X 直接找到独显 → 所以
nvidia-smi里能看到 TESP 进程(C+G),造成"显卡在用"的假象 -
但每帧画完后要从显存回拷到 CPU,再交给软件显示栈上屏 → 约 257 MB/s、100 ms 的固定开销
-
GPU 只干了约 3 ms 的活就闲置 → 驱动报
Idle: Active,锁频无效 -
UE 把 Present 等待从 Draw/RHIT 中扣除 → 三线程全"闲",Frame 却 129 ms
-
拷贝按像素收费 → vkcube 小窗流畅、大窗卡顿
四、修复方法
1. 确认 X 的 NVIDIA 驱动模块存在
ls -l /usr/lib/xorg/modules/drivers/ | grep -i nvidia ls -l /usr/lib/x86_64-linux-gnu/libGLX_*.so.0
若缺少 nvidia_drv.so,说明驱动是按"仅计算"方式安装的(如 .run 包带 --no-opengl-files),需重装完整显示驱动。
2. 查看 X 当初为何未选中 NVIDIA
grep -iE "nvidia|modesetting|\(EE\)|\(WW\).*GLX" /var/log/Xorg.0.log | head -40
3. 生成 NVIDIA 的 X 配置
优先使用 prime 切换器(若存在,比手改配置安全):
prime-select query sudo prime-select nvidia
否则:
sudo nvidia-xconfig
或手写 /etc/X11/xorg.conf.d/10-nvidia.conf(BusID 取自 nvidia-smi 的 00000000:04:00.0):
Section "Device"
Identifier "nvidia"
Driver "nvidia"
BusID "PCI:4:0:0"
EndSection
Section "ServerLayout"
Identifier "layout"
Screen 0 "nvidia"
EndSection
Section "Screen"
Identifier "nvidia"
Device "nvidia"
Option "AllowEmptyInitialConfiguration"
EndSection
4. 重启后验证
glxinfo -B | grep -E "OpenGL renderer|OpenGL vendor"
必须变为:
OpenGL vendor string: NVIDIA Corporation OpenGL renderer string: NVIDIA GeForce RTX 3060 Ti/PCIe/SSE2
xrandr --listproviders
Provider name 应变为 NVIDIA-0。
5. 操作风险与回退
改 X 配置有黑屏风险。动手前备份已有配置:
sudo cp /etc/X11/xorg.conf /etc/X11/xorg.conf.bak
黑屏时按 Ctrl+Alt+F2 切 TTY,删除新增配置后重启:
sudo rm /etc/X11/xorg.conf.d/10-nvidia.conf && sudo reboot
五、经验沉淀
1. Linux 部署交付的开机自检清单
新机器部署 TESP 后,先跑这两条再谈性能:
glxinfo -B | grep -E "OpenGL renderer|OpenGL vendor" xrandr --listproviders
-
renderer 必须是
NVIDIA GeForce ...,出现llvmpipe/softpipe/swrast/VMware, Inc.一律判为显示栈未接独显 -
Provider name 必须是
NVIDIA-0,出现modesetting同样判不合格
2. nvidia-smi 里看到进程 ≠ 走的是硬件路径
Vulkan ICD 独立于 X 加载驱动。渲染在独显上,但呈现路径可能仍绕回 CPU。 判断硬件加速是否真正生效,要看 glxinfo 的 renderer,不是看 nvidia-smi 的进程列表。
3. stat unit 的读法
-
Frame远大于Game/Draw/RHIT之和 → 帧时间花在"等待"上,不在计算或绘制上。 UE 会把 idle/wait 从 Draw、RHIT 中扣除,Present 阻塞只体现在 Frame。 -
Draws少不代表 GPU 负载低:UE5 的 Nanite、Lumen、Virtual Shadow Map 是 Compute 驱动的,不计入 Draws 计数。 -
DynRes: Unsupported在 PC 上是正常显示,不构成任何证据。 -
GPU Time空白在 Shipping 打包版里是正常的(STATS=0编译掉了),不代表驱动缺 timestamp 支持。要精确定位到具体渲染 Pass,需要 Development 打包版才能用stat gpu/ProfileGPU。
4. Clocks Event Reasons 的价值
sudo nvidia-smi -q -d PERFORMANCE | grep -A15 "Clocks Event Reasons"
唯一 Idle : Active、其余全 Not Active = 驱动明确声明 GPU 没活干,可以一次性排除算力/功耗/温度/限频四大类原因,避免在 GPU 侧继续浪费时间。
5. 一个高性价比的二分实验
用 vkcube(Vulkan,与 UE 同路径)和 glxgears(OpenGL)做参照,并观察帧率是否随窗口面积恶化:
-
参照程序同样慢 → 系统级问题,与业务程序无关
-
开销随像素面积线性增长 → 存在逐帧全屏拷贝,指向呈现/显示路径
更多推荐



所有评论(0)