【发布时间】:2015-05-11 16:40:30
【问题描述】:
我有一台运行 Linux (3.19.5-200.fc21.x86_64) 的 128 GB RAM 的计算机。但是,我不能在单个进程中分配超过 ~30 GB 的 RAM。除此之外,malloc 失败:
#include <stdlib.h>
#include <iostream>
int main()
{
size_t gb_in_bytes = size_t(1)<<size_t(30); // 1 GB in bytes (2^30).
// try to allocate 1 block of 'i' GB.
for (size_t i = 25; i < 35; ++ i) {
size_t n = i * gb_in_bytes;
void *p = ::malloc(n);
std::cout << "allocation of 1 x " << (n/double(gb_in_bytes)) << " GB of data. Ok? " << ((p==0)? "nope" : "yes") << std::endl;
::free(p);
}
}
这会产生以下输出:
/tmp> c++ mem_alloc.cpp && a.out
allocation of 1 x 25 GB of data. Ok? yes
allocation of 1 x 26 GB of data. Ok? yes
allocation of 1 x 27 GB of data. Ok? yes
allocation of 1 x 28 GB of data. Ok? yes
allocation of 1 x 29 GB of data. Ok? yes
allocation of 1 x 30 GB of data. Ok? yes
allocation of 1 x 31 GB of data. Ok? nope
allocation of 1 x 32 GB of data. Ok? nope
allocation of 1 x 33 GB of data. Ok? nope
allocation of 1 x 34 GB of data. Ok? nope
找了半天,发现这和最大虚拟内存大小有关:
~> ulimit -all
[...]
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
virtual memory (kbytes, -v) 32505856
[...]
我可以通过ulimit -v 64000000 将此限制增加到 ~64 GB,但不能进一步。除此之外,我收到operation not permitted 错误:
~> ulimit -v 64000000
~> ulimit -v 65000000
bash: ulimit: virtual memory: cannot modify limit: Operation not permitted
~> ulimit -v unlimited
bash: ulimit: virtual memory: cannot modify limit: Operation not permitted
更多搜索表明,原则上应该可以通过/etc/security/limits.conf 中的“as”(地址空间)条目设置这些限制。但是,通过这样做,我只能减少最大虚拟内存量,而不能增加它。
有没有办法完全解除每个进程的虚拟内存限制,或者将其增加到 64 GB 以上?我想在单个应用程序中使用所有物理内存。
编辑:
跟随 Ingo Leonhardt,我在以 root 而非标准用户身份登录后尝试了
ulimits -v unlimited。这样做可以解决 root 的问题(程序可以在以 root 身份登录时分配所有物理内存)。但这仅适用于root,不适用于其他用户。但是,至少这意味着原则上内核可以很好地处理这个问题,并且只是配置问题。-
关于
limits.conf:我尝试明确添加- 硬如无限制
- 软如无限
到
/etc/security/limits.conf,然后重新启动。这没有效果。以标准用户身份登录后,ulimit -v仍然返回大约 32 GB,ulimit -v 65000000仍然显示permission denied(而ulimit -v 64000000有效)。limits.conf的其余部分被注释掉,而在/etc/security/limits.d中只有一个其他不相关的条目(对于非 root 用户,将nproc限制为 4096)。也就是说,虚拟内存限制必须来自limits.conf以外的其他地方。任何想法还有什么可能导致ulimits -v不是“无限”的?
编辑/解决方案:
这是我自己的愚蠢造成的。我的用户设置中有一个(早已被遗忘的)程序,它使用
setrlimit来限制每个进程的内存量,以防止 Linux 死机。它无意中从 32 GB 机器复制到 128 GB 机器。感谢 Paul 和 Andrew Janke 以及其他所有人帮助追踪它。对不起大家:/。如果其他人遇到这种情况:在 bash 和配置文件设置中搜索
ulimit/setrlimit,以及可能调用这些设置的程序(包括您自己的和系统范围的 /etc 设置)并确保/security/limits.conf确实如此不包括这个限制...(或者至少尝试创建一个新用户,看看这是否发生在您的用户或系统设置中)
【问题讨论】:
-
如果有人想在没有 128GB 内存机器的情况下玩这个,在 Amazon EC2 上,
r3.4xlarge有 122GB。不过零售价为 1.30 美元/小时,尚未查看现货市场。 -
我认为 C 没有
std::cout... -
尝试以 root 身份调用
ulimit。至少ulimit -v 65000000和ulimit -v unlimited都应该成功 -
@cgk 当你这样做时,你是重新启动还是只注销/登录?
ulimit -v在启动时自动在/etc/rc.local中运行(不是由您手动运行)是什么?您可以以 root 身份将ulimit -v >/tmp/ulimit.out编辑为/etc/rc.local以通过查看将创建的/tmp/ulimit.out文件来找出这一点。这是尝试查看它是否在初始化时设置并逐渐下降,或者是否在您登录时设置。