Por que mais núcleos de CPU na máquina virtual retardariam o tempo de compilação?

17

[edit # 2] Se alguém do VMWare puder me encontrar com uma cópia do VMWare Fusion, ficarei feliz em fazer o mesmo que uma comparação entre VirtualBox e VMWare. De alguma forma, suspeito que o hipervisor VMWare será melhor ajustado para hyperthreading (veja minha resposta também)

Estou vendo algo curioso. À medida que aumenta o número de núcleos na máquina virtual Windows 7 x64, o tempo total de compilação aumenta em vez de diminuir. A compilação geralmente é muito adequada para processamento paralelo, pois na parte do meio (mapeamento pós-dependência), você pode simplesmente chamar uma instância do compilador em cada arquivo .c / .cpp / .cs / qualquer arquivo para criar objetos parciais para o vinculador sobre. Então, eu imaginaria que a compilação seria realmente muito bem dimensionada com o número de núcleos.

Mas o que estou vendo é:

  • 8 núcleos: 1,89 seg
  • 4 núcleos: 1,33 seg
  • 2 núcleos: 1,24 seg
  • 1 núcleo: 1,15 seg

Isso é simplesmente um artefato de design devido à implementação do hipervisor de um determinado fornecedor (type2: virtualbox no meu caso) ou algo mais difundido em mais VMs para tornar as implementações do hipervisor mais simples? Com tantos fatores, pareço ser capaz de argumentar a favor e contra esse comportamento - por isso, se alguém souber mais sobre isso do que eu, ficaria curioso para ler sua resposta.

Obrigado Sid

[ editar: endereçando comentários ]

@MartinBeckett: compilações a frio foram descartadas.

@MonsterTruck: Não foi possível encontrar um projeto de código aberto para compilar diretamente. Seria ótimo, mas não posso estragar meu env dev agora.

@ Sr. Lister, @ philosodad: Possui 8 threads de hw, usando o VirtualBox, portanto deve ser o mapeamento 1: 1 sem emulação

@Thorbjorn: Eu tenho 6,5 GB para a VM e um projeto pequeno do VS2012 - é bastante improvável que eu esteja trocando in / out a lixeira do arquivo de paginação.

@Todos: se alguém puder apontar para um projeto VS2010 / VS2012 de código aberto, isso pode ser uma referência de comunidade melhor do que o meu projeto VS2012 (proprietário). Orchard e DNN parecem precisar de ajustes no ambiente para compilar no VS2012. Eu realmente gostaria de ver se alguém com o VMWare Fusion também vê isso (para compartimentação VMWare vs VirtualBox)

Detalhes do teste:

  • Equipamento: Macbook Pro Retina
    • CPU: Core i7 a 2.3Ghz (quad core, hiperencadeado = 8 núcleos no gerenciador de tarefas do Windows)
    • Memória: 16 GB
    • Disco: SSD de 256 GB
  • Sistema operacional host: Mac OS X 10.8
  • Tipo de VM: VirtualBox 4.1.18 (hypervisor tipo 2)
  • SO convidado: Windows 7 x64 SP1
  • Compilador: VS2012 compilando uma solução com 3 projetos do Azure em C #
    • Medida dos tempos de compilação pelo plug-in VS2012 chamado 'VSCommands'
    • Todos os testes são executados 5 vezes, os 2 primeiros descartados, os 3 últimos em média
DeepSpace101
fonte
9
Provavelmente o arquivo I / O diminuir a velocidade com tarefas múltiplas e o acesso ao disco estar na unidade virtualizada
Martin Beckett
3
Eu gostaria de reproduzir isso na minha própria máquina. Você pode fazer o upload de um projeto de amostra em algum lugar? Eu suspeito que a máquina virtual está fazendo truques aqui. Tente inicializar no Windows nativamente (Bootcamp) e veja se você observa o mesmo comportamento - duvido que sim.
Apoorv Khurasia
1
O que estamos compilando aqui? Muito tempo, a sobrecarga de paralelizar uma tarefa não compensa até que você atinja determinada escala. Veja como compilar o apache ou o ravendb.
Wyatt Barnett
2
Você provavelmente fica sem memória na sua máquina virtual para que ela comece a trocar.
1
A mesma coisa aconteceu comigo antes com Java usando o Maven 3.x para compilar em um i3. Deixar o padrão "4" encadear era muito mais lento, quase 50% mais lento, do que dizer explicitamente para usar apenas 2 núcleos. Eu acho que tem algo a ver com o contexto de hyperthreading alternando e sobrepondo E / S.

Respostas:

12

Resposta: Não diminui a velocidade, aumenta com o número de núcleos da CPU. O projeto usado na pergunta original era "muito pequeno" (na verdade, é uma tonelada de desenvolvimento, mas pequeno / otimizado para um compilador) para colher os benefícios de vários núcleos. Parece que, em vez de planejar como espalhar o trabalho, gerar vários processos de compilador, etc., nessa pequena escala, é melhor martelar o trabalho em série logo de cara.

Isso se baseia no novo experimento que fiz com base nos comentários da pergunta (e na minha curiosidade pessoal). Usei um projeto maior do VS - o código-fonte do Umbraco CMS, pois é grande, de código aberto e é possível carregar diretamente o arquivo da solução e reconstruir (dica: carregar umbraco_675b272bb0a3\src\umbraco.slnno VS2010 / VS2012).

AGORA, o que vejo é o que espero, ou seja, compilações em escala !! Bem, até um certo ponto, desde que eu acho:

Tabela de resultados

Aprendizado:

  • Um novo núcleo da VM resulta em um novo thread do OS X dentro do processo do VirtualBox
  • Os tempos de compilação aumentam conforme o esperado (as compilações são longas o suficiente)
  • Em 8 núcleos de VM, a emulação de núcleo pode estar entrando no VirtualBox, pois a penalidade é enorme (50% de acerto)
  • O acima é provável porque o OS X não pode apresentar 4 núcleos hiperencadeados (8 h / w thread) como 8 núcleos no VirtualBox

Esse último ponto me levou a monitorar o histórico da CPU em todos os núcleos através do 'Activity Monitor' (histórico da CPU) e o que encontrei foi

Gráfico de histórico de CPU do OS X

Aprendizado:

  • Em um núcleo de VM, a atividade parece estar saltando pelos 4 núcleos de HW. Faz sentido distribuir o calor uniformemente nos níveis centrais.

  • Mesmo em 4 núcleos virtuais (e 27 threads no VirtualBox OS X ou ~ 800 threads no geral), apenas os segmentos HW pares (0,2,4,6) estão quase saturados, enquanto os segmentos HW ímpares (1,3,5,7) estão quase em 0%. É mais provável que o agendador funcione em termos de núcleos HW e threads NÃO HW, por isso especulo que talvez o kernel / agendador OSX de 64 bits não seja otimizado para CPU hiperencadeada? Ou olhando para a configuração do núcleo de 8VM, talvez ela comece a usá-los com uma alta% de utilização da CPU? Algo engraçado está acontecendo ... bem, essa é uma pergunta separada para alguns desenvolvedores de Darwin ...

[edit]: Eu adoraria tentar o mesmo no VMWare Fusion. As chances são de que não será tão ruim assim. Gostaria de saber se eles mostram isso como um produto comercial ...

Rodapé:

Caso as imagens desapareçam, o horário de compilação é (texto, feio!)

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
fonte
Suspeito que a queda entre 4 e 8 seja uma combinação da VM não otimizada para HT, e HT não seja de forma alguma o dobro do número de núcleos (no máximo, um aumento de desempenho de 30%, geralmente muito menos).
Daniel B
@DanielB: Com 4 => 8 núcleos, a questão não é apenas um mero aumento de + 30% (vs + 100%) como você sugeriu - é que o desempenho é realmente de -50%. Se os threads de hardware fossem totalmente 'inoperantes / inúteis' e o trabalho estivesse sendo desviado para os outros núcleos, o delta de desempenho seria 0. Portanto, eu estaria mais inclinado a dizer que é o design do hipervisor do VirtualBox tipo 2. Eu me pergunto como VMWare Fusion é ...
DeepSpace101
"Em um núcleo de VM, a atividade parece estar saltando pelos 4 núcleos de HW. Faz sentido distribuir o calor uniformemente nos níveis de núcleo" - não necessariamente, geralmente é melhor agendar novamente no mesmo núcleo (para cache etc.) mas o hipervisor está apenas escolhendo um na randon, ou o núcleo menos utilizado, porque considera um processamento de uso geral onde outros processos estão usando esses núcleos. Neste caso, a otimização programador trabalha contra você (mas de uma forma muito menor)
gbjbaanb
@Sid concordou, estou apenas apontando que, com o HT, você obterá (muito) retornos decrescentes muito mais cedo do que você imagina, se você assumisse que na verdade é algo como uma melhoria de 100%. Nesse caso, pode ser facilmente uma contenção para o seu HD que está causando isso, portanto, minha sugestão anterior para alguns benchmarks artificiais da CPU.
Daniel B
6

Há apenas uma razão possível para que isso aconteça: sua sobrecarga excede seus ganhos.

Você pode emular os vários núcleos, em vez de atribuir núcleos reais ou mesmo processos ou até threads da máquina host. Isso parece bastante provável para mim, e obviamente vai lhe dar uma aceleração negativa.

A outra possibilidade é que o processo em si não seja paralelo, e mesmo tentando paralelá-lo está custando mais em sobrecarga de comunicação do que você está ganhando.

philosodad
fonte
your overhead is exceeding your gains: Verdadeiro, mas que praticamente cobre tudo sem saber o que realmente está causando isso :) ... Estou usando o VirtualBox e tenho os núcleos físicos, então assumimos que o mapeamento deve ser 1: 1 sem emulação. Vou procurar um VS2012 de código aberto GRANDE para que outros possam fazer referência a ele também ... brb
DeepSpace101
@De acordo com esta resposta superuser.com/a/297727, a VM do Virtualbox deve usar os núcleos do host adequadamente. Mas eu ainda verificaria o que está acontecendo no host, para garantir que o comportamento esperado esteja ocorrendo.
philosodad
0

Você não está sozinho ...

A mesma coisa aconteceu comigo antes com Java usando o Maven 3.x para compilar em um i3. Deixar o padrão "4" encadear era muito mais lento, quase 50% mais lento, do que dizer explicitamente para usar apenas 2 núcleos.

Eu acho que tem algo a ver com o contexto de hyperthreading alternando e sobrepondo E / S.

Faz sentido quando você começa a pensar sobre isso. Você pode provar o que está causando a degeneração dos resultados com uma boa ferramenta de criação de perfil para todo o sistema.


fonte