2013-03-27 1 views
15

Я получаю сообщение об ошибке: титулярногоR многожильного mcfork(): Невозможно вилок: Невозможно выделить память

mcfork(): Unable to fork: Cannot allocate memory 

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

Это на примере EC2, но у меня есть уточненный Р.

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

Благодаря,

-N

+1

R требует последовательных блоков памяти. Вы перезапустили и попытались повторно запустить с минимальными данными? –

+1

Я попытался с другим экземпляром с удвоенной памятью, это решило проблему ... Мне все же хотелось бы понять это лучше, хотя, поэтому я оставлю вопрос открытым. –

ответ

9

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

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

Try:

  1. Использование меньшего количества ядер - Если вы пытаетесь использовать 4 ядра, возможно у вас есть достаточно оперативной памяти для поддержки 3 параллельных потоков, но не 4. registerDoMC(2), например, будет установлен количество параллельных потоков до 2 (если вы используете параллельный бэкэнд doMC).
  2. Использование меньше памяти - не видя остальной части вашего кода, трудно предложить способы этого. Одна вещь, которая может помочь является выяснение того, какие объекты R занимают всю память (Determining memory usage of objects?), а затем удаление любых объектов из памяти, которые вам не нужны (rm(my_big_object))
  3. Добавление больше оперативной памяти - если все остальное терпит неудачу, бросьте оборудование на это, чтобы у вас было больше возможностей.
  4. Взаимодействие с одиночной резьбой - многопоточная обработка в R - это компромисс между процессором и памятью. Похоже, в этом случае у вас может не хватить памяти для поддержки мощности процессора, поэтому лучший способ действий - просто придерживаться одного ядра.
+1

Возможно, я ошибаюсь, но я обнаружил, что вы действительно можете разветвить процесс, который использует 51% вашей памяти без использования 102% вашей оперативной памяти. Это действительно (для моих целей) является частью причины вилки. ОЗУ может использоваться совместно, пока один из процессов не попытается изменить его. – russellpierce

+0

Для получения дополнительной информации см. Http://unix.stackexchange.com/questions/155017/does-fork-immediately-copy-the-entire-process-heap-in-linux. – russellpierce

+0

@Mike. Как и rpierce, я не согласен с вашим утверждением, что fork требует 50% запасной RAM. Достаточно обмена. –

1

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

library(doMC) 
registerDoMC(5) 
1

Я столкнулся с подобной проблемой прямо сейчас. Я не буду утверждать, что знаю правильный ответ. Оба вышеупомянутых ответа предлагают способы действий, которые могут работать, особенно если ваши вилки создают дополнительные требования к записи в память одновременно. Тем не менее, я думал, что что-то еще может быть источником трудности. фрагментация памяти. См. 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 к смежным блокам ОЗУ. Также в ?Memory-limits требование должно быть о адресном пространстве, а не о RAM, поэтому это может быть неверно (например, на 64-битной машине) YMMV.

3

R функция mcfork является лишь оболочкой для системного вызова fork (КСТАТИ, страница человека говорит, что этот вызов сам по себе является оберткой к clone)

Я создал простой C++ программы, чтобы проверить поведение fork «s :

#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 /proc/sys/vm/overcommit_*.
  2. Как и ожидалось, ни один из детей не получает больше памяти, поэтому эта свободная память на 51% остается свободной на протяжении всего курса программы, и все последующие вилки также не терпят неудачу.
  3. Память делится между вилками, поэтому она восстанавливается только после того, как вы убили последнего ребенка.

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

Вы не должны беспокоиться о каком-либо слое фрагментации памяти относительно к вилке. Фрагментация памяти R здесь не применяется, поскольку fork работает в виртуальной памяти. Вы не должны беспокоиться о фрагментации физической памяти, поскольку практически все современные операционные системы используют виртуальную память (что, следовательно, позволяет использовать swap). Единственной фрагментацией памяти, которая может возникнуть, является фрагментация пространства виртуальной памяти, но пространство виртуальной памяти 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 

Вы можете прочитать больше о overcommiting здесь: https://www.win.tue.nl/~aeb/linux/lk/lk-9.html

1

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

The multicore functionality, originally written by Simon Urbanek and subsumed in the parallel package in R 2.14.0, provides functions for parallel execution of R code on machines with multiple cores or processors, using the system fork call to spawn copies of the current process.

The multicore functionality, and therefore registerDoMC, should not be used in a GUI environment, because multiple processes then share the same GUI.

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

+0

Это, вероятно, будет иметь отношение к людям, которые в будущем могут найти вопрос, но исходный Q не указывает использование графического интерфейса. Не могли бы вы добавить первое предложение в строках «если вы используете графический интерфейс, тогда ...»? –

+0

@ N.McA. Благодарю. Сделано обновление. –