Domanda

Background: sto scrivendo un programma C ++ che lavora con grandi quantità di geodati e desidero caricare grossi blocchi da elaborare in una sola volta. Sono costretto a lavorare con un'app compilata per macchine a 32 bit. La macchina su cui sto testando sta eseguendo un sistema operativo a 64 bit (Windows 7) e ha 6 gig di ram. Utilizzando MS VS 2008.

Ho il seguente codice:

byte* pTempBuffer2[3];
try
{
    //size_t nBufSize = nBandBytes*m_nBandCount;
    pTempBuffer2[0] = new byte[nBandBytes];
    pTempBuffer2[1] = new byte[nBandBytes];
    pTempBuffer2[2] = new byte[nBandBytes];
}
catch (std::bad_alloc)
{
    // If we didn't get the memory just don't buffer and we will get data one
    // piece at a time.
    return;
}

Speravo di poter allocare memoria fino a quando l'app non raggiungesse il limite di 4 gigabyte di indirizzamento a 32 bit. Tuttavia, quando nBandBytes è 466.560.000, il nuovo genera std :: bad_alloc al secondo tentativo. A questo punto, il valore del set di lavoro (memoria) per il processo è 665.232 K Quindi, non mi sembra di essere in grado di ottenere nemmeno un concerto di memoria allocato.

È stato menzionato un limite di 2 gig per le applicazioni in Windows a 32 bit che può essere esteso a 3 gig con l'opzione / 3GB per win32. Questo è un buon consiglio in quell'ambiente, ma non è rilevante in questo caso.

Quanta memoria dovresti essere in grado di allocare sotto il sistema operativo a 64 bit con un'applicazione a 32 bit?

È stato utile?

Soluzione

Tanto quanto il sistema operativo vuole darti. Per impostazione predefinita, Windows consente a un processo a 32 bit di disporre di 2 GB di spazio indirizzo. E questo è diviso in diversi pezzi. Un'area è riservata allo stack, altre per ogni eseguibile e dll caricate. Qualunque cosa rimanga può essere allocata dinamicamente, ma non c'è garanzia che sarà un grosso pezzo contiguo. Potrebbero essere diversi blocchi più piccoli di un paio di centinaia di MB ciascuno.

Se esegui la compilazione con il flag LargeAddressAware, Windows a 64 bit ti consentirà di utilizzare l'intero spazio degli indirizzi da 4 GB, il che dovrebbe aiutare un po ', ma in generale,

  • non dovresti supporre che la memoria disponibile sia contigua. Dovresti essere in grado di lavorare con più allocazioni più piccole anziché alcune grandi e
  • Dovresti compilarlo come un'applicazione a 64 bit se hai bisogno di molta memoria.

Altri suggerimenti

su Windows a 32 bit, il normale processo può richiedere al massimo 2 GB, ma con / 3GB passa a 3 GB (per Windows 2003).

ma nel tuo caso penso che stia allocando memoria contigua e quindi si è verificata l'eccezione.

Puoi allocare tutta la memoria che ti consentirà il tuo file di paging - anche senza l'opzione / 3GB, puoi allocare 4GB di memoria senza troppe difficoltà.

Leggi questo articolo per una buona panoramica di come pensare alla memoria fisica, alla memoria virtuale e allo spazio degli indirizzi (tutte e tre sono cose diverse). In poche parole, hai esattamente la stessa quantità di memoria fisica che hai RAM, ma la tua app non ha alcuna interazione con quella memoria fisica - è solo un posto conveniente per archiviare i dati nella tua memoria virtuale. La tua memoria virtuale è limitata dalle dimensioni del tuo file di paging e la quantità che la tua app può usare è limitata da quante altre app stanno usando (anche se puoi allocarne di più, purché tu non lo usi effettivamente). Lo spazio degli indirizzi nel mondo a 32 bit è di 4 GB. Di questi, 2 GB sono assegnati al kernel (o 1 GB se si utilizza l'opzione / 3BG). Dei 2 GB rimasti, alcuni saranno utilizzati dal tuo stack, altri dal programma che stai attualmente eseguendo (e da tutte le DLL, ecc.). Verrà frammentato e sarai in grado di ottenere così tanto spazio contiguo: è qui che l'allocazione non riesce. Ma poiché quello spazio degli indirizzi è solo un modo conveniente per accedere alla memoria virtuale che hai allocato per te, è possibile allocare molta più memoria e portarne alcuni pezzi nello spazio degli indirizzi un po 'alla volta.

Raymond Chen ha un esempio di come per allocare 4 GB di memoria e mapparne parte in una sezione del tuo spazio di indirizzi.

In Windows a 32 bit, il massimo allocabile è di 16 TB e 256 TB in Windows a 64 bit.

E se ti piace davvero come funziona la gestione della memoria in Windows, leggi questo articolo .

Durante il progetto ElephantsDream la Blender Foundation con Blender 3D ha avuto problemi simili (anche se su Mac). Non è possibile includere il collegamento ma google: problema di allocazione della memoria di blender3d e sarà il primo elemento.

La soluzione prevedeva la mappatura dei file. Non l'ho provato da solo ma puoi leggerlo qui: http://msdn.microsoft.com/en-us/library/aa366556 (VS.85) aspx

Con nBandBytes a 466.560.000, si sta tentando di allocare 1,4 GB. Un'app a 32 bit in genere ha accesso solo a 2 GB di memoria (di più se si avvia con / 3 GB e l'eseguibile è contrassegnato come spazio indirizzi esteso). Potresti avere difficoltà a trovare tanti blocchi di spazio di indirizzi contigui per i tuoi grossi blocchi di memoria.

Se si desidera allocare gigabyte di memoria su un sistema operativo a 64 bit, utilizzare un processo a 64 bit.

Dovresti essere in grado di allocare un totale di circa 2 GB per processo. Questo articolo (PDF) spiega i dettagli. Tuttavia, probabilmente non sarai in grado di ottenere un singolo blocco contiguo che è anche vicino a quello di grandi dimensioni.

Anche se si allocano in blocchi più piccoli, non è possibile ottenere la memoria necessaria, soprattutto se il programma circostante ha un comportamento imprevedibile della memoria o se è necessario eseguire su sistemi operativi diversi. Nella mia esperienza, lo spazio heap su un processo a 32 bit si limita a circa 1,2 GB.

A questa quantità di memoria, consiglierei di scrivere manualmente su disco. Avvolgere le matrici in una classe che gestisca la memoria e scriva su file temporanei quando necessario. Speriamo che le caratteristiche del tuo programma siano tali da poter effettivamente memorizzare nella cache parti di quei dati senza colpire troppo il disco.

Sysinternals VMMap è ottimo per studiare la frammentazione dello spazio degli indirizzi virtuali, che probabilmente sta limitando la quantità di memoria contigua che è possibile allocare. Consiglio di impostarlo per visualizzare lo spazio libero, quindi di ordinare per dimensione per trovare le aree libere più grandi, quindi di ordinare per indirizzo per vedere cosa sta separando le aree libere più grandi (probabilmente DLL riformulate, aree di memoria condivise o altri heap).

Evitare allocazioni contigue estremamente grandi è probabilmente la cosa migliore, come altri hanno suggerito.

L'impostazione di LARGE_ADDRESS_AWARE = ??YES (come suggerito da jalf) è buona, purché le librerie da cui dipende l'applicazione siano compatibili. Se lo fai, dovresti testare il tuo codice con < codice> AllocationPreference impostato per abilitare l'allocazione dell'indirizzo virtuale dall'alto verso il basso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top