2011-01-20 5 views
8

que he hecho un poco de rendimiento y consumo de memoria los puntos de referencia básicos y me preguntaba si hay alguna manera de hacer las cosas aún más rápido ...Lock free read only Lista en Python?

  1. Tengo una lista de 70.000 elemento de gigante con una ndarray numpy, y la ruta del archivo en una tupla en dicha lista.

  2. Mi primera versión aprobó una copia en rodajas de la lista para cada uno de los procesos en el módulo Python multiproceso, pero iba a explotar el uso de RAM a más de 20 + Gigabytes

  3. la segunda versión lo moví en el espacio global y acceda a él a través de un índice como foo [i] en un bucle en cada uno de mis procesos que parece ponerlo en un área de memoria compartida/semántica CoW con los procesos por lo que no explota el uso de la memoria (Permanece en ~ 3 Gigabytes)

  4. Sin embargo, de acuerdo con los puntos de referencia de rendimiento/seguimiento, parece que la gran mayoría del tiempo de aplicación se dedica ahora a "adquirir" Modo ...

Así que me preguntaba si hay alguna manera de que me puedo convertir de alguna manera esta lista en una especie de lockfree/sólo lectura para que pueda deshacerse de parte del paso de adquirir para ayudar a acelerar acceda aún más.

Editar 1: Aquí está la pocos salida de línea de la parte superior del perfil de la aplicación

ncalls tottime percall cumtime percall filename:lineno(function) 
    65 2450.903 37.706 2450.903 37.706 {built-in method acquire} 
39320 0.481 0.000 0.481 0.000 {method 'read' of 'file' objects} 
    600 0.298 0.000 0.298 0.000 {posix.waitpid} 
    48 0.271 0.006 0.271 0.006 {posix.fork} 

Editar 2: Aquí está un ejemplo de la estructura de la lista:

# Sample code for a rough idea of how the list is constructed 
sim = [] 
for root, dirs, files in os.walk(rootdir): 
    path = os.path.join(root, filename) 
    image= Image.open(path) 
    np_array = np.asarray(image) 
    sim.append((np_array, path)) 

# Roughly it would look something like say this below 
sim = List((np.array([[1, 2, 3], [4, 5, 6]], np.int32), "/foobar/com/what.something")) 

Entonces adelante la lista SIM debe ser de solo lectura.

Respuesta

10

El módulo multiprocessing proporciona exactamente lo que necesita: una matriz compartida con bloqueo opcional, a saber, la clase multiprocessing.Array. Pase lock=False al constructor para desactivar el bloqueo.

Editar (teniendo en cuenta su actualización): Las cosas en realidad son mucho más complicadas de lo que esperaba inicialmente. Los datos de todos los elementos de su lista deben crearse en la memoria compartida. Ya sea que coloque la lista (es decir, los punteros a los datos reales) en la memoria compartida, no importa demasiado, ya que esto debería ser pequeño en comparación con los datos de todos los archivos. Para almacenar los datos del archivo en la memoria compartida, utilice

shared_data = multiprocessing.sharedctypes.RawArray("c", data) 

donde data es que los datos se lee desde el archivo. Para utilizar esta como una matriz NumPy en uno de los procesos, utilice

numpy.frombuffer(shared_data, dtype="c") 

que creará una vista array NumPy para los datos compartidos. Del mismo modo, para poner el nombre de ruta en la memoria compartida, use

shared_path = multiprocessing.sharedctypes.RawArray("c", path) 

donde ruta es una cadena de Python normal. En sus procesos, puede acceder a esto como una cadena de Python utilizando shared_path.raw. Ahora agregue (shared_data, shared_path) a su lista. La lista se copiará a los otros procesos, pero los datos reales no.

Al principio quise utilizar un multiprocessing.Array para la lista real. Esto sería perfectamente posible y garantizaría que también la lista en sí (es decir, los punteros a los datos) esté en la memoria compartida. Ahora creo que esto no es tan importante en absoluto, siempre que se compartan los datos reales.

+0

Mi problema es que necesito una forma de almacenar un nudy ndarray + filepath. Mi comprensión de las cosas de Array es que solo almacena 1 elemento, como decir 'c', no puede almacenar "char" – Pharaun

+0

@Pharaun: Tal vez no obtuve la estructura de su lista correctamente. ¿Podrías hacer esto más explícito en tu pregunta? Estoy bastante seguro de que la clase 'Array' se puede usar para su aplicación. –

+0

@Sven, he actualizado la pregunta anterior con una muestra aproximada de cómo se construye la lista en edit2, así que eso debería dar una idea ... – Pharaun