¿Por qué más núcleos de CPU en máquinas virtuales ralentizan los tiempos de compilación?

17

[editar # 2] Si alguien de VMWare me puede dar una copia de VMWare Fusion, estaría más que feliz de hacer lo mismo que una comparación de VirtualBox vs VMWare. De alguna manera sospecho que el hipervisor VMWare estará mejor ajustado para hyperthreading (vea mi respuesta también)

Estoy viendo algo curioso. A medida que aumento el número de núcleos en mi máquina virtual Windows 7 x64, el tiempo de compilación general aumenta en lugar de disminuir. La compilación suele ser muy adecuada para el procesamiento paralelo, ya que en la parte media (mapeo posterior a la dependencia) simplemente puede llamar a una instancia del compilador en cada uno de sus archivos .c / .cpp / .cs / cualquiera que sea para construir objetos parciales para que el enlazador los tome terminado. Así que me habría imaginado que la compilación en realidad se escalaría muy bien con # de núcleos.

Pero lo que estoy viendo es:

  • 8 núcleos: 1.89 segundos
  • 4 núcleos: 1,33 segundos
  • 2 núcleos: 1,24 segundos
  • 1 núcleo: 1,15 segundos

¿Es esto simplemente un artefacto de diseño debido a la implementación de un hipervisor de un proveedor en particular (tipo 2: virtualbox en mi caso) o algo más generalizado en más máquinas virtuales para simplificar las implementaciones de hipervisor? Con tantos factores, parece que soy capaz de argumentar a favor y en contra de este comportamiento, por lo que si alguien sabe más sobre esto que yo, me gustaría leer tu respuesta.

Gracias Sid

[ editar: abordar comentarios ]

@ MartinBeckett: las compilaciones en frío se descartaron.

@MonsterTruck: No se pudo encontrar un proyecto de código abierto para compilar directamente. Sería genial, pero no puedo arruinar mi env dev en este momento.

@ Mr Lister, @philosodad: tenga 8 hw hilos, usando VirtualBox, por lo que debería ser una asignación 1: 1 sin emulación

@Thorbjorn: Tengo 6.5GB para la VM y un proyecto VS2012 pequeño; es bastante improbable que esté intercambiando el archivo de la página.

@ Todos: si alguien puede apuntar a un proyecto VS2010 / VS2012 de código abierto, esa podría ser una mejor referencia comunitaria que mi proyecto VS2012 (propietario). Orchard y DNN parecen necesitar ajustes de entorno para compilar en VS2012. Realmente me gustaría ver si alguien con VMWare Fusion también ve esto (para la compartimentación de VMWare vs VirtualBox)

Detalles de la prueba:

  • Hardware: Macbook Pro Retina
    • CPU: Core i7 @ 2.3Ghz (quad core, hyper thread = 8 núcleos en el administrador de tareas de Windows)
    • Memoria: 16 GB.
    • Disco: SSD de 256 GB
  • SO host: Mac OS X 10.8
  • Tipo de VM: VirtualBox 4.1.18 (hipervisor tipo 2)
  • SO invitado: Windows 7 x64 SP1
  • Compilador: VS2012 compilando una solución con 3 proyectos C # Azure
    • Los tiempos de compilación se miden con el complemento VS2012 llamado 'VSCommands'
    • Todas las pruebas se ejecutan 5 veces, se descartan las 2 primeras ejecuciones, se promedian las últimas 3
DeepSpace101
fuente
9
Probablemente la E / S del archivo se ralentiza con múltiples tareas y el acceso del disco a la unidad virtualizada
Martin Beckett
3
Me gustaría reproducir esto en mi propia máquina. ¿Puedes subir un proyecto de muestra en alguna parte? Sospecho que la máquina virtual está jugando trucos aquí. Intente arrancar en Windows de forma nativa (Bootcamp) y vea si observa el mismo comportamiento. Dudo que lo haga.
Apoorv Khurasia
1
¿Qué estamos compilando aquí? Mucho tiempo la sobrecarga de paralelizar una tarea no vale la pena hasta que alcanzas cierta escala. Vea cómo compila apache o ravendb.
Wyatt Barnett
2
Probablemente se quede sin memoria en su máquina virtual, por lo que comienza a intercambiarse.
1
Lo mismo me ha sucedido antes con Java usando Maven 3.x para compilar en un i3. Dejarlo predeterminado en "4" subprocesos fue mucho más lento, casi un 50% más lento, que decirle explícitamente que solo use 2 núcleos. Creo que tiene algo que ver con el cambio de contexto de subprocesamiento y la superposición de E / S.

Respuestas:

12

Respuesta: No se ralentiza, se escala con # de núcleos de CPU. El proyecto utilizado en la pregunta original era "demasiado pequeño" (en realidad es un montón de desarrollo pero pequeño / optimizado para un compilador) para obtener los beneficios de múltiples núcleos. Parece que, en lugar de planificar cómo difundir el trabajo, generando múltiples procesos de compilación, etc., a esta pequeña escala, es mejor martillar el trabajo en serie de inmediato.

Esto se basa en el nuevo experimento que hice en función de los comentarios a la pregunta (y mi curiosidad personal). Utilicé un proyecto VS más grande: el código fuente de Umbraco CMS ya que es grande, de código abierto y uno puede cargar directamente el archivo de solución y reconstruirlo (pista: cargar umbraco_675b272bb0a3\src\umbraco.slnen VS2010 / VS2012).

AHORA, lo que veo es lo que espero, es decir, ¡las compilaciones se amplían! Bueno, hasta cierto punto ya que encuentro:

Tabla de resultados

Comida para llevar:

  • Un nuevo núcleo de VM da como resultado un nuevo subproceso de OS X dentro del proceso de VirtualBox
  • Los tiempos de compilación aumentan según lo esperado (las compilaciones son lo suficientemente largas)
  • Con 8 núcleos de VM, la emulación de núcleo podría estar funcionando dentro de VirtualBox ya que la penalización es masiva (50% de golpe)
  • Lo anterior es probable porque OS X no puede presentar 4 núcleos hiperprocesados ​​(hebra de 8 h / w) como 8 núcleos a VirtualBox

Ese último punto me hizo monitorear el historial de la CPU en todos los núcleos a través del 'Monitor de actividad' (historial de la CPU) y lo que encontré fue

Gráfico de historial de CPU de OS X

Comida para llevar:

  • En un núcleo VM, la actividad parece estar saltando a través de los 4 núcleos HW. Tiene sentido, distribuir el calor de manera uniforme en los niveles centrales.

  • Incluso en 4 núcleos virtuales (y 27 subprocesos VirtualBox OS X o ~ 800 subprocesos OS X en general), solo los subprocesos HW pares (0,2,4,6) están casi saturados mientras que los subprocesos HW impares (1,3,5,7) están casi al 0%. ¿Es más probable que el planificador funcione en términos de núcleos HW y NO hilos HW, por lo que especulo que quizás el kernel / planificador OSX de 64 bits no esté optimizado para CPU hiperprocesada? O mirando la configuración central de 8VM, ¿tal vez comienza a usarlos con un alto porcentaje de utilización de la CPU? Algo gracioso es uno ... bueno, esa es una pregunta separada para algunos desarrolladores de Darwin ...

[editar]: Me encantaría intentar lo mismo en VMWare Fusion. Lo más probable es que no sea tan malo. Me pregunto si muestran esto como un producto comercial ...

Pie de página:

En caso de que las imágenes desaparezcan, la tabla de tiempos de compilación es (¡texto, feo!)

Cores in    Avg compile      Host/OSX    Host/OSX CPU
   VM         times (sec)   Threads      consumption
    1           11.83            24        105-115%
    2           10.04            25        140-190%
    4            9.59            27        180-270%
    8           14.18            31        240-430%
DeepSpace101
fuente
Sospecho que la caída entre 4 y 8 es una combinación de que la VM no está optimizada para HT, y que HT no es de ninguna manera igual al doble de núcleos (en el mejor de los casos, un aumento del rendimiento del 30%, generalmente mucho menos).
Daniel B
@DanielB: con 4 => 8 núcleos, el problema no es solo que es un mero aumento de + 30% (frente a + 100%) como sugirió, sino que el rendimiento es en realidad -50%. Si los hilos de hardware estuvieran totalmente 'muertos / inútiles' y el trabajo se desviara a los otros núcleos, el delta de rendimiento sería 0. Por lo tanto, estaría más inclinado a decir que es el diseño en el hipervisor VirtualBox tipo 2. Me pregunto cómo es VMWare Fusion ...
DeepSpace101
"En un núcleo de VM, la actividad parece estar saltando a través de los núcleos de 4 HW. Tiene sentido, distribuir el calor de manera uniforme en los niveles de núcleo" - no necesariamente, generalmente es mejor reprogramar en el mismo núcleo (para caché, etc.) pero el hipervisor solo está eligiendo uno en randon, o el núcleo menos utilizado porque cree que es un procesamiento de propósito general donde otros procesos están utilizando esos núcleos. En este caso, la optimización del planificador funciona en su contra (pero de una manera muy menor)
gbjbaanb
@Sid estuvo de acuerdo, solo estoy señalando que con HT obtendrás (en gran medida) rendimientos decrecientes mucho antes de lo que piensas, si asumiste que en realidad es algo así como una mejora del 100%. En este caso, podría ser fácilmente una disputa por su HD lo que está causando esto, de ahí mi sugerencia anterior para algunos puntos de referencia de CPU artificial.
Daniel B
6

Solo hay una posible razón para que esto suceda, que es que su sobrecarga excede sus ganancias.

Puede estar emulando los múltiples núcleos, en lugar de asignar núcleos reales o incluso procesos o incluso subprocesos desde la máquina host. Eso me parece bastante probable, y obviamente te dará una aceleración negativa.

La otra posibilidad es que el proceso en sí mismo no se paralelice bien, e incluso intentar hacerlo en paralelo le está costando más en gastos generales de comunicación de lo que está ganando.

filosodad
fuente
your overhead is exceeding your gains: Es cierto, pero eso cubre casi todo sin saber lo que realmente lo está causando :) ... Estoy usando VirtualBox y tengo los núcleos físicos, por lo que asumí que el mapeo debería ser 1: 1 sin emulación. Voy a buscar un VS2012 de código abierto GRANDE para que otros puedan consultarlo también ... brb
DeepSpace101
@Sid de acuerdo con esta respuesta superuser.com/a/297727 el virtualbox VM debe utilizar los núcleos de acogida adecuada. Pero aún verificaría lo que está sucediendo en el host, para asegurarme de que se está produciendo el comportamiento esperado.
philosodad
0

No estas solo ...

Lo mismo me ha sucedido antes con Java usando Maven 3.x para compilar en un i3. Dejarlo predeterminado en "4" subprocesos fue mucho más lento, casi un 50% más lento, que decirle explícitamente que solo use 2 núcleos.

Creo que tiene algo que ver con el cambio de contexto de subprocesamiento y la superposición de E / S.

Tiene sentido cuando empiezas a pensar en ello. Puede probar qué está causando la degeneración de resultados con una buena herramienta de creación de perfiles en todo el sistema.


fuente