Pesquisei processadores e placas gráficas e descobri que as GPUs são muito mais rápidas que as CPUs. Li neste artigo que uma GPU Nvidia de 2 anos superou em 14 vezes o processador Intel Core I7 de 3,2 GHz por 14 vezes em determinadas circunstâncias. Se as GPUs são tão rápidas, por que os desenvolvedores não as usam para todas as funções de um jogo? É possível que as GPUs façam outra coisa que não gráficos?
63
GPU is faster than a CPU
é um falso mito no qual muitas pessoas são levadas a acreditar depois de ver benchmarks baseados em problemas especificamente voltados para a GPU (essa classe de problemas é chamada de "problemas paralelos embaraçosamente paralelos"), veja minha resposta nesta pergunta do superusuário: Por que ainda estamos usando CPUs em vez de GPUs?Respostas:
"Eu li que os carros de F1 são mais rápidos do que aqueles que dirigimos nas ruas ... por que as pessoas não usam carros de F1 então?" Bem ... A resposta a esta pergunta é simples: os carros de F1 não podem quebrar ou girar tão rápido quanto a maioria dos carros (o carro mais lento poderia vencer um F1 nesse caso). O caso das GPUs é muito semelhante, elas são boas em seguir uma linha reta de processamento, mas não são tão boas quando se trata de escolher diferentes caminhos de processamento.
Um programa executado na GPU faz sentido quando deve ser executado várias vezes em paralelo, por exemplo, quando você precisa misturar todos os pixels da Textura A com pixels da Textura B e colocá-los todos na Textura C. Essa tarefa, quando executada em uma CPU, seria processado da seguinte forma:
Mas isso é lento quando você precisa processar muitos pixels; portanto, a GPU, em vez de usar o código acima, apenas usa o próximo:
e preenche todos os núcleos com este programa (essencialmente copiando o programa para o núcleo), atribuindo um valor
i
para cada um. Então é aí que vem a mágica da GPU e faz com que todos os núcleos executem o programa ao mesmo tempo , realizando muitas operações muito mais rapidamente do que o programa de CPU linear poderia fazer.Essa maneira de trabalhar é boa quando você precisa processar da mesma maneira muitas entradas pequenas, mas é muito ruim quando você precisa criar um programa que possa ter ramificações condicionais. Então agora vamos ver o que a CPU faz quando se trata de alguma verificação de condição:
Isso é muito rápido para a CPU definir um índice, mas para a GPU fazer o mesmo, é muito mais complicado. Como o poder da GPU vem da execução da mesma instrução ao mesmo tempo (eles são núcleos SIMD), eles devem ser sincronizados para poder tirar proveito da arquitetura do chip. Ter que preparar a GPU para lidar com filiais implica mais ou menos:
Esse método pode variar com base em muitas coisas (ou seja, algumas muito pequenasas filiais podem ser executadas sem a necessidade dessa distinção), mas agora você já pode ver por que a ramificação seria um problema. Os caches da GPU são muito pequenos, você não pode simplesmente executar um programa a partir da VRAM de maneira linear, ele precisa copiar pequenos blocos de instruções para os núcleos a serem executados e se você tiver ramificações suficientes, sua GPU ficará mais parada do que executando. qualquer código, que não faz sentido quando se executa um programa que segue apenas uma ramificação, como a maioria dos programas, mesmo que seja executado em vários threads. Em comparação com o exemplo da F1, seria como abrir para-quedas de freio em cada esquina e sair do carro para guardá-los de volta no carro até a próxima esquina em que você deseja virar novamente ou encontrar um semáforo vermelho (a próxima esquina provavelmente).
É claro que há o problema de outras arquiteturas serem tão boas na tarefa de operações lógicas, muito mais baratas e mais confiáveis, padronizadas, mais conhecidas, com baixo consumo de energia, etc. As placas de vídeo mais recentes dificilmente são compatíveis com as mais antigas sem emulação de software. use instruções asm diferentes entre eles, mesmo sendo do mesmo fabricante, e que, por enquanto, a maioria dos aplicativos de computador não exige esse tipo de arquitetura paralela e, mesmo que precisem, eles podem usar através de APIs padrão, como OpenCL como mencionados pelo eBusiness, ou através das APIs gráficas. Provavelmente em algumas décadas teremos GPUs que podem substituir CPUs, mas não acho que isso aconteça tão cedo.
Eu recomendo a documentação do AMD APP, que explica muito sobre a arquitetura da GPU, e também vi sobre a NVIDIA nos manuais da CUDA, o que me ajudou muito a entender isso. Ainda não entendo algumas coisas e posso estar enganado, provavelmente alguém que sabe mais pode confirmar ou negar minhas declarações, o que seria ótimo para todos nós.
fonte
the fastest isn't always the fastest
.GPUs são muito boas tarefas paralelas. O que é ótimo ... se você estiver executando tarefas paralelas.
Os jogos são sobre o tipo de aplicativo menos paralelizável. Pense no loop principal do jogo. A IA (vamos supor que o jogador seja tratado como um caso especial da AI) precisa responder a colisões detectadas pela física. Portanto, ele deve ser executado posteriormente. Ou, no mínimo, a física precisa chamar rotinas de IA dentro dos limites do sistema de física (o que geralmente não é uma boa ideia por muitas razões). Os gráficos não podem ser executados até que a física seja executada, porque é a física que atualiza a posição dos objetos. Obviamente, a IA também precisa ser executada antes da renderização, pois pode gerar novos objetos. Os sons precisam ser executados após a IA e os controles do jogador
Em geral, os jogos podem se alinhar de muito poucas maneiras. Os gráficos podem ser desmembrados em um thread; o loop do jogo pode empurrar um monte de dados no segmento de gráficos e dizer: renderize this. Ele pode fazer alguma interpolação básica, para que o loop principal do jogo não precise estar sincronizado com os gráficos. O som é outro segmento; o loop do jogo diz "play this" e é reproduzido.
Depois disso, tudo começa a ficar dolorido. Se você tiver algoritmos de processamento complexos (como os de RTS), poderá encadear esses. Pode levar alguns quadros para que os algoritmos sejam concluídos, mas eles serão simultâneos pelo menos. Além disso, é bem difícil.
Então, você está analisando quatro tópicos: jogo, gráficos, som e possivelmente processamento de AI a longo prazo. Isso não é muito. E isso não é suficiente para GPUs, que podem ter literalmente centenas de threads em execução ao mesmo tempo. É isso que dá às GPUs seu desempenho: poder utilizar todos esses threads de uma vez. E os jogos simplesmente não podem fazer isso.
Agora, talvez você possa ir "longe" em algumas operações. As IAs, por exemplo, geralmente são independentes uma da outra. Assim, você pode processar várias dezenas de IAs ao mesmo tempo. Até que você realmente precise torná-los dependentes um do outro. Então você está com problemas. Objetos de física são igualmente independentes ... a menos que haja uma restrição entre eles e / ou colidem com alguma coisa. Então eles se tornam muito dependentes.
Além disso, há o fato de que a GPU simplesmente não tem acesso à entrada do usuário, o que, pelo que entendi, é meio importante para os jogos. Então isso teria que ser fornecido. Também não possui acesso direto a arquivos ou qualquer método real de comunicação com o sistema operacional; então, novamente, teria que haver algum tipo de maneira de fornecer isso. Ah, e todo esse processamento de som? GPUs não emitem sons. Então eles precisam voltar para a CPU e depois para o chip de som.
Ah, e a codificação para GPUs é terrível. É difícil acertar, e o que é "certo" para uma arquitetura de GPU pode estar muito, muito errado para outra. E isso não é apenas mudar da AMD para a NVIDIA; isso pode estar mudando de uma GeForce 250 para uma GeForce 450. Essa é uma mudança na arquitetura básica. E poderia facilmente fazer com que seu código não funcionasse bem. C ++ e até C não são permitidos; o melhor que você obtém é o OpenCL, que é parecido com o C, mas sem alguns detalhes. Como recursão . É isso mesmo: sem recursão nas GPUs.
Depurando? Ah, espero que você não goste dos recursos de depuração do IDE, porque esses certamente não estarão disponíveis. Mesmo se você estiver usando GDB, dê um beijo de despedida. Você terá que recorrer à
printf
depuração ... espere, não háprintf
GPUs. Portanto, você terá que gravar nos locais da memória e fazer com que seu programa de stub da CPU os leia novamente.É isso mesmo: depuração manual . Boa sorte com isso.
Além disso, essas bibliotecas úteis que você usa em C / C ++? Ou talvez você seja mais do tipo .NET, usando XNA e assim por diante. Como queiras. Não importa, já que você não pode usar nenhum deles na GPU. Você deve codificar tudo do zero. E se você já possui uma base de código, é difícil: é hora de reescrever todo esse código.
Então sim. É horrível fazer qualquer tipo de jogo complexo. E nem funcionaria, porque os jogos simplesmente não são paralelos o suficiente para ajudar.
fonte
Por que não é tão fácil de responder - é importante observar que as GPUs são processadores especializados que não são realmente destinados ao uso generalizado como uma CPU comum. Devido a essa especialização, não é de surpreender que uma GPU possa superar uma CPU pelas coisas para as quais foi especificamente projetada (e otimizada), mas isso não significa necessariamente que possa substituir a funcionalidade e o desempenho completos de uma CPU generalizada.
Suspeito que os desenvolvedores não façam isso por vários motivos, incluindo:
Eles querem que os gráficos sejam da qualidade mais rápida e mais alta possível, e o uso de recursos valiosos da GPU pode interferir nisso.
O código específico da GPU pode ter que ser escrito, e isso provavelmente introduzirá complexidade adicional na programação geral do jogo (ou aplicativo) em questão.
Uma GPU normalmente não tem acesso a recursos como placas de rede, teclados, mouses e joysticks; portanto, não é possível lidar com todos os aspectos do jogo.
Em resposta à segunda parte da sua pergunta: Sim, existem outros usos. Por exemplo, projetos como o SETI @ Home (e provavelmente outros projetos BOINC) estão usando GPUs (como os da nVidia) para cálculos complexos de alta velocidade:
Execute o SETI @ home em sua GPU NVIDIA
http://setiathome.berkeley.edu/cuda.php
( Gostei da sua pergunta porque ela apresenta uma ideia interessante. )
fonte
As CPUs são mais flexíveis, geralmente é mais fácil programá-las, elas podem executar threads únicos muito mais rapidamente.
Embora as GPUs modernas possam ser programadas para resolver praticamente qualquer tarefa, elas apenas obtêm uma vantagem de velocidade quando podem utilizar sua arquitetura paralela. Geralmente é o caso de tarefas "simples" altamente repetitivas. Muito do código que escrevemos é ramificado de maneira imprevisível para executar com eficiência em uma GPU.
Além disso, você pode gastar muito tempo otimizando o código para diferentes chips gráficos. Embora o OpenCL esteja disponível para executar o mesmo código em vários chips gráficos diferentes, você trocará algumas das vantagens de velocidade por esse luxo.
Do ponto de vista do programador de jogos, geralmente também queremos que o jogo seja executado em computadores com placas gráficas menores. Alguns dos chips integrados não têm a capacidade de programação necessária, mas, se o fizerem, são tão lentos que não vencerão o processador por uma margem muito grande, mesmo para o tipo de trabalho em que devem ser bons. E, é claro, se você utilizasse uma GPU de gama baixa para um jogo, obteria o poder de processamento necessário da renderização gráfica.
De fato, as perspectivas são ótimas, mas quando você está criando um jogo, em vez de decifrar senhas, os problemas práticos na maioria dos casos superam os benefícios.
fonte
GPU são muito difíceis de programar. Você deve pesquisar como classificar uma lista em uma GPU . Muitas teses têm pesquisa para fazê-lo.
Usar uma CPU com um thread é fácil, usar multi-threads é mais difícil, usar muitos computadores com biblioteca paralela, pois o PVM ou o MPI é difícil e o uso de uma GPU é o mais difícil.
fonte
Além do que Randolf Richardson respondeu existem algumas funcionalidades que os processadores GPU não conseguem lidar sozinhos. Por exemplo, alguns dos comandos de gerenciamento de memória gráfica são processados pela CPU, pois a GPU não pode lidar com eles.
E há outro grande motivo: a GPU foi projetada para cálculos multithread. Isso significa que os fabricantes de GPU podem facilmente adicionar núcleos sempre que quiserem aumentar o poder computacional. Mas há muitas tarefas que não podem ser divididas em problemas menores, como calcular o número n- ésimo da série Fibonacci . Nessas situações, a CPU é muito mais rápida, pois é mais otimizada para tarefas de thread único.
fonte
Há muitas respostas sugerindo que as GPUs são mais rápidas porque lidam com tarefas em paralelo. Isso está exagerando um pouco a questão. As GPUs podem ser mais eficientes por outros motivos, como poder ter acesso mais restritivo à memória, não ter que suportar tantos tipos de dados, ter um conjunto de instruções mais eficiente etc. As primeiras GPUs ainda podiam desenhar apenas 1 pixel a uma vez, mas era o fato de que eles podiam fazer 1 a cada ciclo que era importante.
A diferença real é que são dois tipos diferentes de máquinas que são personalizadas para executar bem em diferentes categorias de tarefas que parecem semelhantes, mas na verdade são bem diferentes. É como comparar um avião a um carro. O avião tem uma velocidade máxima muito mais alta, mas tem mais restrições sobre como pode ser usado. Nas ocasiões em que você pode fazer a mesma jornada com qualquer um dos tipos, o avião parece superior.
fonte
Os desenvolvedores fazem usam GPUs para todas as funções que são bons. Eles usam CPUs para todas as funções em que são bons. O que faz você pensar que não?
As GPUs são boas em tarefas que podem ser maciçamente paralelizadas e requerem grandes quantidades de computação, com baixos requisitos de memória ou alta correlação temporal, com apenas pequenas quantidades de tomada de decisão. Isso inclui renderizar imagens, simulações de física (partículas, colisão, tecido, água, reflexão) e assim por diante. Portanto, é exatamente para isso que os jogos modernos usam a GPU.
As CPUs são boas em tarefas que não se adaptam bem e exigem grandes quantidades de tomada de decisão. Eles podem tolerar altos requisitos de memória, mesmo com apenas correlação temporal moderada. Isso inclui inteligência artificial, interface do usuário, E / S de disco e rede e assim por diante. Portanto, é exatamente para isso que os jogos modernos usam a CPU.
fonte
O readback é outro motivo pelo qual penso ocasionalmente preferindo a CPU. Não em termos de largura de banda (como GPU-> largura de banda da CPU não é tanto um problema no hardware moderno), mas em termos de paralisar o pipeline. Se você precisar recuperar os resultados de uma computação e fazer algo interessante ou útil com eles, o uso da GPU não é uma escolha sábia (no caso geral - haverá casos especiais em que pode permanecer apropriado), pois a leitura sempre exigirá a GPU pare o que estiver fazendo, limpe todos os comandos pendentes e aguarde a conclusão da readback. Isso pode prejudicar o desempenho na medida em que não apenas elimina os benefícios do uso da GPU, mas pode ser consideravelmente mais lento.
fonte
Este é um tópico antigo, mas este artigo publicado recentemente pode responder a essa pergunta. Este artigo, publicado no ACM Computing Surveys 2015, mostra que cada uma das CPUs e GPUs tem suas vantagens exclusivas e, portanto, este documento justifica a mudança do paradigma "CPU vs GPU" para o paradigma "computação colaborativa CPU-GPU".
Uma pesquisa sobre técnicas de computação heterogênea CPU-GPU
fonte