2011-07-30 35 views
15

Sto scrivendo un algoritmo per eseguire alcuni calcoli di memoria esterna, vale a dire dove i dati di input non si adattano alla memoria principale e si deve considerare la complessità dell'I/O.Limitare la memoria fisica per processo

Poiché per i miei test non sempre voglio utilizzare gli ingressi reali Voglio limitare la quantità di memoria disponibile al mio processo. Quello che ho trovato è, che io possa impostare il parametro mem kernel per limitare la memoria fisica utilizzata di tutti i processi (è corretto?)

C'è un modo di fare lo stesso, ma con un per limite di processo . Ho visto ulimit, ma limita solo la memoria virtuale per processo. Qualche idea (forse posso anche programmarla dal mio codice C++)?

+0

Stai facendo affidamento sulla memoria virtuale e sul paging del linux per caricare i dati rilevanti in memoria, o hai intenzione di caricare manualmente i dati da soli nei buffer? –

+0

Io uso la memoria virtuale + il paging di linux (più una libreria chiamata stxxl per alcune strutture di dati di memoria esterna, ma posso già controllare l'utilizzo di memoria di quelli) – dcn

+1

Aggiunto il tag linux-kernel perché probabilmente devi parlare direttamente con il kernel per questo e i ragazzi del kernel sono i più propensi a saperlo. –

risposta

11

Puoi provare con "cgroups". Per usarli, digitare i seguenti comandi, come 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 

Dove si trova il PID del processo che si desidera aggiungere al cgroup. Si noti che il limite si applica alla somma di tutti i processi assegnati a questo cgroup.

Da questo momento in poi, i processi sono limitati a 10 MB di memoria fisica e 12 MB di pysical + swap.

Ci sono altri parametri sintonizzabili in quella directory, ma l'elenco esatto dipenderà dalla versione del kernel che si sta utilizzando.

È anche possibile creare gerarchie di limiti, creando semplicemente sottodirectory.

Il cgroup viene ereditato quando si esegue fork/exec, quindi se si aggiunge la shell da cui il programma viene avviato in un cgroup verrà assegnato automaticamente.

Nota che puoi montare i cgroup in qualunque directory tu voglia, non solo/dev/cgroups.

+0

I dovrebbe essere in grado di verificare che le limitazioni siano soddisfatte utilizzando '/ proc//status' e la voce' VmHWM', giusto? – dcn

+0

Non sono sicuro che sia così semplice. Confrontando/proc//status con cgroups/*/memory.usage_in_bytes sono leggermente diversi. Forse correlato alla memoria condivisa o alla memoria virtuale o fisica ... Penso che i cgroup limitino solo la nuova memoria richiesta dal processo, ma la memoria condivisa che esisteva prima che il processo venisse aggiunto al cgroup non è tenuta in conto. Vedi i documenti [qui] (http://www.kernel.org/doc/Documentation/cgroups/memory.txt). – rodrigo

+0

Accettare questa risposta: cgroup ha funzionato per me. '-omemory' è un errore di battitura (senza spazio)? Ad ogni modo ho trovato più comodo impostare di conseguenza il cgconfig e avviare il mio processo direttamente in un cgroup (cgexec), come qui ad esempio http://jlebar.com/2011/6/15/Limiting_the_amount_of_RAM_a_program_can_use.html – dcn

5

Non riesco a fornire una risposta diretta, ma riguardo a fare cose del genere, di solito scrivo il mio sistema di gestione della memoria in modo da poter avere il pieno controllo dell'area di memoria e di quanto alloco. Questo è solitamente appliacbile anche quando scrivi per microcontrollori. Spero che sia d'aiuto.

+1

+1 per il semplice approccio di tenere traccia del proprio utilizzo della memoria. –

5

Vorrei utilizzare il setrlimti con il parametro RLIMIT_AS per impostare il limite della memoria virtuale (questo è ciò che ulimit fa) e quindi utilizzare il processo mlockall (MCL_CURRENT | MCL_FUTURE) per forzare il kernel a fare il fault e bloccarlo in fisico RAM tutte le pagine di processo, quindi la quantità virtuale == quantità di memoria fisica per questo processo

+0

'mlockall' è davvero problematico. Tranne il fatto che in alcuni casi si vuole davvero limitare la memoria fisica e godere dello scambio (ad esempio, l'applicazione desktop), alcuni linguaggi di programmazione (ad esempio, golang o java) allocano una quantità enorme di spazio virtuale con mmap + PROTO_ANON, quindi non posso usarli E anche se usi C++, non sarai in grado di usare cose come Asan. –

+0

(appena noto che conosco davvero il ragazzo che ha dato la risposta, piccolo mondo ...) –

1

Il parametro di avvio del kernel mem= limita la quantità di memoria utilizzata dal sistema operativo.

Questo è quasi mai ciò che l'utente desidera.

Per la memoria fisica, c'è RSS rlimit aka RLIMIT_AS.

+0

Intendi RLIMIT_RSS? – dcn

+1

Il doc dice di RLIMIT_RSS "Questo limite ha effetto solo in Linux 2.4.x, x <30" ... – dcn

+1

Ugh, in realtà per processo di rlimit per memoria fisica si chiama "memoria cgroup", altrimenti più o meno nulla è garantito. http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=Documentation/cgroups/memory.txt;h=6f3c598971fc3ef05d2ebfb0e6e8879b3047d839;hb=HEAD – adobriyan

2

hai considerato di provare il tuo codice in una sorta di ambiente virtuale? Una macchina virtuale potrebbe essere troppo per le tue esigenze, ma qualcosa come User-Mode Linux potrebbe essere una buona misura. Questo esegue un kernel Linux come un singolo processo all'interno del tuo normale sistema operativo. Quindi è possibile fornire un'impostazione del kernel mem= separata, nonché uno spazio di swap separato per effettuare esperimenti controllati.

1

Come già indicato da altri poster, setrlimit è la soluzione più probabile, controlla i limiti di tutti gli aspetti configurabili di un ambiente di processo. Utilizzare questo comando per vedere queste singole impostazioni del processo shell:

ulimit -a 

Quelli più pertinenti per lo scenario in output risultante sono le seguenti:

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

Checkout la pagina di manuale per setrlimit (" man setrlimit "), può essere invocato in modo programmatico dal codice C/C++. L'ho usato con buoni risultati in passato per controllare i limiti della dimensione dello stack. (btw, non esiste una pagina man dedicata per ulimit, è in realtà un comando bash incorporato, quindi è nella pagina man bash.)

Problemi correlati