42 天追凶:WSL 侧 nvidia-smi 导致 NVRM Non-Paged Pool 泄漏排查全记录
元信息:
- Date: 2026-07-01
- Categories: 故障排查, Windows, Linux
- Tags: WSL2, RTX5070ti, Windows, NVIDIA, NVRM, ETW, nvidia-smi, ServerMonitor
- Host: ARTICHOKALEYARD (RTX 5070 Ti / Ryzen 7 9800X3D / Win11 24H2 / Driver 610.62)
- Duration: 42 天 (2026-05-18 ~ 2026-06-30)
- Cost: 1 次系统重装、N 次驱动切换、2 次 Build 回退、500GB WPR trace 磁盘撑满事件
这大概是过去一年里最难缠的一次排障。
系统重装无效。多次换驱动无效。Windows Build 回退无效。甚至 WPR 抓 trace 还留下过 500GB 的磁盘空间撑满事件。
42 天后,根因锁定在一行监控配置和一个已知但长期未修复的 WSL vGPU 路径缺陷上。
1. 症状:随时间累积的图形栈劣化
故障现象非常稳定:
- 刚重启后的前几小时一切正常。
- 随着 uptime 增加,系统逐步进入一个“坏状态”。
- 坏状态下,游戏掉帧、硬解视频卡顿、甚至拖动窗口都不流畅。
- 重启能暂时清零,但不能根除。
这一定义在排查早期就被固定下来。它不是“某个游戏卡”,也不是“浏览器硬解有问题”—— 整个图形栈在 uptime 积累后一起劣化。
三个量化信号构成了坏状态的“生命体征”:
信号一:nvidia-smi 响应时间。正常情况下,nvidia-smi 查询 GPU 状态耗时约 50ms。坏状态下,这个数值冲到秒级:
# 正常基线(重启后 19 分钟)
$ nvidia-smi --query-gpu=timestamp --format=csv,noheader
49ms 54ms 55ms <!-- 正常 -->
# 坏状态(uptime ~22h)
$ nvidia-smi --query-gpu=timestamp --format=csv,noheader
2264ms 2881ms 2618ms <!-- 恶化约 50 倍 -->
信号二:NonPaged Pool 累积。Kernel NonPaged Pool 随 uptime 单调上升,从重启后的 ~894 MiB 一路爬到 2,144 MiB。
信号三:LiveKernelEvent 堆积。C:\Windows\LiveKernelReports\ 下 WATCHDOG 转储文件大量产生——在约 20 天的窗口内累积了 1,278 次,含 1b8(648 次)、1a8(447 次)、193(107 次)、141(76 次)。
坏状态 vs 重启后 的数据:
| 指标 | 坏状态(uptime ~22h) | 重启后(uptime ~19m) |
|---|---|---|
| nvidia-smi 延迟 | 2,264–2,881ms | 49–55ms |
| NonPaged Pool | 2,144 MiB | 894 MiB |
同一硬件、同一驱动、同一系统。唯一的变量是 uptime。
2. 盲区:驱动游击战与系统重装(5/18–6/23)
2.1 驱动与第三方软件 A/B 排除
5 月 9 日的记录显示一次环境变化:WSL 从 C: 盘迁移到了 W: 盘(一块新的 TiPlus7100 NVMe),发行版从 Ubuntu 22.04 升级到了 24.04。这划定了后续 WSL / Hyper-V / vGPU 的排查背景;触发锚点见 5 月 18 日 13:43。
与症状起点直接对应的触发锚点,是 5 月 18 日 13:43:ServerMonitor 的 WSL2 target 被设为 enabled=true,开始周期性 SSH 进入 WSL 执行 nvidia-smi 查询 GPU 状态。
当天深夜 23:48,最早的卡顿诊断请求出现在 Codex 会话记录中——距离监控配置变更仅约 10 小时。
当时的排查视野里,没有任何人怀疑 WSL。
当时的系统环境是 Build 26200 + NVIDIA 596.49(32.0.15.9649),排查重心全部压在驱动和常驻软件上。A/B 测试过的嫌疑清单包括 TrafficMonitor、DeepCool、GameViewer、Armoury Crate、Wallpaper Engine——逐进程关停,看哪一个是“罪魁祸首”。
关掉某个进程后卡顿减轻一点,关掉另一个后又减轻一点——但没有一个能单独解释全部症状。这说明当时观察到的是多个放大器和受害者,并不是单一进程根因。
5 月 28 日凌晨 01:06,一场 NVML 崩溃链在系统日志中留下了精确到秒的痕迹:
| 时间 | 事件 |
|---|---|
01:06:37 |
NVIDIA 内核驱动 nvlddmkm 和 NVIDIA Display Container LS 被停止/重置 |
01:06:42 |
deep_service.exe(DeepCool)在 nvml.dll 中崩溃,异常码 0xc0000005 |
01:06:52 |
UsbMonitor.exe 同样在 nvml.dll 中崩溃 |
01:08:16 |
nvlddmkm 被重新启动 |
01:11:02 |
NVIDIA OpenGL Driver 报告:"The GPU has been disconnected",受害者 explorer.exe |
当时对这个崩溃链的解释是:第三方 NVML 轮询工具 → nvml.dll 崩溃 → 图形栈连锁崩塌。这个模型能描述传导路径,但没有回答上游问题:为什么 nvml.dll 在那个时刻变得脆弱。
这个阶段还留下了两条后来反复回看的记录:596.49 → 596.36 的降级尝试在安装中途被会话中断,WPR 抓 trace 则因为僵尸 collector 撑满了 500GB 磁盘。
2.2 系统重装——核选项失败
6 月 3 日 19:00,系统重装。
关键数据点是:19:09——重装后仅 9 分钟——第一批 LiveKernelEvent 出现了。
Windows InstallDate 和最早 dump 时间戳之间只有 9 分钟,因此“旧系统脏了”不足以解释问题。重装后的干净系统也会触发同类图形栈异常。
2.3 Build 回退与驱动交叉实验
随后几周,排查进入“版本交换”阶段。做过的事情包括:
- 移除
KB5083769+KB5078674,UBR 从 8246 跌到 1742。 - 通过 DISM 安装
KB5074105(4.1GB MSU),升到 7705。 - 在 7705 上安装 NVIDIA 610.62(R610 分支),与 596.36(R595 分支)头对头对比。
KB5083769 移除后,WER dump 从 1,278 次降到 0。这个结果支持它是 TDR/LiveKernel 的“放大”因素,但卡顿本身还在。
Build 回退 + 驱动切换的结论被精炼成一句话:都泄漏,只是快慢不同。
3. 量化:DPC 分布、VRAM 占比与泄漏速率(6/22–6/25)
这一阶段把此前模糊的“系统卡”量化成了毫秒和兆字节级别的数据。
3.1 坏状态下的量化现场
DPC/ISR 单核集中。坏状态下抓到过这样的 CPU 中断分布:
Core 0: DPC 15.09% + ISR 4.53% = 19.62%
Core 1–15: 全部接近 0%
这组数据归入平台放大条件。MessageNumberLimit = 1 会让 GPU 中断压力集中到 Core 0;当图形栈已经被 NVRM / NVML 路径拖慢时,中断集中会放大坏状态。3 月、4 月稳定期同样存在这一平台约束,因此它只解释中断分布,不解释 5 月之后的时间线变化。
VRAM 被吃到 90.2%。坏状态下的 nvidia-smi(Windows 侧,admin 权限)揭示了 VRAM 的真实占用:
| 进程 | VRAM 占用 | 备注 |
|---|---|---|
HYPHelper.exe |
9,386.9 MB | WSL / Hyper-V vGPU 相关进程,进程无响应(Not Responding) |
dwm.exe |
3,033.6 MB | 桌面窗口管理器 |
GameViewerServer |
2,343.0 MB | 双路 NVENC 编码持续运行 |
| 合计 | ~14.7 GB / 16.3 GB |
HYPHelper 高 VRAM 是 WSL / Hyper-V vGPU 相关现场信号。本机没有对应的 WSLg GUI 使用场景;这一记录用于提示 vGPU 路径参与排查,主要证据来自 ETW VMBusEscape 栈和 WSL 侧 nvidia-smi 行为差异。
MSI-X MessageNumberLimit = 1。注册表中确凿地记录了 GPU 仅分配到 1 条中断向量的配置。正常情况可能是 8 或 32 条。这个固件/BIOS 层约束解释 Core 0 DPC/ISR 压力集中;3 月稳定期同样存在这个配置,所以它归入放大条件。
3.2 驱动泄漏速率头对头
把系统固定在 7705 上,分别跑 596.36 和 610.62 各 21 小时以上,得到了一组关键数字:
| 驱动版本 | 泄漏速率 | 21h 后 NonPaged |
|---|---|---|
| 596.36(R595) | ~63 MB/h | ~2,900 MB |
| 610.62(R610) | ~47 MB/h | ~2,167 MB |
610.62 的泄漏速率慢了约 25%,但仍然在漏。查了 R550 时代的 553.62——它确实不泄漏,但它不支持 RTX 5070 Ti(Blackwell 最低需要 R570+)。
对这块 GPU 而言,当时没有找到既不泄漏又兼容的驱动。
3.3 证据门槛提高
6 月底,排查者说了一句被写进记录的原话:
“我现在不接受任何 AB 测试,你去继续抓数据查,没有令我信服的结论不要回来。”
这句话的背景是:AI 反复深陷幻觉,给出的解释看似合理,却站不住脚。它提高了工作门槛——后续排查只接受能被复核的现场数据、调用栈或时间锚点。
4. ETW、社区 issue 与 ServerMonitor 时间锚点
4.1 ETW 抓栈——VMBusEscape 进入视野
6 月 26 日,用 admin 权限的 xperf 抓了 kernel pool stack。在 NVRM non-paged pool 分配路径上,一条调用链浮现了:
dxgkrnl!DXGADAPTER::DdiEscape
→ dxgkrnl!DxgkEscape
→ dxgkrnl!DXG_HOST_VIRTUALGPU_VMBUS::VmBusEscape
→ dxgkrnl!VmBusExecuteCommandInProcessContext
→ dxgkrnl!VmBusProcessPacket
VmBusEscape——Hyper-V 虚拟 GPU 总线的 escape 路径——直接出现在内核栈里。这条栈把 WSL2 vGPU 路径纳入了硬证据范围。
这条栈证明 nvlddmkm / NVRM 的承压路径经过虚拟 GPU 总线。后续答案收束到 WSL 侧 nvidia-smi,依赖社区 issue 和本机 ServerMonitor 配置时间戳。
4.2 社区 issue 提供机制对照
microsoft/WSL#12756(status: closed)的标题直接命中:
"nvidia-smi on WSL side causes NVRM driver non-paged pool memory leak"
这个 issue 的价值在于它明确区分了 Windows 侧和 WSL 侧 nvidia-smi 的行为:
- Windows 侧跑大量
nvidia-smi -q -x:NVRM 会涨后回落。 - WSL 侧跑大量
nvidia-smi -q -x:NVRM 会涨上去并停留,不回落。
这与此前 ETW 里看到的 VMBusEscape → NVRM 路径一致。问题范围收敛为:WSL 侧 NVML 查询通过 vGPU/VMBus 路径触发 NVRM non-paged pool 滞留。
与本案例的吻合度:
| 对比项 | 社区反馈 | 本案例 |
|---|---|---|
| 泄漏对象 | NVRM non-paged pool | NVRM non-paged pool(ETW 确认) |
| 触发路径 | WSL 侧 nvidia-smi | ServerMonitor SSH 进入 WSL 采样 nvidia-smi |
| 行为特征 | NonPaged 涨后不回落 | NonPaged 随 uptime 单调上升 |
4.3 ServerMonitor 时间锚点
结合该 issue,ServerMonitor 配置时间戳成为关键证据:
5/09 WSL 迁移到 W: 盘,Ubuntu 22.04 → 24.04
环境变化记录;触发锚点见 5/18 13:43
5/18 13:43 ServerMonitor WSL2 target enabled=true
周期性 SSH 进入 WSL 执行 nvidia-smi
(WSL 侧 NVML 查询 → VMBusEscape → NVRM 滞留)
5/18 23:48 最早可考的卡顿诊断请求(Codex 会话 019e3bc6)
与监控配置变更相隔约 10 小时
5/25 起 LiveKernelEvent 1a8/1b8/193 等硬锚点出现
后续叙述以 5 月 18 日 ServerMonitor 开始在 WSL 内周期性执行 nvidia-smi 作为触发锚点;5 月 9 日保留为 WSL 环境变化记录。
4.4 暂停 WSL 采样路径后的行为变化
随后做了一个低侵入实验:禁用 WSL_Keep_Awake 计划任务,把 WSLService 启动类型从 Auto 改为 Manual。这个实验切断了 WSL distro userland 和 ServerMonitor 采样路径,用于观察坏状态是否继续形成。
两次复查的结果:
| 时间 | uptime | nvidia-smi 延迟 | NonPaged Pool | LiveKernel 新增 |
|---|---|---|---|---|
| 6/27 22:05 | ~22.4h | 54–61ms ✅ | 1,335.6 MiB | 0 |
| 6/28 23:58 | ~48.3h | 53–62ms ✅ | 1,275.7 MiB | 0 |
对比 6/24 坏状态(22h 时 nvidia-smi 已冲到 2,264–2,881ms),两组数据差异明确。
但实验有一个重要的不完美之处:wslservice、vmcompute、vmwp、vmmemWSL 这些进程仍然在运行,只有 WSL distro 显示 Stopped。也就是说,被禁掉的不只是”WSL 本身”,还包括 distro userland 中的所有活动——包括 ServerMonitor 的周期性 nvidia-smi 采样。
因此这个阶段的严谨结论只有一个:坏状态和 WSL distro userland 内的持续活动强相关,下一步必须把“WSL 在跑”和“WSL 内跑 nvidia-smi”拆开。
5. 确认:解耦验证与最终定论(6/29–6/30)
最后一步实验设计基于三个证据:ETW 栈、社区 issue、ServerMonitor 时间锚点。
恢复 WSL distro 运行,但不在 WSL 内执行 nvidia-smi。
6 月 29 日,重新启用 WSL_Keep_Awake 和 WSLService(AUTO_START),手动启动了 WSL distro(中间发现 Keep Awake 脚本的 LogonTrigger 在长 uptime 下不重新触发,手动补了一刀)。ServerMonitor 不再对 WSL target 执行 GPU 采样。
6 月 29 日的数据只能说明方向初步成立:WSL 可以恢复运行,但 WSL 内的 NVML 采样必须继续断开。结论的最终验证依赖 6 月 30 日的 94.5h uptime 复查。
复查数据:
| 日期 | System uptime | WSL 状态 | nvidia-smi | NonPaged |
|---|---|---|---|---|
| 6/29 22:01 | ~70h | Running(数小时) | 59–69ms ✅ | 1,479 MiB |
| 6/30 | ~94.5h | Running(~24h) | 59–69ms ✅ | 1,598 MiB |
94.5 小时 uptime,nvidia-smi 延迟仍保持在 59–69ms。 这是整段排查史中最长的无劣化窗口——旧坏状态在 ~10-15h 就开始秒级延迟了。
把四组数据放一起看:
| 指标 | 坏状态 6/24 (22h) | 暂停WSL 6/28 (48h) | 恢复WSL无采样 6/29 (70h) | 最终 6/30 (94h) |
|---|---|---|---|---|
| nvidia-smi 延迟 | 2,264–2,881ms | 53–62ms | 59–69ms | 59–69ms |
| NonPaged Pool | 2,144 MiB | 1,276 MiB | 1,479 MiB | 1,598 MiB |
解耦实验把变量收束到 WSL 内执行 nvidia-smi,而非 WSL 常驻本身。
6. 因果链:证据分层
| 层级 | 本文采用的判断 | 证据状态 |
|---|---|---|
| 触发锚点 | ServerMonitor 于 5/18 13:43 启用 WSL2 target,周期性 SSH 进入 WSL 执行 nvidia-smi |
本机配置时间线 + 最早诊断请求相隔约 10h |
| 机制路径 | WSL 侧 NVML 查询经 vGPU / VMBusEscape 进入 NVRM,触发 non-paged pool 分配滞留 |
ETW pool stack + microsoft/WSL#12756 外部复现 |
| 区分边界 | Windows 侧 nvidia-smi 涨后回落;WSL 侧 nvidia-smi 涨后不回落 |
社区 issue 与本机行为吻合 |
| 本机放大条件 | MessageNumberLimit = 1 导致 GPU 中断集中在 Core 0,放大坏状态下的 DPC/ISR 压力 |
注册表和坏状态采样确认;不单独构成根因 |
| 叠加放大器 | KB5083769 放大 TDR / LiveKernelEvent 表现 | 移除后 WER dump 从 1,278 降到 0,但卡顿根因未消失 |
| 实验验证 | WSL distro 恢复运行,但停止 WSL 侧 NVML 采样后,94.5h uptime 仍未回到旧坏状态 | 6/29 初步验证,6/30 复查确认 |
这组证据指向同一个结论:WSL 常驻本身没有复现旧坏状态;WSL 内周期性执行 nvidia-smi 触发了已知的 NVRM non-paged pool 滞留路径。
📝 总结
根因:WSL 侧 nvidia-smi 通过 VMBusEscape 路径触发 NVRM non-paged pool 分配,且 WSL 路径下的分配涨后不回落(与 Windows 侧行为不同)。周期性采样导致 NonPaged Pool 随 uptime 单调累积。
解法:不要在 WSL 内执行 nvidia-smi 或任何 NVML 查询。如果需要监控 WSL 的 GPU 状态,从 Windows 侧获取——Windows 侧的 NVML 查询涨后回落,不会造成永久滞留。
三个教训:
| 教训 | 展开 |
|---|---|
| 搜索词选择决定排查效率 | 如果更早围绕 WSL nvidia-smi non-paged pool leak 搜索,可能几周前就找到 microsoft/WSL#12756。事实是花了 40 天、经历系统重装和无数次驱动切换之后,才通过 ETW 栈与 ChatGPT 指出的社区 issue 把线索接上。 |
| 跨边界操作的隐蔽性 | ServerMonitor 在 WSL 里跑了一句 nvidia-smi——对系统管理员来说完全是合理的监控行为。但 WSL vGPU 路径上存在一个已知缺陷,让这个无害的操作变成了 NonPaged 泄漏的触发器。跨边界(Windows ↔ WSL)的副作用极难在本地排查中归因。 |
| 无效方案清单要明确 | 系统重装、驱动切换(596.49/596.36/610.62)、Build 回退(8246→7705)、关停第三方软件(TrafficMonitor/DeepCool/GameViewer/Armoury Crate/Wallpaper Engine)——全部无效或只改变症状强弱。如果有人在排查早期告诉你可以靠换驱动解决 RTX 5070 Ti 上的 NVRM NonPaged 泄漏,这篇文章就是反面证据。 |
后记
感谢 microsoft/WSL#12756 的报告者——你的一条 issue 帮一个陌生人在 42 天后终结了一场排查。
也感谢几套 AI 工作流在不同阶段提供的帮助:ChatGPT 网页端负责反复梳理现象、解释数据和校准排查方向;本地 Codex 会话把机器环境、系统日志和 ETW 栈信息拉到一起,重新审视调用链;接入 DeepSeek 模型的 Claude Code 则参与了取证执行和关键猜想形成,尤其是帮助把视线从驱动游击战转向 WSL/NVML 触发路径。
如果你也在排查类似的卡顿问题,wsl --shutdown 只能算临时隔离动作,不是已验证修复手段。已有经验显示重启能可靠重置坏状态;短暂关闭 WSL 后是否会自行回落,当前没有验证结论。更稳妥的排查方式是:重启后停止所有 WSL 内 NVML / nvidia-smi 轮询,再跨一个完整 uptime 窗口观察 nvidia-smi 延迟和 NVRM / NonPaged Pool 趋势。