2010-02-19 9 views
8

Soy muy nuevo en este módulo Parallel::ForkManager en Perl y tiene muchos créditos, así que creo que es compatible con lo que necesito y aún no lo he descubierto.¿El módulo Parallel :: ForkManager() admite la sincronización en variables globales?

Lo que tengo que hacer es en cada proceso hijo, escribe algunas actualizaciones en un mapa global de hash, de acuerdo con el valor de la clave calculada en cada proceso hijo. Sin embargo, cuando procedo a reclamar un mapa hash fuera del bucle for y espero que el mapa hash se actualice después del bucle, resulta que el mapa hash permanece vacío. Esto significa que aunque la actualización dentro del bucle tiene éxito (imprimiendo el valor), fuera del bucle no lo es.

¿Alguien sabe cómo escribir una pieza de código que hace lo que yo quiero tal?

Respuesta

6

Esto no es realmente un problema Perl-específica, sino una cuestión de comprensión de los procesos basados ​​en Unix. Cuando fork es un proceso nuevo, ninguna parte de la memoria se comparte de forma predeterminada entre los procesos. Hay algunas maneras en que puede lograr lo que desea, dependiendo de lo que necesite.

Una forma fácil sería utilizar algo así como BerkeleyDB para atar un hash de un archivo en el disco. El hash vinculado puede inicializarse antes de que se bifurque y luego cada proceso secundario tendrá acceso a él. Los archivos BerkeleyDB están diseñados para tener acceso seguro desde múltiples procesos simultáneamente.

Un método más complicado sería utilizar alguna forma de comunicación entre procesos. Para todos los detalles sangrientos de lograrlo, consulte la página de manual perlipc, que contiene detalles sobre varios métodos de IPC admitidos por Perl.

Una aproximación final, si su Perl soporta, es el uso de hilos y comparten variables entre ellos.

4

Cada fork llamada genera un nuevo proceso de marca, por lo que cambios a una variable de hash en un proceso hijo no son visibles en los padres (y los cambios en la matriz después de la llamada fork no son visibles en el niño).

Puede usar threads (y ver también threads::shared) para que un cambio escrito en un hilo sea grabable en otro hilo.

Otra opción es utilizar la comunicación entre procesos para pasar mensajes entre los procesos padre e hijo. El módulo Forks::Super (del que soy el autor) puede hacer que esto no sea un dolor de cabeza.

O los procesos secundarios podrían escribir alguna salida en los archivos. Cuando el proceso padre los recoge, podría cargar los datos de esos archivos y actualizar su mapa hash global en consecuencia.

+0

Gracias a todos, ahora entiendo! Esperaba que el ForkManager() se ocupara de este problema. :-) En mi caso, IPC podría ser excesivo. Me gusta la forma concisa de usar ForkManager(), ¿existe una manera fácil de compartir un mapa hash global entre procesos utilizando ForkManager()? – galactica

+3

@Jin: Obtener datos de un proceso a otro * es * IPC. Eso es lo que significa. No tiene que ser difícil, sin embargo. – hobbs

+0

@Jin: sí, use un hash vinculado; ver http://search.cpan.org/perldoc/BerkeleyDB para uno. – ysth

2

Lea las "estructuras de datos recuperar de los procesos secundarios" sección del hombre paralelo :: ForkManager. Hay devoluciones de llamadas, los datos del niño pueden enviarse y el padre puede recuperarlos y completar las estructuras de datos.