Esta é uma pergunta geral sobre um assunto que achei interessante como jogador: gargalos na CPU / GPU e programação. Se não me engano, entendi que tanto a CPU quanto a GPU calculam coisas, mas essa é melhor em alguns cálculos que no outro 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 me perguntei: ter uma GPU com carga de 100% enquanto a CPU é de 50% (por exemplo) é inevitável?
Ou, mais precisamente: alguns cálculos que normalmente são feitos pela GPU podem ser feitos pela CPU se o primeiro estiver com 100% de carga, para que ambos atinjam uma carga de 100%?
Eu pesquisei um pouco sobre o assunto, mas voltei de mãos vazias. Penso e espero que isso tenha seu lugar nesta subseção e esteja aberto a qualquer documentação ou palestra que você possa me dar!
fonte
NO-OP
s ao mesmo tempo, o que fará com que ambos tenham uma carga de 100%.Respostas:
Teoricamente sim, mas na prática raramente vale a pena.
As CPUs e as GPUs estão completas , portanto, qualquer algoritmo que possa ser calculado por um também pode ser calculado pelo 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. Na 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 a pagar é que você precisa programar tudo duas vezes, uma para a CPU e outra para a GPU. Isso é mais do que o dobro de trabalho, porque você também precisará 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. Espere muito obscuro e impossível reproduzir bugs deste golpe.
fonte
Não está relacionado à programação de jogos. Alguns códigos científicos também podem usar a GPU e a CPU.
Com uma programação cuidadosa e dolorosa, por exemplo, 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 (principalmente para enviar à GPU o código do kernel compilado).
No entanto, o código seria complexo e você provavelmente precisará ajustá-lo ao hardware específico em que está executando, principalmente porque a transmissão de dados entre GPU e 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)
fonte
Do ponto de vista da supercomputação, é melhor não pensar na porcentagem de carga da CPU / GPU, mas sim determinar quantas operações o seu problema em questão precisa e depois comparar isso com o desempenho máximo do sistema.
Se você obtiver 100% de utilização da CPU, isso não significa necessariamente que você obtém todo o desempenho do sistema. Muitas vezes, as CPUs podem fazer várias coisas diferentes ao mesmo tempo, digamos uma divisão e uma adição. Se você pode iniciar a divisão mais cedo, ela poderá se sobrepor à adição. A CPU da sua área de trabalho provavelmente possui uma unidade fora de ordem que reordenará as instruções para se beneficiar dessas sobreposições. Ou se você possui o seguinte programa:
Uma CPU reordenada tentará calcular as três expressões ao mesmo tempo e depois descartará o resultado de uma delas. Isso o torna mais rápido no geral. Se você possui algum bloqueador em seu programa e não pode reordenar, está utilizando menos faixas na CPU, mas provavelmente ainda mostrará 100%.
Então você tem recursos SIMD nas CPUs, que são operações vetoriais. É como 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ê precisa usá-lo para acionar os FLOPS.
Coisas como compartilhamento falso podem levar a um alto custo de sincronização que geralmente aparece como carga de kernel no Linux. A CPU é completamente usada, mas você não possui muita taxa de transferência útil.
Eu fiz alguma programação em uma máquina IBM Blue Gene / Q. Possui muitos níveis hierárquicos ( esquemático do Blue Gene / L desatualizado ) e, portanto, é difícil de programar com eficiência. Você precisará usar a hierarquia completa até SIMD e SMT (a Intel chama isso de HyperThreading) para obter o desempenho.
E então a rede geralmente limita você. Portanto, é mais rápido no tempo (relógio de parede) computar coisas em várias CPUs ao mesmo tempo, em vez de comunicá-las pela rede. Isso colocará mais carga nas CPUs e tornará o programa mais rápido. Mas a taxa de transferência real do programa não é tão boa quanto parece dos números brutos.
Se você adicionar GPUs à mistura, será ainda mais difícil orquestrar tudo isso para obter desempenho. Essa será uma das coisas que começarei a fazer na minha dissertação de mestrado Lattice QCD em alguns meses.
fonte
Você pode estar interessado em verificar o mecanismo do navegador Servo que está sendo desenvolvido na Mozilla Research e, mais especificamente, na Web Render (vídeo) .
Embora a mudança dinâmica de uma tarefa da CPU para a GPU possa ser impraticável, como mencionado em outras respostas (principalmente na Philip), pode ser prático estudar antecipadamente a carga da CPU / GPU em cargas de trabalho típicas e alternar algumas tarefas para as geralmente menos carregadas 1.
No caso do Web Render, a novidade é que tradicionalmente os navegadores realizam a maior parte do trabalho de renderização na CPU (ou seja, a CPU é usada para calcular 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-se altamente bem-sucedida 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 agora está trabalhando em uma segunda versão que se destina a ter menos limitações e, principalmente, para suportar a 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 Javascript, atualizar o DOM e todas as outras tarefas.
Assim, embora não tão extrema como a sua sugestão, ele não ir para a direção da concepção de uma estratégia de computação com tanto CPU e GPU em mente.
fonte
Com foco nos jogos (desde que você o mencionou especificamente em sua postagem), existem algumas maneiras de equilibrar a carga. Um exemplo é "skinning", ou seja, animar um modelo. Para cada quadro a ser renderizado, você deve gerar as matrizes de transformação para cada quadro de animação e aplicá-lo aos vértices do modelo para transformá-lo na pose em que 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, irregular).
Nessa situação, você pode fazê-lo 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 "aparência de hardware"): faz sentido, 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 influência no resultado do vértice B.
No entanto, em teoria, você pode alternar dinamicamente entre fazê-lo na CPU ou GPU, dependendo da sobrecarga da GPU e da CPU.
O principal bloqueador para fazer isso em todos os cálculos, porém, é que a CPU e a GPU têm pontos fortes e fracos diferentes. Trabalhos paralelos maciços são mais bem executados na GPU, enquanto tarefas lineares intensivas com ramificação são mais bem executadas na CPU. Apenas alguns trabalhos poderiam ser feitos realisticamente em ambos sem um sério impacto no desempenho.
No geral, o principal problema da programação da GPU (pelo menos no OpenGL e DirectX 11 e abaixo) é que você tem pouco controle sobre como a GPU interpreta seu código de sombreador. Ramificar dentro de um sombreador é arriscado, porque se você criar acidentalmente uma dependência entre os cálculos, a GPU poderá decidir começar a renderizar seus pixels um por um, girando 60fps para 10fps em um instante, apesar dos dados reais serem idênticos.
fonte
Um exemplo do mundo real é o mecanismo de renderização de código aberto LuxRender , capaz de carregar totalmente uma CPU e GPU ao mesmo tempo. Além disso, ele pode carregar várias GPUs ao mesmo tempo e também pode distribuir entre vários computadores.
O LuxRender usa o OpenCL para facilitar isso, embora também existam compilações sem o OpenCL.
Isso é prático porque os algoritmos que o LuxRender usa são altamente paralelizáveis. O algoritmo mais comum que o LuxRender usa é o rastreamento de caminhos , onde muitos caminhos de luz individuais podem ser calculados independentemente um do outro - uma situação ideal para a computação da GPU e uma que não requer sincronização complexa entre os nós de computação. No entanto, as limitações das GPUs (quantidades menores de memória, falta de suporte para alguns recursos complexos de renderização e falta geral de disponibilidade para alguns artistas) garantem que o suporte à CPU ainda seja essencial.
fonte
Sim, certamente é possível.
Qualquer cálculo que uma CPU possa fazer, uma GPU também poderá fazer e vice-versa.
Mas é incomum porque:
Complexidade da engenharia Embora seja possível executar o mesmo código em uma CPU e GPU (por exemplo, CUDA), os processadores possuem 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 um código separado para maximizar o desempenho.
As GPUs de eficiência de custos são agregadas muito mais poderosas que as CPUs. Toda a idéia das GPUs é usar processadores mais baratos, mais lentos, mas mais numerosos, para realizar cálculos muito mais rápidos do que as CPUs pelo mesmo custo. As GPUs são mais eficientes em termos de custo em uma ou duas ordens de magnitude.
Se o seu algoritmo for executado em GPUs, faz mais sentido otimizar para elas e adicionar quantas você precisar.
fonte