OpenCL, CUDA, Brook: processamento usando a GPU

OpenCL, CUDA, Brook: processamento usando a GPU

Tradicionalmente, a diferença fundamental entre os processadores (CPUs) e os chipsets de vídeo (GPUs) é o fato de que as CPUs são otimizadas para cálculos sequenciais (executando aplicativos diversos), enquanto as GPUs são otimizadas para cálculos massivamente paralelos, processando gráficos 3D.

Antigamente, essa divisão era bem mais nítida, já que as placas 3D processavam apenas triângulos, texturas e efeitos simples. Entretanto, com a introdução do uso de shaders (que nada mais são do que pequenos aplicativos, destinados a executarem tarefas específicas na composição das cenas) elas ganharam a capacidade de também executarem código sequencial, assim como os processadores.

Você pode pensar no GT200 ou qualquer outro chip atual como blocos de vários pequenos processadores trabalhando em paralelo. Embora sejam otimizados para o processamento de gráficos 3D e shaders, eles podem ser usados para basicamente qualquer outra tarefa computacional, indo desde a decodificação de vídeos 1080p até aplicações científicas.

Não demorou para que a nVidia e a ATI percebessem o novo filão e passassem a investir no desenvolvimento de ferramentas de desenvolvimento capazes de liberar o potencial oculto das placas. A nVidia começou o ataque com o CUDA (suportado por todos os chipsets a partir do G80), a ATI respondeu com o Brook+ (suportado pelos chipsets a partir do R520) e em seguida surgiu o OpenCL, um padrão aberto que é suportado por ambas.

O CUDA permite acessar as funções das placas usando funções em C (C for CUDA), o que o torna uma ferramenta relativamente simples para desenvolvedores familiarizados com a linguagem. Existem também wrappers que permitem desenvolver em Java (jCUDA), C# (CUDA.NET) ou até mesmo Python (PyCUDA).

O Brook+ por sua vez é baseado na linguagem Brook, que é também uma variação do C, otimizado para computação paralela. Tanto o CUDA quanto o Brook+ oferecem uma boa flexibilidade e permitem gerar aplicativos bastante otimizados. O grande problema é o fato de cada um dos dois ser compatível com apenas uma das arquiteturas.

O OpenCL é uma espécie de primo-irmão do OpenGL, que apesar de não ser mais tão usado em jogos (perdendo espaço para o DirectX) é o mais usado em aplicações profissionais. Ambos são desenvolvidos pelo Khronos Group, uma associação de fabricantes destinada a desenvolver padrões abertos. Ele permite não apenas o uso de GPUs, mas também de outros chips aceleradores (como processadores Cell) o que o torna uma opção mais ou menos universal.

cuda_html_m3f8d33ab

À primeira vista, a escolha do OpenCL parece óbvia, já que com ele seria possível desenvolver aplicativos que poderiam ser usados em qualquer GPU, em vez de desenvolver uma versão para placas da nVidia e outra para placas da ATI. Entretanto, na prática a escolha é um pouco mais complicada, já que o OpenCL oferece funções e extensões que são específicas para cada família.

Embora seja perfeitamente possível desenvolver aplicativos genéricos em OpenCL, isso implica em nivelar por baixo, utilizando apenas as funções mais comuns, o que resulta em um desempenho longe do ideal. Por outro lado, ao otimizar para uma família de placas, perde-se a compatibilidade com a outra, o que obriga os desenvolvedores a duplicarem grande parte do código dos aplicativos, um trabalho que acaba não sendo tão diferente assim de desenvolver duas versões separadas.

Para complicar, teremos também suporte a processamento paralelo no DirectX11 (que será mais uma solução aplicada às duas famílias, com suporte a várias famílias de placas, assim como no caso do Direct3D) e também o Larrabee da Intel, que se comportará como uma GPU, mas poderá ser programado diretamente em C ou C++. Como pode ver, este é ainda um ramo em franca expensão, onde muita coisa vai acontecer.

Além da questão da linguagem, existe também o desafio de otimizar o código para o uso de computação paralela, adaptando-o para as características de uma GPU.

Embora os potenciais benefícios sejam grandes, as dificuldades também são, já que o desenvolvimento de aplicativos massivamente paralelos exige não apenas um bom domínio da linguagem escolhida, mas toda uma nova metodologia de desenvolvimento, especialmente em situações onde o paralelismo não é óbvio, como no caso de filtros gráficos e algoritmos de encriptação. Basta ter em mente que apenas uma pequena porção dos aplicativos são capazes de extrair o máximo de desempenho de processadores com 4 núcleos, o que dizer então de uma GPU com 320 unidades de processamento.

Alguns exemplos de tarefas que podem ser beneficiadas pelo uso de uma GPU são aplicativos de edição e conversão de vídeo e áudio, aplicativos de edição de imagens em geral e aplicativos como o Seti@Home e Folding@Home que executam um grande volume de operações matemáticas.

Embora o ganho varie muito, em algumas situações as GPUs realmente se sobressaem. Uma GeForce 9600 GT é duas vezes mais rápida que um Core 2 Duo E6700 ao codificar vídeos em H.264 usando o PowerDirector 7 (otimizado para o CUDA) e quase 6 vezes mais rápida no SETI@Home, por exemplo. Você pode ver alguns números aqui.

Existem muitas diferenças na arquitetura de uma CPU e uma GPU. Algumas das diferenças mais notáveis são que as GPUs operam a frequências de clock muito mais baixas, mas em troca possuem um poder bruto de processamento muito maior, devido ao uso de múltiplas unidades de processamento. Enquanto um processador atual dedica a maior parte dos transistores aos caches, a arquitetura paralela das GPUs permite que elas dediquem a maior parte às unidades de processamento propriamente ditas, utilizando apenas pequenas quantidades de cache L1. Com isso, o percentual de transístores “úteis” em uma GPU é muito maior, o que explica o maior poder de processamento bruto por ciclo de clock.

card

Em tese, seria possível executar o sistema operacional e aplicativos de uso geral diretamente em uma GPU, mas isso exigiria que tudo (do chipset e o BIOS da placa mãe ao sistema operacional e os aplicativos) fossem adaptados e, mesmo assim, o desempenho no final seria muito baixo, pois eles são exatamente o tipo de tarefa onde as GPUs são mais fracas. Em resumo, não existe a possibilidade de as GPUs substituírem os processadores, pois as duas arquiteturas se complementam.

A tendência para o futuro é que os processadores passem a incorporar unidades de processamento paralelas, passando a executar as duas funções. Em outras palavras, os processadores do futuro terão GPUs integradas e serão capazes de desempenhar os dois tipos de tarefas. As placas 3D offboard não irão desaparecer, mas elas se tornarão periféricos mais especializados, reservados à aplicações de alto desempenho.

A AMD tem trabalhado no Fusion, enquanto a Intel vem silenciosamente desenvolvendo o Larrabee, sem falar nas iniciativas da nVidia e até mesmo da VIA. Não é difícil de imaginar que no futuro os softwares serão capazes de detectar se uma GPU está presente e usá-la para executar tarefas otimizadas, reduzindo o uso do processador principal. A GPU se tornará mais um processador auxiliar, assim como no caso dos processadores aritméticos, incorporados na época do 486.

Sobre o Autor

Redes Sociais:

Deixe seu comentário

X