WSL2 Ubuntu中Julia程序触发OOM-kill但仍有剩余内存求助
问题背景
在WSL2的Ubuntu环境运行Julia程序时,程序突然终止并提示killed,执行sudo dmesg得到OOM相关日志:
oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=/,mems_allowed=0,global_oom,task_memcg=/,task=julia,pid=1412,uid=1000
[ 1772.507795] Out of memory: Killed process 1412 (julia) total-vm:8780912kB, anon-rss:3566556kB, file-rss:4kB, shmem-rss:0kB, UID:1000 pgtables:13772kB oom_score_adj:0
通过println("memory: ", Int(Base.Sys.free_memory()))检测到崩溃前仍有0.5GB空闲内存,程序此前可正常运行,仅在安装CUDA Toolkit后出现异常,回退至旧版本问题依旧。
原因分析
1. WSL2内存模型的统计偏差
WSL2的内存基于Windows虚拟内存子系统动态分配,用户态Base.Sys.free_memory()仅统计WSL内部的空闲用户态内存,但内核层面的内存(如页表、slab缓存、内核栈)、Windows侧的内存占用并未被计入。当Windows系统整体内存不足时,会触发WSL2的OOM-kill,即便WSL内部显示还有空闲内存。
2. CUDA对内存分配的影响
安装CUDA Toolkit后,可能引发以下内存相关变化:
- Julia的CUDA相关依赖(如
CUDA.jl)可能默认预分配GPU内存,或改变内存分配策略,导致程序的虚拟内存占用(total-vm)大幅提升,内核OOM killer会根据进程的内存占用评分选择终止目标。 - WSL2中CUDA驱动与Windows GPU驱动的交互会占用额外的系统内存,这部分内存不会被WSL内部的内存检测工具统计到,实际可用内存远低于显示值。
3. OOM killer的触发逻辑
内核OOM killer并非仅看用户态空闲内存,而是评估系统整体内存压力:
- 当程序尝试分配连续大内存块时,即便有零散空闲内存,也可能因内存碎片无法满足分配需求触发OOM。
- 内核内存(如页表、缓存)耗尽时,用户态仍显示有空闲内存,但内核已无可用资源分配,从而触发OOM-kill。
解决方向
配置WSL2内存限制:在Windows用户目录下创建/编辑
.wslconfig文件,明确WSL2的内存和swap上限,避免占用过多Windows内存:[wsl2] memory=6GB # 根据你的Windows内存调整 swap=4GB修改后需重启WSL(
wsl --shutdown)生效。排查CUDA相关配置:
- 若使用
CUDA.jl,通过CUDA.memory_limit!()限制GPU内存分配,或禁用内存预分配。 - 确认WSL2的CUDA驱动版本与Ubuntu侧CUDA Toolkit版本匹配,避免兼容性问题导致的异常内存占用。
- 检查环境变量(如
CUDA_VISIBLE_DEVICES、CUDA_MEMORY_POOL)是否影响程序内存行为,可临时清空相关变量后测试。
- 若使用
更精准的内存监控:
- 使用
htop或free -h实时监控WSL内部的内存、缓存、swap占用情况。 - 在Windows任务管理器中查看
vmmem进程的内存占用,对比WSL内部统计值,确认Windows侧是否存在内存压力。 - 执行
vmstat 1观察内存交换(si/so)情况,若频繁交换说明内存不足。
- 使用
排查Julia内存分配:
- 使用Julia的
@time宏或Profile工具分析程序的内存分配细节,定位是否存在异常大内存分配或内存泄漏。 - 清空Julia的包缓存(
rm -rf ~/.julia/packages)后重新安装依赖,排除CUDA相关包的缓存异常。
- 使用Julia的
查看完整OOM日志:执行
dmesg | grep -A 10 -B 10 oom获取OOM触发前后的完整内存状态日志,排查是否有内存碎片、内核内存不足等细节。
内容的提问来源于stack exchange,提问作者Ben Wilop

