El paquete multicore de R

Tengo acceso a una máquina que, aunque anda un poco corta de memoria, cuenta con ocho CPUs. Tenía unas simulaciones bastante pesadas que correr y quise aprovechar su naturaleza perfectamente paralelizable. Y, de paso, hacer con R lo mismo por lo que he visto a un consultor de SAS cobrar a razón de 3.000 dólares diarios.

En el fondo, es una trivialidad. Supongamos que la función que implementa la simulación se llama foo. Habitualmente, haríamos

n.iter <- 1000
resultados <- replicate( n.iter, foo() )

y las simulaciones se ejecutarían secuencialmente. Con el paquete multicore, la tarea podría distribuirse por 6 (por ejemplo: es que si uso las ocho me riñen) de las CPUs así:

library( multicore )
resultados <- mclapply( 1:n.iter, foo, mc.set.seed = TRUE, mc.cores = 6 )

Notas:

  • La función foo tiene que admitir un parámetro para poder usar mclapply: no existe una versión paralelizable de replicate en el paquete. Véase una posible solución a este problema en el ejemplo del final.
  • La opción mc.cores limita el número de CPUs que se usarán en la paralelización.
  • La opción mc.set.seed es muy importante: sin ella, cada subproceso compartirá la semilla y los valores aleatorios que generará serán los mismos.  ¡Normalmente no es eso lo que se quiere!

El paquete multicore incluye algunas funciones de más bajo nivel (parallel, fork, etc.) que podrían utilizarse para tareas más específicas. Pero mclapply es cómoda, simple y funciona estupendamente. Hay que hacer notar que el paquete está basado en la función fork tal cual está implementada en los sistemas operativos POSIX. Windows, lástima, no lo es.

Y para acabar, números:

library( multicore )
n.iter <- 1000
foo <- function(i) mean( rnorm( 100000 ) )  

system.time( resultados <- replicate( n.iter, foo() ) )
# 16.47 segundos en mi sistema (elapsed)

system.time( resultados <-
  mclapply( 1:n.iter, foo, mc.set.seed = TRUE, mc.cores = 6 ) )
# 4.34 segundos

4 comentarios sobre “El paquete multicore de R

  1. dcb 18 enero, 2011 18:31

    Hola Carlos, ya sé que esta entrada es antigua, pero me pica la curiosidad antes de poder probar este paquete .. hablas de fork, entiendo que es multiproceso , entonces al hacer copias del proceso original ¿afecta mucho a la memoria? por otro lado , comentas lo de la opción parallel, quiere decir eso que también soporta multithread?

    Bueno si puedo mirarlo antes de que puedas contestar , prometo autoresponderme.

    saludos

  2. datanalytics 18 enero, 2011 20:48

    No soy experto en esas cosas pero:

    1) Cuando me refiero a parallel, hablo de una función de bajo nivel del paquete; la función sigue usando el fork habitual de Linux/UNIX. Se crean procesos (no hilos) distintos e independientes.

    2) He leído por ahí y me consta de usar la librería que las variantes «modernas» de fork sólo copian memoria cuando la necesitan. De hecho, siguiendo el uso de memoria de los hilos, se ve cómo utilizan poca memoria al principio (no hay segmentos «sucios») y cómo poco a poco van creciendo conforme cada uno de ellos hace uso de recursos de memoria propios. ¡Pero no soy experto!

    3) El código fuente del paquete es diminuto. Y muy instructivo. Puedes echarle un vistazo.

  3. dcb 19 enero, 2011 15:55

    gracias! ya lo he visto , queda muy claro con lo que has explicado.. respecto a la memoria , indican que efectivamente no se arrastra toda, aunque hay que tener cuidado al ejecutarlo si estamos en un entorno GUI donde si podemos replicar memoria innecesaria, por ello aconsejan ejecutar en batch o consola.

    saludos

Los comentarios están desabilitados.