hackear - ¿Cuándo hace Foreach llamar a.combine?
como hackear wifi (1)
La respuesta corta es usar ya sea doMPI
o doRedis
como su back-end paralelo. Funcionan más de lo que esperabas.
Los doMC
, doSNOW
y doParallel
son envoltorios relativamente simples para funciones como mclapply
y clusterApplyLB
, y no llaman a la función de combinación hasta que se hayan calculado todos los resultados, como ya ha observado. Los doMPI
, doRedis
y (ahora desaparecidos) doSMP
son más complejos, y obtienen entradas de los iteradores según sea necesario y llaman a la función de combinación sobre la marcha, como suponía que harían. Estos servidores tienen varias ventajas en mi opinión, y te permiten manejar un número arbitrario de tareas si tienes iteradores apropiados y funciones combinadas. Me sorprende que tanta gente se lleve bien con los back-end más simples, pero si tienes muchas tareas, las más sofisticadas son esenciales, lo que te permite hacer cosas que son bastante difíciles con paquetes como el parallel
.
He estado pensando en escribir un backend más sofisticado basado en el paquete parallel
que manejaría los resultados sobre la marcha como mi paquete doMPI
, pero no ha habido ninguna llamada que yo sepa. De hecho, la tuya ha sido la única pregunta de este tipo que he visto.
Actualizar
El backend doSNOW
ahora es compatible con el manejo de resultados sobre la marcha. Desafortunadamente, esto no se puede hacer con doParallel
porque el paquete parallel
no exporta las funciones necesarias.
He escrito un código usando foreach
que procesa y combina una gran cantidad de archivos CSV. Lo estoy ejecutando en una máquina de 32 núcleos, usando %dopar%
y registrando 32 núcleos con doMC
. He establecido .inorder=FALSE
, .multicombine=TRUE
, verbose=TRUE
, y tengo una función de combinación personalizada.
Noto que si ejecuto esto en un conjunto suficientemente grande de archivos, parece que R intenta procesar CADA archivo antes de llamar a .combine por primera vez. Mi evidencia es que al monitorear mi servidor con htop, inicialmente veo todos los núcleos al máximo, y luego, para el resto del trabajo, solo se utilizan uno o dos núcleos, mientras que las combina en lotes de ~ 100 ( .maxcombine
predeterminado de .maxcombine
), como se ve en la salida de consola verbosa. Lo que realmente dice es que cuanto más trabajo le dedico a foreach, más tiempo me toma ver "¡Primera llamada para combinar!"
Esto me parece contrario a la intuición; .maxcombine
esperaba que foreach procesara archivos .maxcombine
, .maxcombine
, luego pasa al siguiente lote, combinando esos con el resultado de la última llamada a .combine
. Supongo que para la mayoría de los usos de .combine
no importaría ya que la salida sería aproximadamente del mismo tamaño que la suma de los tamaños de las entradas; Sin embargo, mi función de combinación reduce el tamaño un poco. Mi trabajo es lo suficientemente grande como para no poder tener más de 4200+ salidas de trabajo foreach individuales en RAM simultáneamente, así que estaba contando con mi .combine
ahorra .combine
y el procesamiento por lotes por separado para que me completara.
¿Tengo razón en que no se llama a .combine hasta que TODOS mis trabajos foreach
se completen individualmente? Si es así, ¿por qué es eso y cómo puedo optimizarlo para eso (que no sea reducir la producción de cada trabajo) o cambiar ese comportamiento?