R multicore mcfork():无法分叉:无法分配内存

N. *_*cA. 18 memory multicore r amazon-ec2 domc

我得到了名义上的错误:

mcfork(): Unable to fork: Cannot allocate memory
Run Code Online (Sandbox Code Playgroud)

试图用mcapply运行一个函数后,但top我说我是51%

这是在EC2实例上,但我确实有最新的R.

有谁知道还有什么可以导致这个错误?

谢谢,

-N

Mik*_*iro 16

问题可能正是错误消息所暗示的:没有足够的内存来分叉和创建并行进程.

R本质上需要为每个单独的进程创建内存中的所有内容的副本(据我所知,它不使用共享内存).如果您已经在一个进程中使用了51%的RAM,那么您没有足够的内存来创建第二个进程,因为这需要总共102%的RAM.

尝试:

  1. 使用更少的内核 - 如果您尝试使用4个内核,则可能有足够的RAM来支持3个并行线程,但不是4. registerDoMC(2)例如,将并行线程数设置为2(如果使用doMC并行后端) ).
  2. 使用更少的内存 - 没有看到你的其余代码,很难建议实现这一目标的方法.有一点可能有帮助,找出哪些R对象占用了所有内存(确定对象的内存使用情况?),然后从内存中删除不需要的任何对象(rm(my_big_object))
  3. 添加更多RAM - 如果所有其他方法都失败了,请将硬件投入其中,以便获得更多容量.
  4. 坚持单线程--R中的多线程处理是CPU和内存的权衡.听起来在这种情况下你可能没有足够的内存来支持你拥有的CPU能力,所以最好的行动方案可能只是坚持一个核心.


Ada*_*ski 5

R函数mcfork只是系统调用的包装器fork(BtW,手册页说,这个调用本身就是一个包装器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;
}
Run Code Online (Sandbox Code Playgroud)

首先,程序在堆上分配大约8GB的数据.然后,它通过fork调用产生2 ^ 2 ^ 2 = 8个子节点并等待被用户杀死,并进入无限循环以便在任务管理器上找到.

以下是我的观察:

  1. 要使fork成功,您需要在我的系统上至少有51%的可用内存,但这包括交换.您可以通过编辑/proc/sys/vm/overcommit_*proc文件来更改此设置.
  2. 正如预期的那样,没有一个孩子需要更多的内存,所以这51%的可用内存在整个程序过程中仍然是免费的,所有后续的分叉也不会失败.
  3. 内存在分叉之间共享,因此只有在您杀死最后一个孩子后才会回收它.

内存碎片问题

你不应该关心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
Run Code Online (Sandbox Code Playgroud)

您可以在此处阅读有关过度使用的更多信息:https://www.win.tue.nl/~aeb/linux/lk/lk-9.html