Acesso ideal à memória ao usar tabelas de pesquisa na GPU?

9

Estou explorando algoritmos isosuperficiais na GPU para um projeto de bacharelado (concentrando-me especificamente em dados binários de entrada / saída de voxel em vez de campos com valor real). Portanto, eu tenho uma implementação de CPU de bons e antigos cubos de marchas em funcionamento no OpenFrameworks, e agora na fase de tentar portá-lo para os shaders de computação GLSL, e considerando as armadilhas antes de eu mergulhar. antes, então é tudo novo para mim.

Meu primeiro problema é como usar com eficiência uma tabela de pesquisa entre dezenas ou centenas de threads em um grupo de trabalho? Entendo que uma GPU possui diferentes tipos de memória para diferentes tarefas, mas não tenho certeza de como cada uma delas opera ou qual tipo usar.

A tabela de copypasta clássica de Paul Bourke é uma matriz de 256 * 16, portanto, se usar um tipo de byte escalar, presumivelmente ele poderá ser compactado em uma textura de 4kb ou SSBO.

A questão é: como impedir que os diferentes threads desagradem uns aos outros? Muitos cubos em cada grupo de trabalho podem potencialmente ter a mesma configuração, portanto, tentando acessar o mesmo local no buffer ao mesmo tempo. Existe uma solução alternativa ou otimização para lidar com isso?

russ
fonte
Se for uma tabela de pesquisa somente leitura, você pode apenas usar um buffer / textura. Você pode compactá-lo em um dos formatos normais de textura ou usar alguns dos recursos mais recentes do DX11 / OpenGL para ter um formato personalizado. UAV no território do DX11 ou um texture / shader_image_load_store no território do OpenGL.
RichieSams
Além disso, dê uma olhada nesta apresentação: cvg.ethz.ch/teaching/2011spring/gpgpu/cuda_memory.pdf É para a CUDA, mas você deve ter uma idéia melhor do que está acontecendo no hardware subjacente
RichieSams
Não é uma resposta completa, mas quanto menor a quantidade de memória usada, melhor, pois será mais provável que ela caiba nos caches e tenha menos falhas no cache. Se você tiver valores interpoláveis, como se estivesse dividindo pontos em uma curva em texturas, verifique isso como uma maneira de obter tabelas de pesquisa de curvas de qualidade mais alta com menos memória: blog.demofox.org/2016/02/22/…
Alan Wolfe

Respostas:

6

O melhor local para colocar uma tabela de consulta para um sombreador de computação de GPU depende do tamanho da tabela de consulta e da frequência / coerência do acesso. No seu caso (você mencionou 4kb), a memória local compartilhada provavelmente seria melhor (supondo que você não precise dessa memória para outros fins no mesmo kernel). Essa memória tem nomes diferentes em APIs diferentes, mas é a mesma coisa de arquitetura e segue as mesmas diretrizes de desempenho:

  • CUDA: memória compartilhada do grupo de threads
  • DirectCompute: memória compartilhada de grupos
  • OpenCL: memória local
  • Metal: memória do grupo de threads
  • OpenGL: memória compartilhada

Armazenar a tabela de pesquisa na memória global como um buffer somente leitura pode ter o mesmo desempenho, dependendo do (s) tamanho (s) de cache da GPU específica em que você está executando.

Observe que estou presumindo que esta seja uma tabela de pesquisa somente leitura. Uma tabela de pesquisa de leitura e gravação é uma fera completamente diferente e você não tem boas opções lá.

GroverManheim
fonte
Também há casos em que um buffer somente leitura funciona melhor do que armazenar 4kb de dados somente leitura na memória local compartilhada. Por exemplo, armazená-lo na memória local pode significar que há uma cópia exclusiva dos seus dados para cada grupo de encadeamentos. Se o buffer couber no cache, é bem possível que o cache tenha um desempenho melhor que a memória local para padrões de acesso somente leitura.
John Calsbeek
Obrigado pelo feedback pessoal. Eu terminei o projeto que eu estava usando isso para agora, e acabou apenas usando um r8ui readonly tampão textura, que funcionou muito bem :)
russ