2015-12-31 32 views
7

Considerare un'applicazione MPI basata su due passaggi che chiameremo carico e globalReduce. Giusto per semplicità, il software viene descritto come tale, ma c'è molto di più in corso, quindi non si tratta semplicemente di un problema di Map/Reduce.Riduzione della dimensione heap di un programma C++ dopo un calcolo di grandi dimensioni

Durante il carico passo , tutti i ranghi in ogni dato nodo vengono accodate in modo tale che uno e solo un rango ha pieno accesso a tutti memoria del nodo. Il motivo di questo disegno deriva dal fatto che durante la fase di caricamento è in corso la lettura di un grande insieme di blocchi I/O e devono essere tutti caricati nella memoria prima dello a a livello locale. Chiameremo il risultato di questa riduzione locale una variabile denominata myRankVector. Una volta ottenuta la variabile myRankVector, i blocchi di I/O vengono rilasciati. La variabile myRankVector utilizza poca memoria, quindi mentre durante la sua creazione il nodo può utilizzare tutta la memoria, dopo il completamento il rank deve solo utilizzare 2-3 GB per contenere myRankVector.

Durante il globalReduce fase nel nodo, si prevede tutti i ranghi nel nodo avevano caricato alla corrispondente globalReduce.

Quindi ecco il mio problema, mentre mi sono assicurato che non ci siano perdite di memoria (programma usando i puntatori condivisi, ho controllato due volte con Valgrind, ecc.), Sono certo che l'heap rimane espanso anche dopo tutto i distruttori hanno rilasciato i blocchi di I/O. Quando il prossimo grado della coda viene a fare il suo lavoro, inizia a chiedere molta memoria proprio come faceva il rank precedente e, naturalmente, il programma ottiene il kill di Linux che produce "Out of memory: Kill process xxx (xxxxxxxx) score xxxx o sacrificare bambino ". È chiaro il motivo per cui questo è il caso, il secondo rango nella coda vuole usare tutta la memoria, ma il primo rango rimane con un grande ammasso.

Quindi, dopo aver impostato il contesto di questa domanda: esiste un modo per ridurre manualmente la dimensione dell'heap in C++ per liberare realmente la memoria non utilizzata?

Grazie.

+2

non possono essere utili, ma si potrebbe sborsare/exec un programma bambino a fare il grande calcolo, allora il suo mucchio sarebbe "veramente liberato" quando è uscito. –

+4

Dovremmo vedere il codice. La domanda è: perché il secondo grado non riutilizza la memoria liberata. –

+0

Perché non si dispone di un singolo processo su ciascun nodo che in un ciclo su tutti i ranghi: 1) ottiene il vettore del rango, 2) lancia un thread separato, bloccato su un nucleo diverso, con accesso al vettore del rango? Quindi tutti i principali utilizzi della memoria si trovano nello stesso processo, risolvendo il problema mentre si utilizza ancora il parallelismo. –

risposta

1

Quindi, dopo l'impostazione il contesto di questa domanda: esiste un modo per ridurre manualmente la dimensione dell'heap in C++ per liberare realmente la memoria non utilizzata?

Dipende dal sistema operativo, ma probabilmente non è possibile.

La maggior parte dei sistemi operativi ti lascia con allocazioni di memoria che hai fatto da un singolo processo fino a quando quel processo non è stato completato e ucciso.

1

Gli heap vengono implementati utilizzando mmap su linux e sarà necessario utilizzare il proprio heap, che è possibile disporre e munmap completamente.

Lo munmap libererebbe lo spazio richiesto.

Consultare codice in boost : pool per un'implementazione che consente di gestire gli heap sottostanti in modo indipendente.

In base alla mia esperienza, è molto difficile gestire i contenitori std con gli allocatori personalizzati, in quanto derivano dalla classe, anziché derivare dall'istanza.

0

La memoria condivisa può risolvere il problema (anche se non si desidera condividere questa memoria)? È possibile allocare un blocco di memoria condivisa nella fase di "caricamento" e sganciarlo dopo aver calcolato "myRankVector".

(vedi shmget, shmat, shmdt, shmctl (..., IPC_RMID,.))