R multicore mcfork (): невозможно выполнить вилку: невозможно выделить память

Получаю заглавную ошибку:

mcfork(): Unable to fork: Cannot allocate memory

после попытки запустить функцию с помощью mcapply, но top говорит, что у меня 51%

Это на экземпляре EC2, но у меня есть последняя версия R.

Кто-нибудь знает, что еще может вызвать эту ошибку?

Спасибо,

-N


person N. McA.    schedule 27.03.2013    source источник
comment
R требует непрерывных блоков памяти. Вы перезагружали и пытались запустить заново с минимальным количеством данных?   -  person IRTFM    schedule 28.03.2013
comment
Я пробовал использовать другой экземпляр с удвоенным объемом памяти, это решило проблему ... Я все же хотел бы понять это лучше, поэтому оставлю вопрос открытым.   -  person N. McA.    schedule 28.03.2013


Ответы (5)


Проблема может заключаться в том, что предлагает сообщение об ошибке: недостаточно памяти для создания параллельных процессов.

R, по сути, должен создавать копию всего, что находится в памяти для каждого отдельного процесса (насколько мне известно, он не использует разделяемую память). Если вы уже используете 51% своей оперативной памяти для одного процесса, значит, у вас недостаточно памяти для создания второго процесса, поскольку для этого потребуется 102% вашей оперативной памяти.

Пытаться:

  1. Использование меньшего количества ядер. Если вы пытались использовать 4 ядра, возможно, у вас достаточно ОЗУ для поддержки 3 параллельных потоков, но не 4. Например, registerDoMC(2) установит количество параллельных потоков равным 2. (если вы используете doMC параллельный бэкэнд).
  2. Использование меньшего объема памяти - не видя остальной части кода, трудно предложить способы достижения этой цели. Одна вещь, которая может помочь, - это выяснить, какие объекты R занимают всю память (Определение использования памяти для объекты?), а затем удалите из памяти все ненужные объекты (rm(my_big_object))
  3. Добавление дополнительной оперативной памяти - если ничего не помогает, используйте оборудование, чтобы у вас было больше возможностей.
  4. Приверженность однопоточности - многопоточная обработка в R - это компромисс между процессором и памятью. Похоже, что в этом случае у вас может не хватить памяти для поддержки имеющейся у вас мощности процессора, поэтому лучшим вариантом может быть просто придерживаться одного ядра.
person Mike Monteiro    schedule 23.08.2015
comment
Возможно, я в чем-то ошибаюсь, но я обнаружил, что вы действительно можете разветвить процесс, который использует 51% вашей оперативной памяти, не используя 102% вашей оперативной памяти. Это действительно (для моих целей) является одной из причин для форк, vis. ОЗУ можно использовать совместно до тех пор, пока один из процессов не попытается изменить ее. - person russellpierce; 10.04.2016
comment
См. unix.stackexchange.com/questions/155017/ для получения дополнительных сведений. - person russellpierce; 10.04.2016
comment
@Майк. Как и rpierce, я не согласен с вашим утверждением, что этой вилке требуется 50% свободной оперативной памяти. Достаточно свопа. - person Adam Ryczkowski; 20.05.2016
comment
@ Адам - ​​ага, спасибо за сборку. похоже, что он использует разделяемую память с копированием при записи. Можем ли мы согласиться с тем, что правильным будет утверждение, что ему требуется 51% свободной оперативной памяти + своп для форк? - person Mike Monteiro; 22.05.2016
comment
@MikeMonteiro При установке Ubuntu по умолчанию - да, но это настраиваемое поведение, и это может быть не так для любого другого дистрибутива Linux. См. Мой собственный ответ на этот вопрос (ниже) для получения подробной информации о чрезмерном выделении памяти. - person Adam Ryczkowski; 25.05.2016
comment
Я получил то же сообщение об ошибке, что и OP, и обошел его, используя только одно ядро ​​для запуска моего кода (registerDoParallel (1)). - person RobertF; 17.06.2019

Функция 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;
}

Во-первых, программа выделяет в куче около 8 ГБ данных. Затем он порождает 2 ^ 2 ^ 2 = 8 дочерних элементов через вызов fork и ждет, пока пользователь их не убьет, и входит в бесконечный цикл, чтобы его было легко обнаружить в диспетчере задач.

Вот мои наблюдения:

  1. Для успешного выполнения форка в моей системе должно быть не менее 51% свободной памяти, но это включает в себя своп. Вы можете изменить это, отредактировав /proc/sys/vm/overcommit_* файлы proc.
  2. Как и ожидалось, ни один из дочерних элементов не занимает больше памяти, поэтому эта свободная память 51% остается свободной на протяжении всей программы, и все последующие вилки также не дают сбоев.
  3. Память распределяется между вилками, поэтому она восстанавливается только после того, как вы убили последнего ребенка.

Проблема фрагментации памяти

Вы не должны беспокоиться о каком-либо уровне фрагментации памяти по отношению к fork. Фрагментация памяти R здесь не применяется, потому что fork работает с виртуальной памятью. Вам не следует беспокоиться о фрагментации физической памяти, потому что практически все современные операционные системы используют виртуальную память (что, следовательно, позволяет им использовать подкачку). Единственная фрагментация памяти, которая может быть проблемой, - это фрагментация пространства виртуальной памяти, но AFAIK в пространстве виртуальной памяти Linux составляет 2 ^ 47, что более чем огромно, и в течение многих десятилетий у вас не должно возникнуть проблем с поиском непрерывных областей любой практичный размер.

Резюме:

Убедитесь, что у вас больше подкачки, чем физической памяти, и, пока вашим вычислениям не требуется больше памяти, чем у вас есть в ОЗУ, вы можете mcfork их сколько угодно.

Или, если вы готовы рискнуть стабильностью (нехваткой памяти) всей системы, попробуйте echo 1 >/proc/sys/vm/overcommit_memory как root в Linux.

Или еще лучше: (безопаснее)

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

person Adam Ryczkowski    schedule 20.05.2016

Примечание для тех, кто хочет использовать графический интерфейс, например RStudio.
Если вы хотите воспользоваться преимуществами параллельной обработки, рекомендуется не использовать графический интерфейс, так как это прерывает многопоточные процессы между ваш код и программу с графическим интерфейсом. Вот выдержка из registerDoMC справочного руководства по R:

Многоядерная функциональность, первоначально написанная Саймоном Урбанеком и включенная в параллельный пакет в R 2.14.0, предоставляет функции для параллельного выполнения кода R на машинах с несколькими ядрами или процессорами, используя вызов системной вилки для создания копий текущего процесса.

Функциональность многоядерности и, следовательно, registerDoMC, не следует использовать в среде графического интерфейса пользователя, поскольку в этом случае несколько процессов используют один и тот же графический интерфейс.

Я решил аналогичную ошибку, с которой столкнулся OP, отключив registerDoMC(cores = n) при запуске моей программы с помощью RStudio. Многопроцессорность лучше всего работает с базовым R. Надеюсь, это поможет.

person Ekaba Bisong    schedule 30.11.2016
comment
Это, вероятно, будет актуально для людей, которые найдут вопрос в будущем, но в исходном Q не указывается использование графического интерфейса. Не могли бы вы добавить первое предложение в строке: если вы используете графический интерфейс, то ...? - person N. McA.; 01.12.2016
comment
@ N.McA. Спасибо. Обновление выполнено. - person Ekaba Bisong; 02.12.2016

У меня была такая же ошибка при использовании каретки для обучения модели rpart в системе с 64 ГБ памяти с параллельной обработкой с использованием 6 ядер на 7-ядерной машине. Поменял на 5 ядер, и проблема исчезла.

library(doMC)
registerDoMC(5)
person Community    schedule 31.12.2014

У меня сейчас похожая проблема. Я не буду утверждать, что знаю правильный ответ. Оба приведенных выше ответа предлагают варианты действий, которые могут сработать, особенно если ваши вилки одновременно создают дополнительные требования к записи в памяти. Однако я подумал, что источником трудностей может быть что-то еще, vis. фрагментация памяти. См. https://raspberrypi.stackexchange.com/questions/7856/log-says-i-cant-allocate-memory-but-i-have-more-than-half-of-my-memory-бесплатно для обсуждения случая, когда пользователь в Unix-подобной системе видит свободную память, но сталкивается с ошибкой нехватки памяти из-за фрагментации памяти. Это кажется вероятным виновником R, в частности, из-за любви R к смежным блокам ОЗУ. Также согласно ?Memory-limits требование должно касаться адресного пространства, а не самой оперативной памяти - так что это может быть неверно (особенно на 64-битной машине) YMMV.

person russellpierce    schedule 10.04.2016