La escritura en un memmap NumPy todavía se carga en la memoria RAM

Estoy probando el memmap de NumPy a través de IPython Notebook, con el siguiente código

Ymap = np.memmap('Y.dat', dtype='float32', mode='w+', shape=(5e6, 4e4)) 

Como puedes ver, la forma de Ymap es bastante grande. Estoy tratando de llenar Ymap como una matriz dispersa. No estoy usando matrices scipy.sparse porque eventualmente necesitaré un producto scipy.sparse con otra matriz densa, que definitivamente no encajará en la memoria.

De todos modos, estoy realizando una serie muy larga de operaciones de indexación:

 Ymap = np.memmap('Y.dat', dtype='float32', mode='w+', shape=(5e6, 4e4)) with open("somefile.txt", 'rb') as somefile: for i in xrange(5e6): # Read a line line = somefile.readline() # For each token in the line, lookup its j value # Assign the value 1.0 to Ymap[i,j] for token in line.split(): j = some_dictionary[token] Ymap[i,j] = 1.0 

Estas operaciones de alguna manera se comen rápidamente mi memoria RAM. Pensé que el mapeo de mem era básicamente un numpy.ndarray fuera de núcleo. ¿Estoy equivocado? ¿Por qué mi uso de memoria se dispara como un loco?

Un mmap (no anónimo) es un enlace entre un archivo y la RAM que, aproximadamente, garantiza que cuando la RAM del mmap esté llena, los datos se paguen al archivo dado en lugar de al disco / archivo de intercambio, y cuando se msync o munmap it, toda la región de RAM se escribe en el archivo. Los sistemas operativos suelen seguir una estrategia perezosa. Accesos al disco (o memoria RAM ansiosa): los datos permanecerán en la memoria mientras quepa. Esto significa que un proceso con grandes mmaps consumirá tanta memoria RAM como pueda / necesita antes de dertwigr el rest en el disco.

Así que tienes razón en que una matriz np.memmap es una matriz fuera de núcleo, pero es una que capturará tanta memoria caché de RAM como sea posible.

Como dicen los doctores :

Los archivos asignados en memoria se utilizan para acceder a pequeños segmentos de archivos grandes en el disco, sin tener que leer todo el archivo en la memoria.

No hay verdadera magia en las computadoras 😉 Si accedes a una matriz gigante muy pequeña, un truco memmap requerirá muy poca memoria RAM; Si accede a una gran cantidad de una matriz gigante, un truco memmap requerirá mucha memoria RAM.

Una solución que puede o no ser útil en su código específico: crear nuevos objetos mmap periódicamente (y deshacerse de los antiguos), en puntos lógicos de su flujo de trabajo. Entonces, la cantidad de RAM necesaria debe ser aproximadamente proporcional al número de elementos de la matriz que toque entre dichos pasos. Contra eso, lleva tiempo crear y destruir nuevos objetos mmap. Así que es un acto de equilibrio.