我收到了名义上的错误:
mcfork(): Unable to fork: Cannot allocate memory
在尝试使用 mcapply 运行函数后,但top
说我在 51%
这是在 EC2 实例上,但我确实有最新的 R。
有谁知道还有什么可能导致此错误?
谢谢,
-N
我收到了名义上的错误:
mcfork(): Unable to fork: Cannot allocate memory
在尝试使用 mcapply 运行函数后,但top
说我在 51%
这是在 EC2 实例上,但我确实有最新的 R。
有谁知道还有什么可能导致此错误?
谢谢,
-N
问题可能正是错误消息所暗示的:没有足够的内存来分叉和创建并行进程。
R 本质上需要为每个单独的进程创建内存中所有内容的副本(据我所知,它不使用共享内存)。如果您已经在单个进程中使用了 51% 的 RAM,那么您没有足够的内存来创建第二个进程,因为这总共需要 102% 的 RAM。
尝试:
registerDoMC(2)
。例如,将并行线程数设置为 2(如果您使用的是doMC
并行后端)。rm(my_big_object)
)R 函数mcfork
只是系统调用的一个包装器fork
(顺便说一句,手册页说,这个调用本身就是一个包装器clone
)
我创建了一个简单的 C++ 程序来测试fork
的行为:
#include <stdio.h>
#include <unistd.h>
#include<vector>
int main(int argc, char **argv)
{
printf("--beginning of program\n");
std::vector<std::vector<int> > l(50000, std::vector<int>(50000, 0));
// while (true) {}
int counter = 0;
pid_t pid = fork();
pid = fork();
pid = fork();
if (pid == 0)
{
// child process
int i = 0;
for (; i < 5; ++i)
{
printf("child process: counter=%d\n", ++counter);
}
}
else if (pid > 0)
{
// parent process
int j = 0;
for (; j < 5; ++j)
{
printf("parent process: counter=%d\n", ++counter);
}
}
else
{
// fork failed
printf("fork() failed!\n");
return 1;
}
printf("--end of program--\n");
while (true) {}
return 0;
}
首先,程序在堆上分配了大约 8GB 的数据。然后,它通过 fork 调用产生 2^2^2 = 8 个孩子并等待被用户杀死,然后进入无限循环以便在任务管理器上轻松发现。
以下是我的观察:
/proc/sys/vm/overcommit_*
proc 文件来更改它。内存碎片问题
您不应该担心与 fork 相关的任何内存碎片层。R 的内存碎片在这里不适用,因为 fork 是在虚拟内存上操作的。您不必担心物理内存的碎片,因为几乎所有现代操作系统都使用虚拟内存(因此它们可以使用交换)。唯一可能存在问题的内存碎片是虚拟内存空间的碎片,但 Linux 虚拟内存空间上的 AFAIK 是 2^47,这非常大,几十年来,您在寻找连续的区域时应该没有任何问题任何实用尺寸。
确保你有比物理内存更多的交换空间,只要你的计算实际上不需要比 RAM 更多的内存,你就可以mcfork
随心所欲地使用它们。
或者,如果您愿意冒整个系统的稳定性(内存不足)的风险,请echo 1 >/proc/sys/vm/overcommit_memory
在 linux 上以 root 身份尝试。
或者更好:(更安全)
echo 2 >/proc/sys/vm/overcommit_memory
echo 100 >/proc/sys/vm/overcommit_ratio
您可以在此处阅读有关过度使用的更多信息:https ://www.win.tue.nl/~aeb/linux/lk/lk-9.html
给那些想要使用 RStudio 等 GUI 的人的注意事项。
如果您想利用并行处理,建议不要使用 GUI,因为这会中断您的代码和 GUI 程序之间的多线程进程。registerDoMC
以下是R 包帮助手册的摘录:
最初由 Simon Urbanek 编写并包含在 R 2.14.0 中的并行包中的多核功能提供了用于在具有多个内核或处理器的机器上并行执行 R 代码的功能,使用系统 fork 调用来生成当前进程的副本。
多核功能,因此 registerDoMC,不应该在 GUI 环境中使用,因为多个进程共享同一个 GUI。
registerDoMC(cores = n)
我通过在使用 RStudio 运行我的程序时禁用来解决了 OP 遇到的类似错误。多处理最适合使用基础 R。希望这会有所帮助。
我有同样的错误,同时使用插入符号在具有 64 GB 内存的系统上训练 rpart 模型,在 7 核机器上使用 6 核进行并行处理。换成5核,问题就出来了。
library(doMC)
registerDoMC(5)
我现在遇到了类似的问题。我不会声称知道正确答案。上述两个答案都提出了可能有效的行动方案,特别是如果您的分叉同时对内存产生额外的写入需求。但是,我一直在想,其他可能是困难的根源。内存碎片。有关以下内容的讨论,请参阅https://raspberrypi.stackexchange.com/questions/7856/log-says-i-cant-allocate-memory-but-i-have-more-than-half-of-my-memory-free类似 Unix 的用户看到可用内存但由于内存碎片而遇到内存不足错误的情况。这似乎是 R 的罪魁祸首,尤其是因为 R 喜欢连续的 RAM 块。也每?Memory-limits
要求应该是关于地址空间而不是 RAM 本身 - 所以这可能是不正确的(尤其是在 64 位机器上)YMMV。