Domanda

[Modificare:Questo problema si applica solo ai sistemi a 32 bit.Se il tuo computer, il tuo sistema operativo e la tua implementazione Python sono a 64 bit, la mappatura di file enormi funziona in modo affidabile ed è estremamente efficiente.]

Sto scrivendo un modulo che, tra le altre cose, consente l'accesso in lettura bit per bit ai file.I file possono essere potenzialmente grandi (centinaia di GB) quindi ho scritto una semplice classe che mi permette di trattare il file come una stringa e nasconde tutte le operazioni di ricerca e lettura.

Al momento in cui ho scritto la mia classe wrapper non sapevo del file modulo mmap.Leggendo la documentazione di mmap ho pensato "fantastico: è proprio quello di cui avevo bisogno, prenderò il mio codice e lo sostituirò con un mmap.Probabilmente è molto più efficiente ed è sempre bene eliminare il codice."

Il problema è che mmap non funziona con file di grandi dimensioni!Questo è molto sorprendente per me perché pensavo che fosse forse l'applicazione più ovvia.Se il file supera alcuni gigabyte, ottengo un file EnvironmentError: [Errno 12] Cannot allocate memory.Ciò accade solo con una build Python a 32 bit, quindi sembra che stia esaurendo lo spazio degli indirizzi, ma non riesco a trovare alcuna documentazione al riguardo.

Il mio codice è giusto

f = open('somelargefile', 'rb')
map = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)

Quindi la mia domanda è mi sto perdendo qualcosa di ovvio qui? C'è un modo per far sì che mmap funzioni in modo portabile su file di grandi dimensioni o dovrei tornare al mio ingenuo wrapper di file?


Aggiornamento:Sembra che ci sia la sensazione che l'mmap Python dovrebbe avere le stesse restrizioni dell'mmap POSIX.Per esprimere meglio la mia frustrazione ecco una semplice classe che ha una piccola parte delle funzionalità di mmap.

import os

class Mmap(object):
    def __init__(self, f):
        """Initialise with a file object."""
        self.source = f

    def __getitem__(self, key):
        try:
            # A slice
            self.source.seek(key.start, os.SEEK_SET)
            return self.source.read(key.stop - key.start)
        except AttributeError:
            # single element
            self.source.seek(key, os.SEEK_SET)
            return self.source.read(1)

È di sola lettura e non fa nulla di speciale, ma posso farlo esattamente come con un mmap:

map2 = Mmap(f)
print map2[0:10]
print map2[10000000000:10000000010]

tranne che non ci sono restrizioni sulla dimensione del file.Non troppo difficile davvero...

È stato utile?

Soluzione

Da IEEE 1003.1:

  

La funzione mmap () stabilisce un   mapping tra un processo indirizzo   spazio e un file, memoria condivisa   oggetto, o [TYM] digitati memoria   oggetto.

Si ha bisogno di tutto lo spazio di indirizzamento virtuale, perché questo è esattamente ciò mmap() fa .

Il fatto che non è davvero a corto di memoria non importa - non si può mappare più spazio per l'indirizzo di quello che hai a disposizione. Dal momento che poi prendere il risultato e l'accesso come se sono stati di memoria, esattamente come si propone di accedere a più di 2 ^ 32 byte nel file? Anche se mmap() non ha mancato, si poteva ancora leggere solo il primo da 4 GB, prima è stato eseguito fuori dello spazio in uno spazio di indirizzamento a 32 bit. È possibile, naturalmente, mmap() una finestra scorrevole a 32 bit sopra il file, ma che non necessariamente si netto alcun beneficio se non è possibile ottimizzare il vostro modello di accesso in modo tale che si limitare quante volte dovete visitare le finestre precedenti.

Altri suggerimenti

Mi dispiace di rispondere alla mia domanda, ma penso che il vero problema che ho avuto non è stato rendendosi conto che mmap è stata una chiamata di sistema POSIX serie con particolari characterisatations e limiti e che la mmap Python si suppone solo per esporre la sua funzionalità.

La documentazione Python non menziona il mmap POSIX e quindi se venite ad esso come un programmatore Python senza molta conoscenza di POSIX (come ho fatto io) allora il problema spazio degli indirizzi appare del tutto arbitraria e mal progettato!

Grazie agli altri manifesti per avermi insegnato il vero significato della mmap. Purtroppo nessuno ha suggerito una migliore alternativa alla mia classe artigianale per il trattamento di file di grandi dimensioni come stringhe, quindi dovrò attaccare con esso per ora. Forse io ripulirlo e renderlo parte della interfaccia pubblica del mio modulo, quando ne ho la possibilità.

Un programma a 32 bit e sistema operativo possono indirizzare solo un massimo di 32 bit di memoria cioè 4GB. Ci sono altri fattori che rendono il totale ancora più piccolo; per esempio, Windows riserva tra 0,5 e 2 GB per l'accesso all'hardware, e, naturalmente, il programma sta andando a prendere un po 'di spazio.

Modifica la cosa più ovvia che ti manca è la comprensione dei meccanismi di mmap, su qualsiasi sistema operativo. Esso consente di mappare una porzione di un file per un intervallo di memoria - una volta che hai fatto che, qualsiasi accesso a quella parte del file avviene con l'overhead minimo possibile. E 'basso overhead, perché la mappatura viene fatto una volta, e non deve cambiare ogni volta che si accede a un intervallo diverso. Lo svantaggio è che è necessario un intervallo di indirizzi aperto sufficiente per la parte che si sta cercando di mappare. Se devi rappresentare l'intero file in una sola volta, avrete bisogno di un buco nella mappa di memoria grande abbastanza da contenere l'intero file. Se un tale buco non esiste, o è più grande il vostro intero spazio di indirizzamento, non riesce.

il modulo mmap fornisce tutti gli strumenti necessari per curiosare nel tuo file di grandi dimensioni, ma a causa delle limitazioni menzionate da altri, non puoi mapparlo tutto in una volta.Puoi mappare un pezzo di buone dimensioni contemporaneamente, eseguire alcune elaborazioni, quindi annullarne la mappatura e mapparne un altro.gli argomenti chiave per il mmap classe sono length E offset, che fanno esattamente quello che sembrano, permettendoti di mappare length byte, a partire da byte offset nel file mappato.Ogni volta che desideri leggere una sezione di memoria che si trova all'esterno della finestra mappata, devi mapparla in una nuova finestra.

Il punto vi manca è che mmap è una funzione di mappatura di memoria che associa un file nella memoria per l'accesso arbitrario su tutta la gamma di dati richiesto con qualsiasi mezzo.

Cosa siete alla ricerca di suoni più come una sorta di una classe di finestra di dati che presenta un'API che consente di guardare alle piccole finestre di una grande struttura di dati al momento nessuno. L'accesso oltre i limiti di questa finestra non sarebbe possibile diversa chiamando propria API della finestra dei dati.

Questo va bene, ma non è una mappa di memoria, è qualcosa che offre il vantaggio di un intervallo di dati più ampia al costo di un api più restrittiva.

Si sta impostando il parametro della lunghezza a zero, il che significa che mappa l'intero file. Su un 32 bit di generazione, questo non sarà possibile se la lunghezza del file è superiore a 2 GB (forse 4 GB).

Utilizzare un computer a 64 bit, con un sistema operativo a 64-bit e un'implementazione pitone a 64-bit, o evitare mmap()

mmap() richiede il supporto hardware di CPU per dare un senso di grandi file più grandi di un paio GiB.

MMU e interrompere sottosistemi per consentire di esporre i dati come se si trattasse già caricato ariete.

La MMU è l'hardware che genererà un interrupt ogni volta che un indirizzo corrispondente ai dati non in RAM fisica si accede, e il sistema operativo gestirà l'interrupt in un modo che abbia senso in fase di esecuzione, in modo che il codice che accede non conosce (o necessità di sapere) che i dati non si adatta in RAM.

Questo rende il codice che accede semplice da scrivere. Tuttavia, per utilizzare mmap() questo modo, tutto ciò che riguarda dovrà gestire 64 indirizzi bit.

Oppure, può essere preferibile evitare mmap() del tutto e fare la propria gestione della memoria.

Si chiede al sistema operativo di mappare l'intero file in un intervallo di memoria. Non verrà letto finché non si attiva errori di pagina di lettura / scrittura, ma ha ancora bisogno per assicurarsi che l'intera gamma è disponibile al vostro processo, e se questo intervallo è troppo grande, non ci saranno difficoltà.

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