Linux 多线程程序虚拟内存占用过大有什么问题吗?

2016-10-09 11:40:21 +08:00
 algas
最近写了一个程序,总是在计算规模比较大的时候异常退出
[1] 47393 segmentation fault ./a.out 300 0.5

发现退出总是发生在启动多线程的部分,多线程部不需要额外申请内存。
在退出发生前,我观察到系统程序虚拟内存比较高, RSS ~ 80G , VSZ ~ 135G 。
机器只有 128G 物理内存,没有分配 swap 分区和文件, VSZ 明显超过了物理内存,不知道是不是因为这个原因导致程序退出的,求指点。


> ulimit -a

-t: cpu time (seconds) unlimited
-f: file size (blocks) unlimited
-d: data seg size (kbytes) unlimited
-s: stack size (kbytes) unlimited
-c: core file size (blocks) 0
-m: resident set size (kbytes) unlimited
-u: processes 515250
-n: file descriptors 1024
-l: locked-in-memory size (kbytes) 64
-v: address space (kbytes) unlimited
-x: file locks unlimited
-i: pending signals 515250
-q: bytes in POSIX msg queues 819200
-e: max nice 0
-r: max rt priority 0
-N 15: unlimited
11766 次点击
所在节点    Linux
43 条回复
wayslog
2016-10-09 11:50:34 +08:00
那个……老兄……你开了多少线程……没记错的话,每个线程默认会分配 8M 的空间。而且,线程过多其实并不是一件好事儿, IO bound 的话考虑开核心数量的 2x 到 4x , CPU bound 的话干脆开 1x 就行……
ryd994
2016-10-09 12:20:35 +08:00
虚拟内存不一定占用物理内存,不说 swap , mmap 也是计入的。
不过如果是内存不足的话应该会 oom 异常。 segfault 建议还是先查内存 bug ,上 valgrind
有可能是多线程有 bug 啊,特别是竞态导致超预期数据
algas
2016-10-09 12:43:13 +08:00
@wayslog
40 线程, cpu 是 12 物理核心,两路服务器,应该没有超开的。
退出前会开启 20 到 30 多个线程。
algas
2016-10-09 12:49:47 +08:00
@ryd994
感觉上更像是 stack 之类的爆了,说实话我对这个不太了解,但是我已经完全手动申请释放内存了。
异常退出的部分没有申请内存,多线程部分只是计算不同序列的平均值之类的东西,读写都是不同位置的内存。
这个程序是同样使用 40 线程计算小一点的系统是完全正常的,不像存在内存泻露的样子。

另外就是,小规模情况下没有问题,出现问题的计算规模都要占用一半以上的物理内存, valgrind 是不是没有办法对付这种情况?
ryd994
2016-10-09 13:04:31 +08:00
@algas 估计会很慢
能不能用更少线程计算大问题呢?
试试至少跑一下,有些内存错误小规模可能神不知鬼不觉没有爆发,但 valgrind 查非法访问一看就知道了
icylord
2016-10-09 13:13:33 +08:00
排除代码 bug 了嘛
reus
2016-10-09 13:27:51 +08:00
用 rust 写就没有 segfault 了,理论上
wayslog
2016-10-09 13:37:26 +08:00
@reus 你试试 let mut v = [1u8; 1024*1024*1024*4+1];
wayslog
2016-10-09 13:38:55 +08:00
@reus 我们不排除 segfault ,该爆栈还是要爆,但是 rust 的极小 runtime 会拦截这些 segfault ,改成 panic ,能更好的 debug 。

另外上一个提问的安全解答是: let mut v = box [1u8; 1024*1024*1024*4+1];
algas
2016-10-09 14:03:58 +08:00
@ryd994
我尝试一下。


@icylord
之前都已经在用来出结果了,最近找了个配置很好的机器,才发现这种问题。


编译参数:
g++ -O3 -fopenmp -mavx -mfma -fPIC --share -g -I ./ testa.cpp -o libtesta.so

gcc basic/*.c *.c -O3 -DSFMT_MEXP=19937 -lpthread -lm -Wall -fopenmp -mavx -mfma -L ./ -ltesta -Wl,-rpath=.

C 和 C++混编,但是程序还没有进入到 c++的库就退出了。
xiaozhaoz
2016-10-09 14:06:19 +08:00
确认系统 /proc/sys/vm/overcommit_* 设置。

overcommit* 控制了进程占用虚拟空间 和 系统物理内存的关系。
xiaozhaoz
2016-10-09 14:09:26 +08:00
cat /proc/meminfo , 贴出来看看
algas
2016-10-09 14:09:53 +08:00
@xiaozhaoz

这 overcommnit_*文件如下,这个完全不明白是什么意思。

[14:08]:ls /proc/sys/vm/overcommit_*
/proc/sys/vm/overcommit_kbytes /proc/sys/vm/overcommit_memory /proc/sys/vm/overcommit_ratio

cat /proc/sys/vm/overcommit_*
0
0
50
algas
2016-10-09 14:10:46 +08:00
@xiaozhaoz

[14:10]:cat /proc/meminfo
MemTotal: 131915360 kB
MemFree: 131296756 kB
MemAvailable: 131385392 kB
Buffers: 20536 kB
Cached: 173024 kB
SwapCached: 0 kB
Active: 151716 kB
Inactive: 104916 kB
Active(anon): 63772 kB
Inactive(anon): 2520 kB
Active(file): 87944 kB
Inactive(file): 102396 kB
Unevictable: 68 kB
Mlocked: 68 kB
SwapTotal: 0 kB
SwapFree: 0 kB
Dirty: 0 kB
Writeback: 0 kB
AnonPages: 63200 kB
Mapped: 53380 kB
Shmem: 3200 kB
Slab: 72120 kB
SReclaimable: 26112 kB
SUnreclaim: 46008 kB
KernelStack: 10416 kB
PageTables: 5484 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 65957680 kB
Committed_AS: 151684 kB
VmallocTotal: 34359738367 kB
VmallocUsed: 499908 kB
VmallocChunk: 34291843068 kB
HardwareCorrupted: 0 kB
AnonHugePages: 10240 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
DirectMap4k: 891976 kB
DirectMap2M: 103849984 kB
DirectMap1G: 31457280 kB
xiaozhaoz
2016-10-09 14:19:46 +08:00
CommitLimit: 65957680 kB
Committed_AS: 151684 kB

单一进程,最多只允许 malloc() 66G 虚拟内存, 超过就会 malloc 失败。

echo 1 > /proc/sys/vm/overcommit_memory

再试试看。
ryd994
2016-10-09 14:20:47 +08:00
@xiaozhaoz 楼主说的 vsz 和你说的虚拟内存根本不是一个东西, windows 下的虚拟内存, Linux 下叫 swap

@algas 我又查了一下,你这应就是 bug 导致的访问错误
如果 oom 的话, kernal log 里会有记录,比如: http://askubuntu.com/questions/399458/out-of-memory-when-booting-ubuntu-or-any-linux-distro-from-live-usb
alqaz
2016-10-09 14:29:40 +08:00
是不是应该还是程序有 bug, 既然跑大一点计算才出问题,可不可能是只有这种情况下某些代码才会执行,然后触发了某个 bug?
xiaozhaoz
2016-10-09 14:35:27 +08:00
@ryd994
如果楼主是 ps 命令看到的 VSZ , 那就是虚拟内存。
VSZ virtual memory size of the process in KiB (1024-byte units). Device mappings are currently excluded

楼主确实没说清楚。
如果整个系统只占用 80G RSS ,一般不会 OOM ,但内存 zone 情况不好说。
所以 dmesg 或者 /var/下面的 log 看一眼才能确定。
xiaozhaoz
2016-10-09 14:37:10 +08:00
楼主的 overcommit_memory 设置是 0 , 所以该程序的虚拟内存 overcommit limit 是动态计算的, 不是 66G 。
如果 overcommit_memory == 2, 超过 66G 会立即异常。
xiaozhaoz
2016-10-09 14:40:04 +08:00
@ryd994 通过楼主提供的信息,收到是 signal 11 。 所以初步认为是 overcommit , 而不是 oom , oom 是 signal 9.

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/311331

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX