2011-07-30 17 views
15

Estoy escribiendo un algoritmo para realizar algunos cálculos de memoria externa, es decir, donde los datos de entrada no encajan en la memoria principal y debe tener en cuenta la complejidad de E/S.Limite la memoria física por proceso

Dado que para mis pruebas no siempre quiero utilizar entradas reales Quiero limitar la cantidad de memoria disponible para mi proceso. Lo que he encontrado es, que pueda establecer el parámetro mem kernel para limitar la memoria usada física de todos los procesos (¿es correcto?)

¿Hay una manera de hacer lo mismo, pero con un límite por proceso . He visto ulimit, pero solo limita la memoria virtual por proceso. Alguna idea (tal vez incluso pueda configurarla programáticamente desde dentro de mi código C++)?

+0

¿Confía en la memoria virtual y en la paginación de Linux para cargar los datos relevantes en la memoria, o ¿planeas cargar los datos manualmente en los buffers? –

+0

uso de memoria virtual + paginación de Linux (además de una biblioteca llamada stxxl para algunas estructuras de datos de memoria externos, pero ya puedo controlar el uso de la memoria de las personas) – dcn

+1

Agregado etiqueta linux-kernel, ya que probablemente necesita hablar con el kernel directamente para este , y los chicos del kernel son los más propensos a saberlo. –

Respuesta

11

Puede probar con 'cgroups'. Para usarlos escriba los siguientes comandos, como root.

# mkdir /dev/cgroups 
# mount -t cgroup -omemory memory /dev/cgroups 
# mkdir /dev/cgroups/test 
# echo 10000000 > /dev/cgroups/test/memory.limit_in_bytes 
# echo 12000000 > /dev/cgroups/test/memory.memsw.limit_in_bytes 
# echo <PID> > /dev/cgroups/test/tasks 

Dónde está el PID del proceso que desea agregar al cgroup. Tenga en cuenta que el límite se aplica a la suma de todos los procesos asignados a este cgroup.

A partir de este momento, los procesos están limitados a 10 MB de memoria física y 12 MB de pysical + swap.

Existen otros parámetros ajustables en ese directorio, pero la lista exacta dependerá de la versión del kernel que esté utilizando.

Incluso puede crear jerarquías de límites, simplemente creando subdirectorios.

El grupo cgroup se hereda cuando fork/exec, por lo que si agrega el shell desde el que se lanza su programa a un grupo cg, se asignará automáticamente.

Tenga en cuenta que puede montar los cgroups en el directorio que desee, no solo en/dev/cgroups.

+0

I debería ser capaz de verificar que las limitaciones se cumplan utilizando '/ proc//status' y la entrada' VmHWM', ¿verdad? – dcn

+0

No estoy seguro de que esto sea tan sencillo. Comparando el/proc//status con cgroups/*/memory.usage_in_bytes son algo diferentes. Tal vez relacionado con la memoria compartida o la memoria virtual vs. física ... Creo que los cgroups limitan solo la nueva memoria solicitada por el proceso, pero la memoria compartida que existía antes de que el proceso se agregue al cgroup no se contabiliza. Vea los documentos [aquí] (http://www.kernel.org/doc/Documentation/cgroups/memory.txt). – rodrigo

+0

Aceptando esta respuesta: cgroups funcionó para mí. ¿'-omemory' es un error tipográfico (sin espacio)? De todos modos, me pareció más cómodo configurar el cgconfig en consecuencia y comenzar mi proceso directamente en un cgroup (cgexec), como aquí, por ejemplo, http://jlebar.com/2011/6/15/Limiting_the_amount_of_RAM_a_program_can_use.html – dcn

5

No puedo proporcionar una respuesta directa pero si se trata de hacer tales cosas, generalmente escribo mi propio sistema de administración de memoria para que pueda tener el control total del área de memoria y cuánto asignar. Esto también suele ser aplicable cuando escribe para microcontroladores. Espero eso ayude.

+1

+1 por el enfoque simple de simplemente hacer un seguimiento de su propio uso de memoria. –

5

Usaría el setrlimti con el parámetro RLIMIT_AS para establecer el límite de la memoria virtual (esto es lo que hace ulimit) y luego usaría el proceso mlockall (MCL_CURRENT | MCL_FUTURE) para forzar al kernel a fallar y bloquear en físico RAM todas las páginas de proceso, de modo que cantidad virtual == cantidad de memoria física para este proceso

+0

'mlockall' es realmente problemático. Excepto por el hecho de que en algunos casos realmente desea limitar la memoria física Y disfrutar el intercambio (por ejemplo, aplicación de escritorio), algunos lenguajes de programación (por ejemplo, golang o java) asignan una gran cantidad de espacio virtual con mmap + PROTO_ANON, por lo que no puedo usarlos E incluso si usa C++, no podrá usar cosas como asan. –

+0

(solo fíjate que realmente conozco al hombre que dio la respuesta, pequeño mundo ...) –

1

Kernel mem= parámetro de arranque limita la cantidad de memoria en el sistema operativo total.

Esto casi nunca es lo que quiere el usuario.

Para la memoria física, existe RSS rlimit aka RLIMIT_AS.

+0

¿Te refieres a RLIMIT_RSS? – dcn

+1

El doc dice acerca RLIMIT_RSS "Este límite solamente tiene efecto en Linux 2.4.x, x <30" ... – dcn

+1

Uf, en realidad por rlimit proceso para la memoria física que se llama "cgroup memoria", de lo contrario, más o menos nada está garantizado. http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=Documentation/cgroups/memory.txt;h=6f3c598971fc3ef05d2ebfb0e6e8879b3047d839;hb=HEAD – adobriyan

2

¿Ha considerado probar su código en algún tipo de entorno virtual? Una máquina virtual puede ser demasiado para sus necesidades, pero algo como User-Mode Linux podría ser una buena opción. Esto ejecuta un kernel de Linux como un proceso único dentro de su sistema operativo regular. Luego puede proporcionar una configuración de kernel mem= por separado, así como un espacio de intercambio separado para realizar experimentos controlados.

1

Como otros carteles ya han indicado, setrlimit es la solución más probable, controla los límites de todos los aspectos configurables de un entorno de proceso. Utilice este comando para ver estos ajustes individuales en su proceso de shell:

ulimit -a 

los más pertinentes a su escenario en los productos resultantes son los siguientes:

data seg size   (kbytes, -d) unlimited 
max locked memory  (kbytes, -l) 64 
max memory size   (kbytes, -m) unlimited 
virtual memory   (kbytes, -v) unlimited 

obtener de la página del manual para setrlimit (" man setrlimit "), puede invocarse programáticamente desde su código C/C++. Lo he usado con buenos resultados en el pasado para controlar los límites de tamaño de pila. (por cierto, no hay una página de manual dedicada para ulimit, en realidad es un comando bash incrustado, por lo que está en la página bash man.)

Cuestiones relacionadas