Pregunta ¿Debería usar cada núcleo al hacer un procesamiento paralelo en R?


Estoy usando R para convertir algunos shapefiles. R hace esto usando solo un núcleo de mi procesador, y quiero acelerarlo usando procesamiento paralelo. Así que he paralelizado el proceso de esta manera.

Dado files que es una lista de archivos para convertir:

library(doMC)
registerDoMC()

foreach(f=files) %dopar% {
  # Code to do the conversion
}

Esto funciona bien y usa 2 núcleos. De acuerdo con la documentación para registerDoMC(), por defecto esa función usa la mitad de los núcleos detectados por parallel paquete.

Mi pregunta es por qué debería usar la mitad de los núcleos en lugar de todos los núcleos? (En este caso, 4 núcleos). Al usar la función registerDoMC(detectCores()) Puedo usar todos los núcleos en mi sistema. ¿Cuáles son los inconvenientes de hacer esto?


9
2017-08-17 16:08


origen


Respuestas:


Cada vez que realiza un procesamiento paralelo, se produce una sobrecarga (que puede ser no trivial, especialmente con el bloqueo de estructuras de datos y el bloqueo de llamadas). Para trabajos de lotes pequeños, ejecutar en un solo núcleo o dos núcleos es mucho más rápido debido al hecho de que no está pagando esa sobrecarga.

No sé el tamaño de tu trabajo, pero probablemente deberías realizar algunos experimentos de escala en los que calculas tu trabajo en 1 procesador, 2 procesadores, 4 procesadores y 8 procesadores, hasta que alcances el recuento de núcleos máximo para tu sistema (por lo general, siempre duplicas el recuento del procesador). EDITAR: Parece que solo está utilizando 4 núcleos, por lo que debe usar 1, 2 y 4.

Ejecute los resultados de tiempo para ~ 32 intentos para cada recuento de núcleos y obtenga un intervalo de confianza, luego puede decir con certeza si ejecutar en todos los núcleos es adecuado para usted. Si su trabajo lleva mucho tiempo, reduzca el número de intentos, hasta 5 o más, pero recuerde que más ensayos le darán un mayor grado de confianza.

Elaborar:

Prueba t de Student:

La prueba de la t de Student dice "calculaste un tiempo promedio para este recuento de núcleos, pero ese no es el promedio real. Solo podemos obtener el promedio verdadero si tuviéramos el promedio de una cantidad infinita de puntos de datos. se encuentra en algún intervalo alrededor de su promedio calculado "

La prueba t de significancia básicamente compara los intervalos alrededor del promedio verdadero para 2 puntos de datos y dice si son significativamente diferentes o no. Por lo tanto, puede tener un tiempo promedio menor que otro, pero debido a que la desviación estándar es suficientemente alta, no podemos decir con certeza que en realidad es menor; los verdaderos promedios pueden ser idénticos.

Por lo tanto, para calcular esta prueba de significancia:

  • Ejecuta tus experimentos de sincronización
  • Para cada recuento de núcleos:
  • Calcule su media y desviación estándar. La desviación estándar debe ser la desviación estándar de población, que es la raíz cuadrada de variación poblacional Varianza poblacional es (1 / N) * summation_for_all_data_points ((datapoint_i - mean) ^ 2)

Ahora tendrá una media y desviaciones estándar para cada recuento de núcleos: (m_1, s_1), (m_2, s_2), etc.  - Por cada par de conteos de núcleos:  - Calcular un valor t: t = (mean_1 - mean_2) / (s_1 / sqrt (#dataPoints))

El valor t de ejemplo que mostré comprueba si los resultados de tiempo medio para el recuento de núcleos de 1 son significativamente diferentes de los resultados de temporización para el recuento de núcleos de 2. Puede probar al revés diciendo:

t = (m_2 - m_1) / (s_2 / sqrt (#dataPoints))

Después de calcular estos valores t, puede determinar si son significativos al mirar el tabla de valor crítico. Ahora, antes de hacer clic en eso, necesita saber acerca de 2 cosas más:

Grados de libertad

Esto está relacionado con la cantidad de puntos de datos que tiene. Cuantos más puntos de datos tenga, menor será probablemente el intervalo alrededor de la media. Grados de libertad tipo de medidas de la capacidad de su media computada para moverse, y es #dataPoints - 1 (v en el enlace que brindé).

Alfa

Alpha es un umbral de probabilidad. En la distribución Gaussiana (Normal, curva de campana), alfa corta la curva de campana tanto a la izquierda como a la derecha. Cualquier probabilidad en el medio de los puntos de corte cae dentro del umbral y es un resultado insignificante. Un alfa inferior hace que sea más difícil obtener un resultado significativo. Eso es alfa = 0.01 significa que solo el 1% superior de las probabilidades son significativas, y alfa = 0.05 significa el 5% superior. La mayoría de las personas usa alfa = 0.05.

En la tabla a la que me enlace, 1-alpha determina la columna en la que buscará un valor crítico. (entonces alfa = 0.05 da 0.95, o un intervalo de confianza del 95%), y v son sus grados de libertad, o fila a mirar.

Si tu valor crítico es Menos que tu calculado t (valor absoluto), entonces su resultado NO es significativo. Si el valor crítico es mas grande que tu calculado t (valor absoluto), entonces tiene significación estadística.

Editar: La prueba t de Student supone que las desviaciones y las desviaciones estándar son las mismas entre los dos medios que se comparan. Es decir, supone que la distribución de puntos de datos alrededor de la media verdadera es igual. Si NO quieres hacer esta suposición, entonces estás buscando Prueba t de Welch, que es ligeramente diferente. La página wiki tiene una buena fórmula para calcular valores t para esta prueba.


5
2017-08-17 16:14



Además de la cuestión de la escalabilidad, existe una regla simple: los núcleos Intel Hyperthreading no ayudan, al menos en Windows. Así que obtengo 8 con detectCores (), pero nunca encontré una mejora al ir más allá de 4 núcleos, incluso con subprocesos paralelos de MCMC que, en general, se escalan perfectamente.

Si alguien tiene un caso (en Windows) donde Hyperthreading presenta tal mejora, publíquelo.


9
2017-08-17 17:21



Hay una situación que desea evitar:

  • extendiendo una tarea sobre todos los N núcleos

  • haciendo que cada núcleo trabaje la tarea usando algo como OpenBLAS o MKL con todos los núcleos

porque ahora tiene una contención de N por N: cada una de las N tareas quiere cultivar su trabajo de álgebra lineal en todos los N núcleos.

Se proporciona otro ejemplo de contador (trivial) en un entorno multiusuario donde no todos los usuarios M en una máquina pueden (simultáneamente) cultivar en N núcleos.


4
2017-08-17 18:04



Otra razón para no utilizar todos los núcleos disponibles es si sus tareas utilizan mucha memoria y no tiene suficiente memoria para admitir esa cantidad de trabajadores. Tenga en cuenta que puede ser difícil determinar cuántos trabajadores pueden ser compatibles con una determinada cantidad de memoria, porque doMC usos mclapply que bifurca a los trabajadores, entonces la memoria puede ser compartida entre los trabajadores a menos que uno de ellos la modifique.

De las respuestas a esta pregunta, está bastante claro que no siempre es fácil determinar la cantidad correcta de trabajadores a usar. Se podría argumentar que no debería haber un valor predeterminado, y el usuario debería verse obligado a especificar el número, pero no estoy seguro de si llegaría tan lejos. En cualquier caso, no hay nada mágico en utilizar la mitad del número de núcleos.


3
2017-08-18 02:26



Hm. No soy un experto en procesamiento en paralelo, pero siempre pensé que la desventaja de usar todos sus núcleos era que hacía que tu máquina funcionara lentamente cuando intentabas cualquier otra cosa. Me he hecho esto personalmente, cuando he usado todos los núcleos, entonces mi práctica ahora es usar 7 de mis 8 núcleos cuando estoy haciendo algo paralelo, dejándome un núcleo para hacer otras cosas.


2
2017-08-17 22:06