ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

GPU内存占用高?Windows与Linux双平台显存释放完整指南

GPU内存占用高?Windows与Linux双平台显存释放完整指南 如果你的机器上同时装着Windows和Linux尤其是日常跑深度学习、渲染或者AI推理的一定遇到过这种场景程序崩了、窗口关了、进程列表里也没了但是打开任务管理器一看GPU内存那一条还是红的下一份训练任务死活加载不进去。更气人的是你找到那个占用进程想结束系统直接给你弹一个“拒绝访问”。这篇文章就用双平台视角把释放被占GPU内存这件事讲透核心是三种方法Windows下用命令行精准清理Linux下用nvidia-smi从根源回收再给一个双平台通用的驱动/图形栈重启方案顺带把任务管理器之外真正好用的监控替代工具也一起列出来。1. 为什么你的GPU内存会被“锁死”先搞清楚占用的来源和释放逻辑1.1 显存与共享内存谁才是那个“钉子户”很多人一看到“GPU内存”就默认指的是显存严格来说它包含两个部分一是GPU自身的显存VRAM用来存纹理、帧缓冲、模型权重二是在Windows上显示为“共享GPU内存”的那部分系统内存它由驱动映射给GPU使用。日常你看到任务管理器里GPU内存占用高绝大多数是显存被某种上下文context占住不还。真正麻烦的“钉子户”通常来自这几个场景训练脚本CtrlC强退但CUDA context没销毁、浏览器开着大量硬件加速页面、Docker容器退出但容器进程没走干净、WSL2里跑完任务虚拟机缓存还在、某个视频解码引擎被异常引用。打个比方每个程序都像酒店客人正常退出等于办退房但如果是“砸门逃跑”酒店系统里那间房仍然挂着“占用”状态直到保洁员驱动/系统服务发现并手动清理。所以释放GPU内存的第一步不是急着杀进程而是判断“是谁的上下文被挂在GPU上”。Windows和Linux在这一层的机制不一样后面两章分开讲。1.2 程序退出后显存为什么不消失上下文释放与驱动回收机制Windows基于WDDM驱动模型GPU上下文由图形驱动统一管理。进程创建GPU资源时驱动维护一张句柄/引用计数表进程退出后驱动会回收显存。但程序是崩溃的、被强杀的或者驱动本身出现bug引用计数没有归零显存就一直悬空。再加上Windows的TDR机制超时检测恢复在GPU无响应时会强制重置重置过程中旧上下文的清理经常不完整必须靠注销或重启才能真正恢复干净。Linux下更直接。NVIDIA驱动加载后会有nvidia、nvidia_modeset、nvidia_uvm、nvidia_drm几个内核模块每个进程通过打开/dev/nvidia*设备节点获得上下文。正常退出时文件描述符关闭、引用计数减一如果进程被kill -9、崩溃或者变成僵尸进程defunct只要父进程没有回收它打开的设备节点就不会关闭显存映射也就一直存在。还有一个容易忽略的是nvidia-persistenced服务它常驻初始化GPU某些异常状态下会把显存状态一直保持在“已分配”状态。理解了这个机制你就知道为什么有时候杀了进程显存还是满的也知道为什么“重载驱动”这种粗暴手段反而是最彻底的。2. Windows下释放GPU内存用命令行和监控工具替代任务管理器2.1 任务管理器看不明白的显存细节以及三个隐藏坑先别急着换工具任务管理器本身也能看显存。快捷键CtrlShiftEsc打开切到“详细信息”页右键表头选择“选择列”把“GPU”“GPU专用内存”“GPU内存”三个复选框勾上。这样每个进程占用多少显存、跑在哪个GPU上就一目了然。这个操作很多人不知道也算是最基础的任务管理器进阶用法。但任务管理器有几个先天不足第一它只能看到进程级的即时占用看不到内核驱动驻留的显存很多“匿名占显存”就是从这里漏掉的第二进程崩溃后留下的悬空上下文在任务管理器里可能已经找不到对应进程了但你确实占着显存第三遇到系统关键进程或者权限不够的进程右键结束任务会直接弹出“拒绝访问”。这三个坑我在实际排查中踩过好多次所以下面的命令行方案才是主力。2.2 nvidia-smi定位 taskkill强杀Windows下最快清场组合NVIDIA显卡在Windows下同样可以使用nvidia-smi工具在CMD或PowerShell里直接运行nvidia-smi输出里会显示每张卡的显存总量、已用量以及占用显存的进程PID和显存大小。你拿到PID后先确认这个进程是什么tasklist /fi PID eq 12345确认无误就执行taskkill /F /PID 12345如果这个进程还有子进程可以加/T参数连同子进程一起结束taskkill /F /T /PID 12345我实测下来这种方式能解决80%以上的显存占用问题。如果进程被安全软件或系统保护机制拦住提示“拒绝访问”你需要用管理员身份打开PowerShell然后考虑两种情况如果进程是普通应用提权后就能杀如果连管理员都杀不掉多半是进程运行在系统会话或受保护的服务里这时候直接看2.3节的驱动重置方案更高效。针对没有NVIDIA显卡的Windows机器可以用性能监视器来替代。WinR输入perfmon /sys添加计数器\GPU Process Memory\Local Usage就能看到每个进程对GPU内存的实际占用再配合任务管理器加列数据交叉对比。2.3 资源监视器、性能监视器与“软重置显卡”任务管理器之外的三个替代方案任务管理器的替代方案我常年保留两个资源监视器resmon和性能监视器perfmon /sys。资源监视器适合看全局内存、磁盘、网络的状态性能监视器适合盯GPU进程内存这种细分指标。日常排查我习惯先开perfmon /sys加上GPU Process Memory计数器如果显存被某个进程悄悄吃满这里是最早能看出来的地方。如果定位不到进程或者进程已经没了但显存依然被占用那就要走“驱动级重置”路线步骤由轻到重排个序按WinCtrlShiftBWindows会重启显卡驱动屏幕会黑一下这个过程一般不会关闭你的应用适合轻度异常。注销当前用户再登录这会释放当前会话持有的所有GPU上下文比重启系统快得多。打开设备管理器找到显示适配器右键你的显卡选择“禁用设备”确认后驱动会释放所有关联的GPU资源再右键“启用设备”恢复。注意如果你正在用这张卡显示输出禁用瞬间会黑屏几秒属正常现象别慌。我个人的习惯是先WinCtrlShiftB不行就注销重登再不行才禁用启用显卡。直接重启系统是最不推荐的因为很多显存泄漏问题是驱动bug或者第三方工具的残留钩子导致的重启只能暂时解决下次还会复现。3. Linux下释放GPU内存从nvidia-smi定位到彻底清理进程3.1 先确认谁在吃显存nvidia-smi的三种查询姿势Linux下第一件事永远是nvidia-smi。默认输出已经列出了显存总容量、已用容量以及当前compute应用CUDA、OpenCL等的PID和显存占用。不过默认输出对进程只显示“compute apps”有时候图形界面进程Xorg、Wayland合成器或者视频解码进程不会列全这时候可以用查询参数把更完整的信息拉出来nvidia-smi --query-compute-appspid,process_name,used_memory --formatcsv想动态观察显存变化用watch -n 1 nvidia-smi每1秒刷新一次实测下来比任务管理器直观得多。除了nvidia-smi我更常用的还有两个命令sudo lsof /dev/nvidia*可以列出所有打开了NVIDIA设备文件的进程包括那些不走compute API、只是映射了显存的进程sudo fuser -v /dev/nvidia*则直接告诉你哪些进程正占用着NVIDIA设备文件。两个配合使用几乎不可能漏掉“匿名占显存”的家伙。3.2 定位到进程后怎么杀才干净fuser定位、kill击杀、僵尸进程处理拿到PID后先用ps -o pid,ppid,stat,cmd -p PID看一眼状态再决定怎么处理。普通进程直接kill -9 PID如果进程已经变成defunct僵尸状态kill -9也无效因为进程内核线程已经死了只是父进程没有调用wait回收。你需要找到它的父进程PIDPPID然后让父进程退出或者重启对应的服务比如容器、守护进程僵尸进程被init进程领养后自然清理。实际工作中我还遇到过进程确实退出、但显存没释放的情况这通常是NVIDIA驱动模块对设备引用的计数没有清零。此时先检查是不是有残留的后台任务ps aux | grep python ps aux | grep defunct确认干净后如果显存仍然没恢复说明驱动状态脏了跳第4章直接重载驱动。理论上你还可以用sudo sysctl vm.drop_caches3之类去释放系统内存缓存但这对显存没用别浪费时间。3.3 容器与WSL2场景显存被“看不见的进程”占用的典型情况Docker和WSL2是Linux下显存泄漏的高发区。Docker容器退出时如果容器内的进程没有正确处理CUDA上下文NVIDIA Container Toolkit有时候不会完全释放显存。排查方法很简单执行docker ps -a列出所有容器看状态为“Exited”的容器还有哪些是挂过GPU的然后docker rm -f 容器ID更彻底的方式是清理所有已退出容器docker container prune它会物理删除所有停止的容器并释放相关资源。WSL2场景更隐蔽。你在Windows的WSL2里跑深度学习跑完关闭了终端窗口但WSL2的后台VM虚拟机可能还在运行显存被它的图形上下文占住。最有效的办法是在Windows的CMD或PowerShell中执行wsl --shutdown这会立即终止WSL2虚拟机相当于给Linux子系统的GPU上下文“断电重启”。实测这招能解决大部分WSL2显存不释放的问题。4. 通用兜底方案不动系统重启图形栈和驱动服务释放显存4.1 为什么重载驱动比重启系统更快理解图形栈重启思路当你既找不到占用进程、又杀不掉残留上下文的时候最有效的就是重载GPU驱动。这相当于把整个酒店系统重置一遍不管哪间房挂着“占用”统统一键清空。整个过程就是对内核驱动模块做卸载再加载比重启系统快而且不影响其他硬件和已开机服务。但重载驱动有一个先决条件不能让任何进程正在使用GPU设备否则模块卸载会失败。所以操作顺序一定是“停服务 - 卸载模块 - 加载模块 - 启动服务”。下面分Windows和Linux两个版本说明。4.2 Windows驱动重置快捷键、设备管理器和注销重登的取舍Windows下最轻量的是WinCtrlShiftB它触发显示驱动超时恢复效果等同于让驱动重置一次但不会关闭当前窗口。如果这个快捷键没效果可以走设备管理器“禁用再启用”显卡的路线这里有一个容易踩的坑如果当前桌面输出就是这张显卡禁用会直接黑屏而且某些笔记本的混合输出架构下禁用独显可能会导致集成显卡状态异常需要重启才能恢复。所以在Windows上我个人更推荐“注销重登”作为重载图形栈的折中方案。注销会彻底结束当前用户的图形会话所有GPU上下文被回收。比起设备管理器它不涉及硬件枚举风险小比起重启系统它通常快一倍以上。只要不是驱动本身的bug注销重登基本都能解决显存不释放的问题。4.3 Linuxmodprobe重载NVIDIA驱动、切换运行级别、重启显示管理器Linux下单独重载驱动前先把占用GPU图形上下文的服务停掉。常见的显示管理器是gdm3、lightdm、sddm用systemctl停掉后系统会退到字符界面然后在SSH会话里操作更安全sudo systemctl stop gdm3接着按依赖顺序卸载NVIDIA模块sudo modprobe -r nvidia_drm nvidia_modeset nvidia_uvm nvidia如果提示模块正被占用用lsmod | grep nvidia和sudo fuser -v /dev/nvidia*排查确认没有进程引用后再试。卸载完重新按逆序加载sudo modprobe nvidia sudo modprobe nvidia_uvm sudo modprobe nvidia_modeset sudo modprobe nvidia_drm modeset1最后一个modprobe nvidia_drm可能需要带modeset1参数否则休眠或图形显示可能不正常取决于你的驱动配置。加载完成后重启显示管理器sudo systemctl start gdm3如果不想手动操作模块还有一个偷懒的办法直接sudo systemctl isolate multi-user.target再sudo systemctl isolate graphical.target效果是切到纯文本模式再切回图形模式这会把所有图形进程连同GPU上下文重置一遍100%有效但体验粗糙。5. 高频问题排查实录这些场景我踩过的坑你也能避开5.1 任务管理器里GPU0和GPU1互换了是坏了吗这个现象在双显卡机器上很常见。任务管理器里的GPU编号是驱动枚举顺序不是物理插槽顺序所以换驱动、换主板BIOS设置、更新Windows后都可能出现之前跑在GPU0的任务现在显示在GPU1上。判断方法用nvidia-smi的-L参数看GPU索引对应的UUID或者进NVIDIA控制面板看“物理GPU”的位置。具体到程序运行时通过环境变量CUDA_VISIBLE_DEVICES来指定使用哪张卡别依赖系统默认编号。出现这种情况不影响性能不需要修。5.2 CPU、GPU、内存占用都不高但电脑就是卡问题出在哪这种“三低还卡”的现象优先级最高的怀疑对象是显卡驱动的TDR复位。Windows会在GPU长时间无响应时重置驱动重置期间图形界面会卡几秒到几十秒任务管理器看起来占用率都很低但画面就是掉帧。处理方法更新显卡驱动关闭浏览器硬件加速如果频繁出现在注册表里调高TdrDelay值可以缓解但不建议随便调这是治标不治本。Linux下类似情况则优先查dmesg看有没有NVRM报错或者Xid错误sudo dmesg | grep -i nvidia能抓住很多线索。5.3 任务管理器结束进程提示“拒绝访问”杀不掉怎么办先确认你是不是管理员。右键任务管理器选择“以管理员身份运行”再试一次。如果还拒绝通常是因为目标进程运行在系统会话或受保护进程列表中这时候命令行加双重参数taskkill /F /T /PID PID依然不行的话用下面这个方案替代任务管理器下载微软官方的Process Explorerprocexp.exe右键以管理员身份运行目标进程上右键选择“Kill Process Tree”它权限比任务管理器高。如果连Process Explorer都杀不掉说明该进程是内核或驱动保护级别的那就别硬杀了直接走第4章的驱动重载方案。5.4 黑屏了任务管理器也是黑的怎么救黑屏但系统还在响应时先按WinCtrlShiftB重置驱动大概率能救回来。不行的话弹不出任务管理器就用CtrlAltDel进入安全选项界面这里有一个小技巧黑屏状态下盲操作按一下CtrlAltDel然后等几秒再按Enter如果运气好能进入锁屏界面。最稳妥的还是提前配好远程桌面或SSH黑屏时通过另一台设备登录机器执行taskkill /F /IM explorer.exe再重启explorer.exe通常就能把桌面拉回来。还有一个容易被忽略的原因是显卡驱动和某个应用冲突导致黑屏这时候如果SSH能连上查看Windows事件日志里“Display”相关的事件ID多半能看到TDR重置记录比盲目重启可靠。6. 最后聊几句实操中的体会我自己的习惯是跑训练任务前先甩一行watch -n 2 nvidia-smi挂在旁边任务结束后瞄一眼显存曲线一旦发现显存回收异常就第一时间去排查进程。清理顺序也有讲究先精确杀进程不行再注销重登最后才动驱动重载。别一上来就重装驱动或者重启系统很多显存问题说白了就是悬空上下文一个注销就能解决的事搞得太隆重反而容易引入新问题。另外如果你是团队里负责维护GPU服务器的人建议把第4章的modprobe重载流程写成一个脚本命名为reset_gpu.sh每次显存异常直接执行一份能省不少时间。脚本里面加一行日志记录什么时候重置过、重置前排除了哪些进程长期看能发现到底是哪个环节频繁泄漏这才是根治问题的方向。
返回列表