6

Disclaimer: Mi scuso per la verbosità di questa domanda (penso che sia un problema interessante, però!), Tuttavia non riesco a capire come per dirlo in modo più conciso.Accesso a file da 2,3,4 GB in processo a 32 bit su Windows a 64 bit (o 32 bit)

ho fatto ore di ricerca per quanto riguarda la apparentemente miriade di modi in cui per risolvere il problema di accesso ai file multi-GB in un processo a 32 bit in 64 bit di Windows 7, che vanno da /LARGEADDRESSAWARE a VirtualAllocEx AWE. Sono un po 'a mio agio nello scrivere un sistema con mappatura multipla della memoria in Windows (CreateFileMapping, MapViewOfFile, ecc.), Ma non riesco a sfuggire alla sensazione che esista una soluzione più elegante a questo problema. Inoltre, sono a conoscenza dei modelli di interprete e di iostream di Boost, anche se sembrano piuttosto leggeri, e richiedono una quantità simile di sforzi per scrivere un sistema che utilizza solo chiamate API di Windows (per non parlare del fatto che ho già una memoria) architettura mappata semi-implementata tramite chiamate API Windows).

Sto tentando di elaborare dataset di grandi dimensioni. Il programma dipende da librerie pre-compilate a 32 bit, motivo per cui, per il momento, il programma stesso è anche in esecuzione in un processo a 32 bit, anche se il sistema è a 64 bit, con un sistema operativo a 64 bit. So che ci sono modi in cui potrei aggiungere librerie di wrapper attorno a questo, eppure, visto che fa parte di una base di codice più ampia, sarebbe davvero un po 'un'impresa. Ho impostato le intestazioni binarie per consentire /LARGEADDRESSAWARE (a scapito della riduzione del mio spazio del kernel?), Tale da ottenere fino a circa 2-3 GB di memoria indirizzabile per processo, dare o fare (a seconda della frammentazione dell'heap, ecc.) .

Ecco il problema: i set di dati sono 4 + GB e su di essi vengono eseguiti algoritmi DSP che richiedono un accesso essenzialmente casuale al file. Un puntatore all'oggetto generato dal file viene gestito in C#, tuttavia il file stesso viene caricato in memoria (con questo sistema parziale mappato in memoria) in C++ (è P/Invocato). Quindi, credo che la soluzione non sia tanto semplice quanto semplicemente regolare le finestre per accedere alla porzione del file che devo accedere, in quanto sostanzialmente voglio che l'intero file sia astratto in un singolo puntatore, dal quale posso chiamare i metodi per accedere ai dati quasi ovunque nel file.

Apparentemente, la maggior parte delle architetture di memoria mappate si basano sulla suddivisione del processo singolare in più processi .. quindi, ad esempio, accedo ad un file da 6 GB con processi 3x, ognuno con una finestra da 2 GB sul file. Dovrei quindi aggiungere una quantità significativa di logica per estrarre e ricombinare i dati da queste diverse finestre/processi. VirtualAllocEx sembra fornire un metodo per aumentare lo spazio degli indirizzi virtuali, ma non sono ancora del tutto sicuro se questo è il modo migliore per farlo.

Ma, diciamo che voglio che questo programma funzioni altrettanto facilmente come un singolo processo a 64 bit su un sistema a 64 bit. Supponiamo che non mi interessi il thrashing, voglio solo essere in grado di manipolare un grande file sul sistema, anche se solo, per esempio, 500 MB sono stati caricati nella RAM fisica in qualsiasi momento. C'è un modo per ottenere questa funzionalità senza dover scrivere a mano un sistema di memoria manuale un po 'ridicolo? O c'è un modo migliore di quello che ho trovato attraverso la combinazione di SO e Internet?

Questo si presta a una domanda secondaria: esiste un modo per limitare la quantità di RAM fisica utilizzata da questo processo? Ad esempio, cosa accadrebbe se volessi limitare il processo a avere solo 500 MB caricati nella RAM fisica in qualsiasi momento (pur mantenendo il file multi-GB paginato su disco)?

Mi dispiace per la lunga domanda, ma mi sento come se fosse un sommario decente di quelle che sembrano essere molte domande (con solo risposte parziali) che ho trovato su SO e sulla rete in generale. Spero che questo possa essere un campo in cui una risposta definitiva (o almeno alcuni pro/contro) può essere arricchita, e tutti noi possiamo imparare qualcosa di prezioso nel processo!

+1

tl; dr, ma se si desidera utilizzare una libreria esterna: Qt può gestire "file di grandi dimensioni" su più piattaforme, sebbene non mappate in memoria (su piattaforme a 32 bit). Ma utilizza una cache di IO interna che * potrebbe * raggiungere prestazioni comparabili? – leemes

+0

Grazie per il commento, leemes (anche se tl; dr è un po 'una cosa maleducata da dire> _> ;;)! Ho cercato di utilizzare una cache di I/O interna, ma questo sembra introdurre una buona dose di complessità, che è quello che sto cercando di evitare. Inoltre, vorrei evitare di aggiungere ulteriori librerie come Qt al mix (Boost è già integrato, però) –

+0

Limitando la RAM, è possibile utilizzare un oggetto di lavoro Windows e limitare il working set, che limita la RAM fisica. Sfortunatamente penso che questo massimizzerà solo lo scambio, quindi non è ciò che si vorrebbe. Suppongo anche che tu sappia dei file mappati in memoria e che non si adattino alle tue esigenze. –

risposta

2

È possibile scrivere una classe di accesso a cui viene fornito un indirizzo di base e una lunghezza. Restituisce dati o genera eccezioni (o comunque si desidera informare delle condizioni di errore) se si verificano condizioni di errore (fuori limite, ecc.).

Quindi, ogni volta che è necessario leggere dal file, l'oggetto accessor può utilizzare SetFilePointerEx() prima di chiamare ReadFile(). È quindi possibile passare la classe accessor al costruttore di qualsiasi oggetto creato durante la lettura del file. Gli oggetti quindi utilizzano la classe accessor per leggere i dati dal file. Quindi restituisce i dati al costruttore dell'oggetto che li analizza in dati oggetto.

Se, in seguito, è possibile compilare a 64 bit, è sufficiente modificare (o estendere) la classe di accesso per leggere invece dalla memoria.

quanto per limitare la quantità di RAM utilizzata dal processo .. che è soprattutto una questione di fare in modo che A) non si dispone di perdite di memoria (in particolare quelli osceni) e B) oggetti distruggendo che non lo fanno bisogno nel momento stesso Anche se ne avrai bisogno in seguito, ma i dati non cambieranno ... distruggi semplicemente l'oggetto. Quindi ricrearlo più tardi quando ne hai bisogno, permettendogli di rileggere i dati dal file.

+1

Hmm ... sembra un'idea interessante, inetknght! Grazie per l'input! Anche se questo sembra un ottimo modo per leggere il file, richiederà comunque l'aggiunta di una buona quantità di logica per lo spostamento manuale delle visualizzazioni attraverso il file, anche se, sono d'accordo che l'utilizzo di un accessorio estensibile sarebbe fantastico, in che solo la classe di accesso dovrebbe essere modificata se questa viene spostata verso 64-bit. Questo potrebbe finire per essere l'implementazione finale, se non ci sono altri modi per avere facilmente il file gestito da qualche altro costrutto. –

Problemi correlati