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
11768 次点击
所在节点    Linux
43 条回复
ryd994
2016-10-09 14:43:47 +08:00
@xiaozhaoz 所以我还是倾向于程序有 bug 然后非法访问
WKPlus
2016-10-09 14:47:51 +08:00
CommitLimit 只有在 overcommit_memory 是 2 的时候才生效啊,现在 overcommit_memory 是 0 , CommitLimit 是多少没关系。
可以 dmesg 看下有没有 OOM ,我觉得还是程序本身有问题的可能性比较大。
xiaozhaoz
2016-10-09 14:50:45 +08:00
@WKPlus

The Linux kernel supports the following overcommit handling modes

0 - Heuristic overcommit handling. Obvious overcommits of
address space are refused. Used for a typical system. It
ensures a seriously wild allocation fails while allowing
overcommit to reduce swap usage. root is allowed to
allocate slightly more memory in this mode. This is the
default.

1 - Always overcommit. Appropriate for some scientific
applications. Classic example is code using sparse arrays
and just relying on the virtual memory consisting almost
entirely of zero pages.

2 - Don't overcommit. The total address space commit
for the system is not permitted to exceed swap + a
configurable amount (default is 50%) of physical RAM.
Depending on the amount you use, in most situations
this means a process will not be killed while accessing
pages but will receive errors on memory allocation as
appropriate.

Useful for applications that want to guarantee their
memory allocations will be available in the future
without having to initialize every page.
WKPlus
2016-10-09 14:55:24 +08:00
@xiaozhaoz 你贴这段话什么意思呢?
xiaozhaoz
2016-10-09 14:59:19 +08:00
@WKPlus ,

overcommit 的意思是是否允许过量使用虚存。

所以
0 是不予许,也就是超过一定的虚存会分配失败,但是一个复杂的算法计算上限。
1 是允许, 也就是虚存可以一直分配下去,知道进程的地址空间,或者 oom 发生。
2 是老模式, 就是 ( 50% * 物理内存) + swap 计算虚存使用上限。
WKPlus
2016-10-09 15:04:06 +08:00
@xiaozhaoz 那么我说的 “ CommitLimit 只有在 overcommit_memory 是 2 的时候才生效啊,现在 overcommit_memory 是 0 , CommitLimit 是多少没关系” 没错啊。我是问你为啥突然贴那个给我
stephenyin
2016-10-09 17:40:32 +08:00
你这些线程是会频繁启停么? 查查是不是有分支没有 join 或 detach 这些线程!
algas
2016-10-09 21:13:03 +08:00
抱歉一直在外面忙,不在电脑前面


@ryd994
貌似用 2 两个线程也算不了更大的情况,退出前 1s 左右记录到的结果如下, ps aux | grep -i pid
username pid cpu mem vsz rss
username 1991 99.9 57.4 105758172 75775140 pts/0 R+ 14:21 6:58 ./a.out 260 0.5
algas
2016-10-09 21:13:09 +08:00
@xiaozhaoz
虽然我看不太明白你的意思,大概是说程序自身有问题吧?下面是 dmesg 最后一部分的内容,希望有用。
[10523563.169856] a.out[1948]: segfault at 5b9a92500 ip 00000000004034f3 sp 00002b7021521e60 error 6 in a.out[400000+5000]
[10523563.169885] a.out[1947]: segfault at 56530c140 ip 00000000004034f3 sp 00002b7021320e60 error 6 in a.out[400000+5000]
[10523563.170921] a.out[1954]: segfault at ffffffffb47b7b80 ip 00000000004034f3 sp 00002b7022127e60 error 7
[10523563.171253] a.out[1951]: segfault at 6b7125040 ip 00000000004034f3 sp 00002b7021b24e60 error 6
[10523563.171259] in a.out[400000+5000]
[10523563.171267] in a.out[400000+5000]
[10524098.407830] a.out[2857]: segfault at 20e363320 ip 00000000004034f3 sp 00002b84d78a7e60 error 6
[10524098.407838] a.out[2858]: segfault at 27b29cd20 ip 00000000004034f3 sp 00002b84d7aa8e60 error 6
[10524098.407840] in a.out[400000+5000]
[10524098.407849] a.out[2862]: segfault at 42ef83520 ip 00000000004034f3 sp 00002b84d82ace60 error 6

[10524098.407856] a.out[2856]: segfault at 1a1429920 ip 00000000004034f3 sp 00002b84d76a6e60 error 6
[10524098.407859] in a.out[400000+5000]
[10524098.407859] in a.out[400000+5000]


[10524098.407867] a.out[2863]: segfault at 49bebcf20 ip 00000000004034f3 sp 00002b84d84ade60 error 6 in a.out[400000+5000]
[10524098.407876] in a.out[400000+5000]
algas
2016-10-09 21:14:53 +08:00
@stephenyin

不会频繁启动终止,这是一个计算程序,在进入多线程的部分会程序停掉,主线程里是有 join 的。
algas
2016-10-09 21:17:21 +08:00
@xiaozhaoz

[10548380.539504] a.out[29535]: segfault at fffffffd08858920 ip 00000000004034f3 sp 00002bab3bb23e60 error 7 in a.out[400000+5000]

这里面的 error 7 是指 signal=7 吗?
algas
2016-10-09 21:21:05 +08:00
@WKPlus

dmesg 的信息贴到上面的回复了,里面有 error 6 也有 error 7 ,这个看不懂....
xiaozhaoz
2016-10-09 23:08:23 +08:00
error 6,7 指的是用户空间写物理内存异常。不是 signal x

现在可以肯定,是不是 oom

你这个问题好查,每次异常的 eip 都相同,都是 0x4034f3 ,所以反汇编,根据偏移可以推算到代码,才能确切定位是什么问题。
algas
2016-10-10 00:07:41 +08:00
@xiaozhaoz
谢谢你,我应该是找到问题,很低级,但是并不常有机会碰到,我放到 append 里了。
ryd994
2016-10-10 01:53:19 +08:00
@algas 主要是我一般没做过这么大规模的。有 segfault 找 valgrind 是我的习惯反射了。
其次就是, int 是 16 位………
long 是 32
long long 是 64
你这个地方应该用 size_t
size_t 的意思是当前环境用于表示地址范围大小,保证不溢出
ryd994
2016-10-10 01:55:21 +08:00
correlationMatrix
是做计算物理的前辈么?希望能交个朋友
alqaz
2016-10-10 09:36:36 +08:00
N*N*8=18G 多,很好奇这是哪方面使用的程序。
araraloren
2016-10-10 09:53:49 +08:00
@alqaz ~~楼主不是大量计算么,保存中间的计算结果什么的吧,不过一次性申请这么多内存也是醉了。。
algas
2016-10-10 12:10:58 +08:00
@ryd994
基本上就是这个问题, linux C int 和 long int 都是 32 位, long long int 是 64 位。

malloc 的参数是 size_t 类型,其实就是 unsigned ,比 int 多一位可用。
所以 malloc 单次申请内存大小受到 size_t 的位数限制,我这里把 size_t 益出了。

如果需要申请连续的一大块内存,可能要研究以下 mmap 函数。

我是学统计物理的,主要对付 toy model ,和真正计算实际问题的那种计算物理不太一样。
algas
2016-10-10 12:19:32 +08:00
@alqaz
@araraloren

这个是用来保存矩阵的一个数组,是完全填充的。
类似于计算晶格上的振动模式,如果考虑的系统是 200*200 个原子的正方形区域(很小对不对),
关联矩阵就需要 4e4 * 4e4 个元素,基本溢出 int 类型了。

分块计算的倒是可以避免一次申请这么大的内存,但是程序复杂性估计就要上天了 2333

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

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

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

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

© 2021 V2EX