Impulso para a programação da GPU

10

Eu sou muito novo na programação GPGPU, então, desculpe-me se a pergunta não for particularmente apropriada. Pelo que entendi, a programação da GPU é um trabalho muito complicado de engenharia, quando comparado à programação usual da CPU. É preciso ter muito cuidado com questões de divergência, lado a lado, alocação de memória fixada e sobreposição de comunicação / computação de dispositivo host.

Depois de fazer um pouco de pesquisa, encontrei a biblioteca de empuxo que parece tentar imitar o C ++ STL. Isso é bem legal. No entanto, com base em minha experiência muito limitada e tendo visto todo o microgerenciamento necessário para obter um bom desempenho, sou um pouco cético em relação ao desempenho. O impulso pode lidar com toda a parte intricada da programação de maneira eficiente? Algumas bibliotecas muito conhecidas, como o PETSc, parecem usar este pacote, o que me faz acreditar que de alguma forma deveria.

Eu queria saber se pessoas com mais experiência em CUDA e impulso poderiam dizer uma palavra ou duas sobre o desempenho do pacote quando comparado à programação CUDA de baixo nível. Quando posso usar o impulso e quando devo voltar para o CUDA?

GradGuy
fonte
Você já considerou o ArrayFire?
arrayfire

Respostas:

2

Não tenho experiência pessoal com empuxo, mas uso o ViennaCL, que é outra biblioteca de GPU de alto nível que oculta quase todos os detalhes. No meu próprio teste de desempenho pessoal, vejo acelerações de 2x a 40x no cálculo real, se você ignorar o tempo que leva para se movimentar na memória.

Quando você deve usar a CPU versus o impulso versus o CUDA, tudo depende do problema que você está resolvendo, da sua habilidade e do tempo disponível. Eu recomendaria começar resolvendo problemas simples com todos os três métodos para ver seu desempenho relativo. Em seguida, você pode escrever o software real de uma maneira rápida, compará-lo e aplicar o método gpu apropriado nas áreas que precisam de aceleração, em vez de perder tempo escrevendo o software CUDA que só lhe renderá alguns minutos de tempo de execução .

Godric Seer
fonte
Isso faz todo o sentido para mim. Sempre é preciso criar um perfil primeiro. Então, no seu exemplo, a velocidade que você obteve foi usando o ViennaCL. Você já tentou o OpenCL direto para verificar a diferença?
GradGuy
Não, como você, eu sou novo na computação GPU. Planejo, ao longo dos próximos dois anos, expandir lentamente minhas habilidades para incluir CUDA e OpenCL, mas atualmente apenas uso a biblioteca. A documentação da ViennaCL afirma que seria possível acelerar ainda mais com uma implementação openCL ajustada que provavelmente seria da ordem de mais de 2x-10x, no entanto, aprendi que a largura de banda da memória é o gorila de 900 libras na sala que realmente define seu desempenho.
Godric Seer
5

Eu usei Thrust no meu projeto de expansão de cluster vinculado. Dependendo da situação, o Thrust pode ter um desempenho tão bom quanto ou melhor que uma implementação de baixo nível que você executa (em particular, o reducekernel tem funcionado muito bem para mim). No entanto, a natureza genérica e a flexibilidade do Thrust significa que às vezes é necessário fazer muitas cópias extras, preenchimento de array etc., o que pode atrasá-lo bastante em alguns casos extremos. A última vez que o usei sortfoi bastante lenta em comparação com outras bibliotecas, como b40c ou mgpu. No entanto, a NVIDIA tem trabalhado para melhorar o desempenho algorítmico da Thrust, para que isso possa ser um problema menor no futuro.

Você deve tentar escrever seu código usando Thrust e CUDA e, em seguida, usando o Visual Profiler para determinar qual é o melhor para a tarefa específica em que está interessado. Se é provável que a transferência de memória ocupe o maior tempo de execução do seu programa e você não não precisa se preocupar em otimizar seus próprios kernels para conflitos bancários, contagem de instruções, etc., então eu usaria o Thrust. Ele também tem a vantagem de tornar seu código muito menos detalhado e fácil para as pessoas que não estão familiarizadas com a programação da GPU.

limas
fonte
3

O objetivo do empuxo (como a maioria das bibliotecas de modelos) é fornecer uma abstração de alto nível, preservando o desempenho bom ou até excelente.

Eu sugeriria não se preocupar muito com o desempenho, mas se perguntar se

  • sua aplicação pode ser descrita em termos dos algoritmos implementados no impulso e, se

  • você gosta da possibilidade de escrever código paralelo "genérico", sem a necessidade de entrar nos detalhes sangrentos de encontrar um mapeamento eficiente para a arquitetura de hardware / software fornecida.

Se você responder positivamente a ambas as perguntas, poderá implementar seu programa com menos esforço em relação a uma implementação apenas do CUDA. Em seguida, você pode criar um perfil do seu aplicativo e decidir se vale a pena tentar melhorar o desempenho.

Dito isto, tenho que confessar que não gosto de programação "genérica", porque estou disposto a aprender algo novo quando escrevo um programa. Eu seguiria outra rota: escreva uma implementação de protótipo em python + numpy + scipy e adicione kernels CUDA para aqueles 1% - 2% do código que realmente precisa de otimização e é adequado para ser executado em uma GPU. Obviamente, ao fazer isso, você precisa de algum tipo de pré-ciência, pois uma decisão errada na fase de prototipagem (por exemplo, uma estrutura de dados inadequada para os kernels CUDA) pode ter resultados terríveis no desempenho. Geralmente, são necessárias mais iterações para obter um bom código e não há garantia de que o desempenho seja melhor do que o impulso.

Stefano M
fonte