我在配备 32 GB RAM 和 Nvidia K80 GPU 的 Dell PowerEdge R730 上运行 Ubuntu 14.04LTS。我有一个可以运行很长时间的 Python 脚本,但实际上只是对其他程序进行了一堆相对短暂的系统调用(其中一些程序在必要时会广泛使用 CUDA)。除了总体 Python 脚本之外,各个系统调用每个只运行大约 45 秒,并且 Python 脚本本身不会“维护”任何东西 - 它只进行系统调用和迭代 - 而不是任何结果存储等。
当我观察程序运行并用“top”监控内存使用情况时,我看到报告的“可用”内存随着时间的推移而减少。我知道这通常不是一个问题,因为使用了缓存。但最终,机器挂起并且不以任何方式响应(即控制台上没有鼠标光标移动,远程终端没有响应等)。当这种情况发生时,我必须硬重启系统,然后一切恢复正常,我可以从上次中断的地方继续,直到它再次挂起。
另一个有趣的点是 - 经过足够的重启后,程序终于完成了。同样,在此之后,系统上没有任何重要的程序在运行,但是,gnome-system-monitor 和 top 都报告内存使用量几乎已满,并且尝试运行其他(最小)命令经常被内核“杀死”。检查系统日志,它报告“内存不足”,这似乎表明正在使用的内存不是缓存,而是实际“声明”的内存。问题是 - 由谁?检查人们在这个论坛和其他论坛上提到的所有内存实用程序,没有进程声称正在使用大量内存。
我读过有关内核内存泄漏的报告,这就是我想要声称的,但这似乎不太可能。
问:如何确定什么占用了所有内存? 我希望能够确定它是否在内核中或者是否正在运行某个进程。
支持信息:
uname -a:
Linux machinename 3.19.0-47-generic #53~14.04.1-Ubuntu SMP Mon Jan 18 16:09:14 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
lscppu:
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 8
On-line CPU(s) list: 0-7
Thread(s) per core: 2
Core(s) per socket: 4
Socket(s): 1
NUMA node(s): 1
Vendor ID: GenuineIntel
CPU family: 6
Model: 63
Stepping: 2
CPU MHz: 1200.351
BogoMIPS: 5993.09
Virtualization: VT-x
L1d cache: 32K
L1i cache: 32K
L2 cache: 256K
L3 cache: 10240K
NUMA node0 CPU(s): 0-7
事先阅读和理解:我读过大量关于理解 Linux 内存使用和报告的帖子。我知道,当像 top 这样的程序报告“可用”内存很少时,这并不一定是问题,因为大部分“已用”内存都被缓存了,而实际上,让 RAM 充满缓存的内容是件好事。但我相信,这不是我看到的问题,因为如果它是缓存,程序似乎可以利用它。内核正在介入并终止新进程,dmesg 报告系统“内存不足”,这似乎表明内存正在以非缓存的方式被占用,但在我尝试过的任何内存分析工具中似乎都没有报告这种情况。
更新:根据下面的答案,当事情开始变糟时,我查看了 /proc/meminfo,虽然我不知道这些都是什么意思,但有几个似乎..可疑..“DirectMap2M”似乎有问题,“VmallocChunk”也是如此,尽管问题不那么严重...
> cat /proc/meminfo
MemTotal: 32828728 kB
MemFree: 166568 kB
MemAvailable: 100656 kB
Buffers: 6520 kB
Cached: 27416 kB
SwapCached: 300 kB
Active: 17904 kB
Inactive: 16076 kB
Active(anon): 360 kB
Inactive(anon): 212 kB
Active(file): 17544 kB
Inactive(file): 15864 kB
Unevictable: 32 kB
Mlocked: 32 kB
SwapTotal: 33452028 kB
SwapFree: 33317332 kB
Dirty: 0 kB
Writeback: 0 kB
AnonPages: 484 kB
Mapped: 23276 kB
Shmem: 144 kB
Slab: 559236 kB
SReclaimable: 60016 kB
SUnreclaim: 499220 kB
KernelStack: 8864 kB
PageTables: 10132 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 49866392 kB
Committed_AS: 1143048 kB
VmallocTotal: 34359738367 kB
VmallocUsed: 358064 kB
VmallocChunk: 34342563088 kB
HardwareCorrupted: 0 kB
AnonHugePages: 0 kB
CmaTotal: 0 kB
CmaFree: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
DirectMap4k: 32637928 kB
DirectMap2M: 18446744073709318144 kB
DirectMap1G: 3145728 kB
更新2刚刚再次运行程序,每 15 秒捕获一次 cmd“free”。我观察到 free 列随着程序的运行而下降,直到达到一个非常低的值(大约 190000),当它达到该水平时,程序挂起,一切开始变得非常缓慢。我按下 ctrl-c 键,在程序挂起一段时间后,最终终端响应并带我回到提示符。但是,“free”仍然在 free 列中报告大约 190000,甚至一般使用(只是在终端中输入)也非常慢 - 当前没有程序正在运行。查看 /proc/meminfo,“DirectMap2M”字段再次变得疯狂。我也定期捕获 /proc/meminfo 的内容,并可以查看情况随时间的变化。
仅供参考:当挂断时,以下是“free”命令的输出:
total used free shared buffers cached
Mem: 32828728 32636496 192232 4 7368 22972
-/+ buffers/cache: 32606156 222572
Swap: 33452028 205160 33246868
这是来自 /proc/meminfo 的 DirectMap2M 值随时间变化的图。在图中的最右侧点之后,它变为一个非常大的值 - 看起来像是下溢。在谷歌上搜索了一下,发现其他人也遇到了下溢问题。但我不知道 DirectMap2M 代表什么。
更新 3: 仍在与此作斗争。一些最近发现的信息需要添加:
我们尽可能将其归结为以下内容:
#include "cublas_v2.h"
int main() {
cublasHandle_t handle;
cublasCreate(&handle);
cublasDestroy(handle);
return 0;
}
每次我们在配备 NVidia K40 的 Dell T630 上运行该程序时,我们都会发现 DirectMap2M 出现故障。如果运行次数足够多,我们会看到下溢问题,并且必须重新启动机器。我们还有一台配备 NVidia K80 的 Dell R730,它会出现同样的行为。
有趣的是,我们还有另一台计算机(一台配备 NVidia GTX980M 的笔记本电脑)运行相同的 Ubuntu 内核,当我们运行上述程序时我们没有观察到这种行为。
答案1
一个好的起点是跟踪 /proc/meminfo 中的统计数据,其中包含大量有关全局内存利用率的详细信息。我建议定期(例如每 30 分钟左右)捕获 /proc/meminfo 的输出,然后可以检查它以查看内存分配增长发生的位置。从那以后,您至少会对下一步该看什么有所了解。
答案2
我们在使用 GTX 970 和 GTX 980Ti GPU 的 Debian Jessie 机器上运行 CUDA 作业时也遇到了同样的问题。您的测试用例也导致我们的机器在几分钟内内存耗尽。
最终,我们解决了这一恼人行为,方法是安装 nvidia 最新的测试版驱动程序(撰写本文时为 364.12 版)。它似乎独立于 Linux 内核(我们尝试了几个)和 CUDA 版本(我们也尝试了几个)。这似乎是 nvidia 驱动程序本身的一个错误,最近才得到修复。