42 天追凶:WSL 侧 nvidia-smi 导致 NVRM Non-Paged Pool 泄漏排查全记录

_

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 内核驱动 nvlddmkmNVIDIA 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),两组数据差异明确。

但实验有一个重要的不完美之处:wslservicevmcomputevmwpvmmemWSL 这些进程仍然在运行,只有 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_AwakeWSLService(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 趋势。

SplitGrid:告别纯手工拉框,专治光伏阵列等密集目标的细粒度标注 2026-03-26