Compartir el estado entre procesos de trabajo bifurcados en un entorno de alto rendimiento

Este es un seguimiento de miPregunta anterior. Según lo sugerido por Tim Peters, utilizando unManager Puede que no sea necesariamente el mejor enfoque. Desafortunadamente tengo demasiado código de andamios para publicar unSSCCE. En su lugar, intentaré proporcionar una explicación detallada de mi problema. Por favor, siéntase libre de navegar por todo el código enGithub, pero es un poco desordenado en este momento.

Fondo

Estoy investigando en el procesamiento del lenguaje natural y me gustaría hacer (algo así como) el suavizado basado en el diccionario para la clasificación de documentos. La idea de entrenar a un clasificador para asociar palabras y frases con una respuesta correcta. Por ejemplo, documentos que contengan la palabra.socialist es probable que sean sobre política, y aquellos que contienen la fraselava temperature son probables sobre geología. El sistema se entrena observando unnúmero pequeño de ejemplos pre-etiquetados. Debido a que el lenguaje es tan variado, un clasificador nunca "conocerá" todas las frases posibles que pueda encontrar en la producción.

Aquí es donde entra el diccionario. Supongamos que tuviéramosuna forma barata y fácil de conseguir sinónimos para casi cualquier frase (me citaré porque es de mal gusto). Cuando el clasificador pobre se enfrenta a una frase que no conoce, podríamos buscarlo en dicho diccionario y decirle al clasificador "Mira, no sabes sobrecommunism, pero es un poco comosocialist, y usted lo sabe ". Si el diccionario es razonable, el clasificador generalmente tendrá un mejor desempeño.

Pseudo codigo
data = Load training and testing documents (300MB on disk)
dictionary = Load dictionary (200MB - 2GB on disk) and place into a `dict` for fast look-ups
Repeat 25 times:
    do_work(data, dictionary)

def do_work(data, dictionary)
    X = Select a random sample of data
    Train a classifier on X
    Y = Select a random sample of data
    Using dictionary, classify all documents in Y
    Write results to disk
El problema

El bucle de arriba es un candidato perfecto para la paralelización. He estado usando un Python 2.7multiprocessing.Pool (mediantejoblib.Parallel, porque es fácil y proporciona un rastreo muy útil si las cosas van al sur). Todos los procesos de trabajo necesitan acceso de solo lectura al diccionario y la colección de documentos. No es necesario que los trabajadores se comuniquen entre sí o con el proceso principal; todo lo que hacen es generar, hacer algo de magia, escribir un archivo y morir.

El diccionario debe admitir acceso aleatorio rápido. No sé qué documenta la muestra.Y contendrá, por lo que no puedo podar fácilmente el diccionario y pasar solo la parte que se necesita para cada trabajador. El diccionario será consultado muy a menudo, los conteos de hits típicos por ejecución son de millones. Actualmente, mi código está enlazado a la memoria, ya que (creo) se están realizando copias de la colección de documentos y del diccionario para cada proceso de trabajo. Cuando se analizadata ydictionary Normalmente se utilizan varios GB de RAM. He intentado usarmultiprocessing.managers.BaseManager para evitar copiar los objetos grandes, pero eso ralentizó a los trabajadores.

La pregunta

¿Qué otras alternativas hay para acelerar las cosas? Las cosas que he pensado incluyen:

MongoDB / CouchDB / memcached debería manejar bien el acceso concurrente, pero me preocupa el rendimiento. zeromq también fue sugerido en un comentario a mi pregunta anterior, no he tenido la oportunidad de analizarlo.en memoriasqlite Las bases de datos y las conexiones de bases de datos no se pueden compartir entre los procesos, por lo que cada trabajador necesitará su propia conexión a una base de datos en el disco. Esto significa una gran cantidad de E / S al principio y un alto uso de memoria a medida que crece la caché de cada trabajador.asignación de memoriaUsando hilos en lugar de procesos.

Esta pregunta tan También sugirió que muchos problemas del mundo real que parecen necesitar acceso de solo lectura a undict puede desencadenarfork()La copia en escritura, por lo que puede ser imposible evitar completamente hacer copias de objetos grandes.

Respuestas a la pregunta(1)

Su respuesta a la pregunta