r memory amazon-ec2 multicore domc

R multinúcleo mcfork(): No se puede bifurcar: No se puede asignar memoria



memory amazon-ec2 (5)

Estoy recibiendo el error titular:

mcfork(): Unable to fork: Cannot allocate memory

después de intentar ejecutar una función con mcapply, pero top dice que estoy al 51%

Esto está en una instancia de EC2, pero tengo una versión actualizada de R.

¿Alguien sabe qué más puede causar este error?

Gracias,

-NORTE


El problema podría ser exactamente lo que sugiere el mensaje de error: no hay suficiente memoria para dividir y crear procesos paralelos.

Esencialmente, R necesita crear una copia de todo lo que está en la memoria para cada proceso individual (que yo sepa, no utiliza memoria compartida). Si ya está usando el 51% de su RAM con un solo proceso, entonces no tiene suficiente memoria para crear un segundo proceso, ya que eso requeriría el 102% de su RAM en total.

Tratar:

  1. Uso de menos núcleos : si intentas usar 4 núcleos, es posible que tengas suficiente RAM para admitir 3 hilos paralelos, pero no 4. registerDoMC(2) , por ejemplo, establecerá el número de hilos paralelos en 2 (si eres utilizando el backend paralelo doMC ).
  2. Usar menos memoria : sin ver el resto de su código, es difícil sugerir formas de lograrlo. Una cosa que podría ayudar es averiguar qué objetos R están ocupando toda la memoria (¿ Determinar el uso de memoria de los objetos? ) Y luego eliminar cualquier objeto de la memoria que no necesite ( rm(my_big_object) )
  3. Agregando más RAM : si todo lo demás falla, agregue hardware para que tenga más capacidad.
  4. Mantenerse en subprocesamiento único : el procesamiento de subprocesos múltiples en R es una compensación de la CPU y la memoria. Parece que, en este caso, es posible que no tenga suficiente memoria para soportar la potencia de CPU que tiene, por lo que el mejor curso de acción podría ser limitarse a un solo núcleo.

La función R mcfork es solo una envoltura para la fork syscall (Por cierto, la página del manual dice que esta llamada es en sí misma una envoltura para el clone )

Creé un programa simple de C ++ para probar el comportamiento de las 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; }

Primero, el programa asigna aproximadamente 8 GB de datos en el montón. Luego, genera 2 ^ 2 ^ 2 = 8 hijos a través de la llamada a la bifurcación y espera a ser asesinado por el usuario, e ingresa en un bucle infinito para que sea fácil de detectar en el administrador de tareas.

Aquí están mis observaciones:

  1. Para que la bifurcación tenga éxito, necesita tener al menos un 51% de memoria libre en mi sistema, pero esto incluye el intercambio . Puede cambiar esto editando los archivos /proc/sys/vm/overcommit_* proc.
  2. Como se esperaba, ninguno de los niños toma más memoria, por lo que esta memoria libre del 51% permanece libre durante todo el programa, y ​​todas las bifurcaciones posteriores tampoco fallan.
  3. La memoria se comparte entre las bifurcaciones, por lo que se recupera solo después de matar al último hijo.

Problema de fragmentacion de la memoria

No debe preocuparse por ninguna capa de fragmentación de la memoria con respecto a la bifurcación . La fragmentación de la memoria de R no se aplica aquí, porque la bifurcación funciona en la memoria virtual. No debe preocuparse por la fragmentación de la memoria física, ya que prácticamente todos los sistemas operativos modernos usan memoria virtual (lo que, en consecuencia, les permite usar swap). La única fragmentación de memoria que podría ser un problema es una fragmentación del espacio de memoria virtual, pero AFAIK en el espacio de memoria virtual de Linux es 2 ^ 47, lo que es más que enorme, y durante muchas décadas no debería tener ningún problema para encontrar regiones continuas de Cualquier tamaño práctico.

Resumen:

Asegúrese de tener más espacio de intercambio que memoria física, y mientras sus computaciones no necesiten más memoria que la que tiene en la memoria RAM, puede mcfork todo lo que quiera.

O, si está dispuesto a arriesgar la estabilidad (falta de memoria) de todo el sistema, intente echo 1 >/proc/sys/vm/overcommit_memory como root en Linux.

O mejor aún: (más seguro)

echo 2 >/proc/sys/vm/overcommit_memory echo 100 >/proc/sys/vm/overcommit_ratio

Puede leer más sobre el compromiso excesivo aquí: https://www.win.tue.nl/~aeb/linux/lk/lk-9.html


Me estoy encontrando con un problema similar en este momento. No pretendo saber la respuesta correcta. Las dos respuestas anteriores proponen cursos de acción que pueden funcionar, especialmente si sus bifurcaciones crean al mismo tiempo exigencias adicionales de escritura en la memoria. Sin embargo, he estado pensando que otra cosa podría ser la fuente de dificultad, vis. fragmentación de la memoria. Consulte https://raspberrypi.stackexchange.com/questions/7856/log-says-i-cant-allocate-memory-but-i-have-more-than-half-of-my-memory-free para una discusión de un caso en el que un usuario similar a Unix ve memoria libre, pero comete un error de falta de memoria debido a la fragmentación de la memoria. Esto parece ser un probable culpable de R en particular debido al amor de R por los bloques contiguos de RAM. También ?Memory-limits el requisito debe ser sobre el espacio de direcciones en lugar de la RAM, por lo que esto podría ser incorrecto (especialmente en una máquina de 64 bits) YMMV.


Tuve el mismo error, mientras usaba caret para entrenar un modelo rpart en un sistema con 64 GB de memoria, con procesamiento paralelo usando 6 núcleos en una máquina de 7 núcleos. Cambiado a 5 núcleos y el problema corrió.

library(doMC) registerDoMC(5)


Una nota para aquellos que quieren usar GUI como RStudio.
Si desea aprovechar el procesamiento paralelo, se recomienda no utilizar una GUI, ya que esto interrumpe los procesos de multiproceso entre su código y el programa de GUI. Aquí hay un extracto del manual de ayuda del paquete registerDoMC en R:

La funcionalidad multinúcleo, originalmente escrita por Simon Urbanek y incluida en el paquete paralelo en R 2.14.0, proporciona funciones para la ejecución paralela del código R en máquinas con múltiples núcleos o procesadores, utilizando la llamada a la horquilla del sistema para generar copias del proceso actual.

La funcionalidad multinúcleo y, por lo tanto, registerDoMC, no se deben usar en un entorno de GUI, ya que varios procesos comparten la misma GUI.

Resolví un error similar experimentado por el OP deshabilitando registerDoMC(cores = n) cuando ejecutaba mi programa usando RStudio. El multiprocesamiento funciona mejor con la base R. Espero que esto ayude.