Instâncias vs. núcleos ao usar o EC2

12

Trabalhando no que geralmente pode ser chamado de projetos de "dados médios", consegui paralelizar meu código (principalmente para modelagem e previsão em Python) em um único sistema, em qualquer lugar de 4 a 32 núcleos. Agora, estou analisando o dimensionamento de clusters no EC2 (provavelmente com StarCluster / IPython, mas aberto a outras sugestões também), e fiquei perplexo com a maneira de reconciliar o trabalho de distribuição entre núcleos em uma instância versus instâncias em um cluster.

É prático paralelizar as instâncias e os núcleos de cada instância? Em caso afirmativo, alguém pode dar um rápido resumo dos prós + contras da execução de muitas instâncias com poucos núcleos cada versus algumas instâncias com muitos núcleos? Existe uma regra prática para escolher a proporção correta de instâncias para núcleos por instância?

Largura de banda e RAM são preocupações não triviais em meus projetos, mas é fácil identificar quando esses são os gargalos e o reajuste. Imagino que seja muito mais difícil comparar a combinação certa de núcleos com instâncias sem testes repetidos, e meus projetos variam muito para que um único teste se aplique a todas as circunstâncias. Agradecemos antecipadamente e, se não consegui pesquisar corretamente no Google, sinta-se à vontade para me indicar a resposta certa em outro lugar!

Therriault
fonte

Respostas:

11

Ao usar o IPython, você quase não precisa se preocupar com isso (às custas de alguma perda de eficiência / maior sobrecarga de comunicação). O plug-in IPython paralelo no StarCluster, por padrão, iniciará um mecanismo por núcleo físico em cada nó (acredito que seja configurável, mas não tenho certeza de onde). Você apenas executa o que quiser em todos os mecanismos usando a API do DirectView (map_sync, apply_sync, ...) ou os comandos mágicos% px. Se você já estiver usando o IPython em paralelo em uma máquina, usá-lo em um cluster não será diferente.

Abordando algumas de suas perguntas específicas:

"como reconciliar o trabalho de distribuição entre núcleos em uma instância versus instâncias em um cluster" - Você obtém um mecanismo por núcleo (pelo menos); o trabalho é distribuído automaticamente em todos os núcleos e em todas as instâncias.

"É prático paralelizar as instâncias e os núcleos de cada instância?" - Sim :) Se o código que você está executando é embaraçosamente paralelo (exatamente o mesmo algo em vários conjuntos de dados), você pode ignorar principalmente onde um mecanismo específico está sendo executado. Se o núcleo exige muita comunicação entre os mecanismos, é claro que você precisa estruturá-lo para que os mecanismos se comuniquem principalmente com outros mecanismos na mesma máquina física; mas esse tipo de problema não é ideal para o IPython, eu acho.

"Em caso afirmativo, alguém pode dar um rápido resumo dos prós + contras da execução de muitas instâncias com poucos núcleos cada versus algumas instâncias com muitos núcleos? Existe uma regra prática para escolher a proporção certa de instâncias para núcleos por instância? " - Use as maiores instâncias c3 para problemas de limite de computação e a menor para problemas de largura de banda da memória; para problemas ligados à passagem de mensagens, use também as maiores instâncias, mas tente particionar o problema para que cada partição seja executada em uma máquina física e a maioria das passagens seja na mesma partição. Os problemas que seriam significativamente mais lentos nas instâncias N quádruplas c3 do que nas 2N duplas c3 são raros (um exemplo artificial pode estar executando vários filtros simples em um grande número de imagens, em que você passa por todas as imagens para cada filtro, em vez de todos os filtros para o mesma imagem).

Alex I
fonte
1
Eu acho que você deve observar que, para processos em uma única máquina, você pode mapear variáveis ​​de memória com joblib / Numpy. Você perde essa capacidade de processos em máquinas diferentes.
gallamine
11

Uma regra geral é não distribuir até que você precise. Geralmente, é mais eficiente ter N servidores com uma certa capacidade que 2N servidores com metade dessa capacidade. Mais do acesso a dados será local e, portanto, rápido na memória versus lento na rede.

Em um determinado momento, a expansão de uma máquina se torna antieconômica porque o custo de recursos adicionais é escalado mais do que linearmente. No entanto, este ponto ainda é surpreendentemente alto.

Porém, na Amazon, em particular, a economia de cada tipo de instância pode variar muito se você estiver usando instâncias do mercado spot. O preço padrão mais ou menos significa que a mesma quantidade de recursos custa aproximadamente a mesma, independentemente do tipo de instância, que pode variar muito; instâncias grandes podem ser mais baratas que as pequenas, ou N instâncias pequenas podem ser muito mais baratas que uma máquina grande com recursos equivalentes.

Uma consideração massiva aqui é que o paradigma de computação pode mudar bastante quando você muda de uma máquina para várias máquinas. As compensações induzidas pela sobrecarga de comunicação podem forçá-lo a, por exemplo, adotar um paradigma paralelo a dados para escalar. Isso significa uma escolha diferente de ferramentas e algoritmo. Por exemplo, o SGD parece muito diferente na memória e no Python do que no MapReduce. Então você teria que considerar isso antes de paralelizar.

Você pode optar por distribuir o trabalho em um cluster, mesmo que um único nó e paradigmas não distribuídos funcionem para você, para garantir a confiabilidade. Se um único nó falhar, você perde toda a computação; uma computação distribuída pode potencialmente recuperar e concluir apenas a parte da computação que foi perdida.

Sean Owen
fonte
6

Todas as coisas consideradas iguais (custo, desempenho da CPU, etc.), você pode escolher a menor instância que pode conter todos os meus dados na memória e expandir. Dessa maneira

  • certifique-se de não induzir latências desnecessárias devido a comunicações em rede e
  • você tende a maximizar a largura de banda de memória disponível geral para seus processos.

Supondo que você esteja executando algum tipo de esquema de validação cruzada para otimizar algum meta-parâmetro do seu modelo, atribua um valor a cada núcleo para testar e escolha várias instâncias, conforme necessário, para cobrir todo o espaço dos parâmetros em poucas rodadas, conforme desejar.

Se seus dados não couberem na memória de um sistema, é claro que você precisará distribuir entre instâncias. Então, é uma questão de equilibrar a latência da memória (melhor com muitas instâncias) com a latência da rede (melhor com menos instâncias), mas, dada a natureza do EC2, aposto que você prefere trabalhar com poucas instâncias gordas.

damienfrancois
fonte