A menudo termino con varios bucles anidados foreach
y, a veces al escribir funciones generales (por ejemplo, para un paquete) no hay ningún nivel que sea obvio para paralelizar en. ¿Hay alguna manera de lograr lo que describe la maqueta a continuación?Ejecutar bucle foreach en paralelo o secuencialmente dado una condición
foreach(i = 1:I) %if(I < J) `do` else `dopar`% {
foreach(j = 1:J) %if(I >= J) `do` else `dopar`% {
# Do stuff
}
}
Por otra parte, ¿hay alguna manera de detectar si un motor en paralelo se ha registrado para que pueda evitar recibir mensajes de advertencia innecesarias? Esto sería útil tanto para verificar los paquetes antes de la presentación de CRAN como para no molestar a los usuarios que ejecutan R en las computadoras de núcleo único.
foreach(i=1:I) %if(is.parallel.backend.registered()) `dopar` else `do`% {
# Do stuff
}
Gracias por su tiempo.
Edit: Muchas gracias por todos los comentarios sobre los núcleos y los trabajadores, y tiene razón en que la mejor manera de tratar con el ejemplo anterior sería replantear toda la configuración. Prefiero algo así como debajo de la idea triu
, pero es esencialmente el mismo punto. Y, por supuesto, también podría hacerse con un tapply
paralelo, como sugirió Joris.
ij <- expand.grid(i=1:I, j=1:J)
foreach(i=ij$I, j=ij$J) %dopar% {
myFuction(i, j)
}
Sin embargo, en mi intento de simplificar la situación que dio lugar a este hilo, omití algunos detalles cruciales. Imagine que tengo dos funciones analyse
y batch.analyse
y el mejor nivel para paralelizar en podría ser diferente dependiendo de los valores de n.replicates
y n.time.points
.
analyse <- function(x, y, n.replicates=1000){
foreach(r = 1:n.replicates) %do% {
# Do stuff with x and y
}
}
batch.analyse <- function(x, y, n.replicates=10, n.time.points=1000){
foreach(tp = 1:time.points) %do% {
my.y <- my.func(y, tp)
analyse(x, my.y, n.replicates)
}
}
Si n.time.points > n.replicates
tiene sentido para paralelizar en batch.analyse
pero por lo demás tiene más sentido para paralelizar en analyse
. ¿Alguna idea sobre cómo abordarlo? ¿Sería de alguna manera posible detectar en analyse
si la paralelización ya ha tenido lugar?
¡Guau, estoy asombrado y me alegro de que te hayas unido! Mientras lo tengo en la línea, si tiene una tarea que consume mucho tiempo, ¿hay alguna forma de guardar resultados parciales y reanudarlo más adelante con el paquete 'foreach'? Para mí, esa es la única pieza que falta en el marco de paralelización perfecto. Si tiene algo que debe ejecutarse durante una semana, es bueno detenerse de vez en cuando y asegurarse de que está en buen camino. – Backlin
@Backlin: Ciertamente no hay una capacidad de control en foreach, pero es sorprendente lo mucho que puede hacer al escribir sus propios iteradores y combinar funciones. Si el iterador que está alimentando el bucle foreach puede coordinarse con la función de combinación, probablemente podría improvisar algo de ese tipo. Puedo intentar escribir un ejemplo que demuestre la idea. –
Ok, solo quería asegurarme de que no me había perdido otra cosa semi obvia. Si escribe un ejemplo de punto de referencia, me gustaría verlo, pero es bastante fácil hacerlo manualmente. – Backlin