Na programação de software, seria possível ter cargas de CPU e GPU a 100%?

43

Esta é uma pergunta geral sobre um assunto que achei interessante como jogador: gargalos e programação de CPU / GPU. Se não me engano, passei a entender que tanto a CPU quanto a GPU calculam as coisas, mas essa é melhor em alguns cálculos do que na outra devido à diferença na arquitetura. Por exemplo, quebrar hashes ou mineração de criptomoedas parece muito mais eficiente em GPUs do que em CPUs.

Então eu imaginei: ter uma GPU com 100% de carga enquanto a CPU está a 50% (por exemplo) inevitável?

Ou, mais precisamente: Alguns cálculos que normalmente são feitos pela GPU podem ser feitos pela CPU se a primeira estiver com 100% de carga, de modo que ambos alcancem uma carga de 100%?

Eu procurei um pouco sobre o assunto, mas voltei de mãos vazias. Penso e espero que isso tenha o seu lugar nesta subseção e esteja aberto a qualquer documentação ou palestra que você possa me dar!

    
por MadWard 24.06.2016 / 11:06
fonte

7 respostas

62

Teoricamente sim, mas praticamente não vale a pena.

Ambas as CPUs e GPUs são turing-complete , então qualquer algoritmo que pode ser calculado por um também pode ser calculado o outro. A questão é quão rápido e conveniente.

Enquanto a GPU se destaca em fazer os mesmos cálculos simples em muitos pontos de dados de um grande conjunto de dados, a CPU é melhor em algoritmos mais complexos com muitas ramificações. Com a maioria dos problemas, a diferença de desempenho entre as implementações de CPU e GPU é enorme. Isso significa que usar um para tirar o trabalho do outro quando está parado não levaria a um aumento notável no desempenho.

No entanto, o preço que você tem que pagar por isso é que você precisa programar tudo duas vezes, uma para a CPU e outra para a GPU. Isso é mais que o dobro do trabalho, porque você também terá que implementar a lógica de comutação e sincronização. Essa lógica é extremamente difícil de testar, porque seu comportamento depende da carga atual. Espera-se muito obscuro e impossível reproduzir bugs dessa cena.

    
por 24.06.2016 / 11:14
fonte
36

Não está relacionado à programação de jogos. Alguns códigos científicos também podem usar a GPU e a CPU.

Com programação cuidadosa e dolorosa, por ex. usando OpenCL ou CUDA , você pode carregar sua GPU e sua CPU perto de 100%. Muito provavelmente você precisará escrever diferentes partes de código para a GPU (o chamado código "kernel") e para a CPU, e algum código de cola chato (especialmente para enviar para a GPU o código compilado do kernel).

No entanto, o código seria complexo e você provavelmente precisará ajustá-lo ao hardware em particular no qual está sendo executado, especialmente porque a transmissão de dados entre GPU & A CPU é cara.

Leia mais sobre computação heterogênea .

Veja também OpenACC , suportado por versões recentes do GCC (por exemplo, GCC 6 em junho de 2016)

    
por 24.06.2016 / 11:11
fonte
11

De um ponto de vista de supercomputação, é melhor não pensar em porcentagem de CPU / GPU, mas sim determinar quantas operações seu problema precisa e depois compará-lo ao desempenho máximo do sistema.

Se você obtiver 100% de utilização da CPU, isso não significa necessariamente que você obtenha todo o desempenho do sistema. As CPUs geralmente podem fazer várias coisas diferentes ao mesmo tempo, digamos uma divisão e uma adição. Se você puder iniciar a divisão mais cedo, ela poderá ser sobreposta com a adição. Sua CPU de desktop provavelmente tem uma unidade fora de ordem que irá reordenar as instruções para se beneficiar de tais sobreposições. Ou se você tiver o seguinte programa:

if (expr1)
    expr2;
else
    expr3;

Um reordenamento da CPU tentará calcular as três expressões ao mesmo tempo e depois descartará o resultado de uma delas. Isso torna mais rápido em geral. Se você tem algum bloqueador em seu programa e não pode reordená-lo, então você está utilizando menos pistas na CPU, mas provavelmente ele ainda mostrará 100%.

Então você tem recursos SIMD nas CPUs, que são operações vetoriais. É como o GPGPU-light, no sentido de que você normalmente só tem quatro ou oito operações ao mesmo tempo, as GPUs têm 32 ou 64. Ainda assim, você tem que usar isso para ativar os FLOPS.

Coisas como o compartilhamento falso podem levar a um custo de sincronização pesado, que geralmente aparece como carga do kernel no Linux. A CPU é completamente usada, mas você não tem muito processamento útil.

Eu fiz alguma programação em uma máquina IBM Blue Gene / Q. Tem muitos níveis hierárquicos ( esquema de desatualizado Blue Gene / L ) e é Portanto, é difícil programar com eficiência. Você terá que usar a hierarquia completa até SIMD e SMT (Intel chama isso de HyperThreading) para obter o desempenho.

E a rede geralmente limita você. Portanto, verifica-se que é mais rápido no tempo (relógio de parede) calcular as coisas em várias CPUs ao mesmo tempo, em vez de comunicá-las pela rede. Isso colocará mais carga nas CPUs e fará o programa rodar mais rápido. Mas a taxa de transferência real do programa não é tão boa quanto parece nos números brutos.

Se você adicionar GPUs ao mix, ficará ainda mais difícil orquestrar tudo isso para gerar desempenho. Essa será uma das coisas que vou começar a fazer na minha tese de mestrado da QCD da Lattice em alguns meses.

    
por 24.06.2016 / 16:02
fonte
1

Você pode estar interessado em conferir o mecanismo de navegador Servo que está sendo desenvolvido na Mozilla Research e, mais especificamente, Web Render (vídeo) .

Embora a transferência de uma tarefa da CPU para a GPU dinamicamente possa ser impraticável, como mencionado em outras respostas (principalmente do Philip), pode ser prático estudar a carga da CPU / GPU em cargas de trabalho típicas com antecedência e alternar alguns tarefas para o geralmente menos carregado.

No caso do Web Render, a novidade é que tradicionalmente os navegadores fazem a maior parte de sua renderização funcionar na CPU (isto é, a CPU é usada para computar quais objetos exibir, onde cortar, etc ...). A GPU normalmente é melhor nisso ... exceto que nem todos os casos de uso são triviais para implementar (seleção parcial, sombras, ... e texto).

Uma versão inicial do Web Render mostrou grande sucesso no aumento de desempenho, mas não tentou resolver o problema da renderização de texto (e tinha algumas outras limitações). A Mozilla Research está agora trabalhando em uma segunda versão que tem menos limitações e, principalmente, suporte à renderização de texto.

O objetivo, claro, é descarregar o máximo possível do processo de renderização para a GPU, deixando a CPU livre para executar o Javascript, atualizar o DOM e todas as outras tarefas.

Portanto, apesar de não ser tão extremo quanto a sua sugestão, ele vai na direção de projetar uma estratégia de computação com tanto CPU e GPU em mente.

    
por 24.06.2016 / 17:10
fonte
0

Com foco nos jogos (desde que você mencionou especificamente em sua postagem), há algumas maneiras de equilibrar a carga. Um exemplo é "esfolar", ou seja, animar um modelo. Para cada quadro a ser renderizado, você precisa gerar as matrizes de transformação para cada quadro de animação e aplicá-lo aos vértices do modelo para transformá-lo na posição em que ele precisa estar. Você também precisa interpolar os quadros para obter um movimento suave. , a menos que você queira que sua animação pareça com o Quake original (ou seja, jerky).

Nesta situação, você pode fazer isso na CPU e carregar os resultados na GPU para renderização, ou fazer o cálculo e a renderização na GPU. Acredito que hoje em dia isso é feito na GPU (conhecida como "skinning"): faz sentido fazê-lo, pois você tem cálculos relativamente simples que precisam ser executados milhares de vezes, e cada vértice pode ser calculado simultaneamente desde o resultado do vértice A não tem qualquer influência sobre o resultado do vértice B.

Em teoria, no entanto, você poderia alternar dinamicamente entre fazê-lo na CPU ou na GPU, dependendo da sobrecarga da GPU e da CPU.

O principal bloqueador para fazer isso em todos os cálculos, no entanto, é que a CPU e a GPU têm diferentes pontos strongs e fracos. Tarefas maciçamente paralelas são feitas melhor na GPU, enquanto tarefas lineares intensivas com ramificação são mais bem feitas na CPU. Apenas alguns trabalhos poderiam ser realisticamente feitos em ambos, sem um sério desempenho.

No geral, o principal problema com a programação da GPU (pelo menos com OpenGL e DirectX 11 e abaixo) é que você tem pouco controle sobre como a GPU interpreta seu código de shader. Ramificar dentro de um shader é arriscado porque se você acidentalmente criar uma dependência entre cálculos, a GPU pode decidir começar a renderizar seus pixels um a um, transformando 60fps a 10fps em um instante, apesar dos dados reais serem renderizados sendo idênticos. / p>     
por 24.06.2016 / 14:32
fonte
0

Um exemplo do mundo real é o mecanismo de renderização de código aberto LuxRender , que é capaz de carregar totalmente uma CPU e GPU em o mesmo tempo. Além disso, ele pode carregar várias GPUs ao mesmo tempo e também pode distribuir em vários computadores.

O LuxRender usa o OpenCL para facilitar isso, embora existam construções sem o OpenCL.

Isso é prático porque os algoritmos que o LuxRender usa são altamente paralelizáveis. O algoritmo mais comum usado pelo LuxRender é o rastreamento de caminho , onde muitos caminhos de luz individuais podem ser computados independentemente um do outro - uma situação ideal para computação GPU e uma que não requer sincronização complexa entre nós de computação. No entanto, as limitações das GPUs (menor quantidade de memória, falta de suporte para alguns recursos de renderização complexos e falta geral de disponibilidade para alguns artistas) garantem que o suporte à CPU ainda seja essencial.

    
por 26.06.2016 / 00:18
fonte
0

Sim, certamente é possível.

Qualquer cálculo que uma CPU pode fazer, uma GPU também pode fazer, e vice-versa.

Mas é incomum porque:

  • Complexidade de engenharia Embora seja possível executar o mesmo código em uma CPU e GPU (por exemplo, CUDA), os processadores têm diferentes habilidades e características de desempenho. Um é o MIMD; o outro, SIMD. O que é rápido em um é lento no outro (por exemplo, ramificação), então você precisa escrever código separado para maximizar o desempenho.

  • As GPUs com eficiência de custo são agregadas muito mais poderosas que as CPUs. A idéia geral das GPUs é usar processadores mais baratos, mais lentos, porém mais numerosos, para executar cálculos muito mais rápido do que os processadores poderiam pelo mesmo custo. As GPUs são mais eficientes em relação ao custo em uma ou duas ordens de magnitude.

Se você conseguir que seu algoritmo seja executado em GPUs, apenas faz mais sentido otimizar para eles e adicionar quantos você precisar.

    
por 26.06.2016 / 20:45
fonte