Estoy usando GNU R en una PC Ubuntu-Lucid que tiene 4 CPU. Para utilizar las 4 CPU, instalé el paquete "r-cran-multicore". Como el manual del paquete carece de ejemplos prácticos que entiendo, necesito consejos sobre cómo optimizar mi script para utilizar las 4 CPU.
Mi conjunto de datos es un data.frame (llamado P1) que tiene 50,000 filas y 1600 cols. Para cada fila, me gustaría calcular el máximo, la suma y la media. Mi guión se ve de la siguiente manera:
p1max <- 0
p1mean <- 0
p1sum <-0
plength <- length(P1[,1])
for(i in 1:plength){
p1max <- c(p1max, max(P1[i,]))
p1mean <- c(p1mean, mean(P1[i,]))
p1sum <- c(p1sum, sum(P1[i,]))
}
¿Podría alguien decirme cómo modificar y ejecutar el script para usar las 4 CPU?
Respuestas:
Use foreach y doMC . La explicación detallada se puede encontrar aquí . Tu guión cambiará muy poco, la línea
debe cambiarse a
Los requisitos previos para cualquier script multitarea que use estos paquetes son
Nota de precaución. De acuerdo con la documentación, no puede usar esto en la GUI.
En cuanto a su problema, ¿realmente necesita multitarea? Su data.frame toma aproximadamente 1.2 GB de RAM, por lo que debe caber en su memoria. Entonces, simplemente puede usar apply:
El resultado será una matriz con resúmenes de cada fila.
También puede usar la función mclapply que se encuentra en el paquete multinúcleo. Entonces su script podría verse así:
Esto devolverá la lista, donde i-ésimo elemento será el resumen de la i-ésima fila. Puedes convertirlo a matriz usando sapply
fuente
Ya tiene una respuesta sobre cómo usar más de un núcleo, pero el verdadero problema es la forma en que ha escrito sus bucles. Nunca extienda su vector / objeto de resultado en cada iteración de un bucle . Si haces esto, obligas a R a copiar tu vector / objeto de resultado y lo extiendes, lo que lleva tiempo. En su lugar, asigne previamente suficiente espacio de almacenamiento antes de comenzar el ciclo y complete a medida que avanza. Aquí hay un ejemplo:
O puede hacer estas cosas a través de
apply()
:Pero tenga en cuenta que esto no es más rápido que hacer el bucle correctamente y, a veces, más lento.
Sin embargo, siempre esté atento al código vectorizado. Puede hacer sumas de filas y medios usando
rowSums()
yrowMeans()
que son más rápidos que el bucle o lasapply
versiones:Si fuera un apostador, tendría dinero en el tercer enfoque que menciono golpear
foreach()
u otras opciones multinúcleo en una prueba de velocidad en su matriz porque tendrían que acelerar las cosas considerablemente para justificar los gastos generales incurridos al configurar el procesos separados que se cultivan en los diferentes núcleos de CPU.Actualización: Siguiendo el comentario de @shabbychef, ¿es más rápido hacer las sumas una vez y reutilizarlas en el cálculo de la media?
No en esta prueba, pero esto está lejos de ser exhaustivo ...
fuente
rowSums
para calcular los medios de la fila (a menos que me falte algo con respecto a, por ejemplo, Na o NaN). El código en su tercer enfoque suma cada columna dos veces .rowSums
y elrowMeans
código compilado y lo que se gana en un solo cálculo de las sumas una vez que están altamente optimizadas, nos suelta de nuevo al hacer el cálculo promedio en código interpretado.system.time({ for (iii in c(1:1000)) { p1max3 <- apply(p1, 1, max) p1mean3 <- rowMeans(p1) p1sum3 <- rowSums(p1) } })
y de manera similarsystem.time({ for (iii in c(1:1000)) { p1max4 <- apply(p1, 1, max) p1sum4 <- rowSums(p1) p1mean4 <- p1sum4 / ncol(p1) } })
; la versión que no vuelve a calcular la suma tarda 1.368 segundos en mi computadora; el que sí toma 1.396. de nuevo, lejos de ser exhaustivo, pero más convincente ...rowMeans
yrowSums
se aplican en código eficiente, optimizado compilado que van a ser difícil de superar.rowMean
será difícil de superar a través de una herramienta R de propósito general como*apply
. Sin embargo, parece sugerir que es más rápido sumar 10000 números dos veces a travésrowMean
y enrowSum
lugar de solo una vez, y usar el operador de división incorporado de R. Sé que R tiene algunos problemas de eficiencia ( por ejemplo, el reciente descubrimiento del problema de las llaves y los paréntesis), pero eso parece una locura.Echa un vistazo a los paquetes de nieve y nieve . Un montón de ejemplos con esos ...
Si desea acelerar ese código específico en lugar de aprender sobre R y el paralelismo, debe hacerlo
fuente